<feed xmlns:atom="http://www.w3.org/2005/Atom">
    <title>Eiggen // Codes</title>
    <link>https://www.eiggen.co/codes/</link>
    <icon>/favicon.ico</icon>
    
        <language>en-us</language>
    
    <updated>2022-02-01T00:00:00+0000</updated><atom:link href="https://www.eiggen.co/codes/index.xml" rel="self" /><generator uri="http://gohugo.io/">Hugo</generator>
    
        <entry>
            <title>Software Engineering Interviewing</title>
            <link href="https://www.eiggen.co/codes/software-engineering-interviewing/"/>
            <updated>2022-02-01T00:00:00+0000</updated>
            <id>https://www.eiggen.co/codes/software-engineering-interviewing/</id>
            <content type="html"><![CDATA[ <h2 id="foreword">Foreword</h2>
<p>In August 2020, and for the first time in my career, I made the decision to leave a job without having another one lined up. This was a highly unusual decision for me: all my previous moves had been planned and I always waited to have an offer in hand before giving notice. I&rsquo;d previously seen friends and coworkers make the same decision and I felt uneasy about it, primarily for material reasons. I tend to be conservative when it comes to managing my personal finances and I don&rsquo;t like the idea of suddenly cutting my main source of income without knowing when –or how– it would come back.</p>
<p>But for the most part, I&rsquo;d seen this approach work, occasionally leading to great results. From experience, I knew interviewing with other companies while still on the job can quickly lead to feeling like you&rsquo;re living a double life (and that the second life feels like no less work than the first one). The idea of having an open schedule to research, prep and to interview was alluring. Over time, I had warmed up to the idea that this might be something I could do myself.</p>
<p>Considering the uncertainty caused by the pandemic and by the upcoming US election, having to look for a new gig in the second half of 2020 wasn&rsquo;t really a position I <em>wanted</em> to find myself in. Along with a few others, two factors principally contributed to my decision to quit before figuring out what would be next:</p>
<ol>
<li>I was simply not happy with my position at Lyft and the environment that the company fostered: the pandemic hit the ride-sharing industry very hard, morale was low and my team suffered from it</li>
<li>My team was on the verge of embarking in a large long-term project and interviewing in parallel of that would mean not being able to properly honor these commitments</li>
</ol>
<p>Once I was out of a job, I first took a bit of time off and then worked to get myself back into interviewing shape. This post unpacks my experience going through the interviewing wringer with about a dozen companies over the course of two months. I can&rsquo;t say I was too surprised by what I found, but being able to compare a handful of companies over a relatively short time span painted an informative picture of what interviewing is like these days.</p>
<h3 id="acknowledgments">Acknowledgments</h3>
<p>I have to acknowledge that the decision to quit my job bore less risk for me than for most. I have enough savings to stop working for a few months without being hit too hard, the employment market for software engineers looked strong despite the pandemic, and my spouse&rsquo;s benefits allowed me to retain medical coverage. I don&rsquo;t think I would have been in the position to do so had any of these conditions not been met.</p>
<p>I would like to credit Carlin Eng for inspiring me to write such a post. He went through a short halt in his career after leaving Strava and wrote an excellent <a href="https://medium.com/@carlineng/my-time-on-the-job-market-as-a-data-engineer-4c711d1fc31f">article</a> that unpacks how the experience went for him. I hope my post can serve as a slightly different take on the same topic: I wanted to go a little deeper than Carlin did on the topics of preparing for interviewing and what the final stages of the process can look like.</p>
<p>I also want to clarify that in spite of explaining my approach for engaging with interviews, this post is not an endorsement of the interviewing process itself. Our industry has, in my opinion, consistently failed at developing a method to vet candidates which is both effective and respectful of people. What I mean by &ldquo;effective&rdquo; here is: scalable in the moment and able to accurately predict the actual performance of engineers on the job. Google itself acknowledged that, in spite of spending tens of millions of dollars every year on moving candidates through the pipeline, stellar candidates can turn into very poor engineers. And we don&rsquo;t hear of poor candidates that would have made great engineers—they were by definition left behind.</p>
<p>What I&rsquo;m getting to here is that companies cynically focus on the process piece (&quot;<em>Does this candidate meet $BAR?</em>&quot;) while candidates care about outcomes (&quot;<em>I&rsquo;m a good engineer, I should be given an offer</em>&quot;). So much frustration stems from that disconnect. It took me about a decade to wrap my head around it and this post contains some of what I learned along the way. But I want to be clear: I&rsquo;m playing this game in spite of its core premise being broken to some degree.</p>
<p>As a final disclaimer: what is written below is my personal take and experience on the interviewing and hiring process. One size doesn&rsquo;t fit all and your mileage may vary. There is no single way to prepare for coding interviews, or to navigate a design a question, or to consider an offer. The approaches and points of view I&rsquo;m sharing here are the ones I hold true, either because they stem from core beliefs or because I&rsquo;ve seen them work as a candidate or interviewer. I believe there&rsquo;s value in making the process less opaque, but please keep a healthy skepticism of what is written below.</p>
<nav id="TableOfContents">
  <ul>
    <li><a href="#foreword">Foreword</a>
      <ul>
        <li><a href="#acknowledgments">Acknowledgments</a></li>
      </ul>
    </li>
    <li><a href="#on-hiring">On Hiring</a></li>
    <li><a href="#preparation">Preparation</a>
      <ul>
        <li><a href="#coding">Coding</a>
          <ul>
            <li><a href="#language">Language</a></li>
            <li><a href="#on-brainteasers">On brainteasers</a></li>
            <li><a href="#algorithms-and-data-structures">Algorithms and data structures</a></li>
          </ul>
        </li>
        <li><a href="#non-technical-skills">Non-technical skills</a></li>
        <li><a href="#design">Design</a>
          <ul>
            <li><a href="#process">Process</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li><a href="#company-selection">Company Selection</a></li>
    <li><a href="#timeline">Timeline</a></li>
    <li><a href="#candidate-experience">Candidate Experience</a>
      <ul>
        <li><a href="#interview-formats">Interview formats</a></li>
        <li><a href="#diversity">Diversity</a></li>
        <li><a href="#logistics">Logistics</a></li>
      </ul>
    </li>
    <li><a href="#offers">Offers</a>
      <ul>
        <li><a href="#comparison">Comparison</a></li>
        <li><a href="#equity">Equity</a></li>
        <li><a href="#benefits">Benefits</a></li>
        <li><a href="#role-fit">Role fit</a></li>
      </ul>
    </li>
    <li><a href="#parting-notes">Parting Notes</a>
      <ul>
        <li><a href="#outcome">Outcome</a></li>
      </ul>
    </li>
  </ul>
</nav>
<h2 id="on-hiring">On Hiring</h2>
<p>By the time it is actively hiring, a company has entered a failure mode: there are needs in the face of which the current staff is unable to scale. In that light, I reason about the hiring process as a method to fail as gracefully as possible: just like a normal incident response, the process needs to be tight, coherent, snappy, and transparent. I began realizing the importance of building a good hiring process since I worked in a startup whose throughput depended on getting the right people. I carried it with me in my following gigs, and that&rsquo;s something I pay a good amount of attention to, both as an interviewer and as a candidate.</p>
<p>For software engineering candidates, interviewing is vastly different task than what they are expected to do on their day job. You&rsquo;d never be expected to have to code yourself out of a never-seen-before problem and ship it without writing any tests in under 20 minutes. You also wouldn&rsquo;t crack out a full-fledged design for a scalable distributed system without doing research or experimentation to inform your proposal. Yet somehow, these are the skills you are expected to demonstrate during interviews.</p>
<p>What I&rsquo;m getting to here is that neither side of the hiring process is effortless: each party should put some work into preparing for it. Part of it is theater, part of it is contrived, but being good at it doesn&rsquo;t come naturally—at least not to me.</p>
<h2 id="preparation">Preparation</h2>
<h3 id="coding">Coding</h3>
<h4 id="language">Language</h4>
<p>An important aspect of going into code interviews is to have <em>some</em> proficiency in a programming language. From my experience conducting interviews, I would actively discourage anyone from using a compiled language. In coding interviews, time is of the essence: running your code is something you will want to do very early and very often.</p>
<p>Compiled languages not only tend to be more verbose, time is also lost with the various type checking and assembly steps that the compiler needs to do every time you want to run the code. Scripting languages are definitely the way to go. A usual favorite is Python, but I myself have developed a strong personal preference for Ruby.</p>
<p>Ruby is full of one-liners and idioms that, once mastered, become very useful shortcuts to use during an interview:</p>
<ul>
<li>Keywords such as <code>unless</code> and common boolean functions such as <code>.nil?</code>, <code>.empty?</code> make the code easier to read and can allow an almost direct translation of the problem statement into code.</li>
<li><code>attr_accessor</code> and friends are great to define value classes in just a few lines, which is something you occasionally have to do.</li>
<li>The built-in <code>Hash</code> class allows for default values: <code>Hash.new { |hash, key| hash[key] = Array.new }</code>, which is a very common task in interviews. Not having to handle this explicitly saves time.</li>
<li>The entire <code>Enumerable</code> module is phenomenal when it comes to dealing with collections.</li>
<li>The lack of <code>return</code> in methods make the code more succinct, albeit possibly less readable for non-Ruby programmers</li>
<li>The chaining of functional calls can be really powerful to do semi-complex transforms and filtering in a bind:</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="o">[</span><span class="s1">&#39;fig&#39;</span><span class="p">,</span> <span class="s1">&#39;pear&#39;</span><span class="p">,</span> <span class="s1">&#39;apple&#39;</span><span class="p">,</span> <span class="s1">&#39;flea&#39;</span><span class="p">,</span> <span class="s1">&#39;kea&#39;</span><span class="p">,</span> <span class="s1">&#39;rhea&#39;</span><span class="o">].</span><span class="n">reject</span> <span class="k">do</span> <span class="o">|</span><span class="n">word</span><span class="o">|</span>
    <span class="n">word</span><span class="o">.</span><span class="n">length</span> <span class="o">&lt;=</span> <span class="mi">3</span>
<span class="k">end</span><span class="o">.</span><span class="n">sort</span> <span class="k">do</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">|</span> 
    <span class="n">a</span><span class="o">.</span><span class="n">length</span> <span class="o">!=</span> <span class="n">b</span><span class="o">.</span><span class="n">length</span> <span class="p">?</span> <span class="n">a</span><span class="o">.</span><span class="n">length</span> <span class="o">&lt;=&gt;</span> <span class="n">b</span><span class="o">.</span><span class="n">length</span> <span class="p">:</span> <span class="n">a</span> <span class="o">&lt;=&gt;</span> <span class="n">b</span>
<span class="k">end</span><span class="o">.</span><span class="n">first</span>
</code></pre></div><p>I wouldn&rsquo;t recommend learning a new language just for the sake of interviewing; my own proficiency in Ruby stems from 4+ years writing production-grade code at Strava. But if you are on the fence, I do believe Ruby to be a great language for coding interviews.</p>
<h4 id="on-brainteasers">On brainteasers</h4>
<p>As Carlin pointed out in his post, <a href="http://www.crackingthecodinginterview.com/">Cracking the Coding Interview</a>(CtCI) is a useful book to refer yourself to ahead of the actual interviews. But I also do not believe there is a ton of value trying to implement or memorize the solution to the hundreds of problems contained in the book. Some trivial problems found in the early pages can be useful to get yourself back into a mode where you have to deliver a working solution quickly and then fiddle with it with an extra constraint.</p>
<p>Other more complex ones may be getting frankly into the brainteaser territory, which, as far as I&rsquo;m concerned, are not worth preparing for. What I qualify as a brainteaser is a problem that meets the following criteria:</p>
<ol>
<li>there is an optimal solution that doesn&rsquo;t lend itself to practical trade-offs</li>
<li>getting to the solution requires an insight or directed hints from the interviewer</li>
</ol>
<p>The fewer hints you get, the better engineer you&rsquo;re supposed to be. But if you Googled the question, you would likely find the one true solution in the first page of results.</p>
<p>It&rsquo;s a <strong>bad sign</strong> if an interviewer is assessing you using problems that can be solved through Google — maybe it means candidates that passed are brilliant problem solvers who can think on their feet, or they might have memorized the solutions when they inevitably ran into the problem on Leetcode. What I&rsquo;m looking for in a good coding problem is one of two things:</p>
<ul>
<li>a rough match with the specific domain that the candidate is expected to work in: build tooling stuff for build tools teams, infra stuff for infra teams, web stuff for web teams, etc…</li>
<li>an open-ended question where there are trade-offs to make and therefore hopefully more than a single valid approach</li>
</ul>
<p>Brainteasers just don&rsquo;t make the cut.</p>
<p>What I&rsquo;m getting to is that if you pass a brainteaser interview, you&rsquo;re going to end up working with other people who have met the same bar. It might work out in the end — and historically, you might argue that it has worked for companies the likes of FAANGs. My point here is that the very questions you are asked during your interview offer an insight into how the company selects candidates, and what is valued in terms of skills.</p>
<p>Good programming interview questions are few and far apart — companies that spend time crafting a good bank of questions have an edge over those that don&rsquo;t. Going off of stuff you find on Leetcode is lazy and provides a weak signal. For candidates, this should be a flag that company isn&rsquo;t taking hiring seriously.</p>
<h4 id="algorithms-and-data-structures">Algorithms and data structures</h4>
<p>As far as preparing to answer coding problems, I forced myself to re-implement a number of commonly used data structures: hash tables, binary search trees, tries, linked lists, heaps, etc… This is the kind of stuff that you would normally always pull out of a standard library but going through those basics provided a playground to brush up my Ruby programming and a refresher on complexities. Once you have these, you can then work on higher-level structures and algorithms: expiring caches, traversal algorithms, bloom filters, tree re-balancing.</p>
<p>I then spent time working through abstractions such as iterators, comparators, streams, and, lastly, sorting algorithms. I did go through some Leetcode-like problems —brainteasers, to call them what they are— but I felt like they were less important to my preparation than most other things I decided to do on my own.</p>
<h3 id="non-technical-skills">Non-technical skills</h3>
<p>One value of <em>CtCI</em> is the preparation it forces you to do for non-technical questions. I&rsquo;m not going to disclose the exact contents of the book but it fundamentally parallels the STAR framework:</p>
<ul>
<li><strong>Situation</strong>: Describe the context of a project you contributed to or led.</li>
<li><strong>Task</strong>: What were you expected to do and what was the scope?</li>
<li><strong>Action</strong>: What did you actually do? Did you go beyond what was expected? Were there trade-offs along the way?</li>
<li><strong>Result</strong>: What was your impact? Don&rsquo;t limit yourself to technical achievements</li>
</ul>
<p>I came ready to discuss these things for 3 to 4 distinct projects or programs I personally worked on. To this, I also added a few follow-up questions that I&rsquo;d be asking myself if I was the interviewer:</p>
<ul>
<li>With the gift of hindsight, what would I do differently?</li>
<li>Some examples of situations where I was a responsible for communicating or coordinating across functions.</li>
<li>Times where personal or technical conflicts arose and how they were handled.</li>
<li>A recent example where I changed my mind about something.</li>
</ul>
<h3 id="design">Design</h3>
<p>100% of the design questions I&rsquo;ve worked on during my month of interviewing were distributed systems problems, which naturally lend themselves to trade-offs between performance, reliability and correctness. The way I went about preparing for this was two-fold:</p>
<ol>
<li>Going over my own previous designs documents and working through the architecture and the decisions I made at the time. It&rsquo;s helpful to look at those with a critical eye and attempt to find faults with certain approaches I took.</li>
<li>Reading up articles / explainers on the implementation of key pieces of software:
<ul>
<li>MySQL <a href="https://dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html">indexing</a> and <a href="https://dev.mysql.com/doc/refman/8.0/en/replication.html">replication</a></li>
<li>Kafka (<a href="https://medium.com/swlh/understanding-kafka-a-distributed-streaming-platform-9a0360b99de8">1</a>, <a href="https://medium.com/@durgaswaroop/a-practical-introduction-to-kafka-storage-internals-d5b544f6925f">2</a>)</li>
<li>Envoy&rsquo;s <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/life_of_a_request">life of a request</a> and support for <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/load_balancing/load_balancing">load balancing</a></li>
<li><a href="https://redis.io/topics/introduction">Redis</a></li>
<li><a href="https://www.instaclustr.com/cassandra-architecture/">Cassandra</a></li>
<li><a href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP</a> — which might seem like a peculiar recommendation, but this is the base protocol that  powers the Internet. It is not only fundamental but also packs a lot of good features that are often overlooked and re-implemented at a higher level of the stack (flow control! congestion control!).</li>
</ul>
</li>
</ol>
<p>Keep in mind that, ultimately, very, very few engineers in the world actually design and develop scalable distributed systems from scratch. Part of an engineer&rsquo;s job is to know how to piece things together in order to meet the stated goals of the system being built. Knowing what those pieces are, and knowing how they work and what their limits are, that&rsquo;s the thing you want to be able to demonstrate during a design interview.</p>
<p>Basically, it&rsquo;s unlikely that an interviewer will grill a candidate on their full understanding of Paxos, but it&rsquo;s good for the candidate to know how a leader election happens. A design interview is just as much an assessment of communication skills as it is of technical skills.</p>
<h4 id="process">Process</h4>
<p>My personal approach to answering design questions is to let my stream of consciousness take over: I openly share the thoughts that come to me, or the struggles I have about an approach. This gives opportunities for the interviewer to intervene, object, assist, or clarify a requirement. I&rsquo;ve generally followed a 5-or-so step process:</p>
<ol>
<li><strong>Ask clarifying questions</strong>, or, alternatively, make statements that clarify the problem at hand: &ldquo;it seems to be a read-heavy system, so I&rsquo;ll make sure to to center my design around that&rdquo;. This is especially important for parts that appear trivial to you, since it&rsquo;ll help the interviewer know that you are thinking this through and not glossing over things.</li>
<li><strong>Top-down first</strong>: decompose the problem in large chunks that each have a coherent role, e.g. &ldquo;I&rsquo;ll need a queue, a load balancer and some storage&rdquo;. Establish the scale for each of those, the interfaces and the invariants that need to remain true between them. If no obvious architectural choices come to you, just talk out loud about your thinking process.</li>
<li><strong>Bottom-up second</strong>: run through the set of components you have identified and make implementation proposals for each of them. Explain out loud what your thinking is and the rationale for those decisions.</li>
<li><strong>Do a run through</strong> of the entire system once and see if the goals are met. Identify bottlenecks or failure modes. Discuss how you would counter them or solve for them. Sometimes, the interviewer will challenge the design or change a parameter that feels like the rug is being pulled from under your feet. This can make you feel like you design suddenly has to cover more ground but it is generally an invitation to discuss trade-offs: no real-world system is perfect, and your design cannot be perfect either.</li>
<li><strong>Open things up</strong>: if you were writing a true technical specification, there would be a ton of other considerations you&rsquo;d need to cover: ease of operations, observability, configurability, security, resilience, deployment, etc… If you have the time, talking about those can yield a solid conversation to wrap things up and convey that you care about more than the base design.</li>
</ol>
<h2 id="company-selection">Company Selection</h2>
<p>I didn&rsquo;t really have a positive filter for the profile of companies I considered. I did however prune out companies and domains early on: this is ultimately a fairly personal choice but it might explain how I ended up with the final slate of companies.</p>
<ul>
<li>Facebook was a no-go from the beginning: their product and leadership team have enabled fascism to take root in the country I live in. They thrive in supplying polarizing content and spreading lies to their users.</li>
<li>I avoided the crypto industry as a whole, mostly because I&rsquo;m not interested in it but also because of the kind of <a href="https://blog.coinbase.com/coinbase-is-a-mission-focused-company-af882df8804">toxicity</a> that festers in circles seeking to profit from sole disruption. With the gift of hindsight, the recent madness around NFTs and <a href="https://web3isgoinggreat.com/">web3</a> has put the final nail in that coffin.</li>
<li>Even though most companies in the Bay Area have called for extended periods where employees are working from home, I wanted to favor a strong presence in San Francisco, which is where I live. This eliminated a number of big targets: Apple, Google, Netflix to name a few.</li>
</ul>
<p>Other than that, I tend to favor companies whose product I use every day, e.g. the ones whose app has a place on my phone&rsquo;s home screen. I made myself available on LinkedIn and began looking for postings on the websites of said companies.</p>
<h2 id="timeline">Timeline</h2>
<p>I overall engaged with a total of 12 companies, across a 10-week period.</p>
<ul>
<li>I directly applied to 8 companies, out of which 3 didn&rsquo;t answer at all (Netlify, GitLab, 1Password), 2 were quick dead-ends (Local Laboratories, Substack), and 3 led to interviews</li>
<li>I responded to 2 sourcers who reached out on LinkedIn, both of which led to interviews</li>
<li>I was referred into 2 companies (GitHub and Slack), both of which fizzled out quickly</li>
</ul>
<p>For the companies I directly applied to, I was intent to write a cover letter — even though I had the intuition they would be dismissed or discarded by screeners, it was a forcing function for me to investigate the company, to dig into job description and write down why I think I&rsquo;d be a match for the role. This was more for my benefit than for theirs.</p>
<p>In total, I was concurrently pursuing 5 leads throughout the month of October. Since I don&rsquo;t feel like there is value in naming them, I will from this point on refer to them using greek letters: α, β, γ, δ, ε. And since my initial selection was fairly open, I ended up with a fairly varied set of company profiles: headcounts ranging from a couple dozen of employees to many thousands, valuations going from $100M to many tens of billions, and a healthy mix of private and public companies.</p>



  
    <svg width="900" height="490" xmlns="http://www.w3.org/2000/svg" version="1.1"><rect height="420" width="25" x="200.67567567567568" y="35" style="fill:whitesmoke;"></rect><rect height="420" width="25" x="271.6216216216216" y="35" style="fill:whitesmoke;"></rect><rect height="420" width="25" x="342.5675675675676" y="35" style="fill:whitesmoke;"></rect><rect height="420" width="25" x="413.5135135135135" y="35" style="fill:whitesmoke;"></rect><rect height="420" width="25" x="484.4594594594595" y="35" style="fill:whitesmoke;"></rect><rect height="420" width="25" x="555.4054054054054" y="35" style="fill:whitesmoke;"></rect><rect height="420" width="25" x="626.3513513513514" y="35" style="fill:whitesmoke;"></rect><rect height="420" width="25" x="697.2972972972973" y="35" style="fill:whitesmoke;"></rect><rect height="420" width="25" x="768.2432432432432" y="35" style="fill:whitesmoke;"></rect><rect height="420" width="25" x="839.1891891891892" y="35" style="fill:whitesmoke;"></rect><text x="231.0810810810811" y="23.333333333333332" style="font-family: Sans-Serif;font-size: small;">Sep</text><text x="535.1351351351352" y="23.333333333333332" style="font-family: Sans-Serif;font-size: small;">Oct</text><text x="849.3243243243243" y="23.333333333333332" style="font-family: Sans-Serif;font-size: small;">Nov</text><circle cx="150" cy="472.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"></circle><text x="162.5" y="476.6666666666667" style="font-family: Sans-Serif;font-size: small;">Application</text><circle cx="251.09716796875" cy="472.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"></circle><text x="263.59716796875" y="476.6666666666667" style="font-family: Sans-Serif;font-size: small;">Introductory call(s)</text><circle cx="395.51708984375" cy="472.5" r="4.166666666666667" stroke-width="3" stroke="#682D63" fill="#682D63"></circle><text x="408.01708984375" y="476.6666666666667" style="font-family: Sans-Serif;font-size: small;">Phone screen</text><circle cx="513.23876953125" cy="472.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"></circle><text x="525.73876953125" y="476.6666666666667" style="font-family: Sans-Serif;font-size: small;">Onsite(s)</text><circle cx="603.46875" cy="472.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"></circle><text x="615.96875" y="476.6666666666667" style="font-family: Sans-Serif;font-size: small;">Final / Offer</text><g transform="translate(0, 35)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">Github</text><line x1="156.25" x2="227.19594594594594" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="156.25" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Mon Aug 24 2020 - Applied</title></circle><circle cx="227.19594594594594" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Mon Aug 31 2020 - Rejected</title></circle></g><g transform="translate(0, 70)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">Netlify</text><line x1="196.79054054054055" x2="399.4932432432432" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="196.79054054054055" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Fri Aug 28 2020 - Applied</title></circle><circle cx="399.4932432432432" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Thu Sep 17 2020 - Followed-up</title></circle></g><g transform="translate(0, 105)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">δ</text><line x1="196.79054054054055" x2="875.8445945945946" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="196.79054054054055" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Fri Aug 28 2020 - Sourcer outreach</title></circle><circle cx="267.73648648648646" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Fri Sep 04 2020 - Second Sourcer outreach</title></circle><circle cx="369.0878378378378" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Mon Sep 14 2020 - Response</title></circle><circle cx="379.22297297297297" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"><title>Tue Sep 15 2020 - First intro call</title></circle><circle cx="521.1148648648648" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#682D63" fill="#682D63"><title>Tue Sep 29 2020 - Phone screen</title></circle><circle cx="663.0067567567568" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Tue Oct 13 2020 - Onsite</title></circle><circle cx="683.277027027027" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Thu Oct 15 2020 - Feedback</title></circle><circle cx="723.8175675675676" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"><title>Mon Oct 19 2020 - Team fit</title></circle><circle cx="835.3040540540541" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"><title>Fri Oct 30 2020 - Team fit follow-up</title></circle><circle cx="865.7094594594595" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"><title>Mon Nov 02 2020 - Offer</title></circle><circle cx="875.8445945945946" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"><title>Tue Nov 03 2020 - Offer follow-up</title></circle></g><g transform="translate(0, 140)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">γ</text><line x1="369.0878378378378" x2="885.9797297297297" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="369.0878378378378" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Mon Sep 14 2020 - Applied</title></circle><circle cx="551.5202702702702" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Fri Oct 02 2020 - Email Response</title></circle><circle cx="581.9256756756756" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"><title>Mon Oct 05 2020 - First Call</title></circle><circle cx="683.277027027027" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#682D63" fill="#682D63"><title>Thu Oct 15 2020 - Phone Screen</title></circle><circle cx="693.4121621621622" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#682D63" fill="#682D63"><title>Fri Oct 16 2020 - Feedback</title></circle><circle cx="804.8986486486486" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Tue Oct 27 2020 - Onsite</title></circle><circle cx="835.3040540540541" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Fri Oct 30 2020 - Feedback</title></circle><circle cx="865.7094594594595" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"><title>Mon Nov 02 2020 - Reference Check</title></circle><circle cx="875.8445945945946" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"><title>Tue Nov 03 2020 - Team fit calls</title></circle><circle cx="885.9797297297297" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"><title>Wed Nov 04 2020 - Offer</title></circle></g><g transform="translate(0, 175)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">GitLab</text><line x1="379.22297297297297" x2="379.22297297297297" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="379.22297297297297" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Tue Sep 15 2020 - Applied</title></circle></g><g transform="translate(0, 210)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">α</text><line x1="399.4932432432432" x2="754.222972972973" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="399.4932432432432" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Thu Sep 17 2020 - Sourcer outreach</title></circle><circle cx="460.30405405405406" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Wed Sep 23 2020 - Response from me</title></circle><circle cx="510.97972972972974" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"><title>Mon Sep 28 2020 - Intro call with recruiter</title></circle><circle cx="541.3851351351352" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"><title>Thu Oct 01 2020 - Intro call with hiring manager</title></circle><circle cx="602.1959459459459" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#682D63" fill="#682D63"><title>Wed Oct 07 2020 - Coding challenge</title></circle><circle cx="663.0067567567568" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#682D63" fill="#682D63"><title>Tue Oct 13 2020 - Feedback on coding challenge</title></circle><circle cx="693.4121621621622" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Fri Oct 16 2020 - Onsite prep call</title></circle><circle cx="744.0878378378378" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Wed Oct 21 2020 - Day of onsite interviews</title></circle><circle cx="754.222972972973" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Thu Oct 22 2020 - Feddback / Rejected</title></circle></g><g transform="translate(0, 245)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">Local Laboratory</text><line x1="409.6283783783784" x2="622.4662162162163" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="409.6283783783784" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Fri Sep 18 2020 - Applied</title></circle><circle cx="541.3851351351352" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Thu Oct 01 2020 - Response</title></circle><circle cx="612.331081081081" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"><title>Thu Oct 08 2020 - Call</title></circle><circle cx="622.4662162162163" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"><title>Fri Oct 09 2020 - No fit</title></circle></g><g transform="translate(0, 280)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">1Password</text><line x1="450.1689189189189" x2="450.1689189189189" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="450.1689189189189" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Tue Sep 22 2020 - Applied</title></circle></g><g transform="translate(0, 315)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">ε</text><line x1="460.30405405405406" x2="835.3040540540541" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="460.30405405405406" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Wed Sep 23 2020 - Applied</title></circle><circle cx="612.331081081081" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"><title>Thu Oct 08 2020 - Email Response</title></circle><circle cx="673.1418918918919" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"><title>Wed Oct 14 2020 - First Call</title></circle><circle cx="733.9527027027027" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#682D63" fill="#682D63"><title>Tue Oct 20 2020 - Phone Screen + Feedback</title></circle><circle cx="794.7635135135135" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Mon Oct 26 2020 - Onsite</title></circle><circle cx="815.0337837837837" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Wed Oct 28 2020 - Onsite</title></circle><circle cx="825.168918918919" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Thu Oct 29 2020 - Feedback</title></circle><circle cx="835.3040540540541" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"><title>Fri Oct 30 2020 - Team fit &amp; Offer</title></circle></g><g transform="translate(0, 350)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">Substack</text><line x1="480.5743243243243" x2="825.168918918919" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="480.5743243243243" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Fri Sep 25 2020 - Applied</title></circle><circle cx="794.7635135135135" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Mon Oct 26 2020 - Response</title></circle><circle cx="825.168918918919" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"><title>Thu Oct 29 2020 - Intro call</title></circle></g><g transform="translate(0, 385)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">β</text><line x1="480.5743243243243" x2="875.8445945945946" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="480.5743243243243" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Fri Sep 25 2020 - Sourcer outreach</title></circle><circle cx="521.1148648648648" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"><title>Tue Sep 29 2020 - First intro call</title></circle><circle cx="581.9256756756756" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Mon Oct 05 2020 - Onsite</title></circle><circle cx="602.1959459459459" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Wed Oct 07 2020 - Feedback</title></circle><circle cx="622.4662162162163" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Fri Oct 09 2020 - Follow-up</title></circle><circle cx="764.3581081081081" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#E5989B" fill="#E5989B"><title>Fri Oct 23 2020 - Pair programming</title></circle><circle cx="794.7635135135135" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"><title>Mon Oct 26 2020 - Reference sent</title></circle><circle cx="835.3040540540541" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"><title>Fri Oct 30 2020 - Offer</title></circle><circle cx="875.8445945945946" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#98DFAF" fill="#98DFAF"><title>Tue Nov 03 2020 - CEO call</title></circle></g><g transform="translate(0, 420)"><line x1="0" x2="900" y1="35" y2="35" stroke="lightgray"></line><text x="5" y="23.333333333333332" style="font-family: Sans-Serif;">Slack</text><line x1="642.7364864864865" x2="663.0067567567568" y1="17.5" y2="17.5" stroke="gray" stroke-width="2"></line><circle cx="642.7364864864865" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#FED766" fill="#FED766"><title>Sun Oct 11 2020 - Referred</title></circle><circle cx="663.0067567567568" cy="17.5" r="4.166666666666667" stroke-width="3" stroke="#009FB7" fill="#009FB7"><title>Tue Oct 13 2020 - First intro call</title></circle></g></svg>
  


<p>Beyond searching for a job, I spent the rest of my days working on personal projects, playing games, running errands, going on runs or on bike rides. Following Carlin&rsquo;s example, I tried to set aside a day a week to go outside on a ride and empty my head. In spite of this, I didn&rsquo;t feel quite enough in control of the whole process to really be at ease.</p>
<p>Some companies I was excited about were entirely non-responsive and I had to make peace with that. The process dragged on with certain companies while others were really snappy. Offers that came with deadlines meant having to rush things — which is good to an extent, but also incurs a higher level of stress.</p>
<p>The end-to-end timeline ran from the tail-end of August to the beginning of November (actually, election week 😬). I kicked it off with a couple of companies which I applied to in the couple of weeks right after leaving Lyft. I resumed applying in mid-September and sent applications or responded to a handful of companies each week.</p>
<p>In addition to sending my resume around, I started going through my interview training program. There wasn&rsquo;t a ton of responses at first but things warmed up once October came around.</p>
<h2 id="candidate-experience">Candidate Experience</h2>
<p>Overall, the interviewing process went pretty well across the board, with the notable exception of one company where the day of onsite went poorly: company α.</p>
<h3 id="interview-formats">Interview formats</h3>
<p>I was happily surprised to see new interview formats introduced since the last time I went though the process:</p>
<ul>
<li>Three companies have adopted a format where two interviewers are present on all or most of the calls, presumably to avoid situations where a candidate feels cornered (or discriminated against) and isolated in the presence of a single interviewer. This mostly worked well, especially when both interviewers made a effort to create a three-way conversation. At other times, the third person on the call remained silent for the entire interview, which instead triggered a feeling of being put under extra scrutiny.</li>
<li>Ahead of the &ldquo;onsite&rdquo;, one company asked me to prepare a 20 minute presentation on a past project of my choosing, which the interviewers then used as a basis for asking follow-up questions. This ended being a great interview, since I felt like I was given a chance to showcase my best work.</li>
<li>Rather than doing a coding challenge, one company offered to pair me with an engineer for a full day of (compensated) work where I went through the engineering onboarding process, ran the stack locally and worked through a coding problem. I was also given the chance to attend the company all-hands.</li>
</ul>
<h3 id="diversity">Diversity</h3>
<p>I identify as the absolute dominant profile in the north american software industry: white, cisgender, straight, and male. I&rsquo;ve also been on the organizing side of DEI initiatives in companies and products I worked on. I wanted to pay attention to this as I was going through my interview process and it&rsquo;s no surprise: no company is really doing this well.</p>
<p>As I went through the &ldquo;onsites&rdquo;, I tried to keep a running tally of the profiles of people who were interviewing me: their role and seniority, but also their apparent gender and ethnicity. A major caveat here is that I never explicitly asked my interviewers how they identify in terms of gender identity or racial background, which means the data presented below is tainted by my own perception and bias.</p>
<p>I was interviewed by 35 people in total, and the panels were all between 6 and 8 people. I&rsquo;ve opted against presenting a per-company breakdown in this post because I believe the samples are too small to be meaningful. As a whole, however, the data paints a relevant picture:</p>
<ol>
<li>Bar for one, all my panels had at least one female interviewer. Two thirds of my interviewers were male.</li>
<li>All panels had at at least one non-white person, sometimes just a single one. Two of the five companies had people of color in positions of leadership. Only one black person interviewed me.</li>
<li>One interviewer shared that they were involved in their LGBT ERG</li>
</ol>
<p>Two caveats are worth mentioning: in some cases, a single interviewer was wearing multiple of those hats, and sometimes those interviewers were in non-technical roles (e.g. designer or product manager). The numbers would be grimmer if I focused solely on engineering roles.</p>
<p>Similarly to the questions they chose to ask, the makeup of an interview panel can clue candidates as to what is valued at the company. Three of the five companies had me interview with non-engineers, and another one had three of my onsite interviews grill me extensively about cross-functional collaboration and project management. This is great! Companies should absolutely vet an engineer&rsquo;s experience working with less technical partners.</p>
<p>Notably, company α&rsquo;s panel was solely comprised of men, all of them engineers. I was only asked technical questions, a few of these being brainteasers. In the moment, I was honestly frustrated that I didn&rsquo;t do better. In hindsight, and despite the hiring manager&rsquo;s reassurance that the company fostered a very healthy culture, I didn&rsquo;t have a ton of regret about flunking.</p>
<h3 id="logistics">Logistics</h3>
<p>The pandemic threw a wrench in many processes, and the interviewing one is no exception. By the time I started to interview, I had worked from home since the sheltering in place had begun almost six months prior. For companies, onsites are an opportunity to showcase their offices and perks. Meeting some prospective teammates in person and casually chatting over lunch is part of the experience as well.</p>
<p>All of that is gone in 2020. It makes for a less appealing day, but also requires a bit more preparation for candidates — things that coordinators would normally be in charge of. Here&rsquo;s what was helpful for me:</p>
<ul>
<li>A cell phone plan with plenty of minutes, as I expected having to receive and place a lot of calls. Not having to bother about overages is really nice.</li>
<li>A good Bluetooth headset with a built-in mic is great for both phone calls and VC</li>
<li>A water bottle refilled in full before each interview, especially during the &ldquo;onsite&rdquo;</li>
<li>Some snacks to refuel between interviews</li>
</ul>
<p>Companies also need to change their ways — notably, it becomes harder for candidates and interviewers to exchange non-verbal cues. This means communication skills become increasingly important for both. The one notable negative experience I had was a design interview where both interviewers kept their webcams turned off, which obviously made the interview a lot harder for me. Putting candidates at ease by doing proper introduction also becomes more important, and increases the chances that candidates will perform their best. Interviewers that cut the introduction short without expressing the slightest interest in what I had to say were a clear red flag for me.</p>
<h2 id="offers">Offers</h2>
<h3 id="comparison">Comparison</h3>
<p>It&rsquo;s already hard enough to precisely know what lies within a single offer, and the fit for the role and with the folks also plays a huge part in a decision that is deeply personal. In my case, 4 of the 5 companies I interviewed with ended up extending an offer. The basic components are still the same: base pay, equity, bonus and benefits. There&rsquo;s no tried and true method for comparing those uniformly, especially as the cost of equity can differ significantly:</p>
<ul>
<li>ISOs have a cost but are eligible to be taxed as capital gains once you hold them for over 1 year — but the value might fluctuate in the meantime.</li>
<li>RSUs are &lsquo;free&rsquo; — they&rsquo;re essentially income given to you as stock — but are taxed as such, at a much higher rate than ISOs.</li>
</ul>
<p>Equity compensation is a complex, potentially thorny problem which warrants knowing what you get into before you sign a contract. The Holloway <a href="https://www.holloway.com/g/equity-compensation">guide to equity compensation</a> is a free, comprehensive document about equity compensation that I cannot recommend enough.</p>
<p>Below is the framework I came up with to compare offers:</p>
<table>
    <thead>
        <tr>
        <th rowspan="2">Label</th>
        <th rowspan="2">Yearly Base</th>
        <th colspan="3">Equity</th>
        <th colspan="2">Bonus</th>
        <th colspan="3">Benefits</th>
        </tr>
        <tr>
        <th>Value</th>
        <th>Type</th>
        <th>Cost</th>
        <th>Sign-on</th>
        <th>Annual</th>
        <th>Parental Leave</th>
        <th>401K Matching</th>
        <th>PTO</th>
        </tr>
    </thead>
    <tbody>
        <tr>
        <td>β</td>
        <td>B<sub>β</sub> = .802 ⨉ B̅</td>
        <td>5.615 ⨉ B<sub>β</sub></td>
        <td>ISO</td>
        <td>.071 ⨉ B<sub>β</sub></td>
        <td>No</td>
        <td>No</td>
        <td>N/A</td>
        <td>No</td>
        <td>Untracked</td>
        </tr>
        <tr>
        <td>γ</td>
        <td>B<sub>γ</sub> = 1.054 ⨉ B̅</td>
        <td>4.671 ⨉ B<sub>γ</sub></td>
        <td>RSU</td>
        <td>0</td>
        <td>.144 ⨉ B<sub>γ</sub></td>
        <td>.200 ⨉ B<sub>γ</sub></td>
        <td>16 weeks</td>
        <td>50% of $2,000</td>
        <td>21 days</td>
        </tr>
        <tr>
        <td>δ</td>
        <td>B<sub>δ</sub> = .997 ⨉ B̅</td>
        <td>2.401 ⨉ B<sub>δ</sub></td>
        <td>RSU</td>
        <td>0</td>
        <td>.174 ⨉ B<sub>δ</sub></td>
        <td>🚧</td>
        <td>16 weeks</td>
        <td>No</td>
        <td>Untracked</td>
        </tr>
        <tr>
        <td>ε</td>
        <td>B<sub>ε</sub> = 1.148 ⨉ B̅</td>
        <td>2.755  ⨉ B<sub>ε</sub></td>
        <td>ISO</td>
        <td>.187 ⨉ B<sub>ε</sub></td>
        <td>.094 ⨉ B<sub>ε</sub></td>
        <td>No</td>
        <td>16 weeks</td>
        <td>100% of $3,000,<br/>then 25%</td>
        <td>Untracked</td>
        </tr>
    </tbody>
</table>
<ul>
<li><strong>Yearly Base</strong> is the cash part of the offer, expressed as a fraction of the average of all yearly bases.</li>
<li><strong>Equity Value</strong> is the current presumed value of the full equity grant, as a fraction of the base. Grants across all offers have a 4-year vesting schedule.</li>
<li><strong>Equity Cost</strong> is the yearly cost of acquiring the equity, i.e. the number of options that vest in a year multiplied by the strike price, which is relevant for ISOs.</li>
<li><strong>Sign-on</strong> is a one-time bonus, expressed as a fraction of the base</li>
<li><strong>Annual Bonus</strong> is a yearly target for bonus, expressed as a fraction of the base</li>
</ul>
<h3 id="equity">Equity</h3>
<p>My philosophy in terms of equity is two-fold:</p>
<ul>
<li>As far as offers and compensation packages go, equity is almost the least important component of the lot: companies can do well and they can also do terrible, sometimes for reasons entirely out of their control. Equity is the cherry on top of the cake. And even though the cherry can sometimes become its own standalone cake, the stars need to align for that to happen.</li>
<li>In spite of treating equity as second class income, I&rsquo;ve <em>consistently</em> chosen to purchase my initial grant of options: the premise is that I wouldn&rsquo;t join a company if I didn&rsquo;t believe its capital would eventually turn up. This requires budgeting for the purchase of the options, which makes a dent in the yearly base.</li>
</ul>
<p>Equipped with this framework, let&rsquo;s look at company ε: the base pay is the highest of the lot but 18.7% of it needs to go into purchasing equity each year, which is also quite high. In the case of company γ, the equity more than <em>doubles</em> the base pay year after year, which comes at no direct cost except for the associated tax burden, which is high because RSUs are taxed as income.</p>
<p>One offer should clearly stand out in the table above: company β is a small, early-stage company. The quoted base (which was presented as non-negotiable) was lower than my previous one at Lyft, and it significantly drags down the average presented in the table. To make up for it, the cost of acquiring the equity is fairly low (7.1% of the base) and the stock has a lot of room to grow since the company is so young. This company also has no sign-on, no bonus structure and the parental leave is unspecified at this time.</p>
<h3 id="benefits">Benefits</h3>
<p>Benefits are where comparing offers gets a lot harder, primarily because there&rsquo;s so much ground to cover and what matters to people is so personal. Some companies offer stipends for gym memberships, internet access reimbursement, lump sums for buying office equipment, etc… Health coverage can be such a personal decision that I&rsquo;m not even going to begin trying to pitch policies against one another. I focused on three aspects of benefit packages:</p>
<ul>
<li><strong>PTO</strong>: it&rsquo;s very common for companies these days to offer untracked PTO, which is then presented as &ldquo;unlimited&rdquo;. This is a problem for two reasons:
<ol>
<li>Studies have shown that people with &ldquo;unlimited&rdquo; PTO end up taking <em>less</em> time-off than when PTO was capped.</li>
<li>Untracked PTO is not actually paid. Capped PTO accrues and has value which is owed to you in case you do not take it by the time to you leave.</li>
</ol>
</li>
<li><strong>Parental leave</strong>: While I personally do not have kids, I recognize parental leave as a staple of a good benefits package. The smallest company I received an offer from didn&rsquo;t have a parental leave policy and claimed this was something they will get to eventually, and that folks have taken time-off ad-hoc at the time they became parents.</li>
<li><strong>401K matching</strong>: all companies run 401K programs, but the ones that match contributions tend to be few and far apart. I&rsquo;ve always maxed out my 401K contributions — matching is essentially free pre-tax money going from the company to my future self. Some companies such as Google match 100% of the contribution up to the <a href="https://www.investopedia.com/retirement/401k-contribution-limits/">federal limit</a>, while others set lower caps and rates.</li>
</ul>
<h3 id="role-fit">Role fit</h3>
<p>While the compensation package is definitely a factor, I&rsquo;ve primarily made my decision based on how excited I was about the role. As can be seen in the timeline, company δ took well over two weeks to extend an offer after giving me the thumbs up. It was apparent that it took time for the hiring team to come up with a compensation package, which was not a good sign: compensation packages should be an easy thing for a company to figure out and companies should strive to work on the candidate&rsquo;s schedule.</p>
<p>The other reason for this delay is that I had several follow-up conversations with prospective managers in order to determine team fit. Even though I originally applied for a TLM position, it was clear that the expected people management aspect of that role was going to be too heavy for my taste. I was oriented towards a different team and talked with another manager, then with an engineer on that team, until another switch was made to have me report to a higher-level manager at the very last minute of the process.</p>
<p>It also became evident that the organization and reporting structure was a work in progress, which made it hard to have a consistent conversation about the role, the context of the work and expectations. In contrast, the other companies I interviewed with were clearer as to what they were looking for, and they crafted the process around that goal. From my perspective, the exchanges with those companies were more consistent and productive.</p>
<h2 id="parting-notes">Parting Notes</h2>
<p>Upon making the decision to quit, I knew I would need to keep an open mind about the path this job search would lead me on. I&rsquo;d never been in a situation where I interviewed with so many companies at once, which turned out to be a fairly involved process. It required some level of work pretty much every day over the course of two months. This is about the average workload I originally anticipated, but I don&rsquo;t think I expected how fragmented this time would be, and how unevenly distributed it would be.</p>
<p>I try not to let it get to me too much, but I was raised with the idea that work —and, by extension, employment— serves not just a social purpose but also a personal one. In other words, labor is expected to fulfill individuals and idleness is good only in small quantities. As such, the decision to go into unemployment voluntarily and for an unknown length of time didn&rsquo;t only have financial or logistical consequences. To an extent, having a day job sort of alleviates the pressure of having to answer the age-old question: <em>&ldquo;Am I doing the right thing with my time?&rdquo;.</em></p>
<p>I felt varying degrees of guilt from the moment I last closed my Lyft laptop and until my signature was at the bottom of an offer letter. This feeling was only reinforced by the fact that my spouse was in the room next door, working her ass off every day.</p>
<p>There was also a broader context to this: on top of a pandemic that had brutally changed our day-to-day for over half a year, the US election was set to be a very disputed one, with more in the balance than any other in my lifetime. Working through a deeply personal process at a time where so much was at stake on a global scale felt quite odd — a feeling that was sometimes openly shared by my interviewers.</p>
<h3 id="outcome">Outcome</h3>
<p>🎉 I joined <a href="https://www.stripe.com">Stripe</a>&rsquo;s Payments API team in January of 2021 🎉</p>
<p>Based on this outcome, I can&rsquo;t look back and say that quitting and making room for job searching was a bad decision: Stripe was on the shortlist of companies I was excited about when I began my search.</p>
<p>But it&rsquo;s also clear that the whole process didn&rsquo;t <em>feel</em> great and I can&rsquo;t say precisely how I would change things if I had do to it again. I&rsquo;m happy about where I landed but I came out of it spent, and I&rsquo;m wary that this isn&rsquo;t avoidable. The guilt I experienced is also something that&rsquo;s too personal for me to just shake off.</p>
<p>The two takeaways I have from this experience are:</p>
<ol>
<li>Working with several companies in parallel made me more empowered to ask questions that got me a better grasp of what the company really needed: knowing what will be expected out of my work made me a lot more at ease when signing an offer</li>
<li>Anyone who&rsquo;s gone through the tech interviewing wringer knows too well that this is a nerve-racking process: multiplying this five-ways makes only makes sense when your time is clear from other distractions</li>
</ol>
<p>For me, in hindsight, part of the value was in exploring the variety of roles I could see myself in: TLM, staff engineering or founding engineer of an org. It&rsquo;s one thing to daydream about making such moves and another to have real people trusting you to act in that capacity in real, critical projects they want to ship. I came out of it with a refined sense of what I like to do and a chance to match that with a company&rsquo;s needs. Which is about as graceful as a failure can be.</p>
]]></content>
        </entry>
    
        <entry>
            <title>Go Learnings and Gotchas</title>
            <link href="https://www.eiggen.co/codes/go-learnings-and-gotchas/"/>
            <updated>2020-05-02T00:00:00+0000</updated>
            <id>https://www.eiggen.co/codes/go-learnings-and-gotchas/</id>
            <content type="html"><![CDATA[ <p>In the second half of 2019, I transferred onto a project that was written in Go. This was the highest priority project in the company, and I found myself in a position to have to learn this language as fast as possible in order to remove myself from the critical path.</p>
<p>Luckily, the language itself is actually fairly simple and well documented and the official tutorials are well-structured. I wholeheartedly recommend <a href="https://tour.golang.org/welcome/1">A Tour of Go</a> followed by <a href="https://golang.org/doc/effective_go.html#init">Effective Go</a> — reading through these should take about a day or so and give you a sense of what the language can do for you.</p>
<p>But not everything I needed to do was trivial and I was taken aback more than once spending hours trying to get to something working when I felt like it should have taken minutes. Other times, I was actually thrilled to see lesser-known capabilities of the language shine and allow myself to be as expressive as I needed to be. This post is an ongoing collection of those times, and what I&rsquo;ve learned from them.</p>
<nav id="TableOfContents">
  <ul>
    <li><a href="#build-constraints">Build Constraints</a></li>
    <li><a href="#field-tags">Field Tags</a></li>
    <li><a href="#enumerations">Enumerations</a></li>
    <li><a href="#json">JSON</a></li>
    <li><a href="#time-formatting">Time formatting</a></li>
    <li><a href="#decorating-an-interface-implementation">Decorating an interface implementation</a></li>
    <li><a href="#testing">Testing</a>
      <ul>
        <li><a href="#gomock-do">GoMock <code>.Do()</code></a></li>
        <li><a href="#skipping-tests">Skipping tests</a></li>
        <li><a href="#running-a-specific-test">Running a specific test</a></li>
        <li><a href="#compiling-tests-without-running-them">Compiling tests without running them</a></li>
        <li><a href="#subtests">Subtests</a></li>
      </ul>
    </li>
    <li><a href="#precommit">Precommit</a></li>
  </ul>
</nav>
<h2 id="build-constraints">Build Constraints</h2>
<p><a href="https://golang.org/pkg/go/build/#hdr-Build_Constraints">Build constraints</a> are directives to the Go tooling to either include or exclude a given file. There exists a set of default tags but you may also define your own custom tags:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="c1">// +build foo
</span></code></pre></div><p>Tags may be OR&rsquo;d, AND&rsquo;d and NOT&rsquo;d:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="c1">// +build foo,!bar baz
</span><span class="c1">// +build qux
</span></code></pre></div><p>This evaluates to <code>((foo AND NOT bar) OR baz) AND qux</code> — in other words, if someone tries to run any Go tool and sets a <code>-tags=bar,qux</code>, the file in the example above will not be considered.</p>
<p>Tags apply to most of the Go toolchain: the compiler (<code>build</code>), but also the testing and the lint tooling. Files will be included by the tooling if their tag directive(s) match the tags currently active in the build. By default, Go has a set of tags that let you match the host OS, the architecture of the CPU, the current version of Go, etc… Any tool that iterates over Go files will have a way to specify the tags you would like to include.</p>
<p>Tags are useful to define category of files that you want to include conditionally — for instance, you may want have a tag for <code>// +build integration</code> tests — since they are generally slower to run and might require a specific setup. As an example, let&rsquo;s say you have code accessing S3 that you need to write a test for: <code>clients/s3/s3_test.go</code></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="c1">// +build integration
</span><span class="c1"></span>
<span class="kn">package</span> <span class="nx">s3</span>

<span class="kn">import</span> <span class="p">(</span>
    <span class="s">&#34;testing&#34;</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">TestS3</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// Actual testing code here
</span><span class="c1"></span><span class="p">}</span>
</code></pre></div><p>Simply running <code>go test ./...</code> would not include the integration test by default, since the constraint is not set. To run the integration test, you would need to run:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh">go <span class="nb">test</span> -tags<span class="o">=</span>integration ./clients/s3/
</code></pre></div><h2 id="field-tags">Field Tags</h2>
<p>When you define a <code>struct</code> type, the fields declared in it may be annotated with <a href="https://golang.org/ref/spec#Struct_types"><em>tags</em></a>, which are declared as a string literal that follows the field declaration:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">type</span> <span class="nx">Foo</span> <span class="kd">struct</span> <span class="p">{</span>
    <span class="nx">bar</span> <span class="kt">int</span> <span class="s">&#34;this is a tag&#34;</span>
    <span class="nx">baz</span> <span class="kt">string</span> <span class="s">`tag declared with backticks in order to use a literal &#34;`</span>
<span class="p">}</span> 
</code></pre></div><p>Those tags become available at runtime, through the <code>reflect</code> package. They are represented by the <code>reflect.StructTag</code> type. This type implements a convention that a tag to specify multiple values, each keyed by a name and enclosed in quotes: <code>`foo:&quot;bar&quot; baz:&quot;qux&quot;`</code> is tag with two keys: <code>foo</code> and <code>baz</code>.</p>
<p>Tagging fields is relevant in the context where a <code>struct</code> is a model that may be serialized in and out of the Go runtime. In such cases, the tag for a given field can contain a pseudo configuration for how that field should be written or read. The list of <a href="https://github.com/golang/go/wiki/Well-known-struct-tags">well-known struct tags</a> is informative, and links to popular serialization formats such as JSON and XML. But certain ORMs and cloud providers have also opted for an approach that uses tags to map Go fields to column names.</p>
<p>Tags allow programmers to define the external shape of a type at once and across a range of formats. The directives present in each tags' value can be as complex as the serialization scheme allows. The <a href="https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/dynamodbattribute/#Marshal">DynamoDB</a> client is such an example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">type</span> <span class="nx">EmailThread</span> <span class="kd">struct</span> <span class="p">{</span>
    <span class="nx">Labels</span> <span class="p">[]</span><span class="kt">string</span> <span class="s">`dynamodbav:&#34;labels,omitemptyelem,stringset&#34;`</span>
    <span class="nx">Title</span> <span class="kt">string</span> <span class="s">`dynamodbav:&#34;title&#34;`</span>
    <span class="nx">LastEmailSentAt</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Time</span> <span class="s">`dynamodbav:&#34;lastEmailSentAt,unixtime&#34;`</span>
<span class="p">}</span> 
</code></pre></div><h2 id="enumerations">Enumerations</h2>
<p>This is a head scratcher: there is no strongly-typed enumerations in Go. Enum-like types should be defined as type aliases for <code>int</code> and their values declared as <code>const</code>s whose first value is <code>iota</code>. <a href="https://golang.org/ref/spec#Iota"><code>iota</code></a> is a special variable in the Go language:</p>
<ul>
<li>its default value is zero</li>
<li>it is auto-incremented for every line in a <code>const</code> block</li>
<li>uninitialized constants declared within that <code>const</code> block will default to the current value of <code>iota</code></li>
<li>its value is reset to zero when exiting the <code>const</code> block</li>
</ul>
<p>For a language seeking to reduce confusion and surprises, this is immensely confusing and surprising. Practically, you define an enum in the following way:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">type</span> <span class="nx">HTTPMethod</span> <span class="kt">int</span>

<span class="kd">const</span> <span class="p">(</span>
    <span class="nx">Get</span> <span class="nx">HTTPMethod</span> <span class="p">=</span> <span class="kc">iota</span>
    <span class="nx">Post</span>
    <span class="nx">Put</span>
    <span class="nx">Delete</span>
<span class="p">)</span>
</code></pre></div><p>Since the Go type-system doesn&rsquo;t provide first-level support for enumerated types, the names of the constants are lost in the compilation. In other words, you must write custom code to get the name an enumerated value at runtime. This is commonly done by defining a <code>String()</code> function:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="nx">HTTPMethod</span><span class="p">)</span> <span class="nf">String</span><span class="p">()</span> <span class="kt">string</span> <span class="p">{</span>
    <span class="k">return</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;GET&#34;</span><span class="p">,</span> <span class="s">&#34;POST&#34;</span><span class="p">,</span> <span class="s">&#34;PUT&#34;</span><span class="p">,</span> <span class="s">&#34;DELETE&#34;</span><span class="p">}[</span><span class="nx">m</span><span class="p">]</span>
<span class="p">}</span>
</code></pre></div><p>Note that the order of the strings in the array <strong>must</strong> be in the same order as the one in which the individual constant declarations is done, and there is no compile-time guarantee that you will not go out of bounds, which would happen if you defined a new value in the enumeration but forget to add it to the array of names.</p>
<h2 id="json">JSON</h2>
<p>The <code>encoding/json</code> package encapsulates the logic for serializing structs into JSON and deserializing JSON into structs. It&rsquo;s a reflection-based engine that will do a decent job by default and that may be customized using <a href="#field-tags"><code>field tags</code></a>. In case you need full control of how struct is serialized, you need to implement custom interfaces.</p>
<p>A good example of such a need is enumerations: if they are defined used <code>iota</code> values, a value will by default be encoded as an integer. If you prefer to have a string, you can make the type implement the <code>Marshaller</code> interface, which has a single <code>MarshalJSON</code> function:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">type</span> <span class="nx">HTTPMethod</span> <span class="kt">int</span>

<span class="kd">const</span> <span class="p">(</span>
    <span class="nx">Get</span> <span class="nx">HTTPMethod</span> <span class="p">=</span> <span class="kc">iota</span>
    <span class="nx">Post</span>
    <span class="nx">Put</span>
    <span class="nx">Delete</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="nx">HTTPMethod</span><span class="p">)</span> <span class="nf">String</span><span class="p">()</span> <span class="kt">string</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">methods</span><span class="p">[</span><span class="nx">m</span><span class="p">]</span>
<span class="p">}</span>

<span class="kd">var</span> <span class="nx">methods</span> <span class="p">=</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;GET&#34;</span><span class="p">,</span> <span class="s">&#34;POST&#34;</span><span class="p">,</span> <span class="s">&#34;PUT&#34;</span><span class="p">,</span> <span class="s">&#34;DELETE&#34;</span><span class="p">}</span>
<span class="kd">var</span> <span class="nx">methodsByName</span> <span class="p">=</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="nx">HTTPMethod</span><span class="p">{</span>
    <span class="s">&#34;GET&#34;</span><span class="p">:</span> <span class="nx">Get</span><span class="p">,</span>
    <span class="s">&#34;POST&#34;</span><span class="p">:</span> <span class="nx">Post</span><span class="p">,</span>
    <span class="s">&#34;PUT&#34;</span><span class="p">:</span> <span class="nx">Put</span><span class="p">,</span>
    <span class="s">&#34;DELETE&#34;</span><span class="p">:</span> <span class="nx">Delete</span><span class="p">,</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="nx">HTTPMethod</span><span class="p">)</span> <span class="nf">MarshalJSON</span><span class="p">()</span> <span class="p">([]</span><span class="kt">byte</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">json</span><span class="p">.</span><span class="nf">Marshal</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nf">String</span><span class="p">())</span>
<span class="p">}</span>
</code></pre></div><p>Conversely, you would need to implement the <code>Unmarshaler</code> interface to convert the string back into the enumerated value — you might want to refactor the previously defined <code>String()</code> method to share the string constants between the marshalling and unmarshalling functions</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">HTTPMethod</span><span class="p">)</span> <span class="nf">UnmarshalJSON</span><span class="p">(</span><span class="nx">b</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">)</span> <span class="kt">error</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">s</span> <span class="kt">string</span>
    <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="nx">b</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">s</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nx">err</span>
    <span class="p">}</span>
    <span class="nx">value</span><span class="p">,</span> <span class="nx">ok</span> <span class="o">:=</span> <span class="nx">methodsByName</span><span class="p">[</span><span class="nx">s</span><span class="p">]</span>
    <span class="k">if</span> <span class="p">!</span><span class="nx">ok</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;Unable to unmarshal HTTPMethod value %s&#34;</span><span class="p">,</span> <span class="nx">s</span><span class="p">)</span>
    <span class="p">}</span>
    <span class="o">*</span><span class="nx">m</span> <span class="p">=</span> <span class="nx">value</span>
    <span class="k">return</span> <span class="kc">nil</span>
<span class="p">}</span>
</code></pre></div><h2 id="time-formatting">Time formatting</h2>
<p>This is just a complete head scratcher and there&rsquo;s no way around it except biting the bullet: Go&rsquo;s built-in time formatting doesn&rsquo;t use traditional format strings such as <code>YYYY-MM-DD</code> but instead chose an unambiguous fixed point in time that you have to write your desired format in. That point in time is January 2nd 2006, 3:04pm and 5 seconds, in the GMT -7 timezone. Which, written another way is: <code>01/02 03:04:05PM '06 -0700</code> — 1, 2, 3, 4…</p>
<p>So, date formats are actually written as a plain date, e.g. ISO 8601 datetime is: <code>2006-01-02T15:04:05</code>. <a href="https://golang.org/pkg/time/#pkg-constants">Ref</a></p>
<h2 id="decorating-an-interface-implementation">Decorating an interface implementation</h2>
<p>Go&rsquo;s type system allows for declaring <code>struct</code>s that wrap an interface implementation and decorate specific methods. There&rsquo;s no special syntax for it — it works just like interface composition. Let&rsquo;s say you have a naive in-memory database that stores models that have an identifier and a name:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">type</span> <span class="nx">Model</span> <span class="kd">struct</span> <span class="p">{</span>
    <span class="nx">Id</span> <span class="kt">uint64</span>
    <span class="nx">Name</span> <span class="kt">string</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">Database</span> <span class="kd">interface</span> <span class="p">{</span>
    <span class="nf">Create</span><span class="p">(</span><span class="nx">name</span> <span class="kt">string</span><span class="p">)</span> <span class="o">*</span><span class="nx">Model</span>
    <span class="nf">Save</span><span class="p">(</span><span class="nx">model</span> <span class="o">*</span><span class="nx">Model</span><span class="p">)</span>
    <span class="nf">Get</span><span class="p">(</span><span class="nx">id</span> <span class="kt">uint64</span><span class="p">)</span> <span class="o">*</span><span class="nx">Model</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">database</span> <span class="kd">struct</span> <span class="p">{</span>
    <span class="nx">models</span> <span class="kd">map</span><span class="p">[</span><span class="kt">uint64</span><span class="p">]</span><span class="o">*</span><span class="nx">Model</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">db</span> <span class="o">*</span><span class="nx">database</span><span class="p">)</span> <span class="nf">Create</span><span class="p">(</span><span class="nx">name</span> <span class="kt">string</span><span class="p">)</span> <span class="o">*</span><span class="nx">Model</span> <span class="p">{</span>
    <span class="nx">id</span> <span class="o">:=</span> <span class="nx">rand</span><span class="p">.</span><span class="nf">Uint64</span><span class="p">()</span>
    <span class="nx">db</span><span class="p">.</span><span class="nx">models</span><span class="p">[</span><span class="nx">id</span><span class="p">]</span> <span class="p">=</span> <span class="o">&amp;</span><span class="nx">Model</span><span class="p">{</span><span class="nx">Id</span><span class="p">:</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">Name</span><span class="p">:</span> <span class="nx">name</span><span class="p">}</span>
    <span class="k">return</span> <span class="nx">db</span><span class="p">.</span><span class="nx">models</span><span class="p">[</span><span class="nx">id</span><span class="p">]</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">db</span> <span class="o">*</span><span class="nx">database</span><span class="p">)</span> <span class="nf">Save</span><span class="p">(</span><span class="nx">model</span> <span class="o">*</span><span class="nx">Model</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">db</span><span class="p">.</span><span class="nx">models</span><span class="p">[</span><span class="nx">model</span><span class="p">.</span><span class="nx">Id</span><span class="p">]</span> <span class="p">=</span> <span class="nx">model</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">db</span> <span class="o">*</span><span class="nx">database</span><span class="p">)</span> <span class="nf">Get</span><span class="p">(</span><span class="nx">id</span> <span class="kt">uint64</span><span class="p">)</span> <span class="o">*</span><span class="nx">Model</span> <span class="p">{</span>
    <span class="k">return</span> <span class="nx">db</span><span class="p">.</span><span class="nx">models</span><span class="p">[</span><span class="nx">id</span><span class="p">]</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">NewDatabase</span><span class="p">()</span> <span class="nx">Database</span> <span class="p">{</span>
  <span class="k">return</span> <span class="o">&amp;</span><span class="nx">database</span><span class="p">{</span><span class="nx">models</span><span class="p">:</span> <span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kt">uint64</span><span class="p">]</span><span class="o">*</span><span class="nx">Model</span><span class="p">)}</span>
<span class="p">}</span>
</code></pre></div><p>The <code>Database</code> interface is public, and as such may be relied-upon by external code. Now let&rsquo;s say you want to track the &ldquo;popularity&rdquo; of a certain model, say, by the number of times it is accessed by <code>Get</code>. Your options are:</p>
<ol>
<li>Modify the <code>database</code> implementation to add a counter - but any other implementation of the <code>Database</code> interface will not inherit that behavior.</li>
<li>Implement your own <code>Database</code>, which is not great because there are two methods out of three you don&rsquo;t care about at all</li>
</ol>
<p>The third option is to decorate the <code>Database</code> interface:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">type</span> <span class="nx">trackingDecorator</span> <span class="kd">struct</span> <span class="p">{</span>
    <span class="nx">Database</span> <span class="c1">// wrap an arbitrary implementation of Database 
</span><span class="c1"></span>    <span class="nx">getCounter</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int32</span>
<span class="p">}</span>

<span class="c1">// Override the method you care about
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">td</span> <span class="o">*</span><span class="nx">trackingDecorator</span><span class="p">)</span> <span class="nf">Get</span><span class="p">(</span><span class="nx">id</span> <span class="kt">uint64</span><span class="p">)</span> <span class="o">*</span><span class="nx">Model</span> <span class="p">{</span>
    <span class="nx">model</span> <span class="o">:=</span> <span class="nx">td</span><span class="p">.</span><span class="nx">Database</span><span class="p">.</span><span class="nf">Get</span><span class="p">(</span><span class="nx">id</span><span class="p">)</span>
    <span class="k">if</span> <span class="nx">model</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
        <span class="nx">td</span><span class="p">.</span><span class="nx">getCounter</span><span class="p">[</span><span class="nx">model</span><span class="p">.</span><span class="nx">Name</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nx">model</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">NewTrackingDecorator</span><span class="p">(</span><span class="nx">wrapped</span> <span class="nx">Database</span><span class="p">)</span> <span class="nx">Database</span> <span class="p">{</span>
    <span class="k">return</span> <span class="o">&amp;</span><span class="nx">popularityTrackingDatabase</span><span class="p">{</span>
        <span class="nx">Database</span><span class="p">:</span>     <span class="nx">wrapped</span><span class="p">,</span>
        <span class="nx">getCounter</span><span class="p">:</span>    <span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int32</span><span class="p">),</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div><p>Declaring the <code>Database</code> interface as an anonymous field of the <code>trackingDecorator</code> struct will automatically make the latter implement the interface. Upon construction, you will need to supply an actual implementation you want wrapped:</p>
<ul>
<li>By default, all interface method calls are forwarded to the wrapped instance</li>
<li>If the new struct declares any method of the interface, that method will be called instead</li>
</ul>
<p>Most importantly: in the second case, the methods on the wrapped instance can be called from the overridden code e.g. <code>td.Database.Get(id)</code> in the example above. This lets you decorate select methods of arbitrary interfaces, even if you can&rsquo;t access the underlying implementation.</p>
<h2 id="testing">Testing</h2>
<h3 id="gomock-do">GoMock <code>.Do()</code></h3>
<p>When you use GoMock, you can use custom matchers in order to assert on the correctness of the arguments received by your mocked functions. Matchers are nice but they need to be reusable to prove their worth. There are certain cases when you don&rsquo;t know (or don&rsquo;t care) about the full argument, e.g. you just want to make sure that a dictionary containing headers has the one key-value pair you care about, or that a URL contains just the one param you need.</p>
<p>GoMock&rsquo;s <code>.Do</code> is designed for cases like this: it lets you capture the parameters passed to the mocked function and run arbitrary assertions on them. Say you have a raw client for a &ldquo;TaskQueue&rdquo; and a class wrapping that client to provide convenience functions to enqueue messages of a certain type to certain routes:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="c1">// This is the mocked interface - not going into the details of what a Task contains but assume
</span><span class="c1">// that it is a complex object with lots of fields and implementation details.
</span><span class="c1"></span><span class="kd">type</span> <span class="nx">TaskScheduler</span> <span class="kd">interface</span> <span class="p">{</span>
    <span class="nf">ScheduleTask</span><span class="p">(</span><span class="nx">ctx</span> <span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span> <span class="nx">task</span> <span class="o">*</span><span class="nx">Task</span><span class="p">)</span> <span class="p">(</span><span class="o">*</span><span class="nx">ScheduleResponse</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">TestEnqueueMyTask</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">t</span><span class="p">.</span><span class="nf">Parallel</span><span class="p">()</span>
    <span class="nx">ctrl</span> <span class="o">:=</span> <span class="nx">gomock</span><span class="p">.</span><span class="nf">NewController</span><span class="p">(</span><span class="nx">t</span><span class="p">)</span>
    <span class="k">defer</span> <span class="nx">ctrl</span><span class="p">.</span><span class="nf">Finish</span><span class="p">()</span>

    <span class="nx">ts</span> <span class="o">:=</span> <span class="nx">taskScheduler</span><span class="p">.</span><span class="nf">NewMockTaskScheduler</span><span class="p">(</span><span class="nx">ctrl</span><span class="p">)</span>
    <span class="c1">// Pass `gomock.Any()` in lieu of asserting on a fully built Task
</span><span class="c1"></span>    <span class="nx">client</span><span class="p">.</span><span class="nf">EXPECT</span><span class="p">().</span><span class="nf">ScheduleTask</span><span class="p">(</span><span class="nx">gomock</span><span class="p">.</span><span class="nf">Any</span><span class="p">(),</span> <span class="nx">gomock</span><span class="p">.</span><span class="nf">Any</span><span class="p">()).</span>
        <span class="nf">Return</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">tq</span><span class="p">.</span><span class="nx">ScheduleResponse</span><span class="p">{},</span> <span class="kc">nil</span><span class="p">).</span>
        <span class="c1">// The signature of the function passed to `.Do` should be the same as `ScheduleTask`
</span><span class="c1"></span>        <span class="c1">// but we don&#39;t care about the context
</span><span class="c1"></span>        <span class="nf">Do</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">_</span> <span class="nx">context</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span> <span class="nx">task</span> <span class="o">*</span><span class="nx">Task</span><span class="p">)</span> <span class="p">{</span>
            <span class="c1">// You can run assertions on just the parts of Task that you care about
</span><span class="c1"></span>            <span class="nx">assert</span><span class="p">.</span><span class="nf">Equal</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span> <span class="nx">tq</span><span class="p">.</span><span class="nx">Method_PUT</span><span class="p">,</span> <span class="nx">task</span><span class="p">.</span><span class="nx">Payload</span><span class="p">.</span><span class="nx">Method</span><span class="p">)</span>
            <span class="c1">// etc…
</span><span class="c1"></span>    <span class="p">})</span>

    <span class="nx">controller</span> <span class="o">:=</span> <span class="nf">MyController</span><span class="p">(</span><span class="nx">scheduler</span><span class="p">:</span> <span class="nx">ts</span><span class="p">)</span>
    <span class="nx">err</span> <span class="o">:=</span> <span class="nx">controller</span><span class="p">.</span><span class="nf">MethodThatSchedulesATaks</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">(),</span> <span class="err">…</span><span class="p">)</span>
    <span class="nx">assert</span><span class="p">.</span><span class="nf">NoError</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div><h3 id="skipping-tests">Skipping tests</h3>
<p>It&rsquo;s useful every now and then to disable a test without wanting to delete the code. You can use <code>Skip</code> or <code>Skipf</code> to do that:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">func</span> <span class="nf">TestProductionRequestEndToEnd</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">t</span><span class="p">.</span><span class="nf">Skipf</span><span class="p">(</span><span class="s">&#34;Disabled because of the refactoring in FOO-539&#34;</span><span class="p">)</span>
    <span class="nx">ctx</span> <span class="o">:=</span> <span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">()</span>
    <span class="nx">tc</span> <span class="o">:=</span> <span class="nf">getTestConfig</span><span class="p">()</span>
    <span class="err">…</span>
<span class="p">}</span>
</code></pre></div><p>This is better than renaming the request or commenting the code out because the test runner will print a message every time the test is run, reminding you that it should be re-enabled at some later point in time.</p>
<h3 id="running-a-specific-test">Running a specific test</h3>
<p>The <code>go test</code> command has a <code>-run</code> flag which may be used to specify a specific test method to run, but the actual syntax is incredibly subdocumented. You need to pass in the directory in which the test is, not just the test name:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh">go <span class="nb">test</span> -run<span class="o">=</span>TestFoo ./path/to/you/test/file/ -v -count<span class="o">=</span><span class="m">1</span>
</code></pre></div><p><code>-count=1</code> will disable test caching, which would otherwise occur when your source files do not require rebuilding. As per the doc: &ldquo;The idiomatic way to disable test caching explicitly is to use -count=1&rdquo; 🤷.</p>
<h3 id="compiling-tests-without-running-them">Compiling tests without running them</h3>
<p>The Go test tooling does not decouple the compilation of tests from their execution. In other words, the philosophy is that you either want to run your tests or… run your tests – and there&rsquo;s no way to just check that your tests compile, which is the first step before they can be run.</p>
<p>It turns out the <code>-run</code> flag discussed above doesn&rsquo;t actually just take the name of a test, but a regular expression that matches the names of the test functions to run. If you set that expression to something that cannot match any function, the testing framework will stop just after the compilation step. The most common trick is to use a line beginning (<code>^</code>) immediately followed by a line ending (<code>$</code>)</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh">go <span class="nb">test</span> -run<span class="o">=</span>^$ ./...
</code></pre></div><p><strong>Here be dragons</strong>: the testing framework will not execute any tests but it <em>will</em> execute code that belongs in package <a href="https://golang.org/doc/effective_go.html#init">initializers</a>: should this code have any side-effects, this command would trigger them.</p>
<h3 id="subtests">Subtests</h3>
<p>Go&rsquo;s standard test framework notably lacks the concepts of setup and teardown phases, which in other languages allow for, well, setting up the context of multiple tests and disposing of those resources once the tests have run.</p>
<p>Not all hope is lost though: <code>t.Run()</code> is a method intended to isolate the behavior to test in a dedicated block. Because you can nest them, you can progressively specialize  The structure of the code can resemble Ruby&rsquo;s <a href="https://rspec.info/">RSpec</a></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="kd">func</span> <span class="nf">TestBowling</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">bowling</span> <span class="o">:=</span> <span class="nx">Bowling</span><span class="p">{}</span>

    <span class="nx">t</span><span class="p">.</span><span class="nf">Run</span><span class="p">(</span><span class="s">&#34;When there are no strikes or spare&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">bowling</span><span class="p">.</span><span class="nf">Frame</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
        <span class="nx">assert</span><span class="p">.</span><span class="nf">Equal</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="nx">bowling</span><span class="p">.</span><span class="nf">Score</span><span class="p">())</span>
    <span class="p">})</span>

    <span class="nx">t</span><span class="p">.</span><span class="nf">Run</span><span class="p">(</span><span class="s">&#34;When there is a spare&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">bowling</span><span class="p">.</span><span class="nf">Frame</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
        <span class="nx">assert</span><span class="p">.</span><span class="nf">Equal</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="nx">bowling</span><span class="p">.</span><span class="nf">Score</span><span class="p">())</span>

        <span class="nx">t</span><span class="p">.</span><span class="nf">Run</span><span class="p">(</span><span class="s">&#34;Followed by a regular frame&#34;</span><span class="p">,</span> <span class="kd">func</span><span class="p">(</span><span class="nx">t</span> <span class="o">*</span><span class="nx">testing</span><span class="p">.</span><span class="nx">T</span><span class="p">)</span> <span class="p">{</span>
            <span class="nx">bowling</span><span class="p">.</span><span class="nf">Frame</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
            <span class="nx">assert</span><span class="p">.</span><span class="nf">Equal</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span> <span class="mi">24</span><span class="p">,</span> <span class="nx">bowling</span><span class="p">.</span><span class="nf">Score</span><span class="p">())</span>
        <span class="p">})</span>
    <span class="p">})</span>
<span class="p">}</span>
</code></pre></div><p>As you can sort of guess, the problem with this approach is that all tests will share the same instance under test — if that object is stateful, you will end with tests whose sequencing cannot change. This is a pretty big anti-pattern in general, but especially in Go where parallelism is built into the test framework.</p>
<p><code>t.Run()</code> can still prove useful to break down long test methods into chunks that are easier to digest and help with making common scenarios clearer for the next maintainer.</p>
<h2 id="precommit">Precommit</h2>
<p>When I get into a new language or stack, I try to write a pre-commit script with the goal of catching problems and correcting them before the code is pushed to a remote branch (I know about <a href="https://pre-commit.com/">pre-commit</a> but personally find it cumbersome). This is the Ruby script I have for my Go projects and here&rsquo;s what it does:</p>
<ul>
<li>Runs <code>go fmt</code>, <code>goimports</code>, <code>go vet</code> and <code>golangci-lint run --fix</code> on all new and modified files</li>
<li>Checks whether new files have an associated <code>_test.go</code> file</li>
<li>Check for calls to <code>fmt.Print*</code> – those should likely be logs statements instead</li>
<li><a href="https://blog.golang.org/generate">Generates</a> files that need it</li>
<li>Runs all the tests</li>
<li>Builds the integration tests: files with <code>integration</code> or <code>endtoend</code> constraints, which would not be picked up by <code>go test</code></li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="ch">#!/usr/bin/env ruby</span>

<span class="k">class</span> <span class="nc">String</span>
  <span class="c1"># colorization</span>
  <span class="k">def</span> <span class="nf">colorize</span><span class="p">(</span><span class="n">color_code</span><span class="p">)</span>
    <span class="s2">&#34;</span><span class="se">\e</span><span class="s2">[</span><span class="si">#{</span><span class="n">color_code</span><span class="si">}</span><span class="s2">m</span><span class="si">#{</span><span class="nb">self</span><span class="si">}</span><span class="se">\e</span><span class="s2">[0m&#34;</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">red</span>
    <span class="n">colorize</span><span class="p">(</span><span class="mi">31</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">green</span>
    <span class="n">colorize</span><span class="p">(</span><span class="mi">32</span><span class="p">)</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">yellow</span>
    <span class="n">colorize</span><span class="p">(</span><span class="mi">33</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="nb">require</span> <span class="s1">&#39;pathname&#39;</span>
<span class="nb">require</span> <span class="s1">&#39;set&#39;</span>

<span class="k">def</span> <span class="nf">generated_file?</span><span class="p">(</span><span class="n">file_path</span><span class="p">)</span>
  <span class="o">!</span><span class="no">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">file_path</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sr">/^\/\/ Code generated .* DO NOT EDIT\.$/</span><span class="p">)</span><span class="o">.</span><span class="n">nil?</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">needs_generation?</span><span class="p">(</span><span class="n">file_path</span><span class="p">)</span>
  <span class="o">!</span><span class="no">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">file_path</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sr">/^\/\/go:generate /</span><span class="p">)</span><span class="o">.</span><span class="n">nil?</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">test_file?</span><span class="p">(</span><span class="n">file_path</span><span class="p">)</span>
  <span class="o">!</span><span class="n">file_path</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sr">/_test\.go$/</span><span class="p">)</span><span class="o">.</span><span class="n">nil?</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">abort_unless</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">failure_message</span><span class="o">=</span><span class="s1">&#39;Failure&#39;</span><span class="p">,</span> <span class="n">success_message</span><span class="o">=</span><span class="s1">&#39;Success&#39;</span><span class="p">)</span>
  <span class="nb">print</span> <span class="n">command</span> <span class="ow">and</span> <span class="no">STDOUT</span><span class="o">.</span><span class="n">flush</span>
  <span class="n">output</span> <span class="o">=</span> <span class="sb">`</span><span class="si">#{</span><span class="n">command</span><span class="si">}</span><span class="sb"> 2&gt;&amp;1`</span>
  <span class="k">if</span> <span class="o">!</span><span class="vg">$?</span><span class="o">.</span><span class="n">success?</span>
    <span class="nb">puts</span> <span class="s2">&#34;  \u{1F44A}  </span><span class="si">#{</span><span class="n">failure_message</span><span class="si">}</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">red</span>
    <span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="n">output</span><span class="o">.</span><span class="n">red</span>
    <span class="nb">abort</span><span class="p">(</span><span class="s2">&#34;\u{1F44A}  run: </span><span class="si">#{</span><span class="n">command</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
  <span class="k">else</span>
    <span class="nb">puts</span> <span class="s2">&#34;  \u{1F44C}  </span><span class="si">#{</span><span class="n">success_message</span><span class="si">}</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">green</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="k">class</span> <span class="nc">CommandResult</span>
  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">output</span><span class="p">,</span> <span class="n">failure</span><span class="p">,</span> <span class="n">failure_message</span><span class="o">=</span><span class="s1">&#39;Failure&#39;</span><span class="p">,</span> <span class="n">success_message</span><span class="o">=</span><span class="s1">&#39;Success&#39;</span><span class="p">)</span>
    <span class="vi">@command</span> <span class="o">=</span> <span class="n">command</span>
    <span class="vi">@output</span> <span class="o">=</span> <span class="n">output</span>
    <span class="vi">@failure</span> <span class="o">=</span> <span class="n">failure</span>
    <span class="vi">@failure_message</span> <span class="o">=</span> <span class="n">failure_message</span>
    <span class="vi">@success_message</span> <span class="o">=</span> <span class="n">success_message</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">result</span>
    <span class="nb">print</span> <span class="vi">@command</span> <span class="ow">and</span> <span class="no">STDOUT</span><span class="o">.</span><span class="n">flush</span>
    <span class="k">if</span> <span class="vi">@failure</span>
      <span class="nb">puts</span> <span class="s2">&#34;  \u{1F44A}  </span><span class="si">#{</span><span class="vi">@failure_message</span><span class="si">}</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">red</span>
      <span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="vi">@output</span><span class="o">.</span><span class="n">red</span>
      <span class="nb">abort</span><span class="p">(</span><span class="s2">&#34;\u{1F44A}  run: </span><span class="si">#{</span><span class="vi">@command</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
    <span class="k">else</span>
      <span class="nb">puts</span> <span class="s2">&#34;  \u{1F44C}  </span><span class="si">#{</span><span class="vi">@success_message</span><span class="si">}</span><span class="s2">&#34;</span><span class="o">.</span><span class="n">green</span>
    <span class="k">end</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">abort_unless_async</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">failure_message</span><span class="o">=</span><span class="s1">&#39;Failure&#39;</span><span class="p">,</span> <span class="n">success_message</span><span class="o">=</span><span class="s1">&#39;Success&#39;</span><span class="p">)</span>
  <span class="n">output</span> <span class="o">=</span> <span class="sb">`</span><span class="si">#{</span><span class="n">command</span><span class="si">}</span><span class="sb"> 2&gt;&amp;1`</span>
  <span class="no">CommandResult</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">output</span><span class="p">,</span> <span class="o">!</span><span class="vg">$?</span><span class="o">.</span><span class="n">success?</span><span class="p">,</span> <span class="n">failure_message</span><span class="p">,</span> <span class="n">success_message</span><span class="p">)</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">run_go_fmt</span><span class="p">(</span><span class="n">files</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">&#34;Running go fmt…&#34;</span>
  <span class="n">files</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span>
    <span class="n">abort_unless</span><span class="p">(</span><span class="s2">&#34;go fmt </span><span class="si">#{</span><span class="n">file</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
  <span class="k">end</span>
  <span class="c1"># Eagerly re-add all files, as they may have been modified</span>
  <span class="sb">`git add </span><span class="si">#{</span><span class="n">files</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span><span class="si">}</span><span class="sb">`</span> <span class="k">unless</span> <span class="n">files</span><span class="o">.</span><span class="n">empty?</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">run_go_imports</span><span class="p">(</span><span class="n">files</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">&#34;Running goimports…&#34;</span>
  <span class="n">abort_unless</span><span class="p">(</span><span class="s2">&#34;goimports -w </span><span class="si">#{</span><span class="n">files</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
  <span class="c1"># Eagerly re-add all files, as they may have been modified</span>
  <span class="sb">`git add </span><span class="si">#{</span><span class="n">files</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span><span class="si">}</span><span class="sb">`</span> <span class="k">unless</span> <span class="n">files</span><span class="o">.</span><span class="n">empty?</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">run_lint</span><span class="p">(</span><span class="n">files</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">&#34;Running lint&#34;</span>
  <span class="n">abort_unless</span><span class="p">(</span><span class="s2">&#34;golangci-lint run --fix&#34;</span><span class="p">)</span>
  <span class="c1"># Eagerly re-add all files, as they may have been modified</span>
  <span class="sb">`git add </span><span class="si">#{</span><span class="n">files</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span><span class="si">}</span><span class="sb">`</span> <span class="k">unless</span> <span class="n">files</span><span class="o">.</span><span class="n">empty?</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">run_go_generate</span><span class="p">(</span><span class="n">go_files</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">&#34;Running go generate…&#34;</span>
  <span class="c1"># threads = go_files.map { |go_file| Thread.new { abort_unless_async(&#34;go generate #{go_file}&#34;) } }</span>
  <span class="c1"># threads.each do |thread|</span>
  <span class="c1">#   thread.value.result</span>
  <span class="c1"># end</span>
  <span class="n">go_files</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">go_file</span><span class="o">|</span>
    <span class="n">abort_unless</span><span class="p">(</span><span class="s2">&#34;go generate </span><span class="si">#{</span><span class="n">go_file</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
  <span class="k">end</span>
  <span class="n">generated_files</span> <span class="o">=</span> <span class="sb">`git diff --name-only --diff-filter=AM | grep &#39;\.go$&#39;`</span><span class="o">.</span><span class="n">split</span><span class="o">.</span><span class="n">select</span> <span class="p">{</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span> <span class="n">generated_file?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="p">}</span>
  <span class="c1"># Re-add all generated files</span>
  <span class="sb">`git add </span><span class="si">#{</span><span class="n">generated_files</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span><span class="si">}</span><span class="sb">`</span> <span class="k">unless</span> <span class="n">generated_files</span><span class="o">.</span><span class="n">empty?</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">run_go_vet</span><span class="p">(</span><span class="n">go_files</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">&#34;Running go vet…&#34;</span>
  <span class="n">go_files</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span>
    <span class="n">abort_unless</span><span class="p">(</span><span class="s2">&#34;go vet </span><span class="si">#{</span><span class="n">file</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">check_tests_for_new_files</span><span class="p">(</span><span class="n">new_go_application_files</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">&#34;Checking for tests…&#34;</span>
  <span class="n">new_go_application_files</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">new_go_application_file</span><span class="o">|</span>
    <span class="n">target_test_file</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">#{</span><span class="n">new_go_application_file</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/\.go$/</span><span class="p">,</span> <span class="s1">&#39;_test.go&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span>
    <span class="no">STDERR</span><span class="o">.</span><span class="n">puts</span> <span class="s2">&#34;</span><span class="si">#{</span><span class="n">new_go_application_file</span><span class="si">}</span><span class="s2"> was added in this change but is missing a matching test (</span><span class="si">#{</span><span class="n">target_test_file</span><span class="si">}</span><span class="s2">)&#34;</span><span class="o">.</span><span class="n">yellow</span> <span class="k">unless</span> <span class="no">Pathname</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">target_test_file</span><span class="p">)</span><span class="o">.</span><span class="n">exist?</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">check_fmt_print</span><span class="p">(</span><span class="n">go_files</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">&#34;Checking for fmt.Print…&#34;</span>
  <span class="n">abort_unless</span><span class="p">(</span><span class="s2">&#34;! grep -Hn &#39;fmt\.Print&#39; </span><span class="si">#{</span><span class="n">go_files</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">run_tests</span><span class="p">()</span>
  <span class="nb">puts</span> <span class="s1">&#39;Running tests…&#39;</span>
  <span class="n">abort_unless</span><span class="p">(</span><span class="s2">&#34;go test ./...&#34;</span><span class="p">)</span>
<span class="k">end</span>

<span class="k">def</span> <span class="nf">build_integration_tests</span><span class="p">()</span>
  <span class="nb">puts</span> <span class="s1">&#39;Building integration tests&#39;</span>
  <span class="n">abort_unless</span><span class="p">(</span><span class="s2">&#34;go test -run=^$ -tags &#39;integration endtoend&#39; ./...&#34;</span><span class="p">)</span>
<span class="k">end</span>

<span class="n">new_go_files</span> <span class="o">=</span> <span class="sb">`git diff --cached --name-only --diff-filter=A | grep &#39;\.go$&#39;`</span><span class="o">.</span><span class="n">split</span>
<span class="n">new_go_application_files</span><span class="p">,</span> <span class="n">new_go_test_files</span> <span class="o">=</span> <span class="n">new_go_files</span><span class="o">.</span><span class="n">partition</span> <span class="p">{</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span> <span class="ow">not</span> <span class="n">test_file?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="p">}</span>
<span class="n">new_go_application_files</span><span class="p">,</span> <span class="n">new_go_generated_files</span> <span class="o">=</span> <span class="n">new_go_application_files</span><span class="o">.</span><span class="n">partition</span> <span class="p">{</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span> <span class="ow">not</span> <span class="n">generated_file?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="p">}</span>
<span class="n">go_files</span> <span class="o">=</span> <span class="sb">`git diff --cached --name-only --diff-filter=ACM | grep &#39;\.go$&#39;`</span><span class="o">.</span><span class="n">split</span>
<span class="n">go_application_files</span><span class="p">,</span> <span class="n">go_test_files</span> <span class="o">=</span> <span class="n">go_files</span><span class="o">.</span><span class="n">partition</span> <span class="p">{</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span> <span class="ow">not</span> <span class="n">test_file?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="p">}</span>
<span class="n">go_application_files</span><span class="p">,</span> <span class="n">go_generated_files</span> <span class="o">=</span> <span class="n">go_application_files</span><span class="o">.</span><span class="n">partition</span> <span class="p">{</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span> <span class="ow">not</span> <span class="n">generated_file?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="p">}</span>

<span class="k">def</span> <span class="nf">all_go_files</span><span class="p">()</span>
  <span class="c1"># Recursively list all go files in current package and emit lines in the format</span>
  <span class="c1"># /absolute/path/to/module/directory:[file.go otherfile.go]</span>
  <span class="n">modules_and_files</span> <span class="o">=</span> <span class="sb">`go list -find -f &#39;{{.Dir}}:{{.GoFiles}}&#39; ./...`</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
  <span class="n">git_root</span> <span class="o">=</span> <span class="sb">`git rev-parse --show-toplevel`</span><span class="o">.</span><span class="n">strip</span> <span class="o">+</span> <span class="s1">&#39;/&#39;</span>
  <span class="n">all_go_files</span> <span class="o">=</span> <span class="o">[]</span>
  <span class="n">modules_and_files</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">module_and_files</span><span class="o">|</span>
    <span class="c1"># Split module path and files</span>
    <span class="n">module_dir</span><span class="p">,</span> <span class="n">files</span> <span class="o">=</span> <span class="n">module_and_files</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;:&#39;</span><span class="p">)</span>
    <span class="c1"># Remove git root directory from absolute path of module</span>
    <span class="n">module_dir</span> <span class="o">=</span> <span class="n">module_dir</span><span class="o">[</span><span class="n">git_root</span><span class="o">.</span><span class="n">length</span><span class="o">..-</span><span class="mi">1</span><span class="o">]</span>
    <span class="n">module_dir</span> <span class="o">=</span> <span class="p">(</span><span class="n">module_dir</span><span class="o">.</span><span class="n">nil?</span> <span class="ow">or</span> <span class="n">module_dir</span><span class="o">.</span><span class="n">empty?</span><span class="p">)</span> <span class="p">?</span> <span class="s2">&#34;&#34;</span> <span class="p">:</span> <span class="s2">&#34;</span><span class="si">#{</span><span class="n">module_dir</span><span class="si">}</span><span class="s2">/&#34;</span>
    <span class="n">files</span><span class="o">[</span><span class="mi">1</span><span class="o">..-</span><span class="mi">2</span><span class="o">].</span><span class="n">split</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span>
      <span class="n">all_go_files</span> <span class="o">&lt;&lt;</span> <span class="s2">&#34;</span><span class="si">#{</span><span class="n">module_dir</span><span class="si">}#{</span><span class="n">file</span><span class="si">}</span><span class="s2">&#34;</span>
    <span class="k">end</span>
  <span class="k">end</span>
  <span class="n">all_go_files</span>
<span class="k">end</span>

<span class="k">unless</span> <span class="n">go_files</span><span class="o">.</span><span class="n">empty?</span>
  <span class="n">run_go_fmt</span><span class="p">(</span><span class="n">go_application_files</span> <span class="o">+</span> <span class="n">go_test_files</span><span class="p">)</span>
  <span class="n">run_go_imports</span><span class="p">(</span><span class="n">go_application_files</span> <span class="o">+</span> <span class="n">go_test_files</span><span class="p">)</span>
  <span class="n">check_fmt_print</span><span class="p">(</span><span class="n">go_application_files</span> <span class="o">+</span> <span class="n">go_test_files</span><span class="p">)</span>
  <span class="n">run_go_vet</span><span class="p">(</span><span class="n">go_application_files</span> <span class="o">+</span> <span class="n">go_test_files</span><span class="p">)</span>
  <span class="n">run_lint</span><span class="p">(</span><span class="n">go_application_files</span> <span class="o">+</span> <span class="n">go_test_files</span><span class="p">)</span>
  <span class="n">check_tests_for_new_files</span><span class="p">(</span><span class="n">new_go_application_files</span><span class="p">)</span>
  <span class="n">run_go_generate</span><span class="p">(</span><span class="n">all_go_files</span><span class="p">()</span><span class="o">.</span><span class="n">select</span> <span class="p">{</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span> <span class="n">needs_generation?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="p">})</span>
  <span class="n">run_tests</span><span class="p">()</span>
  <span class="n">build_integration_tests</span><span class="p">()</span>
  <span class="nb">puts</span> <span class="s2">&#34;\u{1F389}  All good!&#34;</span><span class="o">.</span><span class="n">green</span>
  <span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">end</span>
</code></pre></div>]]></content>
        </entry>
    
        <entry>
            <title>AWS Infrastructure Offerings</title>
            <link href="https://www.eiggen.co/codes/aws-infrastructure-offerings/"/>
            <updated>2020-04-05T00:00:00+0000</updated>
            <id>https://www.eiggen.co/codes/aws-infrastructure-offerings/</id>
            <content type="html"><![CDATA[ <p>As I&rsquo;ve recently been suddenly confronted to the AWS learning curve, I quickly came to a realization that I was in over my head:</p>



  
    
      <img src="/codes/aws-infrastructure-offerings/afraid.png" alt="I don&#39;t know what a security group is, and at this point I&#39;m too afraid to ask"/>
    
  


<p>AWS is ubiquitous in the infrastructure world but an application developer like me can mostly get by without understanding its intricacies and subtleties. Ironically, engineers that work at some of the largest Internet companies in the world (e.g. Google, Microsoft, Facebook) may also find themselves lost when having to rely on public cloud offerings, because their experience lies with homegrown technologies.</p>
<p>The AWS reference documentation is well-written and plentiful, but lacks a narrative that takes the reader from basic to simple to slightly more advanced concepts. This post is the result of my own learning experience and is seeking to be a pragmatic, progressive introduction to AWS. In other words, this document is selective as to the technologies it covers and (lightly) opinionated. Feedback is <a href="mailto:julien@eiggen.co">welcome</a>.</p>
<nav id="TableOfContents">
  <ul>
    <li><a href="#regions">Regions</a></li>
    <li><a href="#availability-zones">Availability Zones</a></li>
    <li><a href="#ec2">EC2</a>
      <ul>
        <li><a href="#types">Types</a></li>
        <li><a href="#cpu">CPU</a></li>
        <li><a href="#mass-storage">Mass storage</a></li>
        <li><a href="#provisioning-and-pricing">Provisioning and Pricing</a></li>
      </ul>
    </li>
    <li><a href="#ami">AMI</a></li>
    <li><a href="#launch-configuration-and-templates">Launch Configuration and Templates</a></li>
    <li><a href="#auto-scaling-group">Auto-Scaling Group</a></li>
    <li><a href="#elastic-load-balancing">Elastic Load Balancing</a></li>
    <li><a href="#virtual-private-cloud">Virtual Private Cloud</a>
      <ul>
        <li><a href="#addresses-cidr-block-and-subnets">Addresses, CIDR Block and Subnets</a></li>
        <li><a href="#route-tables-and-internet-gateways">Route Tables and Internet Gateways</a></li>
        <li><a href="#security-groups-and-network-acls">Security Groups and Network ACLs</a></li>
        <li><a href="#default-vpcs">Default VPCs</a></li>
      </ul>
    </li>
    <li><a href="#elastic-ip-address">Elastic IP Address</a></li>
    <li><a href="#elastic-network-interfaces">Elastic Network Interfaces</a></li>
  </ul>
</nav>
<h2 id="regions">Regions</h2>
<p>A region is a real-world area in the world where AWS servers are co-located. Regions have a broad geographical location which is reflected in their name, e.g. &ldquo;ap-south-1&rdquo; (Asia Pacific South) or &ldquo;us-west-2&rdquo; (West Coast of the United States). Regions allow you to deploy your application to a location physically close to where your users are, with the goal of reducing the network roundtrip. The list of AWS regions can be found <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html">here</a>.</p>
<h2 id="availability-zones">Availability Zones</h2>
<p>An availability zone (abbreviated AZ) is a physical subdivision of a region that has its own power source and network links to the public Internet, each of which are 100% independent from  other AZs in the same region. As their name indicates AZs are intended to provide resilience within a region: running your application across multiple AZs in a region should allow for your users to still use it when one of them goes offline.</p>
<p>Even though they are physically independent, you should be able to make network requests across AZs without incurring a performance penalty: AZs are in close proximity and are interconnected by dedicated high-throughput, low-latency network links. Regions provide between 2 and 5 AZs each.</p>
<h2 id="ec2">EC2</h2>
<p>An Elastic Cloud Computing (EC2) instance is a virtual machine which provides core resources such CPU, RAM, mass storage and networking. It is the base unit for running application code on the AWS platform. Unlike physical servers, EC2 instances are <em>ephemeral</em>: once it is shut down, the same instance cannot be turned back on and, if needed, a distinct instance must be provisioned to replace it.</p>
<h3 id="types">Types</h3>
<p>EC2 instances have a type, which determines the amounts and attributes of each resource. Over time, the number of <a href="https://aws.amazon.com/ec2/instance-types/">instance types</a> has grown to cover a wide range of use cases. The nomenclature is fairly confusing and intricate, so you need to reason in terms of what the application code you need to run is going to need:</p>
<ul>
<li>For general purpose applications: A, T, and M types</li>
<li>CPU-intensive applications: C types</li>
<li>Memory-intensive applications: R, X, and z types</li>
<li>Applications requiring GPUs: P, G, Inf, and F types</li>
<li>Storage-intensive applications: I, D, and H types</li>
</ul>
<p>Comparing EC2 instances should be a science, and it turns out to be more of an art. As is the case when you provision a machine in the real world, there is a ton of flexibility and tradeoffs to consider. At a high-level, you should first determine the primary bottleneck of your application and chose an appropriate letter-type, then benchmark it across a range of actual types to figure out determine which is right.</p>
<h3 id="cpu">CPU</h3>
<p>Not all EC2 instance classes run on the same CPU, so AWS uses <em>vCPU</em> as a mean to compare them — a vCPU generally corresponds to having exclusive access to a single thread of the virtual CPU. But there are exceptions to this rule: for instance, the T2 type provides a physical core as opposed to a single thread. More variables also need to be considered:</p>
<ul>
<li>The brand and the class of the CPU varies across instance types, e.g. AMD EPYC or Intel Xeon</li>
<li>The model of the CPU is not the same across instances either: Xeon E5 2686 v4, Intel Xeon Platinum,…</li>
<li>For some instance types, AWS reasons in terms of CPU capabilities, e.g. Intel AVX or Intel Turbo.</li>
<li>AWS recently introduced Graviton, which uses an entirely different architecture (ARM).</li>
</ul>
<h3 id="mass-storage">Mass storage</h3>
<p>As noted earlier, an instance that was shut down cannot be brought back up. This is specifically a concern if the instance has stored data locally that needs to be persisted past its termination. The top-level dichotomy in terms of mass storage is EBS v. local instance store:</p>
<ul>
<li>Certain instance types only support Elastic Block Store (EBS). EBS is AWS' offering for a network store, i.e. it allows persisting data independently of the instance it is attached to. Some instance types are optimized for EBS usage, which means the throughput of the network link will be guaranteed (the specific value of the throughput may be different across instance types).</li>
<li>Certain instance types will come with built-in local storage, which can be either spinning disks or SSD.</li>
</ul>
<h3 id="provisioning-and-pricing">Provisioning and Pricing</h3>
<p>The default mode of provisioning EC2 instances is called <strong>&ldquo;on-demand&rdquo;</strong> and is the most intuitive one. The instance will be provisioned on the fly and will run until it is shut down. The cost is based on the amount of the instance was running: the amount of computing resources available is linear with the cost a customer is willing to pay.</p>
<p><strong>Reserved instances</strong> provide the same range of options as the on-demand offering, but offer a lower cost in return for a lasting commitment: the customer declares a need for a given number of instances for up to 3 years. By being able to anticipate demand, AWS can deliver the supply more efficiently, and pass down the savings.</p>
<p><strong>Spot</strong> is a different mode of provisioning, where the instances that are not reserved and not used on-demand are made available at a discounted price to workloads that are either stateless or highly fault-tolerant.</p>
<p>Spot instances run at a lower priority that on-demand or reserved instances, so that when a request is made for a number of spot instances, the request may be only partially fulfilled if there isn&rsquo;t enough supply. Conversely, AWS reserves the right to reclaim Spot instances if they are needed to fulfill on-demand requests. This is why Spot instances make sense for workloads that can be interrupted rapidly: in exchange for a decreased availability, Spot instances come at a very large discount compared to either of the other modes.</p>
<p>These provisioning modes are not exclusive to one another: it&rsquo;s actually a common practice to &ldquo;pad&rdquo; a pool of reserved instances with on-demand or spot instances when the application is confronted with a spike that couldn&rsquo;t be anticipated, e.g. large one-off migrations.</p>
<h2 id="ami">AMI</h2>
<p>An Amazon Machine Image (AMI) is a data bundle, which packs the software required to launch an EC2 instance. Several operating system vendors (e.g. Microsoft, RedHat, Ubuntu) publish their operating systems as AMIs, which makes it trivial to use on AWS. Some AMIs may be subject to licensing restrictions or need to be purchased directly from the vendor.</p>
<p>It is common practice to build <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html#creating-an-ami">custom AMIs</a>, which allows for the application to be installed and baked into the image ahead of it running in production. The resulting image may be kept private in case it includes proprietary software.</p>
<p>The typical build process of an AMI consists in provisioning an EC2 instance with a public AMI to use as a base, install any custom software needed at runtime and finally register the resulting volume as an AMI. The process is different depending on whether you intend to use the AMI to image an EBS volume or a local instance store.</p>
<h2 id="launch-configuration-and-templates">Launch Configuration and Templates</h2>
<p>Provisioning a single EC2 instance is a tedious task, as you need to pick a wide range of parameters: region, AZ, type, AMI are required parameters, but the number of options and parameters can be tedious to specify every time. Since launching EC2 instances is something that can happen several times a day even for medium-sized setups, there is a clear need for that process to be automated.</p>
<p>Launch configurations capture the set of parameters needed to launch an instance. Launch <em>templates</em> serve the same purpose as launch configurations but are more capable in that they can be versioned. Modifying a template creates a new version where parameters may be changed, added, or removed. You can then launch EC2 instances from any version, but only one version can be the default one at a given time. Templates are the preferred way to launch EC2 instances in Auto-Scaling Groups.</p>
<h2 id="auto-scaling-group">Auto-Scaling Group</h2>
<p>An Auto-Scaling Group (ASG) is tasked with managing a set of EC2 instances, with the goal of adjusting the number of instances up and down, as configured by a scaling policy. ASG have the following properties and constraints:</p>
<ul>
<li>ASGs require having the full set of parameters needed to launch new EC2 instances at any given time.</li>
<li>ASGs must also be configured with an upper and lower bound of instances to keep around at a given time.</li>
<li>ASGs may manage instances across multiple Availability Zones but not across multiple Regions.</li>
</ul>
<p>The scaling policy of an ASG determines when and how the ASG will grow or shrink the pool of EC2 instances it manages. The simplest policy is a static one, where the the upper and lower bound are equal: in this case, the ASG will simply monitor the health of instances and bring up a new instance only in case a previous one was deemed unhealthy. Beyond this simple use case, scaling policies can be configured in a variety of ways:</p>
<ul>
<li>Time-based scheduling allows adjusting the number of instances at a set time, which is useful when the change in demand is predictable</li>
<li>Built-in metrics such as CPU utilization can directly feed into the scaling policy, or you can specify any metric AWS has access to</li>
<li>Policies define by how much to adjust the size of the pool, either as an absolute change or relative to the current healthy count</li>
<li>Cooldown settings allow to avoid scaling down too fast and finding yourself in a situation where the ASG oscillates between scale-ups and scale-downs</li>
</ul>
<p>Lastly, be aware that multiple scaling policies can be active within a single ASG at once. When they conflict, AWS honors the ones that keeps capacity the highest.</p>
<fieldset>
  <legend>ASG v. Application Service</legend>
  <ol>
    <li>A single EC2 instance has the ability to concurrently run as many <em>services</em> as the hardware can support, e.g. a web frontend <em>and</em> a database <em>and</em> and Kafka node. </li>
    <li>When an EC2 instance is managed by an ASG, all the applications running on the instance will scale up and down in the same way.</li>
    <li>However, one of the key value proposal of fragmenting complex applications in multiple services is to allow for each to scale independently of the other: the Web tier presumably doesn't have the same scaling characteristics as a the backing database.</li>
    <li>Is it a common approach to define one ASG per service type, and to specialize the instance types and setup for the specific task they run.</li>
</fieldset>
<h2 id="elastic-load-balancing">Elastic Load Balancing</h2>
<p>An Elastic Load Balancer (ELB) is tasked with fronting and dispatching network traffic. An ELB dispatches traffic to targets in a <em>target group</em>, which in the most common case is an ASG. An ELB can also distribute traffic to a set of IP addresses, or to AWS Lambda functions. ELBs can operate at two levels of the <a href="https://en.wikipedia.org/wiki/OSI_model">networking model</a>:</p>
<ul>
<li>At the transport level (OSI 4), individual TCP or UDP socket connections will be streamed to the backend targets: ELBs of this kind are called Network Load Balancers (NLB)</li>
<li>At the application level (OSI 7), incoming HTTP requests are parsed and individually distributed to the backend targets: ELBs of this kind are called Application Load Balancers (ALB) and are more featureful than NLBs. They can be configured to route traffic to a specific group based on the data within an HTTP request: path, header value, query parameter, etc…</li>
</ul>
<p>Because it specializes in handling and routing network traffic, an ELB can augment an ASG in a couple of ways:</p>
<ul>
<li>By measuring the inbound traffic and allowing the ASG to use it as a metric to drive a scaling policy</li>
<li>By performing instance health checks that use the network, e.g. simple ICMP pings or HTTP probes</li>
</ul>
<p>Lastly, the routing logic of an ELB can be configured in a few ways:</p>
<ul>
<li>How long to let a new target warmup for, or how long it should be given to process the requests in flight after being de-registered</li>
<li>Stickiness parameters between clients and targets: an ALB can be made to consistently connect clients to the same target</li>
<li>The method for picking a target in a group, e.g. round-robin or least-loaded target in the group</li>
</ul>
<p>Lastly, and importantly, an ELB may be reachable from the public Internet but its IP shouldn&rsquo;t be expected to remain static over time. All ELBs will be provisioned with a publicly resolvable DNS name (*.elb.amazonaws.com), which will remain constant throughout the lifespan of the ELB. This record can be used directly or can be <a href="https://en.wikipedia.org/wiki/CNAME_record">CNAME&rsquo;d</a> to a more user-friendly form (api.example.com → api-1234567890.ap-south-1.elb.amazonaws.com).</p>
<h2 id="virtual-private-cloud">Virtual Private Cloud</h2>
<p>A Virtual Private Cloud (VPC) is a bit of an umbrella term for a set of related capabilities that are intended to isolate and protect the network traffic to and from EC2 instances. Even though AWS resources are generally shared between AWS customers, a VPC provides a logical separation of your AWS resources from other accounts. A VPC can span multiple availability zones but is limited to a single region.</p>
<p>There is a pre and post-VPC world in AWS, but VPCs have been the default networking stack for EC2 instances since 2013. Concepts and resources introduced prior to the advent of VPCs are generally labelled as &ldquo;Classic&rdquo; in the AWS terminology. The rest of this post will focus on the VPC stack and avoid discussing the legacy stack.</p>
<h3 id="addresses-cidr-block-and-subnets">Addresses, CIDR Block and Subnets</h3>
<p>When it comes to networking, half of the problem is addressing: A VPC is assigned a range of at most 2<sup>16</sup> <a href="https://en.wikipedia.org/wiki/Private_network">private IP addresses</a> which can not be routed over the public Internet. This range is broken down in disjoint subnets, each of which maps to one Availability Zone.</p>
<p>The common notation for these ranges is called the CIDR notation, where a range is written as a IP address followed by a slash and a mask, e.g. 192.0.2.0/24. The value of the mask is used to tell how many addresses are in the block. In the case of IPv4, which uses 32 bits, a mask of 24 bits gives you 8 variable bits: 2<sup>8</sup> = 256 addresses. The lower the value of the mask, the larger the block.</p>
<p>On AWS, it is common to have VPCs with a 172.x.0.0/16 address space, which in turn is divided in multiple /20 subnets – for instance, with 4 availability zones:</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>CIDR</th>
<th>Number of Addresses</th>
<th>First Address</th>
<th>Last Address</th>
</tr>
</thead>
<tbody>
<tr>
<td>VPC</td>
<td>172.x.0.0/16</td>
<td>65,536</td>
<td>172.x.0.1</td>
<td>172.x.255.255</td>
</tr>
<tr>
<td>Subnet 1</td>
<td>172.x.0.0/20</td>
<td>4,096</td>
<td>172.x.0.0</td>
<td>172.x.15.254</td>
</tr>
<tr>
<td>Subnet 2</td>
<td>172.x.16.0/20</td>
<td>4,096</td>
<td>172.x.16.1</td>
<td>172.x.31.254</td>
</tr>
<tr>
<td>Subnet 3</td>
<td>172.x.32.0/20</td>
<td>4,096</td>
<td>172.x.32.1</td>
<td>172.x.47.254</td>
</tr>
<tr>
<td>Subnet 4</td>
<td>172.x.48.0/20</td>
<td>4,096</td>
<td>172.x.48.1</td>
<td>172.x.63.254</td>
</tr>
</tbody>
</table>
<p>Beyond private IPs, a Subnet can also be configured to supply a public IP address to the instances that are launched in it. If so, the network interface of the instance will be given a random publicly routable IP address coming from AWS&rsquo;s pool. If you prefer for instances to not get a public IP address, this behavior can be overridden in the launch template.</p>
<h3 id="route-tables-and-internet-gateways">Route Tables and Internet Gateways</h3>
<p>After addressing, the other half of networking is routing. VPCs have a routing table which governs the way traffic is routed within the VPC, as well as ingress and egress traffic. Inter-VPC traffic is kept within through a local route in the routing table: this route cannot be changed.</p>
<p>Egress traffic to the public Internet is generally directed at an Internet Gateway (IGW), which interfaces the VPC with the public Internet. Internet Gateways have two purposes:</p>
<ul>
<li>routing egress traffic out of the VPC</li>
<li>routing ingress traffic for instances that have a public IP address</li>
</ul>
<p>By default, a VPC will have a route to the IGW that applies to all subnets in the VPC - such subnets are called public subnets. When that route is not present for a given subnet, the subnet is fully isolated from the Internet and is deemed private.</p>
<p>Even though directly accepting ingress traffic through an Internet Gateway is feasible, it&rsquo;s a more common pattern to use ELBs to front the traffic and dispatch it to an ASG where the instances do not need to be provisioned with a public IP address.</p>
<h3 id="security-groups-and-network-acls">Security Groups and Network ACLs</h3>
<p>VPCs allow for fine grained control over the traffic that is allowed to flow to and from instances. Network ACLs apply to one or many subnets and act like a standard firewall: they are tasked with filtering packets. They consist of matching rules that are evaluated in order: the first rule that matches the traffic will determine whether the packet is allowed to proceed. ACLs for ingress and egress traffic are defined separately.</p>
<p>Security Groups (SGs) also offer filtering capabilities but they act at the instance level: a given Security Group may only apply to select instances in a subnet, and they may span over instances across multiple subnets. Importantly, SGs also offer the flexibility to match traffic based other SGs. This allows grouping instances by &ldquo;type&rdquo; on a network basis and enforcing a given network topology between different groups.</p>
<p>For instance, say you have a Web frontend which relies on two backend services: Backend Service 1 and Backend Service 2. Each backend service uses the same Database server. The Web frontend shouldn&rsquo;t talk to the database directly. Additionally, let&rsquo;s assume that Backend Service 2 is of a higher tier of importance that Backend Service 1, and should therefore avoid making calls to it:</p>
<table>
<thead>
<tr>
<th>Component</th>
<th>Security Group</th>
<th>Rules</th>
</tr>
</thead>
<tbody>
<tr>
<td>Web frontend</td>
<td><code>sg-web</code></td>
<td>Allow egress to <code>sg-be1</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td>Allow egress to <code>sg-be2</code></td>
</tr>
<tr>
<td>Backend Service 1</td>
<td><code>sg-be1</code></td>
<td>Allow ingress from <code>sg-web</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td>Allow egress to <code>sg-db</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td>Allow egress to <code>sg-be2</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td>Deny ingress from <code>sg-be2</code></td>
</tr>
<tr>
<td>Backend Service 2</td>
<td><code>sg-be2</code></td>
<td>Allow ingress from <code>sg-web</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td>Deny egress to <code>sg-be1</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td>Allow egress to <code>sg-db</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td>Allow ingress from <code>sg-be1</code></td>
</tr>
<tr>
<td>Database</td>
<td><code>sg-db</code></td>
<td>Allow ingress from <code>sg-be1</code></td>
</tr>
<tr>
<td></td>
<td></td>
<td>Allow ingress from <code>sg-be2</code></td>
</tr>
</tbody>
</table>
<p>Some of these rules are redundant and could therefore be omitted, but the principle remains: Security Groups are powerful in that they can apply at once to multiple instances of the same kind.</p>
<h3 id="default-vpcs">Default VPCs</h3>
<p>VAs mentioned earlier, VPCs have become the default mode of managing EC2 instances and network setups. When you create a new account, a default VPC and subnets are provisioned by default in every AWS region. In each region, this VPC will consist of a /16 CIDR block (65K private addresses), divided in as many /20 subnets (4K private addresses) as there as AZs.</p>
<p>All subnets will be public ones and a default route will allow them to reach the Internet through the Internet Gateway. There will be a default Network ACL allowing for all traffic to flow, and a default Security Group as well. You can chose to either take the default VPC and tune it to your needs, or to provision a new VPC from scratch.</p>
<h2 id="elastic-ip-address">Elastic IP Address</h2>
<p>An Elastic IP Address (EIP) represents a single public IP address that is routable and reachable from the public Internet. An EIP can be provisioned within your account and assigned to an instance, which then becomes accessible on the Internet.</p>
<p>Unlike instances, which are ephemeral, EIPs are static and can be freely attached to a given instance, then detached and moved to a different one. When an EIP is attached to an instance, the public IP of that instance changes to be that specified by the EIP. EIPs will retain their associated public address until they are explicitly released.</p>
<p>The goal of EIPs is to provide resilience: in case of an issue with the underlying instance or the application it runs, the EIP can be reassigned to another instance running the same application. The new instance will immediately begin receiving connections directed at that IP (with the caveat than previous connections will be interrupted and need to be re-established).</p>
<p>Note that EIPs can be created for free, but will incur charges when they are not attached to a running instance (because they consume an address that is left unused).</p>
<h2 id="elastic-network-interfaces">Elastic Network Interfaces</h2>
<p>An Elastic Network Interface (ENI) augments the concept of EIP by adding more settings such as private IP addresses and Security Groups but still remain decoupled from instances. Just like EIPs, ENIs can be freely attached to and detached from instances.</p>
<p>An ENI can only be mapped to one instance, but an instance can have multiple ENIs at once: the limit is dependent on the instance <a href="#types">type</a>. All EC2 instances come with a default primary interface which is proper to the instance and cannot be detached.</p>
<p>An ENI possesses the following attributes:</p>
<ul>
<li>One private IPv4 address (and, optionally, secondary private addresses)</li>
<li>Up to one Elastic IP per private IPv4 address</li>
<li>One optional public IPv4 address</li>
<li>Security Groups</li>
<li>A MAC address</li>
</ul>
<p>An ENI can only be defined within a VPC, and is more specifically defined within a <em>Subnet</em>: it will use private IPs that are in the CIDR block for that Subnet. You can choose to automatically obtain a private IP from the pool of the subnet, or If the Subnet is configured to allocate a public IP for each instance, creating an ENI will also give it a random public IP from the AWS pool of public IP addresses.</p>
<p>Conversely, an ENI can only be associated with Security Groups from the VPC they belong to.</p>
<p>Finally, an ENI can be attached to an Elastic IP address: this allows the same kind of failover scenario as with plain EIPs with the added benefit that the ENI also carries the Security Groups to the new instance.</p>
]]></content>
        </entry>
    
        <entry>
            <title>The Unicode Algorithms</title>
            <link href="https://www.eiggen.co/codes/i-love-unicode-algorithms/"/>
            <updated>2020-03-20T00:00:00+0000</updated>
            <id>https://www.eiggen.co/codes/i-love-unicode-algorithms/</id>
            <content type="html"><![CDATA[ <p>This article is the third in a series intended to demystify the Unicode standard and explore in some depth the aspects that programmers have issues with. It is recommended that you follow the articles in sequence, as the concepts in later articles build upon the ones explained in earlier ones.</p>
<ol>
<li><a href="/codes/i-love-unicode">I � Unicode (Intro)</a></li>
<li><a href="/codes/i-love-unicode-character-set">The Character Set</a></li>
<li><a href="/codes/i-love-unicode-encodings">The Encodings</a></li>
<li>The Algorithms (This article)</li>
</ol>
<fieldset>
  <legend>⌘ The Rundown</legend>
  <ol>
    <li>Beyond defining a character set and encodings, the Unicode standard also elevates itself to address problems of a higher order when it comes to handling text</li>
    <li>Characters are intended to form words and sentences in languages, each of which has rules that can be subtly different when it comes to performing common computing tasks such as sorting</li>
    <li>Most Unicode algorithms are implemented in a library called ICU (International Components for Unicode) and can be easily tapped into programmatically</li>
    <li>ICU itself uses CLDR (Common Locale Data Repository) as a structured data source for applying the algorithm in a way that is compliant with a given region or language (a locale)</li>
  </ol>
</fieldset>
<p>As seen in the other two parts of this series, Unicode concerns itself with defining a universal set of characters and representing those characters as sequences of bytes. The Unicode standard also concerns itself with <em>text</em> as a broader domain. In this section, we are going to dive a bit deeper in</p>
<ul>
<li>How is text sorted? How do you define an ordering across characters in a set as vast as the one defined by Unicode?</li>
<li>How is text compared? We saw that Unicode sometimes defined distinct code points for the same entity, e.g. U+FF76 <code>HALFWIDTH KATAKANA LETTER KA</code> ｶ and U+30AB <code>KATAKANA LETTER KA</code> カ. What happens when those two are compared?</li>
</ul>
<p>All of these are defined by algorithms, which are specified as part of the standard</p>
<h3 id="the-collation-algorithm">The collation algorithm</h3>
<p>Collation is fancy term for sorting: your goal in this case is to go from an unordered collection of Unicode strings to a state where these are in the correct order. What is critical to understand here is that the &ldquo;correct order&rdquo; is neither universal nor invariant: it changes from person to person, and it changes over time.</p>
<p>Different scripts and different languages impose different rules for deciding the ordering of strings. All code points do have a U number but it does not imply any kind of ordering. The Unicode Collation Algorithm is specified as <a href="https://unicode.org/reports/tr10/">Technical Report 10</a> in the Unicode standard.</p>
<p>There is generally a notion of basic order across distinct characters in a script, but languages have an incredible variety when it comes to defining the ordering rules:</p>
<ul>
<li>Characters that have diacritical marks (e.g. accents) generally follow specific ordering rules, or can occasionally be considered as separate characters than the one they are graphically based on.</li>
<li>Groups of multiple characters may be contracted as a single token for the purpose of sorting the string, e.g. &ldquo;ch&rdquo; in Czech sorts after &ldquo;h&rdquo;, whereas it sorts after the &ldquo;c&rdquo; character in Spanish.</li>
<li>Characters may be expanded into clusters of multiple distinct characters, e.g. &ldquo;ä&rdquo; in certain German contexts expends to &ldquo;ae&rdquo;, which means a word such as &ldquo;Äquivalent&rdquo; will be sorted before &ldquo;Affekt&rdquo;.</li>
<li>When more than single words are compared, the rules for handling punctuation such as a dash may vary.</li>
<li>Text may need to be <em>normalized</em>, which will be covered in details further down in this post.</li>
<li>When it applies in the script, the casing of letters might be an element for determining the ordering rule.</li>
</ul>
<p>In other words, trying to sort text without knowing the expectations of the person who will read the result is pointless: you need to know the language and the context in which the sorted content will be used and presented.</p>
<p>The Unicode Collation Algorithm is therefore more of a framework for collation to be defined and implemented for a given context. The goal of the algorithm is to translate strings of Unicode code points into a sort key, which is an array of 16-bit integers. The sort keys can then be compared in binary to establish the order of the source strings they were computed for.</p>
<p>The following snippet of code demonstrates how to build a collator to properly sort a list of strings, in Java:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">co.eiggen.unicode</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">com.ibm.icu.text.CollationKey</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.ibm.icu.text.Collator</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.ibm.icu.util.ULocale</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.math.BigInteger</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.ArrayList</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.List</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Collections</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Collation</span> <span class="o">{</span>
  <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">...</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
    <span class="n">ULocale</span> <span class="n">germanPhoneBookLocale</span> <span class="o">=</span> <span class="n">ULocale</span><span class="o">.</span><span class="na">GERMAN</span><span class="o">.</span><span class="na">setKeywordValue</span><span class="o">(</span><span class="s">&#34;collation&#34;</span><span class="o">,</span> <span class="s">&#34;phonebook&#34;</span><span class="o">);</span>
    <span class="n">Collator</span> <span class="n">germanPhoneBookCollator</span> <span class="o">=</span> <span class="n">Collator</span><span class="o">.</span><span class="na">getInstance</span><span class="o">(</span><span class="n">germanPhoneBookLocale</span><span class="o">);</span>
    
    <span class="n">List</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="n">words</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ArrayList</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;();</span>
    <span class="n">words</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="s">&#34;Affekt&#34;</span><span class="o">);</span>
    <span class="n">words</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="s">&#34;Äquivalent&#34;</span><span class="o">);</span>

    <span class="k">for</span> <span class="o">(</span><span class="n">String</span> <span class="n">word</span> <span class="o">:</span> <span class="n">words</span><span class="o">)</span> <span class="o">{</span>
      <span class="kt">byte</span><span class="o">[]</span> <span class="n">collationKey</span> <span class="o">=</span> <span class="n">germanPhoneBookCollator</span><span class="o">.</span><span class="na">getCollationKey</span><span class="o">(</span><span class="n">word</span><span class="o">).</span><span class="na">toByteArray</span><span class="o">();</span>
      <span class="n">BigInteger</span> <span class="n">collationKeyAsInteger</span> <span class="o">=</span> <span class="k">new</span> <span class="n">BigInteger</span><span class="o">(</span><span class="n">1</span><span class="o">,</span> <span class="n">collationKey</span><span class="o">);</span>
      <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">printf</span><span class="o">(</span><span class="s">&#34;Collation key for %s is %s\n&#34;</span><span class="o">,</span> <span class="n">word</span><span class="o">,</span>  <span class="n">collationKeyAsInteger</span><span class="o">.</span><span class="na">toString</span><span class="o">(</span><span class="n">16</span><span class="o">));</span>
    <span class="o">}</span>

    <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">printf</span><span class="o">(</span><span class="s">&#34;Initial order: %s\n&#34;</span><span class="o">,</span> <span class="n">words</span><span class="o">.</span><span class="na">toString</span><span class="o">());</span>
    <span class="n">Collections</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">words</span><span class="o">,</span> <span class="n">germanPhoneBookCollator</span><span class="o">);</span>
    <span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">printf</span><span class="o">(</span><span class="s">&#34;Sorted order: %s\n&#34;</span><span class="o">,</span> <span class="n">words</span><span class="o">.</span><span class="na">toString</span><span class="o">());</span>
  <span class="o">}</span>
<span class="o">}</span>

</code></pre></div><p>The code yields the following output:</p>
<pre tabindex="0"><code>Collation key for Affekt is 2a3434323e50010a01dc0900
Collation key for Äquivalent is 2a324a523a542a403244500145480d01dcc60d00
Initial order: [Affekt, Äquivalent]
Sorted order: [Äquivalent, Affekt]
</code></pre><p>As can be seen in the above snippet, the most popular implementation of the Unicode Collation Algorithm is <a href="http://site.icu-project.org/home">ICU</a>, which stands for International Components for Unicode. It&rsquo;s a library developed for C/++ and Java that provides bindings to <a href="http://cldr.unicode.org/">CLDR</a>, the Common Locale Data Repository.</p>
<p>CLDR, as the name implies, is a repository of data that pertains to regions and languages of the world, and the combination thereof. Specifically for the purpose of sorting, CLDR encodes all the differences mentioned above: diacritics, casing, expansion and contraction, etc… CLDR is also an authority for a range of tasks pertaining to software internationalization: formatting of dates, numbers, currencies, pluralization rules, calendars, segmentation, etc…</p>
<p>Even though CLDR is maintained by the Unicode consortium, its scope goes well beyond the handling of text. In addition to Java and C/C++, bindings of CLDR have been created for <a href="https://github.com/twitter/twitter-cldr-rb">Ruby</a> and <a href="https://github.com/twitter/twitter-cldr-js">JavaScript</a>, even though the latter is being progressively replaced by the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl">Intl object</a>.</p>
<h3 id="the-normalization-algorithm">The normalization algorithm</h3>
<p>Normalization is an issue that occurs when you want to <em>compare</em> strings rather than order them. As the <a href="/codes/i-love-unicode-character-set">first part</a> of this series explained, Unicode defines over a million code points, with some of them being strikingly similar to others.</p>
<p>In other cases, the standard included code points that explicitly represent typographic ligatures: groupings of multiple characters that are rendered on screen by a single font glyph. One of the most common ligature in the Latin script is U+FB01 <code>LATIN SMALL LIGATURE FI</code> (ﬁ). Ligatures do not have any standalone semantic, they are just a presentation artifact.</p>
<p>The normalization forms, defined at the standard level by <a href="https://unicode.org/reports/tr15/">Technical Report 15</a>, intend to bring a solution to this issue. &ldquo;Why is normalization important?&rdquo;, you might ask.</p>
<p>The most common use case is <em>indexing</em>: if you want to build a search engine, or a database engine, a lot of the work will consist in making sense of the content indexed and making it queryable. On either side of it, the user data should be normalized so that a text containing the &ldquo;ﬁ&rdquo; ligature would actually match an input such as &ldquo;fi&rdquo;.</p>
<p>The same logic applies to a number of other characters beyond ligatures:</p>
<ul>
<li>Unicode has dedicated code points for superscript numbers, e.g. U+2078 <code>SUPERSCRIPT EIGHT</code> (⁸)</li>
<li>Full-width and half-width Katakana characters and Latin characters, which were covered in the first post in this series</li>
<li>Unicode defines circled alphanumeric code points such as U+2466 <code>CIRCLED DIGIT SEVEN</code> (⑦)</li>
<li>Old Roman numerals such as U+216F <code>ROMAN NUMERAL ONE THOUSAND</code> (Ⅿ) or even composed forms such as U+2177 <code>SMALL ROMAN NUMERAL EIGHT</code> (ⅷ)</li>
</ul>
<p>The normalization algorithm defines 4 normal forms which have different characteristics and will yield distinct results:</p>
<ul>
<li>A normalization form may be concerned with canonical equivalence (NF) or compatibility (NFK) — canonical normalization mandates strict canonicity of the strings, while compatible normalization is more lenient and considers distinct code points or combination of code points to have the same meaning.</li>
<li>A normalization form may be concerned with the composed (C) or decomposed form (D) of the underlying characters – some diacritical characters may have a standalone form, e.g. U+F4 <code>LATIN SMALL LETTER WITH CIRCUMFLEX</code> (ô), but may also be written as a sequence of U+6F <code>LATIN SMALL LETTER O</code> (o) and U+302 <code>COMBINING CIRCUMFLEX ACCENT</code> ( ̂). In the latter case, the order in which the code points are combined affect the normalized form of the string.</li>
</ul>
<p>Picking which form is the best suited for the task depends on the goal you have. The table below shows the result of testing for equality in the normalized forms of two input strings:</p>
<table>
<thead>
<tr>
<th>Left string</th>
<th>Left code points</th>
<th>Right String</th>
<th>Right code points</th>
<th>NFD</th>
<th>NFC</th>
<th>NFKD</th>
<th>NFKC</th>
</tr>
</thead>
<tbody>
<tr>
<td>foo</td>
<td>U+66 <code>LATIN SMALL LETTER F</code><br>U+6F <code>LATIN SMALL LETTER O</code><br>U+6F <code>LATIN SMALL LETTER O</code></td>
<td>bar</td>
<td>U+62 <code>LATIN SMALL LETTER B</code><br>U+61 <code>LATIN SMALL LETTER A</code><br>U+72 <code>LATIN SMALL LETTER R</code></td>
<td>false</td>
<td>false</td>
<td>false</td>
<td>false</td>
</tr>
<tr>
<td>ﬁ</td>
<td>U+FB01 <code>LATIN SMALL LIGATURE FI</code></td>
<td>fi</td>
<td>U+66 <code>LATIN SMALL LETTER F</code><br>U+69 <code>LATIN SMALL LETTER I</code></td>
<td>false</td>
<td>false</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>Å</td>
<td>U+212B <code>ANGSTROM SIGN</code></td>
<td>Å</td>
<td>U+C5 <code>LATIN CAPITAL LETTER A WITH RING ABOVE</code></td>
<td>true</td>
<td>true</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>ｶ</td>
<td>U+FF76 <code>HALFWIDTH KATAKANA LETTER KA</code></td>
<td>カ</td>
<td>U+30AB <code>KATAKANA LETTER KA</code></td>
<td>false</td>
<td>false</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>⑦</td>
<td>U+2466 <code>CIRCLED DIGIT SEVEN</code></td>
<td>7</td>
<td>U+37 <code>DIGIT SEVEN</code></td>
<td>false</td>
<td>false</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>8</td>
<td>U+38 <code>DIGIT EIGHT</code></td>
<td>⁸</td>
<td>U+2078 <code>SUPERSCRIPT EIGHT</code></td>
<td>false</td>
<td>false</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>ⅷ</td>
<td>U+2177 <code>SMALL ROMAN NUMERAL EIGHT</code></td>
<td>viii</td>
<td>U+76 <code>LATIN SMALL LETTER V</code><br>U+69 <code>LATIN SMALL LETTER I</code><br>U+69 <code>LATIN SMALL LETTER I</code><br>U+69 <code>LATIN SMALL LETTER I</code></td>
<td>false</td>
<td>false</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>ñ</td>
<td>U+F1 <code>LATIN SMALL LETTER N WITH TILDE</code></td>
<td>ñ</td>
<td>U+6E <code>LATIN SMALL LETTER N</code><br>U+303 <code>COMBINING TILDE</code></td>
<td>true</td>
<td>true</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>ế</td>
<td>U+1EBF <code>LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE</code></td>
<td>ế</td>
<td>U+65 <code>LATIN SMALL LETTER E</code><br>U+302 <code>COMBINING CIRCUMFLEX ACCENT</code><br>U+301 <code>COMBINING ACUTE ACCENT</code></td>
<td>true</td>
<td>true</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>ế</td>
<td>U+1EBF <code>LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE</code></td>
<td>é̂</td>
<td>U+65 <code>LATIN SMALL LETTER E</code><br>U+301 <code>COMBINING ACUTE ACCENT</code><br>U+302 <code>COMBINING CIRCUMFLEX ACCENT</code></td>
<td>false</td>
<td>false</td>
<td>false</td>
<td>false</td>
</tr>
<tr>
<td>ế</td>
<td>U+1EBF <code>LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE</code></td>
<td>ế</td>
<td>U+EA <code>LATIN SMALL LETTER E WITH CIRCUMFLEX</code><br>U+301 <code>COMBINING ACUTE ACCENT</code></td>
<td>true</td>
<td>true</td>
<td>true</td>
<td>true</td>
</tr>
<tr>
<td>ế</td>
<td>U+65 <code>LATIN SMALL LETTER E</code><br>U+302 <code>COMBINING CIRCUMFLEX ACCENT</code><br>U+301 <code>COMBINING ACUTE ACCENT</code></td>
<td>é̂</td>
<td>U+65 <code>LATIN SMALL LETTER E</code><br>U+301 <code>COMBINING ACUTE ACCENT</code><br>U+302 <code>COMBINING CIRCUMFLEX ACCENT</code></td>
<td>false</td>
<td>false</td>
<td>false</td>
<td>false</td>
</tr>
</tbody>
</table>
<p>As can be seen from these results, the largest difference in normalization results stems from the distinction between canonical and compatibility forms: the canonical normalization is very strict, while the compatibility one matches code points based on semantics.</p>
<p>There are no examples where the decomposition criteria matters when it is used consistently. Which you pick is up to you but be consistent in your choice. If you were to compare the normalized outputs of, e.g. NFKD and NFKC for the same string input string, they would be non-equal for any string that contains composed characters:</p>
<table>
<thead>
<tr>
<th>Input</th>
<th>Code points</th>
<th>NFKD =? NFKC</th>
</tr>
</thead>
<tbody>
<tr>
<td>foo</td>
<td>U+66 <code>LATIN SMALL LETTER F</code><br>U+6F <code>LATIN SMALL LETTER O</code><br>U+6F <code>LATIN SMALL LETTER O</code></td>
<td>true</td>
</tr>
<tr>
<td>ﬁ</td>
<td>U+FB01 <code>LATIN SMALL LIGATURE FI</code></td>
<td>true</td>
</tr>
<tr>
<td>ñ</td>
<td>U+F1 <code>LATIN SMALL LETTER N WITH TILDE</code></td>
<td>false</td>
</tr>
<tr>
<td>Å</td>
<td>U+212B <code>ANGSTROM SIGN</code></td>
<td>false</td>
</tr>
<tr>
<td>Å</td>
<td>U+C5 <code>LATIN CAPITAL LETTER A WITH RING ABOVE</code></td>
<td>false</td>
</tr>
<tr>
<td>ế</td>
<td>U+1EBF <code>LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE</code></td>
<td>false</td>
</tr>
</tbody>
</table>
<p>The code used to generate these tables is available <a href="https://github.com/jsilland/unicode">here</a>.</p>
<h3 id="miscellaneous-other-algorithms">Miscellaneous other algorithms</h3>
<h4 id="segmentation">Segmentation</h4>
<p>As we just saw in the previous section about the Normalization algorithm, characters may actually be represented by several code points — these are called combined characters and are semantically equivalent to their combined form. What this means pragmatically is that the end user doesn&rsquo;t care how the underlying text is formed, they care about the end result that they can see and interact with. Whether &ldquo;ñ&rdquo; is written as U+F1 <code>LATIN SMALL LETTER N WITH TILDE</code> or U+6E <code>LATIN SMALL LETTER N</code> along with U+303 <code>COMBINING TILDE</code> makes no difference.</p>
<p>The problem becomes more complex with more advanced forms of composing characters, e.g. &ldquo;👨🏿‍🦲&rdquo; is actually a combination of four (!) code points—but when it is rendered in a UI, it should still be represented as a single character. Segmentation (specified in Unicode <a href="https://www.unicode.org/reports/tr29/">Technical Report 29</a>) is intended to allow the programmatic chunking of a Unicode string into clusters of code points that match more closely what an end-user might expect.</p>
<p>Segmentation doesn&rsquo;t just address the grouping of code points into higher-level symbols, it also defines how to break a text into words, sentences and paragraphs. There are several use cases for this:</p>
<ul>
<li>Computing the user-visible <a href="https://www.eiggen.co/codes/on-string-lengths/">length of a string</a></li>
<li>Sentence-level breaking is useful for search engines to index content</li>
<li>Implementing text selection, e.g. double-clicking on a word extends the selection to the full word</li>
</ul>
<p>ICU ships with a <a href="http://userguide.icu-project.org/boundaryanalysis">segmentation implementation</a> of compliant with the Unicode standard.</p>
<h4 id="the-bidirectional-algorithm">The Bidirectional Algorithm</h4>
<p>The bidirectional algorithm (Unicode <a href="https://unicode.org/reports/tr9/">Technical Report 9</a>) is perhaps the most abstract of one, making it arduous to grasp and to implement correctly. You should almost never need to directly interact with it, and instead rely on the implementation at the OS or browser level to do the right things.</p>
<p>Writing systems of the worlds have a natural directionality, which is proper to each of them. Latin, Greek, and many other scripts are written left to right (LTR), but scripts such as Hebrew and Arabic are written and read from right to left (RTL). The bidirectional algorithm concerns itself with the rendering of text in mixed contexts, e.g. when Arabic and Latin characters belong in the same sentence or paragraph.</p>
<p>It introduces formatting characters that can be used to assign segments of text an explicit directionality, which may be different than the one they would have by default. These characters have no semantics of their own and are only hints to systems tasked with rendering text to the user:</p>
<blockquote>
<p>The directional formatting characters are used only to influence the display ordering of text. In all other respects they should be ignored—they have no effect on the comparison of text or on word breaks, parsing, or numeric analysis.</p>
</blockquote>
]]></content>
        </entry>
    
        <entry>
            <title>The Unicode Encodings</title>
            <link href="https://www.eiggen.co/codes/i-love-unicode-encodings/"/>
            <updated>2020-03-19T00:00:00+0000</updated>
            <id>https://www.eiggen.co/codes/i-love-unicode-encodings/</id>
            <content type="html"><![CDATA[ <p>This article is the second in a series intended to demystify the Unicode standard and explore in some depth the aspects that programmers have issues with. It is recommended that you follow the articles in sequence, as the concepts in later articles build upon the ones explained in earlier ones.</p>
<ol>
<li><a href="/codes/i-love-unicode">I � Unicode (Intro)</a></li>
<li><a href="/codes/i-love-unicode-character-set">The Character Set</a></li>
<li>The Encodings (This article)</li>
<li><a href="/codes/i-love-unicode-algorithms">The Algorithms</a></li>
</ol>
<fieldset>
  <legend>⌘ The Rundown</legend>
  <ol>
    <li>Unlike most other character sets, there is no straightforward mapping between Unicode code point and bytes</li>
    <li>You must specify an <em>encoding</em> when converting bytes into Unicode code points, and code points into bytes</li>
    <li>All Unicode encodings support the full set of 1,114,112 possible Unicode code points</li>
    <li>The Unicode standard defines several encodings which are called transformation formats: UTF-32, UTF-16 and UTF-8 are all part of the Unicode standard</li>
    <li>UTF-16 leverages an indexing scheme called surrogate pairs, which was devised when the character set grew past the BMP</li>
    <li>UTF-8 is by far the most popular encoding in the world and the recommended one for several document formats, such as JSON and HTML</li>
  </ol>
</fieldset>
<p>Perhaps Unicode&rsquo;s greatest insight is the decoupling of characters from bytes. Before Unicode, most systems used for representing strings equated the bytes read from, e.g., a file, to the characters in memory. It made systems easy to understand but inherently limited.</p>
<p>For instance, the C programming language defines a very minimal <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf">character set</a> which contains basic latin characters and the built-in <code>char</code> type as follows:</p>
<blockquote>
<p>If a member of the basic execution character set is stored in a <code>char</code> object, its value is guaranteed to be nonnegative. If any other character is stored in a <code>char</code> object, the resulting value is implementation-defined but shall be within the range of values that can be represented in that type.</p>
</blockquote>
<p>When it came down to representing those characters in memory and writing them to a file, all C implementations settled on ASCII. <code>'a'</code> the ASCII character was mapped to <code>0x61</code> and that was also the byte value of the character <code>'a'</code> when declared in C. That is not the case in Unicode: the lowercase latin letter &lsquo;a&rsquo; is defined as U+0061. That&rsquo;s a subtle difference but a critical one: the <code>U+</code> notation is how you know the value is referring to a Unicode code point and not bytes.</p>
<p>Encodings sit between between bytes and code points. They consist of rules for translating code points into bytes and bytes into code points. What it implies is that you cannot just take bytes and turn them into a meaningful Unicode string of text without knowing what encoding was used to write the bytes.</p>
<p>Unicode defines several encodings and all of them are designed to support the full range of all possible code points across all planes. Encodings are designated by the &ldquo;UTF&rdquo; prefix, which stands for &ldquo;Unicode Transformation Format&rdquo;</p>
<h3 id="utf-32">UTF-32</h3>
<p>UTF-32 is the simplest and most straightforward of all Unicode encodings. It&rsquo;s a fixed-length encoding where each code point is encoded over 32 bits. The U+ value of a code point is directly converted into bytes with the same value:</p>
<table>
<thead>
<tr>
<th>Number of bytes</th>
<th>Bits for code point</th>
<th>First code point</th>
<th>Last code point</th>
<th>Byte 1</th>
<th>Byte 2</th>
<th>Byte 3</th>
<th>Byte 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>4</td>
<td>21</td>
<td>U+0000</td>
<td>U+10FFFF</td>
<td>00000000 (0x00)</td>
<td>000xxxxx</td>
<td>xxxxxxxx</td>
<td>xxxxxxxx</td>
</tr>
</tbody>
</table>
<p>Because there are &ldquo;only&rdquo; over one million Unicode code points but that 32 bits can represent up to 4 billion values, 11 bits are always set to 0. This makes UTF-32 an extremely wasteful encoding.</p>
<p>One useful purpose for it is to trivially index a code point in a string of bytes: the code point at index <code>n</code> is simply the n<sup>th</sup> 32-bit chunk in your string. But there&rsquo;s little practical use to this: Unicode code points may combine with adjacent ones to form the actual <a href="https://en.wikipedia.org/wiki/Grapheme">grapheme</a>, which is the unit of text that is truly meaningful to end users.</p>
<h4 id="example">Example</h4>
<p>Here&rsquo;s an example of select code points and how they are encoded into bytes using UTF-32:</p>
<table>
<thead>
<tr>
<th>Code point</th>
<th>Name</th>
<th>Glyph</th>
<th>Byte 1</th>
<th>Byte 2</th>
<th>Byte 3</th>
<th>Byte 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>U+61</td>
<td>LATIN SMALL LETTER A</td>
<td>a</td>
<td>0x00</td>
<td>0x00</td>
<td>0x00</td>
<td>0x61</td>
</tr>
<tr>
<td>U+27A4</td>
<td>BLACK RIGHTWARDS ARROWHEAD</td>
<td>➤</td>
<td>0x00</td>
<td>0x00</td>
<td>0x27</td>
<td>0xA4</td>
</tr>
<tr>
<td>U+130E6</td>
<td>EGYPTIAN HIEROGLYPH E017A</td>
<td>𓃦</td>
<td>0x00</td>
<td>0x01</td>
<td>0x30</td>
<td>0xE6</td>
</tr>
<tr>
<td>U+1F60D</td>
<td>SMILING FACE WITH HEART-SHAPED EYES</td>
<td>😍</td>
<td>0x00</td>
<td>0x01</td>
<td>0xF6</td>
<td>0x0D</td>
</tr>
</tbody>
</table>
<h3 id="utf-16">UTF-16</h3>
<p>UTF-16 is a more complex form of encoding, perhaps the most peculiar of all Unicode encodings. It&rsquo;s a variable-length encoding with 16-bit chunks: a given code point may be encoded using one or two chunks. As with other encodings, it supports all Unicode code points and follows the following structure:</p>
<table>
<thead>
<tr>
<th>Number of bytes</th>
<th>Bits for code point</th>
<th>First code point</th>
<th>Last code point</th>
<th>Byte 1</th>
<th>Byte 2</th>
<th>Byte 3</th>
<th>Byte 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>2</td>
<td>0</td>
<td>U+0000</td>
<td>U+D7FF</td>
<td>xxxxxxxx</td>
<td>xxxxxxxx</td>
<td></td>
<td></td>
</tr>
<tr>
<td>N/A</td>
<td>N/A</td>
<td>U+D800</td>
<td>U+DFFF</td>
<td>N/A</td>
<td>N/A</td>
<td>N/A</td>
<td>N/A</td>
</tr>
<tr>
<td>2</td>
<td>0</td>
<td>U+E000</td>
<td>U+FFFF</td>
<td>xxxxxxxx</td>
<td>xxxxxxxx</td>
<td></td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>20</td>
<td>U+10000</td>
<td>U+10FFFF</td>
<td>110110xx</td>
<td>xxxxxxxx</td>
<td>110111xx</td>
<td>xxxxxxxx</td>
</tr>
</tbody>
</table>
<p>The reason UTF-16 is more complex than other encodings lies in its tight coupling with the definition of the character set itself. At the beginning of this article, I said that Unicode&rsquo;s greatest insight was the decoupling between characters and bytes: this is true today but was not always the case.</p>
<h4 id="the-reason-behind-the-17-planes">The reason behind the 17 planes</h4>
<p>In its very first version, Unicode defined a single plane of 65,536 elements and the UTF-16 encoding was a direct map from U numbers to bytes — this was a very simple architectural choice for implementors of the standard to follow.</p>
<p>When the BMP started running short of space and that the need to grow beyond it became clear, Unicode was confronted with a choice:</p>
<ul>
<li>Deprecate UTF-16 and define a new encoding that would cover the new full breadth of the new space. This has the downside asking implementors to roll out and adopt a brand new encoding.</li>
<li>Define a scheme that would make the encoding more complex but allow backwards compatibility with existing implementations.</li>
</ul>
<p>The Unicode Consortium chose the latter option: out the already packed BMP, the standard would reserve a range of 2,048 code points that would be guaranteed to never be allocated: U+D800 → U+DFFF. This space would instead be used create an index for pointing at code points outside of the BMP.</p>
<p>UTF-16 needed to remain an encoding where chunks would take 16 bits each. Characters beyond the BMP would necessarily take at least 2 16-bit chunks to be represented: UTF-16 calls those chunk surrogate <em>pairs</em>: this required further dividing the 2,048 block in 2 blocks of 1,024 values each: U+D800 → U+DBFF and U+DC00 → U+DFFF: one for the high surrogate and one for the low surrogate.</p>
<p>1,024 values requires 10 significant bits to represent, which means that a single 1,024 block is able to map to 2<sup>10</sup> values. Since there are 2 blocks, their indexing powers are multiplied and bring the total of supplementary code points to 2<sup>10</sup> × 2<sup>10</sup> = 2<sup>20</sup>.</p>
<p>In other words, sacrificing just over two thousand code points in the BMP opened up the space for 2<sup>20</sup> brand new code points. Since a plane contains 2<sup>16</sup> code points, the total number of planes outside of the BMP is 2<sup>20</sup> ÷ 2<sup>16</sup> = 2<sup>4</sup> = 16, bringing the total count of planes to 17.</p>
<p>Even though the scheme was first published in 1996 in Unicode 2.0, it took until 2004 for implementors such as Sun to surface this new mechanism to developers in Java 1.5.</p>
<p>That&rsquo;s the secret of UTF-16, and the reason it is tightly coupled to the Unicode standard itself: The U+D800 → U+DFFF range of code points is guaranteed by the standard to never be assigned and its values are instead used for indexing characters outside the BMP, but exclusively for the purpose of allowing UTF-16 do do to (neither UTF-32 nor UTF-8 have that problem). When this is needed, the two resulting 16-bit chunks are called a surrogate pair.</p>
<h4 id="the-utf-16-scheme">The UTF-16 scheme</h4>
<p>To encode a character in non-BMP planes requires some bit fiddling:</p>
<ol>
<li>Take the U-value of the code point and map it to bytes, e.g. U+1F976 → 0x1F976</li>
<li>Subtract 0x10000 (65536) — since the maximum code point value is U+10FFFF (1114111), the range of the remaining value is 0x0–0xFFFFF (0–1048575)
<ol>
<li>Left-pad the value with 0, up to to 20 bits</li>
<li>Take the high ten bits of that value (range 0x000–0x3FF, 0–1023) and add 0xD800 (55296) to form the <em>high surrogate</em> (range 0xD800-0xDBFF, 55296–56319)</li>
<li>Take the low ten bits of that value (also in range 0x000–0x3FF) and add 0xDC00 (56320) to form the <em>low surrogate</em> (range 0xDC00–0xDFFF, 56320–57343)</li>
</ol>
</li>
</ol>
<h4 id="properties">Properties</h4>
<p>UTF-16 has properties that make it a good general purpose encoding. Primarily, any code point in the BMP will be encoded over 16 bits: this is a use case that covers most language on Earth in a decently low number of bits. Second, despite the apparent complexity the encoding rules, decoding a UTF-16 stream is relatively simple to implement in code: if a chunk is in the high surrogate range, consume another chunk and combine the two.</p>
<h4 id="examples">Examples</h4>
<p>Below is an example of the same code points being encoded to UTF-16<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>:</p>
<table>
<thead>
<tr>
<th>Code point</th>
<th>Name</th>
<th>Glyph</th>
<th>Byte 1</th>
<th>Byte 2</th>
<th>Byte 3</th>
<th>Byte 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>U+61</td>
<td>LATIN SMALL LETTER A</td>
<td>a</td>
<td>0x00</td>
<td>0x61</td>
<td></td>
<td></td>
</tr>
<tr>
<td>U+27A4</td>
<td>BLACK RIGHTWARDS ARROWHEAD</td>
<td>➤</td>
<td>0x27</td>
<td>0xA4</td>
<td></td>
<td></td>
</tr>
<tr>
<td>U+130E6</td>
<td>EGYPTIAN HIEROGLYPH E017A</td>
<td>𓃦</td>
<td>0xD8</td>
<td>0x0C</td>
<td>0xDC</td>
<td>0xE6</td>
</tr>
<tr>
<td>U+1F60D</td>
<td>SMILING FACE WITH HEART-SHAPED EYES</td>
<td>😍</td>
<td>0xD8</td>
<td>0x3D</td>
<td>0xDE</td>
<td>0x0D</td>
</tr>
</tbody>
</table>
<h3 id="utf-8">UTF-8</h3>
<p>UTF-8 is by far the most popular of Unicode encodings and the one most developers are familiar with. Like UTF-16, it is a variable-length encoding where code points are encoded using chunks of 1 byte (8 bits). Just like other Unicode encodings, any code point may be encoded and decoded using UTF-8. The scheme for encoding a code point into UTF-8 is as follows. UTF-8 divides the set of code points in four contiguous ranges and maps them to be represented over 1, 2, 3 or 4 bytes:</p>
<table>
<thead>
<tr>
<th>Number of bytes</th>
<th>Bits for code point</th>
<th>First code point</th>
<th>Last code point</th>
<th>Byte 1</th>
<th>Byte 2</th>
<th>Byte 3</th>
<th>Byte 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>7</td>
<td>U+0000</td>
<td>U+007F</td>
<td>0xxxxxxx</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>11</td>
<td>U+0080</td>
<td>U+07FF</td>
<td>110xxxxx (0xC0)</td>
<td>10xxxxxx</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>16</td>
<td>U+0800</td>
<td>U+FFFF</td>
<td>1110xxxx (0xE0)</td>
<td>10xxxxxx</td>
<td>10xxxxxx</td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>21</td>
<td>U+10000</td>
<td>U+10FFFF</td>
<td>11110xxx (0xF0)</td>
<td>10xxxxxx</td>
<td>10xxxxxx</td>
<td>10xxxxxx</td>
</tr>
</tbody>
</table>
<p>Encoding a code point is a relatively simple task, especially compared to UTF-16. Let&rsquo;s take U+801 <code>SAMARITAN LETTER BIT</code> (ࠁ) as an example.</p>
<ol>
<li>From the code point, determine the number of bytes needed to encode it using the ranges in the table above (3 bytes in this case)</li>
<li>Take the U number of the code point and turn it into binary U+801 → 0x801 = 0b100000000001</li>
<li>Pad left with 0s to reach the target number of bytes, which is 16 in our case: 0b100000000001 → 0b0000100000000001</li>
<li>Fill in the blanks starting from the left:
<ol>
<li>The first byte will take the form 0b11xxxxxx → 0b11100000 (0xE0)</li>
<li>The second byte will take the form 0b10xxxxxx → 0b10100000 (0xA0)</li>
<li>The third byte will take the form 0b10xxxxxx → 0b10000001 (0x81)</li>
</ol>
</li>
</ol>
<p>Decoding UTF-8 is also relatively simple, as the first bytes tells you how many bytes are expected to participate in the encoding of the code point.</p>
<p>As of 2020, UTF-8 is <em>by far</em> the most popular form of encoding for text. There are a few reasons for this, but the obvious one is the encoding&rsquo;s backwards compatibility with ASCII. ASCII is a Latin-centric codec which was incredibly popular in the early days of computing and was still in use through the 2010&rsquo;s To this day, it is still fairly common for programs written today to special case characters that are outside the set of characters defined in ASCII.</p>
<p>The genius of UTF-8 is that any valid ASCII content is naturally valid UTF-8 content. In other words, a file written as ASCII text when the standard was initially published in 1963 (almost 60 years ago!) can be read by a program interpreting it as UTF-8 in 2020.</p>
<p>On the Web, this encoding went from being used by ~5% of pages in 2006 to under just 65% in 2012 and 95% in 2020. UTF-8 benefited from being the recommended encoding for HTML5 documents, JSON, and a variety of other formats and standards. It is also the internal encoding for strings in the Go and Rust programming languages.</p>
<p>The following table shows the encoded values of the same code points used in the previous examples:</p>
<table>
<thead>
<tr>
<th>Code point</th>
<th>Name</th>
<th>Glyph</th>
<th>Byte 1</th>
<th>Byte 2</th>
<th>Byte 3</th>
<th>Byte 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>U+61</td>
<td>LATIN SMALL LETTER A</td>
<td>a</td>
<td>0x61</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>U+27A4</td>
<td>BLACK RIGHTWARDS ARROWHEAD</td>
<td>➤</td>
<td>0xE2</td>
<td>0x9E</td>
<td>0xA4</td>
<td></td>
</tr>
<tr>
<td>U+130E6</td>
<td>EGYPTIAN HIEROGLYPH E017A</td>
<td>𓃦</td>
<td>0xF0</td>
<td>0x93</td>
<td>0x83</td>
<td>0xA6</td>
</tr>
<tr>
<td>U+1F60D</td>
<td>SMILING FACE WITH HEART-SHAPED EYES</td>
<td>😍</td>
<td>0xF0</td>
<td>0x9F</td>
<td>0x98</td>
<td>0x8D</td>
</tr>
</tbody>
</table>
<h3 id="a-note-on-byte-order-marks">A note on byte-order marks</h3>
<p>Whenever a data serialization format encodes data over multiple bytes, the question of <a href="https://en.wikipedia.org/wiki/Endianness">endianness</a> is one that must be addressed. A UTF-16 implementation that would naively rely on the native of the host machine might produce a different output than a machine using the converse endianness mode. This can be an issue for UTF-32 and UTF-16.</p>
<p>To that effect, the Unicode standard defines a code point that has a special status: U+FEFF <code>ZERO WIDTH NO-BREAK SPACE</code>. This code point, which is called a byte-order mark (BOM) is expected to be present as the first characters of byte strings that encode Unicode strings over multiple bytes:</p>
<ul>
<li>Upon encoding a string, encoders would prefix it with the BOM and then run the normal encoding logic in their native endianness</li>
<li>When reading bytes that are expected to encode code point over multiple bytes, decoders would peek the first chunk of bytes:
<ul>
<li>If the result is <code>0xFEFF</code>, the rest of the bytes should be decoded as little-endian</li>
<li>If the result is <code>0xFFFE</code>, the rest of the bytes should be decoded as big-endian</li>
</ul>
</li>
</ul>
<p>This is a step that is generally transparently handled by implementations and that you shouldn&rsquo;t have to pay attention to:</p>
<ul>
<li>UTF-32 would normally require a BOM (encoded on 4 bytes, i.e. <code>0x0000FFFE</code> or <code>0x0000FEFF</code>) but since the encoding is practically never used, implementations are inconsistent and may omit it.</li>
<li>UTF-16 remains a relatively common encoding and most encoders would automatically prefix the BOM to the bytes they produce — this was the case for the Java code used to generate the encoding table above, I chose to omit the BOM from the output but it was actually present.</li>
<li>UTF-8 operates at the byte level, and therefore doesn&rsquo;t need the BOM in either encoding or decoding. It occasionally happens that UTF-16 content that is then serialized into UTF-8 embed a BOM, but implementations are expected to ignore it.</li>
</ul>
<section class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1" role="doc-endnote">
<p>The byte-order mark was omitted from these examples, please refer to the paragraph on byte-order marks later in this article to understand their purpose.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</section>
]]></content>
        </entry>
    
        <entry>
            <title>The Unicode Character Set</title>
            <link href="https://www.eiggen.co/codes/i-love-unicode-character-set/"/>
            <updated>2020-03-18T00:00:00+0000</updated>
            <id>https://www.eiggen.co/codes/i-love-unicode-character-set/</id>
            <content type="html"><![CDATA[ <p>This article is the first in a series intended to demystify the Unicode standard and explore in some depth the aspects that programmers have issues with. It is recommended that you follow the articles in sequence, as the concepts in later articles build upon the ones explained in earlier ones.</p>
<ol>
<li><a href="/codes/i-love-unicode">I � Unicode</a></li>
<li>The Character Set (this article)</li>
<li><a href="/codes/i-love-unicode-encodings">The Encodings</a></li>
<li><a href="/codes/i-love-unicode-algorithms">The Algorithms</a></li>
</ol>
<fieldset>
  <legend>⌘ The Rundown</legend>
  <ol>
    <li>The Unicode character set aims to cover all characters of all scripts in the world, and to assign each of them a number and a name</li>
    <li>Characters in Unicode are named code points, and their number is noted as U+ followed by their index as hexadecimal</li>
    <li>The space in which characters are assigned can host a total of 1,114,112 possible code points, and is divided in 17 <em>planes</em> each containing 65,536 elements</li>
    <li>The first plane is called the Basic Multilingual Plane and contains most characters used by most scripts in the world</li>
    <li>Out of 1,114,112 total possible code points, and as of March 2020, 143,859 are currently allocated to real, usable code points: Unicode has room to grow and does so when it releases a new version</li>
  </ol>
</fieldset>
<p>To understand Unicode&rsquo;s contributions to the space of character sets, it&rsquo;s worth taking a look at what the landscape looked like before it came around:</p>
<ul>
<li>character sets were numerous: over the decades that saw the explosion of enterprise and personal computing, dozens if not hundreds of character sets were defined. Some were defined as pure standards (ASCII, EBCDIC), while others were tied to platforms (Windows 125x, Mac OS Roman)</li>
<li>character sets were limited: they generally targeted regions (&ldquo;ISO 8859-1 Western Europe&rdquo;) or scripts (&ldquo;Windows 1254&rdquo; for Turkish) but none would really be able to capture the full breadth of the world&rsquo;s languages by itself. At best, they defined a few thousand characters</li>
</ul>
<h3 id="space">Space</h3>
<p>Unicode set out to solve those issues by primarily giving itself space: rather than collecting the characters and putting them in a set, Unicode first defined the structure in which the characters would exist: in its first version, the space of all characters was specified as an array of 65,536 elements (2<sup>16</sup>).</p>
<p>As the standard progressed in its task to inventory the world&rsquo;s characters, it became clear that the initial space was going to run out. To that effect, the second major version of Unicode allocated 16 more <em>planes</em>, each having 65,536 elements of their own. The total number of possible characters is 1,114,112 (17 × 65,536)</p>
<p>There are <em>way</em> fewer known characters in all of the world&rsquo;s scripts and languages. From that point on, Unicode had plenty of room to grow.</p>
<p>The very first of the 17 planes is called the Basic Multilingual Plane (BMP) and contains characters that cover most of the written languages on Earth:</p>



  
    <?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 792 792" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;"><path id="Supplement-ary-Private-Use-Area-plane-B" serif:id="Supplement­ary Private Use Area plane B" d="M239.871,604.706l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#979797;stroke:#000;stroke-width:0.24px;"/><path id="Supplement-ary-Private-Use-Area-plane-A" serif:id="Supplement­ary Private Use Area plane A" d="M239.871,591.568l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#989898;stroke:#000;stroke-width:0.24px;"/><path id="Supplement-ary-Special-purpose-Plane" serif:id="Supplement­ary Special-purpose Plane" d="M239.871,538.925l-197.103,111.993l216.325,62.083l197.103,-111.993l-216.325,-62.083Z" style="fill:#d887ce;stroke:#000;stroke-width:0.24px;"/><path id="Plane-13" serif:id="Plane 13" d="M239.871,476.303l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#ebebeb;stroke:#000;stroke-width:0.24px;"/><path id="Plane-12" serif:id="Plane 12" d="M239.871,462.398l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#ebebeb;stroke:#000;stroke-width:0.24px;"/><path id="Plane-11" serif:id="Plane 11" d="M239.871,448.493l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#ebebeb;stroke:#000;stroke-width:0.24px;"/><path id="Plane-10" serif:id="Plane 10" d="M239.871,434.588l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#ebebeb;stroke:#000;stroke-width:0.24px;"/><path id="Plane-9" serif:id="Plane 9" d="M239.871,420.683l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#ebebeb;stroke:#000;stroke-width:0.24px;"/><path id="Plane-8" serif:id="Plane 8" d="M239.871,406.778l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#ebebeb;stroke:#000;stroke-width:0.24px;"/><path id="Plane-7" serif:id="Plane 7" d="M239.871,392.873l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#ebebeb;stroke:#000;stroke-width:0.24px;"/><path id="Plane-6" serif:id="Plane 6" d="M239.871,378.968l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#ebebeb;stroke:#000;stroke-width:0.24px;"/><path id="Plane-5" serif:id="Plane 5" d="M239.871,365.063l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#ebebeb;stroke:#000;stroke-width:0.24px;"/><path id="Plane-4" serif:id="Plane 4" d="M239.871,351.157l-197.103,111.993l216.325,62.083l197.103,-111.993l-216.325,-62.083Z" style="fill:#ebebeb;stroke:#000;stroke-width:0.24px;"/><path id="Tertiary-Ideographic-Plane" serif:id="Tertiary Ideographic Plane" d="M239.871,275.513l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#f5c77c;stroke:#000;stroke-width:0.24px;"/><g transform="matrix(0.24,0,0,0.24,0.578781,-5.47852)"><g transform="matrix(100,0,0,100,2365.66,1388.32)"><path d="M0.226,-0.586l-0.198,0l0,-0.07l0.48,0l0,0.07l-0.198,0l0,0.586l-0.084,0l0,-0.586Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2412.66,1388.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2462.26,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.088l0.003,0c0.017,-0.031 0.037,-0.055 0.06,-0.073c0.024,-0.018 0.05,-0.027 0.078,-0.027c0.019,0 0.037,0.003 0.052,0.01l-0.016,0.072c-0.008,-0.003 -0.015,-0.005 -0.022,-0.006c-0.007,-0.001 -0.015,-0.002 -0.025,-0.002c-0.021,0 -0.042,0.008 -0.064,0.025c-0.023,0.017 -0.042,0.046 -0.059,0.087l0,0.312l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2496.96,1388.32)"><path d="M0.096,-0.419l-0.072,0l0,-0.062l0.076,-0.005l0.01,-0.136l0.069,0l0,0.136l0.131,0l0,0.067l-0.131,0l0,0.27c0,0.03 0.006,0.053 0.017,0.069c0.01,0.017 0.03,0.025 0.058,0.025c0.009,0 0.018,-0.001 0.028,-0.004c0.01,-0.003 0.019,-0.006 0.027,-0.009l0.016,0.062c-0.013,0.005 -0.028,0.009 -0.044,0.012c-0.015,0.004 -0.031,0.006 -0.046,0.006c-0.026,0 -0.048,-0.004 -0.066,-0.012c-0.017,-0.008 -0.032,-0.019 -0.043,-0.033c-0.011,-0.014 -0.018,-0.031 -0.023,-0.051c-0.005,-0.02 -0.007,-0.042 -0.007,-0.066l0,-0.269Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2530.76,1388.32)"><path d="M0.124,-0.586c-0.016,0 -0.029,-0.005 -0.04,-0.015c-0.011,-0.01 -0.017,-0.023 -0.017,-0.038c0,-0.016 0.006,-0.029 0.017,-0.038c0.011,-0.01 0.024,-0.015 0.04,-0.015c0.016,0 0.029,0.005 0.041,0.015c0.01,0.009 0.016,0.022 0.016,0.038c0,0.015 -0.006,0.028 -0.016,0.038c-0.011,0.01 -0.025,0.015 -0.041,0.015Zm-0.042,0.1l0.082,0l0,0.486l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2555.36,1388.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2606.56,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.088l0.003,0c0.017,-0.031 0.037,-0.055 0.06,-0.073c0.024,-0.018 0.05,-0.027 0.078,-0.027c0.019,0 0.037,0.003 0.052,0.01l-0.016,0.072c-0.008,-0.003 -0.015,-0.005 -0.022,-0.006c-0.007,-0.001 -0.015,-0.002 -0.025,-0.002c-0.021,0 -0.042,0.008 -0.064,0.025c-0.023,0.017 -0.042,0.046 -0.059,0.087l0,0.312l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2643.16,1388.32)"><path d="M0.049,0.134c0.005,0.001 0.011,0.003 0.018,0.005c0.007,0.001 0.013,0.002 0.019,0.002c0.028,0 0.051,-0.01 0.068,-0.03c0.018,-0.019 0.032,-0.044 0.042,-0.074l0.011,-0.036l-0.195,-0.487l0.085,0l0.099,0.269c0.007,0.021 0.015,0.044 0.023,0.067c0.009,0.024 0.017,0.047 0.024,0.07l0.004,0c0.007,-0.022 0.014,-0.045 0.021,-0.069c0.007,-0.024 0.013,-0.047 0.02,-0.068l0.087,-0.269l0.08,0l-0.183,0.526c-0.009,0.024 -0.018,0.046 -0.029,0.067c-0.011,0.021 -0.023,0.038 -0.038,0.053c-0.015,0.015 -0.031,0.027 -0.05,0.036c-0.019,0.009 -0.04,0.013 -0.065,0.013c-0.011,0 -0.022,-0.001 -0.031,-0.003c-0.009,-0.001 -0.018,-0.004 -0.026,-0.007l0.016,-0.065Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2710.06,1388.32)"><rect x="0.09" y="-0.656" width="0.083" height="0.656" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2736.36,1388.32)"><path d="M0.047,-0.242c0,-0.039 0.006,-0.075 0.018,-0.107c0.011,-0.031 0.027,-0.058 0.046,-0.08c0.019,-0.022 0.042,-0.039 0.067,-0.051c0.025,-0.012 0.052,-0.018 0.08,-0.018c0.028,0 0.052,0.005 0.073,0.015c0.021,0.01 0.042,0.024 0.063,0.041l-0.004,-0.083l0,-0.187l0.083,0l0,0.712l-0.068,0l-0.007,-0.057l-0.003,0c-0.019,0.019 -0.042,0.035 -0.067,0.049c-0.025,0.013 -0.051,0.02 -0.08,0.02c-0.061,0 -0.11,-0.022 -0.147,-0.066c-0.036,-0.044 -0.054,-0.107 -0.054,-0.188Zm0.085,-0.001c0,0.059 0.012,0.104 0.035,0.137c0.023,0.033 0.056,0.049 0.099,0.049c0.023,0 0.044,-0.006 0.064,-0.017c0.02,-0.011 0.04,-0.027 0.06,-0.05l0,-0.254c-0.021,-0.019 -0.041,-0.032 -0.059,-0.039c-0.02,-0.008 -0.039,-0.012 -0.059,-0.012c-0.019,0 -0.038,0.004 -0.055,0.013c-0.017,0.009 -0.031,0.022 -0.044,0.038c-0.013,0.017 -0.023,0.036 -0.03,0.059c-0.007,0.023 -0.011,0.048 -0.011,0.076Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2791.86,1388.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2841.46,1388.32)"><path d="M0.046,-0.242c0,-0.041 0.006,-0.077 0.019,-0.109c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.021,-0.022 0.045,-0.039 0.071,-0.05c0.027,-0.011 0.056,-0.017 0.086,-0.017c0.03,0 0.058,0.006 0.085,0.017c0.027,0.011 0.051,0.028 0.072,0.05c0.021,0.022 0.037,0.049 0.049,0.08c0.013,0.032 0.019,0.068 0.019,0.109c0,0.04 -0.006,0.076 -0.019,0.107c-0.012,0.032 -0.028,0.059 -0.049,0.081c-0.021,0.021 -0.045,0.038 -0.072,0.049c-0.027,0.011 -0.055,0.017 -0.085,0.017c-0.03,0 -0.059,-0.006 -0.086,-0.017c-0.026,-0.011 -0.05,-0.028 -0.071,-0.049c-0.021,-0.022 -0.037,-0.049 -0.049,-0.081c-0.013,-0.031 -0.019,-0.067 -0.019,-0.107Zm0.085,0c0,0.028 0.003,0.053 0.01,0.076c0.007,0.023 0.016,0.042 0.028,0.058c0.013,0.017 0.028,0.029 0.045,0.038c0.017,0.009 0.036,0.014 0.057,0.014c0.021,0 0.04,-0.005 0.057,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.035 0.029,-0.058c0.007,-0.023 0.01,-0.048 0.01,-0.076c0,-0.028 -0.003,-0.054 -0.01,-0.077c-0.007,-0.022 -0.016,-0.042 -0.029,-0.059c-0.012,-0.017 -0.027,-0.03 -0.044,-0.038c-0.017,-0.01 -0.036,-0.014 -0.057,-0.014c-0.021,0 -0.04,0.005 -0.057,0.014c-0.017,0.008 -0.032,0.021 -0.045,0.038c-0.012,0.017 -0.021,0.037 -0.028,0.059c-0.007,0.023 -0.01,0.049 -0.01,0.077Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2895.66,1388.32)"><path d="M0.117,0.082c0,0.026 0.012,0.047 0.037,0.062c0.025,0.015 0.06,0.023 0.104,0.023c0.023,0 0.044,-0.003 0.064,-0.009c0.019,-0.005 0.035,-0.013 0.048,-0.021c0.013,-0.01 0.024,-0.02 0.031,-0.032c0.007,-0.012 0.011,-0.024 0.011,-0.037c0,-0.023 -0.008,-0.038 -0.025,-0.047c-0.017,-0.009 -0.041,-0.013 -0.073,-0.013l-0.084,0c-0.009,0 -0.019,-0.001 -0.03,-0.002c-0.011,-0.001 -0.022,-0.003 -0.033,-0.006c-0.017,0.013 -0.03,0.026 -0.038,0.04c-0.008,0.014 -0.012,0.028 -0.012,0.042Zm-0.072,0.011c0,-0.021 0.006,-0.04 0.019,-0.059c0.013,-0.019 0.03,-0.036 0.052,-0.051l0,-0.004c-0.012,-0.007 -0.022,-0.018 -0.03,-0.031c-0.009,-0.013 -0.013,-0.029 -0.013,-0.048c0,-0.021 0.006,-0.039 0.017,-0.054c0.011,-0.015 0.023,-0.027 0.036,-0.036l0,-0.004c-0.016,-0.013 -0.03,-0.031 -0.043,-0.053c-0.013,-0.023 -0.02,-0.049 -0.02,-0.078c0,-0.027 0.005,-0.051 0.015,-0.072c0.009,-0.021 0.022,-0.039 0.039,-0.054c0.017,-0.016 0.036,-0.027 0.059,-0.035c0.022,-0.008 0.045,-0.012 0.07,-0.012c0.013,0 0.026,0.001 0.038,0.004c0.011,0.002 0.022,0.005 0.031,0.008l0.169,0l0,0.063l-0.1,0c0.011,0.011 0.021,0.026 0.029,0.043c0.007,0.017 0.011,0.036 0.011,0.057c0,0.026 -0.005,0.049 -0.014,0.071c-0.009,0.02 -0.022,0.038 -0.038,0.052c-0.016,0.015 -0.035,0.026 -0.057,0.034c-0.021,0.008 -0.044,0.012 -0.069,0.012c-0.012,0 -0.024,-0.002 -0.037,-0.005c-0.013,-0.003 -0.025,-0.007 -0.036,-0.012c-0.009,0.007 -0.016,0.016 -0.022,0.025c-0.006,0.009 -0.009,0.02 -0.009,0.033c0,0.015 0.006,0.028 0.018,0.038c0.012,0.01 0.035,0.015 0.068,0.015l0.094,0c0.057,0 0.099,0.009 0.127,0.028c0.029,0.018 0.043,0.047 0.043,0.088c0,0.023 -0.006,0.044 -0.017,0.065c-0.011,0.02 -0.028,0.038 -0.049,0.053c-0.021,0.015 -0.047,0.028 -0.078,0.037c-0.03,0.009 -0.064,0.013 -0.102,0.013c-0.03,0 -0.057,-0.003 -0.082,-0.009c-0.025,-0.005 -0.046,-0.014 -0.064,-0.025c-0.017,-0.011 -0.031,-0.025 -0.041,-0.041c-0.009,-0.016 -0.014,-0.035 -0.014,-0.056Zm0.201,-0.302c0.014,0 0.027,-0.003 0.039,-0.008c0.013,-0.005 0.024,-0.013 0.033,-0.023c0.01,-0.01 0.018,-0.022 0.023,-0.037c0.005,-0.014 0.008,-0.03 0.008,-0.048c0,-0.036 -0.01,-0.064 -0.03,-0.084c-0.02,-0.019 -0.044,-0.029 -0.073,-0.029c-0.029,0 -0.053,0.01 -0.073,0.029c-0.02,0.02 -0.03,0.048 -0.03,0.084c0,0.018 0.003,0.034 0.008,0.048c0.005,0.015 0.013,0.027 0.022,0.037c0.01,0.01 0.021,0.018 0.033,0.023c0.013,0.005 0.026,0.008 0.04,0.008Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2946.06,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.088l0.003,0c0.017,-0.031 0.037,-0.055 0.06,-0.073c0.024,-0.018 0.05,-0.027 0.078,-0.027c0.019,0 0.037,0.003 0.052,0.01l-0.016,0.072c-0.008,-0.003 -0.015,-0.005 -0.022,-0.006c-0.007,-0.001 -0.015,-0.002 -0.025,-0.002c-0.021,0 -0.042,0.008 -0.064,0.025c-0.023,0.017 -0.042,0.046 -0.059,0.087l0,0.312l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2978.26,1388.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3029.46,1388.32)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3084.96,1388.32)"><path d="M0.082,-0.712l0.082,0l0,0.194l-0.003,0.1c0.023,-0.022 0.048,-0.041 0.073,-0.056c0.025,-0.016 0.055,-0.024 0.089,-0.024c0.051,0 0.089,0.016 0.113,0.048c0.023,0.032 0.035,0.079 0.035,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.099c-0.015,-0.021 -0.038,-0.031 -0.07,-0.031c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.712Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3139.36,1388.32)"><path d="M0.124,-0.586c-0.016,0 -0.029,-0.005 -0.04,-0.015c-0.011,-0.01 -0.017,-0.023 -0.017,-0.038c0,-0.016 0.006,-0.029 0.017,-0.038c0.011,-0.01 0.024,-0.015 0.04,-0.015c0.016,0 0.029,0.005 0.041,0.015c0.01,0.009 0.016,0.022 0.016,0.038c0,0.015 -0.006,0.028 -0.016,0.038c-0.011,0.01 -0.025,0.015 -0.041,0.015Zm-0.042,0.1l0.082,0l0,0.486l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3163.96,1388.32)"><path d="M0.046,-0.242c0,-0.041 0.006,-0.077 0.019,-0.109c0.013,-0.031 0.03,-0.058 0.051,-0.08c0.021,-0.022 0.046,-0.039 0.075,-0.05c0.028,-0.011 0.058,-0.017 0.089,-0.017c0.032,0 0.059,0.006 0.082,0.018c0.023,0.011 0.043,0.025 0.06,0.04l-0.041,0.053c-0.015,-0.013 -0.03,-0.023 -0.046,-0.031c-0.015,-0.008 -0.033,-0.012 -0.052,-0.012c-0.022,0 -0.042,0.005 -0.061,0.014c-0.019,0.009 -0.035,0.021 -0.048,0.038c-0.013,0.017 -0.024,0.037 -0.032,0.06c-0.007,0.023 -0.011,0.048 -0.011,0.076c0,0.028 0.004,0.053 0.011,0.076c0.007,0.023 0.017,0.042 0.03,0.059c0.013,0.016 0.029,0.029 0.048,0.038c0.019,0.009 0.039,0.013 0.061,0.013c0.023,0 0.044,-0.005 0.063,-0.014c0.019,-0.01 0.036,-0.022 0.051,-0.035l0.037,0.054c-0.022,0.019 -0.047,0.035 -0.074,0.046c-0.027,0.011 -0.055,0.017 -0.084,0.017c-0.032,0 -0.062,-0.006 -0.09,-0.017c-0.028,-0.011 -0.052,-0.028 -0.073,-0.049c-0.02,-0.022 -0.036,-0.049 -0.048,-0.08c-0.011,-0.032 -0.017,-0.068 -0.017,-0.108Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2970.96,1488.32)"><path d="M0.09,-0.656l0.201,0c0.036,0 0.069,0.003 0.099,0.01c0.03,0.007 0.055,0.018 0.077,0.032c0.02,0.015 0.037,0.035 0.048,0.06c0.012,0.025 0.018,0.055 0.018,0.091c0,0.035 -0.006,0.065 -0.018,0.09c-0.011,0.025 -0.028,0.046 -0.049,0.063c-0.021,0.017 -0.047,0.029 -0.077,0.038c-0.029,0.008 -0.062,0.012 -0.098,0.012l-0.118,0l0,0.26l-0.083,0l0,-0.656Zm0.191,0.328c0.057,0 0.1,-0.011 0.128,-0.032c0.027,-0.022 0.041,-0.056 0.041,-0.103c0,-0.047 -0.014,-0.08 -0.042,-0.098c-0.028,-0.019 -0.07,-0.028 -0.127,-0.028l-0.108,0l0,0.261l0.108,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3028.56,1488.32)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3054.06,1488.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3105.26,1488.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3159.96,1488.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g></g><g transform="matrix(0.24,0,0,0.24,-10.2165,255.909)"><g transform="matrix(100,0,0,100,2561.96,1388.32)"><path d="M0.092,-0.143c0.023,0.025 0.051,0.045 0.083,0.06c0.031,0.015 0.064,0.022 0.098,0.022c0.043,0 0.077,-0.01 0.101,-0.029c0.024,-0.02 0.036,-0.046 0.036,-0.078c0,-0.017 -0.003,-0.031 -0.009,-0.042c-0.005,-0.012 -0.013,-0.022 -0.023,-0.03c-0.009,-0.009 -0.021,-0.016 -0.034,-0.023c-0.013,-0.007 -0.028,-0.014 -0.043,-0.021l-0.094,-0.041c-0.015,-0.007 -0.031,-0.015 -0.047,-0.024c-0.016,-0.009 -0.03,-0.021 -0.043,-0.034c-0.013,-0.013 -0.023,-0.029 -0.031,-0.047c-0.008,-0.019 -0.012,-0.04 -0.012,-0.064c0,-0.025 0.005,-0.048 0.016,-0.069c0.01,-0.021 0.024,-0.04 0.043,-0.055c0.018,-0.016 0.04,-0.028 0.065,-0.037c0.025,-0.009 0.052,-0.013 0.082,-0.013c0.039,0 0.076,0.008 0.109,0.023c0.033,0.015 0.062,0.034 0.085,0.058l-0.045,0.054c-0.02,-0.019 -0.042,-0.034 -0.067,-0.045c-0.024,-0.011 -0.051,-0.017 -0.082,-0.017c-0.037,0 -0.066,0.009 -0.088,0.026c-0.023,0.017 -0.034,0.04 -0.034,0.07c0,0.016 0.003,0.03 0.01,0.041c0.006,0.011 0.014,0.02 0.025,0.029c0.011,0.008 0.022,0.015 0.035,0.022c0.013,0.006 0.026,0.012 0.039,0.017l0.093,0.04c0.019,0.008 0.036,0.017 0.053,0.028c0.017,0.01 0.031,0.022 0.043,0.036c0.012,0.013 0.022,0.029 0.029,0.048c0.007,0.018 0.01,0.039 0.01,0.063c0,0.026 -0.005,0.05 -0.015,0.073c-0.011,0.023 -0.026,0.043 -0.045,0.06c-0.019,0.017 -0.043,0.03 -0.07,0.04c-0.027,0.009 -0.058,0.014 -0.093,0.014c-0.046,0 -0.089,-0.009 -0.128,-0.026c-0.039,-0.017 -0.073,-0.041 -0.102,-0.071l0.05,-0.058Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2615.36,1388.32)"><path d="M0.075,-0.486l0.083,0l0,0.297c0,0.046 0.007,0.079 0.021,0.1c0.015,0.02 0.038,0.03 0.07,0.03c0.025,0 0.048,-0.007 0.067,-0.02c0.019,-0.013 0.041,-0.033 0.064,-0.062l0,-0.345l0.082,0l0,0.486l-0.068,0l-0.007,-0.076l-0.003,0c-0.023,0.027 -0.046,0.048 -0.072,0.064c-0.024,0.016 -0.054,0.024 -0.088,0.024c-0.052,0 -0.09,-0.016 -0.114,-0.048c-0.023,-0.032 -0.035,-0.079 -0.035,-0.142l0,-0.308Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2669.76,1388.32)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2725.26,1388.32)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2780.76,1388.32)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2806.26,1388.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2855.86,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.021,-0.023 0.044,-0.043 0.069,-0.059c0.025,-0.015 0.053,-0.023 0.082,-0.023c0.037,0 0.066,0.008 0.087,0.024c0.021,0.017 0.037,0.04 0.047,0.069c0.025,-0.028 0.051,-0.051 0.076,-0.068c0.026,-0.017 0.054,-0.025 0.084,-0.025c0.05,0 0.087,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.037,-0.03 -0.068,-0.03c-0.037,0 -0.077,0.025 -0.122,0.075l0,0.352l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.099c-0.015,-0.021 -0.038,-0.031 -0.069,-0.031c-0.037,0 -0.077,0.025 -0.122,0.075l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2938.76,1388.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2988.36,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3043.06,1388.32)"><path d="M0.096,-0.419l-0.072,0l0,-0.062l0.076,-0.005l0.01,-0.136l0.069,0l0,0.136l0.131,0l0,0.067l-0.131,0l0,0.27c0,0.03 0.006,0.053 0.017,0.069c0.01,0.017 0.03,0.025 0.058,0.025c0.009,0 0.018,-0.001 0.028,-0.004c0.01,-0.003 0.019,-0.006 0.027,-0.009l0.016,0.062c-0.013,0.005 -0.028,0.009 -0.044,0.012c-0.015,0.004 -0.031,0.006 -0.046,0.006c-0.026,0 -0.048,-0.004 -0.066,-0.012c-0.017,-0.008 -0.032,-0.019 -0.043,-0.033c-0.011,-0.014 -0.018,-0.031 -0.023,-0.051c-0.005,-0.02 -0.007,-0.042 -0.007,-0.066l0,-0.269Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3075.06,1388.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3126.26,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.088l0.003,0c0.017,-0.031 0.037,-0.055 0.06,-0.073c0.024,-0.018 0.05,-0.027 0.078,-0.027c0.019,0 0.037,0.003 0.052,0.01l-0.016,0.072c-0.008,-0.003 -0.015,-0.005 -0.022,-0.006c-0.007,-0.001 -0.015,-0.002 -0.025,-0.002c-0.021,0 -0.042,0.008 -0.064,0.025c-0.023,0.017 -0.042,0.046 -0.059,0.087l0,0.312l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3162.86,1388.32)"><path d="M0.049,0.134c0.005,0.001 0.011,0.003 0.018,0.005c0.007,0.001 0.013,0.002 0.019,0.002c0.028,0 0.051,-0.01 0.068,-0.03c0.018,-0.019 0.032,-0.044 0.042,-0.074l0.011,-0.036l-0.195,-0.487l0.085,0l0.099,0.269c0.007,0.021 0.015,0.044 0.023,0.067c0.009,0.024 0.017,0.047 0.024,0.07l0.004,0c0.007,-0.022 0.014,-0.045 0.021,-0.069c0.007,-0.024 0.013,-0.047 0.02,-0.068l0.087,-0.269l0.08,0l-0.183,0.526c-0.009,0.024 -0.018,0.046 -0.029,0.067c-0.011,0.021 -0.023,0.038 -0.038,0.053c-0.015,0.015 -0.031,0.027 -0.05,0.036c-0.019,0.009 -0.04,0.013 -0.065,0.013c-0.011,0 -0.022,-0.001 -0.031,-0.003c-0.009,-0.001 -0.018,-0.004 -0.026,-0.007l0.016,-0.065Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2527.26,1488.32)"><path d="M0.092,-0.143c0.023,0.025 0.051,0.045 0.083,0.06c0.031,0.015 0.064,0.022 0.098,0.022c0.043,0 0.077,-0.01 0.101,-0.029c0.024,-0.02 0.036,-0.046 0.036,-0.078c0,-0.017 -0.003,-0.031 -0.009,-0.042c-0.005,-0.012 -0.013,-0.022 -0.023,-0.03c-0.009,-0.009 -0.021,-0.016 -0.034,-0.023c-0.013,-0.007 -0.028,-0.014 -0.043,-0.021l-0.094,-0.041c-0.015,-0.007 -0.031,-0.015 -0.047,-0.024c-0.016,-0.009 -0.03,-0.021 -0.043,-0.034c-0.013,-0.013 -0.023,-0.029 -0.031,-0.047c-0.008,-0.019 -0.012,-0.04 -0.012,-0.064c0,-0.025 0.005,-0.048 0.016,-0.069c0.01,-0.021 0.024,-0.04 0.043,-0.055c0.018,-0.016 0.04,-0.028 0.065,-0.037c0.025,-0.009 0.052,-0.013 0.082,-0.013c0.039,0 0.076,0.008 0.109,0.023c0.033,0.015 0.062,0.034 0.085,0.058l-0.045,0.054c-0.02,-0.019 -0.042,-0.034 -0.067,-0.045c-0.024,-0.011 -0.051,-0.017 -0.082,-0.017c-0.037,0 -0.066,0.009 -0.088,0.026c-0.023,0.017 -0.034,0.04 -0.034,0.07c0,0.016 0.003,0.03 0.01,0.041c0.006,0.011 0.014,0.02 0.025,0.029c0.011,0.008 0.022,0.015 0.035,0.022c0.013,0.006 0.026,0.012 0.039,0.017l0.093,0.04c0.019,0.008 0.036,0.017 0.053,0.028c0.017,0.01 0.031,0.022 0.043,0.036c0.012,0.013 0.022,0.029 0.029,0.048c0.007,0.018 0.01,0.039 0.01,0.063c0,0.026 -0.005,0.05 -0.015,0.073c-0.011,0.023 -0.026,0.043 -0.045,0.06c-0.019,0.017 -0.043,0.03 -0.07,0.04c-0.027,0.009 -0.058,0.014 -0.093,0.014c-0.046,0 -0.089,-0.009 -0.128,-0.026c-0.039,-0.017 -0.073,-0.041 -0.102,-0.071l0.05,-0.058Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2580.66,1488.32)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2636.16,1488.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2685.76,1488.32)"><path d="M0.046,-0.242c0,-0.041 0.006,-0.077 0.019,-0.109c0.013,-0.031 0.03,-0.058 0.051,-0.08c0.021,-0.022 0.046,-0.039 0.075,-0.05c0.028,-0.011 0.058,-0.017 0.089,-0.017c0.032,0 0.059,0.006 0.082,0.018c0.023,0.011 0.043,0.025 0.06,0.04l-0.041,0.053c-0.015,-0.013 -0.03,-0.023 -0.046,-0.031c-0.015,-0.008 -0.033,-0.012 -0.052,-0.012c-0.022,0 -0.042,0.005 -0.061,0.014c-0.019,0.009 -0.035,0.021 -0.048,0.038c-0.013,0.017 -0.024,0.037 -0.032,0.06c-0.007,0.023 -0.011,0.048 -0.011,0.076c0,0.028 0.004,0.053 0.011,0.076c0.007,0.023 0.017,0.042 0.03,0.059c0.013,0.016 0.029,0.029 0.048,0.038c0.019,0.009 0.039,0.013 0.061,0.013c0.023,0 0.044,-0.005 0.063,-0.014c0.019,-0.01 0.036,-0.022 0.051,-0.035l0.037,0.054c-0.022,0.019 -0.047,0.035 -0.074,0.046c-0.027,0.011 -0.055,0.017 -0.084,0.017c-0.032,0 -0.062,-0.006 -0.09,-0.017c-0.028,-0.011 -0.052,-0.028 -0.073,-0.049c-0.02,-0.022 -0.036,-0.049 -0.048,-0.08c-0.011,-0.032 -0.017,-0.068 -0.017,-0.108Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2731.36,1488.32)"><path d="M0.124,-0.586c-0.016,0 -0.029,-0.005 -0.04,-0.015c-0.011,-0.01 -0.017,-0.023 -0.017,-0.038c0,-0.016 0.006,-0.029 0.017,-0.038c0.011,-0.01 0.024,-0.015 0.04,-0.015c0.016,0 0.029,0.005 0.041,0.015c0.01,0.009 0.016,0.022 0.016,0.038c0,0.015 -0.006,0.028 -0.016,0.038c-0.011,0.01 -0.025,0.015 -0.041,0.015Zm-0.042,0.1l0.082,0l0,0.486l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2755.96,1488.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2807.16,1488.32)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2832.66,1488.32)"><rect x="0.041" y="-0.282" width="0.23" height="0.063" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2863.76,1488.32)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2919.26,1488.32)"><path d="M0.075,-0.486l0.083,0l0,0.297c0,0.046 0.007,0.079 0.021,0.1c0.015,0.02 0.038,0.03 0.07,0.03c0.025,0 0.048,-0.007 0.067,-0.02c0.019,-0.013 0.041,-0.033 0.064,-0.062l0,-0.345l0.082,0l0,0.486l-0.068,0l-0.007,-0.076l-0.003,0c-0.023,0.027 -0.046,0.048 -0.072,0.064c-0.024,0.016 -0.054,0.024 -0.088,0.024c-0.052,0 -0.09,-0.016 -0.114,-0.048c-0.023,-0.032 -0.035,-0.079 -0.035,-0.142l0,-0.308Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2973.66,1488.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.088l0.003,0c0.017,-0.031 0.037,-0.055 0.06,-0.073c0.024,-0.018 0.05,-0.027 0.078,-0.027c0.019,0 0.037,0.003 0.052,0.01l-0.016,0.072c-0.008,-0.003 -0.015,-0.005 -0.022,-0.006c-0.007,-0.001 -0.015,-0.002 -0.025,-0.002c-0.021,0 -0.042,0.008 -0.064,0.025c-0.023,0.017 -0.042,0.046 -0.059,0.087l0,0.312l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3008.36,1488.32)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3063.86,1488.32)"><path d="M0.046,-0.242c0,-0.041 0.006,-0.077 0.019,-0.109c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.021,-0.022 0.045,-0.039 0.071,-0.05c0.027,-0.011 0.056,-0.017 0.086,-0.017c0.03,0 0.058,0.006 0.085,0.017c0.027,0.011 0.051,0.028 0.072,0.05c0.021,0.022 0.037,0.049 0.049,0.08c0.013,0.032 0.019,0.068 0.019,0.109c0,0.04 -0.006,0.076 -0.019,0.107c-0.012,0.032 -0.028,0.059 -0.049,0.081c-0.021,0.021 -0.045,0.038 -0.072,0.049c-0.027,0.011 -0.055,0.017 -0.085,0.017c-0.03,0 -0.059,-0.006 -0.086,-0.017c-0.026,-0.011 -0.05,-0.028 -0.071,-0.049c-0.021,-0.022 -0.037,-0.049 -0.049,-0.081c-0.013,-0.031 -0.019,-0.067 -0.019,-0.107Zm0.085,0c0,0.028 0.003,0.053 0.01,0.076c0.007,0.023 0.016,0.042 0.028,0.058c0.013,0.017 0.028,0.029 0.045,0.038c0.017,0.009 0.036,0.014 0.057,0.014c0.021,0 0.04,-0.005 0.057,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.035 0.029,-0.058c0.007,-0.023 0.01,-0.048 0.01,-0.076c0,-0.028 -0.003,-0.054 -0.01,-0.077c-0.007,-0.022 -0.016,-0.042 -0.029,-0.059c-0.012,-0.017 -0.027,-0.03 -0.044,-0.038c-0.017,-0.01 -0.036,-0.014 -0.057,-0.014c-0.021,0 -0.04,0.005 -0.057,0.014c-0.017,0.008 -0.032,0.021 -0.045,0.038c-0.012,0.017 -0.021,0.037 -0.028,0.059c-0.007,0.023 -0.01,0.049 -0.01,0.077Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3118.06,1488.32)"><path d="M0.069,-0.11c0.021,0.017 0.043,0.031 0.066,0.042c0.022,0.011 0.048,0.016 0.077,0.016c0.032,0 0.056,-0.007 0.072,-0.022c0.016,-0.015 0.024,-0.033 0.024,-0.054c0,-0.013 -0.003,-0.024 -0.01,-0.033c-0.007,-0.009 -0.015,-0.018 -0.026,-0.024c-0.01,-0.008 -0.022,-0.014 -0.035,-0.019c-0.013,-0.005 -0.027,-0.011 -0.04,-0.016c-0.017,-0.006 -0.035,-0.013 -0.052,-0.021c-0.017,-0.007 -0.033,-0.017 -0.047,-0.028c-0.013,-0.011 -0.024,-0.023 -0.033,-0.038c-0.009,-0.015 -0.013,-0.032 -0.013,-0.053c0,-0.019 0.004,-0.038 0.011,-0.055c0.008,-0.017 0.019,-0.031 0.033,-0.044c0.015,-0.012 0.032,-0.022 0.053,-0.029c0.021,-0.007 0.044,-0.01 0.07,-0.01c0.031,0 0.059,0.005 0.084,0.016c0.026,0.011 0.048,0.024 0.067,0.039l-0.039,0.052c-0.017,-0.013 -0.034,-0.023 -0.052,-0.031c-0.018,-0.008 -0.038,-0.012 -0.059,-0.012c-0.031,0 -0.053,0.007 -0.068,0.021c-0.014,0.014 -0.021,0.03 -0.021,0.049c0,0.011 0.003,0.021 0.009,0.029c0.006,0.009 0.014,0.016 0.024,0.022c0.01,0.007 0.021,0.012 0.034,0.017c0.013,0.005 0.027,0.011 0.041,0.016c0.017,0.007 0.035,0.014 0.052,0.021c0.018,0.007 0.034,0.016 0.048,0.027c0.014,0.011 0.025,0.025 0.034,0.041c0.009,0.016 0.014,0.035 0.014,0.058c0,0.02 -0.004,0.039 -0.012,0.056c-0.007,0.017 -0.019,0.033 -0.034,0.046c-0.015,0.013 -0.033,0.024 -0.056,0.031c-0.022,0.008 -0.047,0.012 -0.076,0.012c-0.035,0 -0.068,-0.006 -0.099,-0.019c-0.031,-0.013 -0.059,-0.029 -0.082,-0.048l0.041,-0.055Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3159.96,1488.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2970.96,1588.32)"><path d="M0.09,-0.656l0.201,0c0.036,0 0.069,0.003 0.099,0.01c0.03,0.007 0.055,0.018 0.077,0.032c0.02,0.015 0.037,0.035 0.048,0.06c0.012,0.025 0.018,0.055 0.018,0.091c0,0.035 -0.006,0.065 -0.018,0.09c-0.011,0.025 -0.028,0.046 -0.049,0.063c-0.021,0.017 -0.047,0.029 -0.077,0.038c-0.029,0.008 -0.062,0.012 -0.098,0.012l-0.118,0l0,0.26l-0.083,0l0,-0.656Zm0.191,0.328c0.057,0 0.1,-0.011 0.128,-0.032c0.027,-0.022 0.041,-0.056 0.041,-0.103c0,-0.047 -0.014,-0.08 -0.042,-0.098c-0.028,-0.019 -0.07,-0.028 -0.127,-0.028l-0.108,0l0,0.261l0.108,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3028.56,1588.32)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3054.06,1588.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3105.26,1588.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3159.96,1588.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g></g><g transform="matrix(0.24,0,0,0.24,-10.2165,362.496)"><g transform="matrix(100,0,0,100,2561.96,1388.32)"><path d="M0.092,-0.143c0.023,0.025 0.051,0.045 0.083,0.06c0.031,0.015 0.064,0.022 0.098,0.022c0.043,0 0.077,-0.01 0.101,-0.029c0.024,-0.02 0.036,-0.046 0.036,-0.078c0,-0.017 -0.003,-0.031 -0.009,-0.042c-0.005,-0.012 -0.013,-0.022 -0.023,-0.03c-0.009,-0.009 -0.021,-0.016 -0.034,-0.023c-0.013,-0.007 -0.028,-0.014 -0.043,-0.021l-0.094,-0.041c-0.015,-0.007 -0.031,-0.015 -0.047,-0.024c-0.016,-0.009 -0.03,-0.021 -0.043,-0.034c-0.013,-0.013 -0.023,-0.029 -0.031,-0.047c-0.008,-0.019 -0.012,-0.04 -0.012,-0.064c0,-0.025 0.005,-0.048 0.016,-0.069c0.01,-0.021 0.024,-0.04 0.043,-0.055c0.018,-0.016 0.04,-0.028 0.065,-0.037c0.025,-0.009 0.052,-0.013 0.082,-0.013c0.039,0 0.076,0.008 0.109,0.023c0.033,0.015 0.062,0.034 0.085,0.058l-0.045,0.054c-0.02,-0.019 -0.042,-0.034 -0.067,-0.045c-0.024,-0.011 -0.051,-0.017 -0.082,-0.017c-0.037,0 -0.066,0.009 -0.088,0.026c-0.023,0.017 -0.034,0.04 -0.034,0.07c0,0.016 0.003,0.03 0.01,0.041c0.006,0.011 0.014,0.02 0.025,0.029c0.011,0.008 0.022,0.015 0.035,0.022c0.013,0.006 0.026,0.012 0.039,0.017l0.093,0.04c0.019,0.008 0.036,0.017 0.053,0.028c0.017,0.01 0.031,0.022 0.043,0.036c0.012,0.013 0.022,0.029 0.029,0.048c0.007,0.018 0.01,0.039 0.01,0.063c0,0.026 -0.005,0.05 -0.015,0.073c-0.011,0.023 -0.026,0.043 -0.045,0.06c-0.019,0.017 -0.043,0.03 -0.07,0.04c-0.027,0.009 -0.058,0.014 -0.093,0.014c-0.046,0 -0.089,-0.009 -0.128,-0.026c-0.039,-0.017 -0.073,-0.041 -0.102,-0.071l0.05,-0.058Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2615.36,1388.32)"><path d="M0.075,-0.486l0.083,0l0,0.297c0,0.046 0.007,0.079 0.021,0.1c0.015,0.02 0.038,0.03 0.07,0.03c0.025,0 0.048,-0.007 0.067,-0.02c0.019,-0.013 0.041,-0.033 0.064,-0.062l0,-0.345l0.082,0l0,0.486l-0.068,0l-0.007,-0.076l-0.003,0c-0.023,0.027 -0.046,0.048 -0.072,0.064c-0.024,0.016 -0.054,0.024 -0.088,0.024c-0.052,0 -0.09,-0.016 -0.114,-0.048c-0.023,-0.032 -0.035,-0.079 -0.035,-0.142l0,-0.308Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2669.76,1388.32)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2725.26,1388.32)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2780.76,1388.32)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2806.26,1388.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2855.86,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.021,-0.023 0.044,-0.043 0.069,-0.059c0.025,-0.015 0.053,-0.023 0.082,-0.023c0.037,0 0.066,0.008 0.087,0.024c0.021,0.017 0.037,0.04 0.047,0.069c0.025,-0.028 0.051,-0.051 0.076,-0.068c0.026,-0.017 0.054,-0.025 0.084,-0.025c0.05,0 0.087,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.037,-0.03 -0.068,-0.03c-0.037,0 -0.077,0.025 -0.122,0.075l0,0.352l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.099c-0.015,-0.021 -0.038,-0.031 -0.069,-0.031c-0.037,0 -0.077,0.025 -0.122,0.075l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2938.76,1388.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2988.36,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3043.06,1388.32)"><path d="M0.096,-0.419l-0.072,0l0,-0.062l0.076,-0.005l0.01,-0.136l0.069,0l0,0.136l0.131,0l0,0.067l-0.131,0l0,0.27c0,0.03 0.006,0.053 0.017,0.069c0.01,0.017 0.03,0.025 0.058,0.025c0.009,0 0.018,-0.001 0.028,-0.004c0.01,-0.003 0.019,-0.006 0.027,-0.009l0.016,0.062c-0.013,0.005 -0.028,0.009 -0.044,0.012c-0.015,0.004 -0.031,0.006 -0.046,0.006c-0.026,0 -0.048,-0.004 -0.066,-0.012c-0.017,-0.008 -0.032,-0.019 -0.043,-0.033c-0.011,-0.014 -0.018,-0.031 -0.023,-0.051c-0.005,-0.02 -0.007,-0.042 -0.007,-0.066l0,-0.269Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3075.06,1388.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3126.26,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.088l0.003,0c0.017,-0.031 0.037,-0.055 0.06,-0.073c0.024,-0.018 0.05,-0.027 0.078,-0.027c0.019,0 0.037,0.003 0.052,0.01l-0.016,0.072c-0.008,-0.003 -0.015,-0.005 -0.022,-0.006c-0.007,-0.001 -0.015,-0.002 -0.025,-0.002c-0.021,0 -0.042,0.008 -0.064,0.025c-0.023,0.017 -0.042,0.046 -0.059,0.087l0,0.312l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3162.86,1388.32)"><path d="M0.049,0.134c0.005,0.001 0.011,0.003 0.018,0.005c0.007,0.001 0.013,0.002 0.019,0.002c0.028,0 0.051,-0.01 0.068,-0.03c0.018,-0.019 0.032,-0.044 0.042,-0.074l0.011,-0.036l-0.195,-0.487l0.085,0l0.099,0.269c0.007,0.021 0.015,0.044 0.023,0.067c0.009,0.024 0.017,0.047 0.024,0.07l0.004,0c0.007,-0.022 0.014,-0.045 0.021,-0.069c0.007,-0.024 0.013,-0.047 0.02,-0.068l0.087,-0.269l0.08,0l-0.183,0.526c-0.009,0.024 -0.018,0.046 -0.029,0.067c-0.011,0.021 -0.023,0.038 -0.038,0.053c-0.015,0.015 -0.031,0.027 -0.05,0.036c-0.019,0.009 -0.04,0.013 -0.065,0.013c-0.011,0 -0.022,-0.001 -0.031,-0.003c-0.009,-0.001 -0.018,-0.004 -0.026,-0.007l0.016,-0.065Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2530.86,1488.32)"><path d="M0.09,-0.656l0.201,0c0.036,0 0.069,0.003 0.099,0.01c0.03,0.007 0.055,0.018 0.077,0.032c0.02,0.015 0.037,0.035 0.048,0.06c0.012,0.025 0.018,0.055 0.018,0.091c0,0.035 -0.006,0.065 -0.018,0.09c-0.011,0.025 -0.028,0.046 -0.049,0.063c-0.021,0.017 -0.047,0.029 -0.077,0.038c-0.029,0.008 -0.062,0.012 -0.098,0.012l-0.118,0l0,0.26l-0.083,0l0,-0.656Zm0.191,0.328c0.057,0 0.1,-0.011 0.128,-0.032c0.027,-0.022 0.041,-0.056 0.041,-0.103c0,-0.047 -0.014,-0.08 -0.042,-0.098c-0.028,-0.019 -0.07,-0.028 -0.127,-0.028l-0.108,0l0,0.261l0.108,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2588.46,1488.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.088l0.003,0c0.017,-0.031 0.037,-0.055 0.06,-0.073c0.024,-0.018 0.05,-0.027 0.078,-0.027c0.019,0 0.037,0.003 0.052,0.01l-0.016,0.072c-0.008,-0.003 -0.015,-0.005 -0.022,-0.006c-0.007,-0.001 -0.015,-0.002 -0.025,-0.002c-0.021,0 -0.042,0.008 -0.064,0.025c-0.023,0.017 -0.042,0.046 -0.059,0.087l0,0.312l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2623.16,1488.32)"><path d="M0.124,-0.586c-0.016,0 -0.029,-0.005 -0.04,-0.015c-0.011,-0.01 -0.017,-0.023 -0.017,-0.038c0,-0.016 0.006,-0.029 0.017,-0.038c0.011,-0.01 0.024,-0.015 0.04,-0.015c0.016,0 0.029,0.005 0.041,0.015c0.01,0.009 0.016,0.022 0.016,0.038c0,0.015 -0.006,0.028 -0.016,0.038c-0.011,0.01 -0.025,0.015 -0.041,0.015Zm-0.042,0.1l0.082,0l0,0.486l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2647.76,1488.32)"><path d="M0.012,-0.486l0.085,0l0.092,0.276c0.007,0.024 0.015,0.048 0.022,0.072c0.008,0.024 0.016,0.048 0.023,0.071l0.004,0c0.007,-0.023 0.015,-0.047 0.022,-0.071c0.007,-0.024 0.015,-0.048 0.022,-0.072l0.092,-0.276l0.081,0l-0.172,0.486l-0.096,0l-0.175,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2692.46,1488.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2743.66,1488.32)"><path d="M0.096,-0.419l-0.072,0l0,-0.062l0.076,-0.005l0.01,-0.136l0.069,0l0,0.136l0.131,0l0,0.067l-0.131,0l0,0.27c0,0.03 0.006,0.053 0.017,0.069c0.01,0.017 0.03,0.025 0.058,0.025c0.009,0 0.018,-0.001 0.028,-0.004c0.01,-0.003 0.019,-0.006 0.027,-0.009l0.016,0.062c-0.013,0.005 -0.028,0.009 -0.044,0.012c-0.015,0.004 -0.031,0.006 -0.046,0.006c-0.026,0 -0.048,-0.004 -0.066,-0.012c-0.017,-0.008 -0.032,-0.019 -0.043,-0.033c-0.011,-0.014 -0.018,-0.031 -0.023,-0.051c-0.005,-0.02 -0.007,-0.042 -0.007,-0.066l0,-0.269Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2776.46,1488.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2846.26,1488.32)"><path d="M0.087,-0.656l0.083,0l0,0.387c0,0.039 0.004,0.072 0.012,0.099c0.008,0.027 0.019,0.048 0.032,0.064c0.014,0.016 0.03,0.028 0.049,0.035c0.019,0.007 0.039,0.01 0.06,0.01c0.022,0 0.042,-0.003 0.061,-0.011c0.019,-0.006 0.035,-0.018 0.049,-0.034c0.014,-0.016 0.025,-0.037 0.033,-0.064c0.008,-0.027 0.012,-0.06 0.012,-0.099l0,-0.387l0.08,0l0,0.385c0,0.053 -0.006,0.097 -0.018,0.133c-0.012,0.036 -0.028,0.065 -0.049,0.088c-0.021,0.022 -0.046,0.038 -0.075,0.048c-0.029,0.009 -0.06,0.014 -0.093,0.014c-0.033,0 -0.064,-0.005 -0.093,-0.014c-0.029,-0.01 -0.054,-0.026 -0.075,-0.048c-0.021,-0.023 -0.038,-0.052 -0.05,-0.088c-0.012,-0.036 -0.018,-0.08 -0.018,-0.133l0,-0.385Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2910.36,1488.32)"><path d="M0.069,-0.11c0.021,0.017 0.043,0.031 0.066,0.042c0.022,0.011 0.048,0.016 0.077,0.016c0.032,0 0.056,-0.007 0.072,-0.022c0.016,-0.015 0.024,-0.033 0.024,-0.054c0,-0.013 -0.003,-0.024 -0.01,-0.033c-0.007,-0.009 -0.015,-0.018 -0.026,-0.024c-0.01,-0.008 -0.022,-0.014 -0.035,-0.019c-0.013,-0.005 -0.027,-0.011 -0.04,-0.016c-0.017,-0.006 -0.035,-0.013 -0.052,-0.021c-0.017,-0.007 -0.033,-0.017 -0.047,-0.028c-0.013,-0.011 -0.024,-0.023 -0.033,-0.038c-0.009,-0.015 -0.013,-0.032 -0.013,-0.053c0,-0.019 0.004,-0.038 0.011,-0.055c0.008,-0.017 0.019,-0.031 0.033,-0.044c0.015,-0.012 0.032,-0.022 0.053,-0.029c0.021,-0.007 0.044,-0.01 0.07,-0.01c0.031,0 0.059,0.005 0.084,0.016c0.026,0.011 0.048,0.024 0.067,0.039l-0.039,0.052c-0.017,-0.013 -0.034,-0.023 -0.052,-0.031c-0.018,-0.008 -0.038,-0.012 -0.059,-0.012c-0.031,0 -0.053,0.007 -0.068,0.021c-0.014,0.014 -0.021,0.03 -0.021,0.049c0,0.011 0.003,0.021 0.009,0.029c0.006,0.009 0.014,0.016 0.024,0.022c0.01,0.007 0.021,0.012 0.034,0.017c0.013,0.005 0.027,0.011 0.041,0.016c0.017,0.007 0.035,0.014 0.052,0.021c0.018,0.007 0.034,0.016 0.048,0.027c0.014,0.011 0.025,0.025 0.034,0.041c0.009,0.016 0.014,0.035 0.014,0.058c0,0.02 -0.004,0.039 -0.012,0.056c-0.007,0.017 -0.019,0.033 -0.034,0.046c-0.015,0.013 -0.033,0.024 -0.056,0.031c-0.022,0.008 -0.047,0.012 -0.076,0.012c-0.035,0 -0.068,-0.006 -0.099,-0.019c-0.031,-0.013 -0.059,-0.029 -0.082,-0.048l0.041,-0.055Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2952.26,1488.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3022.06,1488.32)"><path d="M0.369,-0.267l-0.031,-0.1c-0.012,-0.037 -0.023,-0.073 -0.034,-0.11c-0.011,-0.036 -0.021,-0.073 -0.032,-0.111l-0.004,0c-0.01,0.038 -0.02,0.075 -0.031,0.111c-0.011,0.037 -0.022,0.073 -0.034,0.11l-0.031,0.1l0.197,0Zm0.021,0.067l-0.239,0l-0.063,0.2l-0.085,0l0.222,-0.656l0.094,0l0.222,0.656l-0.089,0l-0.062,-0.2Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3076.46,1488.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.088l0.003,0c0.017,-0.031 0.037,-0.055 0.06,-0.073c0.024,-0.018 0.05,-0.027 0.078,-0.027c0.019,0 0.037,0.003 0.052,0.01l-0.016,0.072c-0.008,-0.003 -0.015,-0.005 -0.022,-0.006c-0.007,-0.001 -0.015,-0.002 -0.025,-0.002c-0.021,0 -0.042,0.008 -0.064,0.025c-0.023,0.017 -0.042,0.046 -0.059,0.087l0,0.312l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3110.16,1488.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3158.36,1488.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2929.06,1588.32)"><path d="M0.09,-0.656l0.201,0c0.036,0 0.069,0.003 0.099,0.01c0.03,0.007 0.055,0.018 0.077,0.032c0.02,0.015 0.037,0.035 0.048,0.06c0.012,0.025 0.018,0.055 0.018,0.091c0,0.035 -0.006,0.065 -0.018,0.09c-0.011,0.025 -0.028,0.046 -0.049,0.063c-0.021,0.017 -0.047,0.029 -0.077,0.038c-0.029,0.008 -0.062,0.012 -0.098,0.012l-0.118,0l0,0.26l-0.083,0l0,-0.656Zm0.191,0.328c0.057,0 0.1,-0.011 0.128,-0.032c0.027,-0.022 0.041,-0.056 0.041,-0.103c0,-0.047 -0.014,-0.08 -0.042,-0.098c-0.028,-0.019 -0.07,-0.028 -0.127,-0.028l-0.108,0l0,0.261l0.108,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2986.66,1588.32)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3012.16,1588.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3063.36,1588.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3118.06,1588.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3167.66,1588.32)"><path d="M0.069,-0.11c0.021,0.017 0.043,0.031 0.066,0.042c0.022,0.011 0.048,0.016 0.077,0.016c0.032,0 0.056,-0.007 0.072,-0.022c0.016,-0.015 0.024,-0.033 0.024,-0.054c0,-0.013 -0.003,-0.024 -0.01,-0.033c-0.007,-0.009 -0.015,-0.018 -0.026,-0.024c-0.01,-0.008 -0.022,-0.014 -0.035,-0.019c-0.013,-0.005 -0.027,-0.011 -0.04,-0.016c-0.017,-0.006 -0.035,-0.013 -0.052,-0.021c-0.017,-0.007 -0.033,-0.017 -0.047,-0.028c-0.013,-0.011 -0.024,-0.023 -0.033,-0.038c-0.009,-0.015 -0.013,-0.032 -0.013,-0.053c0,-0.019 0.004,-0.038 0.011,-0.055c0.008,-0.017 0.019,-0.031 0.033,-0.044c0.015,-0.012 0.032,-0.022 0.053,-0.029c0.021,-0.007 0.044,-0.01 0.07,-0.01c0.031,0 0.059,0.005 0.084,0.016c0.026,0.011 0.048,0.024 0.067,0.039l-0.039,0.052c-0.017,-0.013 -0.034,-0.023 -0.052,-0.031c-0.018,-0.008 -0.038,-0.012 -0.059,-0.012c-0.031,0 -0.053,0.007 -0.068,0.021c-0.014,0.014 -0.021,0.03 -0.021,0.049c0,0.011 0.003,0.021 0.009,0.029c0.006,0.009 0.014,0.016 0.024,0.022c0.01,0.007 0.021,0.012 0.034,0.017c0.013,0.005 0.027,0.011 0.041,0.016c0.017,0.007 0.035,0.014 0.052,0.021c0.018,0.007 0.034,0.016 0.048,0.027c0.014,0.011 0.025,0.025 0.034,0.041c0.009,0.016 0.014,0.035 0.014,0.058c0,0.02 -0.004,0.039 -0.012,0.056c-0.007,0.017 -0.019,0.033 -0.034,0.046c-0.015,0.013 -0.033,0.024 -0.056,0.031c-0.022,0.008 -0.047,0.012 -0.076,0.012c-0.035,0 -0.068,-0.006 -0.099,-0.019c-0.031,-0.013 -0.059,-0.029 -0.082,-0.048l0.041,-0.055Z" style="fill-rule:nonzero;"/></g></g><g transform="matrix(0.24,0,0,0.24,0.0674531,140.296)"><g transform="matrix(100,0,0,100,2418.86,1388.32)"><path d="M0.087,-0.656l0.083,0l0,0.387c0,0.039 0.004,0.072 0.012,0.099c0.008,0.027 0.019,0.048 0.032,0.064c0.014,0.016 0.03,0.028 0.049,0.035c0.019,0.007 0.039,0.01 0.06,0.01c0.022,0 0.042,-0.003 0.061,-0.011c0.019,-0.006 0.035,-0.018 0.049,-0.034c0.014,-0.016 0.025,-0.037 0.033,-0.064c0.008,-0.027 0.012,-0.06 0.012,-0.099l0,-0.387l0.08,0l0,0.385c0,0.053 -0.006,0.097 -0.018,0.133c-0.012,0.036 -0.028,0.065 -0.049,0.088c-0.021,0.022 -0.046,0.038 -0.075,0.048c-0.029,0.009 -0.06,0.014 -0.093,0.014c-0.033,0 -0.064,-0.005 -0.093,-0.014c-0.029,-0.01 -0.054,-0.026 -0.075,-0.048c-0.021,-0.023 -0.038,-0.052 -0.05,-0.088c-0.012,-0.036 -0.018,-0.08 -0.018,-0.133l0,-0.385Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2483.36,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2538.06,1388.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2589.26,1388.32)"><path d="M0.069,-0.11c0.021,0.017 0.043,0.031 0.066,0.042c0.022,0.011 0.048,0.016 0.077,0.016c0.032,0 0.056,-0.007 0.072,-0.022c0.016,-0.015 0.024,-0.033 0.024,-0.054c0,-0.013 -0.003,-0.024 -0.01,-0.033c-0.007,-0.009 -0.015,-0.018 -0.026,-0.024c-0.01,-0.008 -0.022,-0.014 -0.035,-0.019c-0.013,-0.005 -0.027,-0.011 -0.04,-0.016c-0.017,-0.006 -0.035,-0.013 -0.052,-0.021c-0.017,-0.007 -0.033,-0.017 -0.047,-0.028c-0.013,-0.011 -0.024,-0.023 -0.033,-0.038c-0.009,-0.015 -0.013,-0.032 -0.013,-0.053c0,-0.019 0.004,-0.038 0.011,-0.055c0.008,-0.017 0.019,-0.031 0.033,-0.044c0.015,-0.012 0.032,-0.022 0.053,-0.029c0.021,-0.007 0.044,-0.01 0.07,-0.01c0.031,0 0.059,0.005 0.084,0.016c0.026,0.011 0.048,0.024 0.067,0.039l-0.039,0.052c-0.017,-0.013 -0.034,-0.023 -0.052,-0.031c-0.018,-0.008 -0.038,-0.012 -0.059,-0.012c-0.031,0 -0.053,0.007 -0.068,0.021c-0.014,0.014 -0.021,0.03 -0.021,0.049c0,0.011 0.003,0.021 0.009,0.029c0.006,0.009 0.014,0.016 0.024,0.022c0.01,0.007 0.021,0.012 0.034,0.017c0.013,0.005 0.027,0.011 0.041,0.016c0.017,0.007 0.035,0.014 0.052,0.021c0.018,0.007 0.034,0.016 0.048,0.027c0.014,0.011 0.025,0.025 0.034,0.041c0.009,0.016 0.014,0.035 0.014,0.058c0,0.02 -0.004,0.039 -0.012,0.056c-0.007,0.017 -0.019,0.033 -0.034,0.046c-0.015,0.013 -0.033,0.024 -0.056,0.031c-0.022,0.008 -0.047,0.012 -0.076,0.012c-0.035,0 -0.068,-0.006 -0.099,-0.019c-0.031,-0.013 -0.059,-0.029 -0.082,-0.048l0.041,-0.055Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2631.16,1388.32)"><path d="M0.069,-0.11c0.021,0.017 0.043,0.031 0.066,0.042c0.022,0.011 0.048,0.016 0.077,0.016c0.032,0 0.056,-0.007 0.072,-0.022c0.016,-0.015 0.024,-0.033 0.024,-0.054c0,-0.013 -0.003,-0.024 -0.01,-0.033c-0.007,-0.009 -0.015,-0.018 -0.026,-0.024c-0.01,-0.008 -0.022,-0.014 -0.035,-0.019c-0.013,-0.005 -0.027,-0.011 -0.04,-0.016c-0.017,-0.006 -0.035,-0.013 -0.052,-0.021c-0.017,-0.007 -0.033,-0.017 -0.047,-0.028c-0.013,-0.011 -0.024,-0.023 -0.033,-0.038c-0.009,-0.015 -0.013,-0.032 -0.013,-0.053c0,-0.019 0.004,-0.038 0.011,-0.055c0.008,-0.017 0.019,-0.031 0.033,-0.044c0.015,-0.012 0.032,-0.022 0.053,-0.029c0.021,-0.007 0.044,-0.01 0.07,-0.01c0.031,0 0.059,0.005 0.084,0.016c0.026,0.011 0.048,0.024 0.067,0.039l-0.039,0.052c-0.017,-0.013 -0.034,-0.023 -0.052,-0.031c-0.018,-0.008 -0.038,-0.012 -0.059,-0.012c-0.031,0 -0.053,0.007 -0.068,0.021c-0.014,0.014 -0.021,0.03 -0.021,0.049c0,0.011 0.003,0.021 0.009,0.029c0.006,0.009 0.014,0.016 0.024,0.022c0.01,0.007 0.021,0.012 0.034,0.017c0.013,0.005 0.027,0.011 0.041,0.016c0.017,0.007 0.035,0.014 0.052,0.021c0.018,0.007 0.034,0.016 0.048,0.027c0.014,0.011 0.025,0.025 0.034,0.041c0.009,0.016 0.014,0.035 0.014,0.058c0,0.02 -0.004,0.039 -0.012,0.056c-0.007,0.017 -0.019,0.033 -0.034,0.046c-0.015,0.013 -0.033,0.024 -0.056,0.031c-0.022,0.008 -0.047,0.012 -0.076,0.012c-0.035,0 -0.068,-0.006 -0.099,-0.019c-0.031,-0.013 -0.059,-0.029 -0.082,-0.048l0.041,-0.055Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2673.06,1388.32)"><path d="M0.124,-0.586c-0.016,0 -0.029,-0.005 -0.04,-0.015c-0.011,-0.01 -0.017,-0.023 -0.017,-0.038c0,-0.016 0.006,-0.029 0.017,-0.038c0.011,-0.01 0.024,-0.015 0.04,-0.015c0.016,0 0.029,0.005 0.041,0.015c0.01,0.009 0.016,0.022 0.016,0.038c0,0.015 -0.006,0.028 -0.016,0.038c-0.011,0.01 -0.025,0.015 -0.041,0.015Zm-0.042,0.1l0.082,0l0,0.486l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2697.66,1388.32)"><path d="M0.117,0.082c0,0.026 0.012,0.047 0.037,0.062c0.025,0.015 0.06,0.023 0.104,0.023c0.023,0 0.044,-0.003 0.064,-0.009c0.019,-0.005 0.035,-0.013 0.048,-0.021c0.013,-0.01 0.024,-0.02 0.031,-0.032c0.007,-0.012 0.011,-0.024 0.011,-0.037c0,-0.023 -0.008,-0.038 -0.025,-0.047c-0.017,-0.009 -0.041,-0.013 -0.073,-0.013l-0.084,0c-0.009,0 -0.019,-0.001 -0.03,-0.002c-0.011,-0.001 -0.022,-0.003 -0.033,-0.006c-0.017,0.013 -0.03,0.026 -0.038,0.04c-0.008,0.014 -0.012,0.028 -0.012,0.042Zm-0.072,0.011c0,-0.021 0.006,-0.04 0.019,-0.059c0.013,-0.019 0.03,-0.036 0.052,-0.051l0,-0.004c-0.012,-0.007 -0.022,-0.018 -0.03,-0.031c-0.009,-0.013 -0.013,-0.029 -0.013,-0.048c0,-0.021 0.006,-0.039 0.017,-0.054c0.011,-0.015 0.023,-0.027 0.036,-0.036l0,-0.004c-0.016,-0.013 -0.03,-0.031 -0.043,-0.053c-0.013,-0.023 -0.02,-0.049 -0.02,-0.078c0,-0.027 0.005,-0.051 0.015,-0.072c0.009,-0.021 0.022,-0.039 0.039,-0.054c0.017,-0.016 0.036,-0.027 0.059,-0.035c0.022,-0.008 0.045,-0.012 0.07,-0.012c0.013,0 0.026,0.001 0.038,0.004c0.011,0.002 0.022,0.005 0.031,0.008l0.169,0l0,0.063l-0.1,0c0.011,0.011 0.021,0.026 0.029,0.043c0.007,0.017 0.011,0.036 0.011,0.057c0,0.026 -0.005,0.049 -0.014,0.071c-0.009,0.02 -0.022,0.038 -0.038,0.052c-0.016,0.015 -0.035,0.026 -0.057,0.034c-0.021,0.008 -0.044,0.012 -0.069,0.012c-0.012,0 -0.024,-0.002 -0.037,-0.005c-0.013,-0.003 -0.025,-0.007 -0.036,-0.012c-0.009,0.007 -0.016,0.016 -0.022,0.025c-0.006,0.009 -0.009,0.02 -0.009,0.033c0,0.015 0.006,0.028 0.018,0.038c0.012,0.01 0.035,0.015 0.068,0.015l0.094,0c0.057,0 0.099,0.009 0.127,0.028c0.029,0.018 0.043,0.047 0.043,0.088c0,0.023 -0.006,0.044 -0.017,0.065c-0.011,0.02 -0.028,0.038 -0.049,0.053c-0.021,0.015 -0.047,0.028 -0.078,0.037c-0.03,0.009 -0.064,0.013 -0.102,0.013c-0.03,0 -0.057,-0.003 -0.082,-0.009c-0.025,-0.005 -0.046,-0.014 -0.064,-0.025c-0.017,-0.011 -0.031,-0.025 -0.041,-0.041c-0.009,-0.016 -0.014,-0.035 -0.014,-0.056Zm0.201,-0.302c0.014,0 0.027,-0.003 0.039,-0.008c0.013,-0.005 0.024,-0.013 0.033,-0.023c0.01,-0.01 0.018,-0.022 0.023,-0.037c0.005,-0.014 0.008,-0.03 0.008,-0.048c0,-0.036 -0.01,-0.064 -0.03,-0.084c-0.02,-0.019 -0.044,-0.029 -0.073,-0.029c-0.029,0 -0.053,0.01 -0.073,0.029c-0.02,0.02 -0.03,0.048 -0.03,0.084c0,0.018 0.003,0.034 0.008,0.048c0.005,0.015 0.013,0.027 0.022,0.037c0.01,0.01 0.021,0.018 0.033,0.023c0.013,0.005 0.026,0.008 0.04,0.008Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2748.06,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2802.76,1388.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2852.36,1388.32)"><path d="M0.047,-0.242c0,-0.039 0.006,-0.075 0.018,-0.107c0.011,-0.031 0.027,-0.058 0.046,-0.08c0.019,-0.022 0.042,-0.039 0.067,-0.051c0.025,-0.012 0.052,-0.018 0.08,-0.018c0.028,0 0.052,0.005 0.073,0.015c0.021,0.01 0.042,0.024 0.063,0.041l-0.004,-0.083l0,-0.187l0.083,0l0,0.712l-0.068,0l-0.007,-0.057l-0.003,0c-0.019,0.019 -0.042,0.035 -0.067,0.049c-0.025,0.013 -0.051,0.02 -0.08,0.02c-0.061,0 -0.11,-0.022 -0.147,-0.066c-0.036,-0.044 -0.054,-0.107 -0.054,-0.188Zm0.085,-0.001c0,0.059 0.012,0.104 0.035,0.137c0.023,0.033 0.056,0.049 0.099,0.049c0.023,0 0.044,-0.006 0.064,-0.017c0.02,-0.011 0.04,-0.027 0.06,-0.05l0,-0.254c-0.021,-0.019 -0.041,-0.032 -0.059,-0.039c-0.02,-0.008 -0.039,-0.012 -0.059,-0.012c-0.019,0 -0.038,0.004 -0.055,0.013c-0.017,0.009 -0.031,0.022 -0.044,0.038c-0.013,0.017 -0.023,0.036 -0.03,0.059c-0.007,0.023 -0.011,0.048 -0.011,0.076Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2929.06,1388.32)"><path d="M0.09,-0.656l0.201,0c0.036,0 0.069,0.003 0.099,0.01c0.03,0.007 0.055,0.018 0.077,0.032c0.02,0.015 0.037,0.035 0.048,0.06c0.012,0.025 0.018,0.055 0.018,0.091c0,0.035 -0.006,0.065 -0.018,0.09c-0.011,0.025 -0.028,0.046 -0.049,0.063c-0.021,0.017 -0.047,0.029 -0.077,0.038c-0.029,0.008 -0.062,0.012 -0.098,0.012l-0.118,0l0,0.26l-0.083,0l0,-0.656Zm0.191,0.328c0.057,0 0.1,-0.011 0.128,-0.032c0.027,-0.022 0.041,-0.056 0.041,-0.103c0,-0.047 -0.014,-0.08 -0.042,-0.098c-0.028,-0.019 -0.07,-0.028 -0.127,-0.028l-0.108,0l0,0.261l0.108,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2986.66,1388.32)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3012.16,1388.32)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3063.36,1388.32)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3118.06,1388.32)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3167.66,1388.32)"><path d="M0.069,-0.11c0.021,0.017 0.043,0.031 0.066,0.042c0.022,0.011 0.048,0.016 0.077,0.016c0.032,0 0.056,-0.007 0.072,-0.022c0.016,-0.015 0.024,-0.033 0.024,-0.054c0,-0.013 -0.003,-0.024 -0.01,-0.033c-0.007,-0.009 -0.015,-0.018 -0.026,-0.024c-0.01,-0.008 -0.022,-0.014 -0.035,-0.019c-0.013,-0.005 -0.027,-0.011 -0.04,-0.016c-0.017,-0.006 -0.035,-0.013 -0.052,-0.021c-0.017,-0.007 -0.033,-0.017 -0.047,-0.028c-0.013,-0.011 -0.024,-0.023 -0.033,-0.038c-0.009,-0.015 -0.013,-0.032 -0.013,-0.053c0,-0.019 0.004,-0.038 0.011,-0.055c0.008,-0.017 0.019,-0.031 0.033,-0.044c0.015,-0.012 0.032,-0.022 0.053,-0.029c0.021,-0.007 0.044,-0.01 0.07,-0.01c0.031,0 0.059,0.005 0.084,0.016c0.026,0.011 0.048,0.024 0.067,0.039l-0.039,0.052c-0.017,-0.013 -0.034,-0.023 -0.052,-0.031c-0.018,-0.008 -0.038,-0.012 -0.059,-0.012c-0.031,0 -0.053,0.007 -0.068,0.021c-0.014,0.014 -0.021,0.03 -0.021,0.049c0,0.011 0.003,0.021 0.009,0.029c0.006,0.009 0.014,0.016 0.024,0.022c0.01,0.007 0.021,0.012 0.034,0.017c0.013,0.005 0.027,0.011 0.041,0.016c0.017,0.007 0.035,0.014 0.052,0.021c0.018,0.007 0.034,0.016 0.048,0.027c0.014,0.011 0.025,0.025 0.034,0.041c0.009,0.016 0.014,0.035 0.014,0.058c0,0.02 -0.004,0.039 -0.012,0.056c-0.007,0.017 -0.019,0.033 -0.034,0.046c-0.015,0.013 -0.033,0.024 -0.056,0.031c-0.022,0.008 -0.047,0.012 -0.076,0.012c-0.035,0 -0.068,-0.006 -0.099,-0.019c-0.031,-0.013 -0.059,-0.029 -0.082,-0.048l0.041,-0.055Z" style="fill-rule:nonzero;"/></g></g><path id="Supplementary-Ideographic-Plane" serif:id="Supplementary Ideographic Plane" d="M239.871,188.475l-197.103,111.993l216.325,62.083l197.103,-111.993l-216.325,-62.083Z" style="fill:#90bfc0;stroke:#000;stroke-width:0.24px;"/><path id="Supplementary-Multilingual-Plane" serif:id="Supplementary Multilingual Plane" d="M239.871,101.438l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#e65864;stroke:#000;stroke-width:0.24px;"/><path id="Basic-Multilingual-Plane" serif:id="Basic Multilingual Plane" d="M239.871,14.4l-197.103,111.993l216.325,62.082l197.103,-111.993l-216.325,-62.082Z" style="fill:#566a9b;stroke:#000;stroke-width:0.24px;"/><g transform="matrix(0.24,0,0,0.24,-107.451,32.559)"><g transform="matrix(100,0,0,100,1027.76,352.594)"><path d="M0.079,-0.656l0.084,0l0,0.41c0,0.034 0.004,0.063 0.011,0.086c0.006,0.024 0.016,0.043 0.028,0.057c0.013,0.015 0.027,0.025 0.044,0.032c0.017,0.007 0.035,0.01 0.055,0.01c0.02,0 0.038,-0.003 0.055,-0.01c0.017,-0.007 0.031,-0.017 0.044,-0.032c0.013,-0.014 0.023,-0.033 0.03,-0.057c0.007,-0.023 0.01,-0.052 0.01,-0.086l0,-0.41l0.081,0l0,0.408c0,0.047 -0.005,0.087 -0.016,0.12c-0.011,0.033 -0.027,0.059 -0.046,0.081c-0.019,0.021 -0.042,0.036 -0.069,0.045c-0.027,0.009 -0.057,0.014 -0.089,0.014c-0.032,0 -0.062,-0.005 -0.089,-0.014c-0.027,-0.009 -0.051,-0.024 -0.07,-0.046c-0.02,-0.021 -0.035,-0.047 -0.046,-0.08c-0.011,-0.033 -0.017,-0.073 -0.017,-0.12l0,-0.408Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1087.76,352.594)"><path d="M0.267,-0.299l-0.182,0l0,-0.062l0.182,0l0,-0.195l0.066,0l0,0.195l0.182,0l0,0.062l-0.182,0l0,0.195l-0.066,0l0,-0.195Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1149.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1209.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1269.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1329.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1449.76,352.594)"><path d="M0.582,-0.25l-0.273,0.265l-0.042,-0.046l0.201,-0.187l-0.439,0l0,-0.068l0.439,0l-0.201,-0.187l0.042,-0.046l0.273,0.265l0,0.004Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1569.76,352.594)"><path d="M0.079,-0.656l0.084,0l0,0.41c0,0.034 0.004,0.063 0.011,0.086c0.006,0.024 0.016,0.043 0.028,0.057c0.013,0.015 0.027,0.025 0.044,0.032c0.017,0.007 0.035,0.01 0.055,0.01c0.02,0 0.038,-0.003 0.055,-0.01c0.017,-0.007 0.031,-0.017 0.044,-0.032c0.013,-0.014 0.023,-0.033 0.03,-0.057c0.007,-0.023 0.01,-0.052 0.01,-0.086l0,-0.41l0.081,0l0,0.408c0,0.047 -0.005,0.087 -0.016,0.12c-0.011,0.033 -0.027,0.059 -0.046,0.081c-0.019,0.021 -0.042,0.036 -0.069,0.045c-0.027,0.009 -0.057,0.014 -0.089,0.014c-0.032,0 -0.062,-0.005 -0.089,-0.014c-0.027,-0.009 -0.051,-0.024 -0.07,-0.046c-0.02,-0.021 -0.035,-0.047 -0.046,-0.08c-0.011,-0.033 -0.017,-0.073 -0.017,-0.12l0,-0.408Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1629.76,352.594)"><path d="M0.267,-0.299l-0.182,0l0,-0.062l0.182,0l0,-0.195l0.066,0l0,0.195l0.182,0l0,0.062l-0.182,0l0,0.195l-0.066,0l0,-0.195Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1689.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1749.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1809.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1869.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#e0e0e0;fill-rule:nonzero;"/></g></g><g transform="matrix(0.24,0,0,0.24,-136.251,132.434)"><g transform="matrix(100,0,0,100,1027.76,352.594)"><path d="M0.079,-0.656l0.084,0l0,0.41c0,0.034 0.004,0.063 0.011,0.086c0.006,0.024 0.016,0.043 0.028,0.057c0.013,0.015 0.027,0.025 0.044,0.032c0.017,0.007 0.035,0.01 0.055,0.01c0.02,0 0.038,-0.003 0.055,-0.01c0.017,-0.007 0.031,-0.017 0.044,-0.032c0.013,-0.014 0.023,-0.033 0.03,-0.057c0.007,-0.023 0.01,-0.052 0.01,-0.086l0,-0.41l0.081,0l0,0.408c0,0.047 -0.005,0.087 -0.016,0.12c-0.011,0.033 -0.027,0.059 -0.046,0.081c-0.019,0.021 -0.042,0.036 -0.069,0.045c-0.027,0.009 -0.057,0.014 -0.089,0.014c-0.032,0 -0.062,-0.005 -0.089,-0.014c-0.027,-0.009 -0.051,-0.024 -0.07,-0.046c-0.02,-0.021 -0.035,-0.047 -0.046,-0.08c-0.011,-0.033 -0.017,-0.073 -0.017,-0.12l0,-0.408Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1087.76,352.594)"><path d="M0.267,-0.299l-0.182,0l0,-0.062l0.182,0l0,-0.195l0.066,0l0,0.195l0.182,0l0,0.062l-0.182,0l0,0.195l-0.066,0l0,-0.195Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1149.76,352.594)"><path d="M0.528,-0.068l0,0.068l-0.43,0l0,-0.068l0.181,0l0,-0.47l-0.136,0l0,-0.053c0.034,-0.005 0.064,-0.012 0.089,-0.019c0.025,-0.008 0.048,-0.017 0.068,-0.028l0.061,0l0,0.57l0.167,0Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1209.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1269.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1329.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1389.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1509.76,352.594)"><path d="M0.582,-0.25l-0.273,0.265l-0.042,-0.046l0.201,-0.187l-0.439,0l0,-0.068l0.439,0l-0.201,-0.187l0.042,-0.046l0.273,0.265l0,0.004Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1629.76,352.594)"><path d="M0.079,-0.656l0.084,0l0,0.41c0,0.034 0.004,0.063 0.011,0.086c0.006,0.024 0.016,0.043 0.028,0.057c0.013,0.015 0.027,0.025 0.044,0.032c0.017,0.007 0.035,0.01 0.055,0.01c0.02,0 0.038,-0.003 0.055,-0.01c0.017,-0.007 0.031,-0.017 0.044,-0.032c0.013,-0.014 0.023,-0.033 0.03,-0.057c0.007,-0.023 0.01,-0.052 0.01,-0.086l0,-0.41l0.081,0l0,0.408c0,0.047 -0.005,0.087 -0.016,0.12c-0.011,0.033 -0.027,0.059 -0.046,0.081c-0.019,0.021 -0.042,0.036 -0.069,0.045c-0.027,0.009 -0.057,0.014 -0.089,0.014c-0.032,0 -0.062,-0.005 -0.089,-0.014c-0.027,-0.009 -0.051,-0.024 -0.07,-0.046c-0.02,-0.021 -0.035,-0.047 -0.046,-0.08c-0.011,-0.033 -0.017,-0.073 -0.017,-0.12l0,-0.408Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1689.76,352.594)"><path d="M0.267,-0.299l-0.182,0l0,-0.062l0.182,0l0,-0.195l0.066,0l0,0.195l0.182,0l0,0.062l-0.182,0l0,0.195l-0.066,0l0,-0.195Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1749.76,352.594)"><path d="M0.528,-0.068l0,0.068l-0.43,0l0,-0.068l0.181,0l0,-0.47l-0.136,0l0,-0.053c0.034,-0.005 0.064,-0.012 0.089,-0.019c0.025,-0.008 0.048,-0.017 0.068,-0.028l0.061,0l0,0.57l0.167,0Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1809.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1869.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1929.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1989.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#f1f1f1;fill-rule:nonzero;"/></g></g><g transform="matrix(0.24,0,0,0.24,-136.251,218.198)"><g transform="matrix(100,0,0,100,1027.76,352.594)"><path d="M0.079,-0.656l0.084,0l0,0.41c0,0.034 0.004,0.063 0.011,0.086c0.006,0.024 0.016,0.043 0.028,0.057c0.013,0.015 0.027,0.025 0.044,0.032c0.017,0.007 0.035,0.01 0.055,0.01c0.02,0 0.038,-0.003 0.055,-0.01c0.017,-0.007 0.031,-0.017 0.044,-0.032c0.013,-0.014 0.023,-0.033 0.03,-0.057c0.007,-0.023 0.01,-0.052 0.01,-0.086l0,-0.41l0.081,0l0,0.408c0,0.047 -0.005,0.087 -0.016,0.12c-0.011,0.033 -0.027,0.059 -0.046,0.081c-0.019,0.021 -0.042,0.036 -0.069,0.045c-0.027,0.009 -0.057,0.014 -0.089,0.014c-0.032,0 -0.062,-0.005 -0.089,-0.014c-0.027,-0.009 -0.051,-0.024 -0.07,-0.046c-0.02,-0.021 -0.035,-0.047 -0.046,-0.08c-0.011,-0.033 -0.017,-0.073 -0.017,-0.12l0,-0.408Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1087.76,352.594)"><path d="M0.267,-0.299l-0.182,0l0,-0.062l0.182,0l0,-0.195l0.066,0l0,0.195l0.182,0l0,0.062l-0.182,0l0,0.195l-0.066,0l0,-0.195Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1149.76,352.594)"><path d="M0.073,-0.049c0.054,-0.048 0.102,-0.091 0.144,-0.13c0.041,-0.039 0.076,-0.074 0.104,-0.107c0.029,-0.032 0.05,-0.062 0.065,-0.09c0.015,-0.028 0.022,-0.055 0.022,-0.082c0,-0.037 -0.011,-0.067 -0.034,-0.09c-0.023,-0.023 -0.058,-0.035 -0.105,-0.035c-0.03,0 -0.058,0.008 -0.084,0.023c-0.025,0.015 -0.048,0.033 -0.069,0.054l-0.047,-0.047c0.029,-0.029 0.059,-0.053 0.092,-0.071c0.033,-0.017 0.073,-0.026 0.118,-0.026c0.032,0 0.061,0.005 0.086,0.014c0.026,0.009 0.048,0.021 0.066,0.038c0.018,0.016 0.032,0.036 0.041,0.059c0.01,0.023 0.015,0.049 0.015,0.077c0,0.03 -0.007,0.06 -0.022,0.091c-0.014,0.03 -0.034,0.061 -0.06,0.093c-0.026,0.033 -0.057,0.067 -0.093,0.102c-0.036,0.035 -0.076,0.072 -0.119,0.111c0.019,-0.001 0.039,-0.003 0.059,-0.004c0.021,-0.001 0.041,-0.002 0.06,-0.002l0.21,0l0,0.071l-0.449,0l0,-0.049Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1209.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1269.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1329.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1389.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1509.76,352.594)"><path d="M0.582,-0.25l-0.273,0.265l-0.042,-0.046l0.201,-0.187l-0.439,0l0,-0.068l0.439,0l-0.201,-0.187l0.042,-0.046l0.273,0.265l0,0.004Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1629.76,352.594)"><path d="M0.079,-0.656l0.084,0l0,0.41c0,0.034 0.004,0.063 0.011,0.086c0.006,0.024 0.016,0.043 0.028,0.057c0.013,0.015 0.027,0.025 0.044,0.032c0.017,0.007 0.035,0.01 0.055,0.01c0.02,0 0.038,-0.003 0.055,-0.01c0.017,-0.007 0.031,-0.017 0.044,-0.032c0.013,-0.014 0.023,-0.033 0.03,-0.057c0.007,-0.023 0.01,-0.052 0.01,-0.086l0,-0.41l0.081,0l0,0.408c0,0.047 -0.005,0.087 -0.016,0.12c-0.011,0.033 -0.027,0.059 -0.046,0.081c-0.019,0.021 -0.042,0.036 -0.069,0.045c-0.027,0.009 -0.057,0.014 -0.089,0.014c-0.032,0 -0.062,-0.005 -0.089,-0.014c-0.027,-0.009 -0.051,-0.024 -0.07,-0.046c-0.02,-0.021 -0.035,-0.047 -0.046,-0.08c-0.011,-0.033 -0.017,-0.073 -0.017,-0.12l0,-0.408Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1689.76,352.594)"><path d="M0.267,-0.299l-0.182,0l0,-0.062l0.182,0l0,-0.195l0.066,0l0,0.195l0.182,0l0,0.062l-0.182,0l0,0.195l-0.066,0l0,-0.195Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1749.76,352.594)"><path d="M0.073,-0.049c0.054,-0.048 0.102,-0.091 0.144,-0.13c0.041,-0.039 0.076,-0.074 0.104,-0.107c0.029,-0.032 0.05,-0.062 0.065,-0.09c0.015,-0.028 0.022,-0.055 0.022,-0.082c0,-0.037 -0.011,-0.067 -0.034,-0.09c-0.023,-0.023 -0.058,-0.035 -0.105,-0.035c-0.03,0 -0.058,0.008 -0.084,0.023c-0.025,0.015 -0.048,0.033 -0.069,0.054l-0.047,-0.047c0.029,-0.029 0.059,-0.053 0.092,-0.071c0.033,-0.017 0.073,-0.026 0.118,-0.026c0.032,0 0.061,0.005 0.086,0.014c0.026,0.009 0.048,0.021 0.066,0.038c0.018,0.016 0.032,0.036 0.041,0.059c0.01,0.023 0.015,0.049 0.015,0.077c0,0.03 -0.007,0.06 -0.022,0.091c-0.014,0.03 -0.034,0.061 -0.06,0.093c-0.026,0.033 -0.057,0.067 -0.093,0.102c-0.036,0.035 -0.076,0.072 -0.119,0.111c0.019,-0.001 0.039,-0.003 0.059,-0.004c0.021,-0.001 0.041,-0.002 0.06,-0.002l0.21,0l0,0.071l-0.449,0l0,-0.049Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1809.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1869.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1929.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1989.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g></g><g transform="matrix(0.24,0,0,0.24,-136.251,311.017)"><g transform="matrix(100,0,0,100,1027.76,352.594)"><path d="M0.079,-0.656l0.084,0l0,0.41c0,0.034 0.004,0.063 0.011,0.086c0.006,0.024 0.016,0.043 0.028,0.057c0.013,0.015 0.027,0.025 0.044,0.032c0.017,0.007 0.035,0.01 0.055,0.01c0.02,0 0.038,-0.003 0.055,-0.01c0.017,-0.007 0.031,-0.017 0.044,-0.032c0.013,-0.014 0.023,-0.033 0.03,-0.057c0.007,-0.023 0.01,-0.052 0.01,-0.086l0,-0.41l0.081,0l0,0.408c0,0.047 -0.005,0.087 -0.016,0.12c-0.011,0.033 -0.027,0.059 -0.046,0.081c-0.019,0.021 -0.042,0.036 -0.069,0.045c-0.027,0.009 -0.057,0.014 -0.089,0.014c-0.032,0 -0.062,-0.005 -0.089,-0.014c-0.027,-0.009 -0.051,-0.024 -0.07,-0.046c-0.02,-0.021 -0.035,-0.047 -0.046,-0.08c-0.011,-0.033 -0.017,-0.073 -0.017,-0.12l0,-0.408Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1087.76,352.594)"><path d="M0.267,-0.299l-0.182,0l0,-0.062l0.182,0l0,-0.195l0.066,0l0,0.195l0.182,0l0,0.062l-0.182,0l0,0.195l-0.066,0l0,-0.195Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1149.76,352.594)"><path d="M0.099,-0.132c0.021,0.02 0.047,0.038 0.077,0.053c0.029,0.015 0.065,0.023 0.106,0.023c0.022,0 0.042,-0.003 0.061,-0.008c0.019,-0.006 0.035,-0.014 0.049,-0.024c0.013,-0.01 0.024,-0.022 0.032,-0.036c0.007,-0.015 0.011,-0.031 0.011,-0.049c0,-0.019 -0.004,-0.036 -0.012,-0.051c-0.009,-0.016 -0.022,-0.03 -0.041,-0.041c-0.019,-0.011 -0.043,-0.02 -0.072,-0.026c-0.029,-0.006 -0.065,-0.009 -0.107,-0.009l0,-0.063c0.038,0 0.07,-0.003 0.097,-0.009c0.026,-0.006 0.047,-0.014 0.064,-0.025c0.017,-0.011 0.029,-0.023 0.037,-0.038c0.007,-0.015 0.011,-0.03 0.011,-0.047c0,-0.031 -0.012,-0.056 -0.035,-0.074c-0.024,-0.018 -0.056,-0.027 -0.095,-0.027c-0.03,0 -0.058,0.006 -0.085,0.018c-0.027,0.012 -0.051,0.028 -0.072,0.047l-0.044,-0.052c0.027,-0.023 0.057,-0.042 0.091,-0.057c0.034,-0.015 0.072,-0.023 0.113,-0.023c0.03,0 0.058,0.004 0.084,0.011c0.025,0.007 0.048,0.018 0.067,0.032c0.019,0.013 0.033,0.03 0.044,0.05c0.011,0.02 0.016,0.043 0.016,0.069c0,0.039 -0.013,0.07 -0.038,0.095c-0.025,0.025 -0.058,0.044 -0.098,0.057l0,0.004c0.021,0.005 0.042,0.012 0.061,0.021c0.019,0.009 0.035,0.02 0.05,0.033c0.015,0.014 0.026,0.03 0.035,0.048c0.008,0.018 0.012,0.038 0.012,0.06c0,0.028 -0.006,0.053 -0.018,0.076c-0.012,0.023 -0.028,0.042 -0.049,0.058c-0.021,0.015 -0.046,0.027 -0.074,0.036c-0.028,0.008 -0.058,0.012 -0.09,0.012c-0.055,0 -0.102,-0.009 -0.139,-0.027c-0.037,-0.019 -0.068,-0.04 -0.091,-0.063l0.042,-0.054Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1209.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1269.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1329.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1389.76,352.594)"><path d="M0.3,0.012c-0.071,0 -0.127,-0.029 -0.168,-0.086c-0.041,-0.058 -0.061,-0.14 -0.061,-0.247c0,-0.107 0.02,-0.189 0.061,-0.245c0.041,-0.056 0.097,-0.084 0.168,-0.084c0.071,0 0.127,0.028 0.168,0.084c0.041,0.056 0.061,0.138 0.061,0.245c0,0.107 -0.02,0.189 -0.061,0.247c-0.041,0.057 -0.097,0.086 -0.168,0.086Zm0,-0.596c-0.022,0 -0.042,0.005 -0.061,0.015c-0.019,0.01 -0.035,0.026 -0.048,0.048c-0.014,0.021 -0.025,0.049 -0.032,0.082c-0.007,0.032 -0.011,0.072 -0.011,0.118c0,0.091 0.014,0.159 0.043,0.202c0.028,0.043 0.064,0.065 0.109,0.065c0.045,0 0.081,-0.022 0.11,-0.065c0.028,-0.043 0.042,-0.111 0.042,-0.202c0,-0.046 -0.004,-0.086 -0.011,-0.118c-0.007,-0.033 -0.018,-0.061 -0.031,-0.082c-0.014,-0.022 -0.03,-0.038 -0.049,-0.048c-0.019,-0.01 -0.039,-0.015 -0.061,-0.015Zm0,0.323c-0.017,0 -0.031,-0.006 -0.043,-0.017c-0.013,-0.012 -0.019,-0.029 -0.019,-0.05c0,-0.021 0.006,-0.037 0.019,-0.048c0.012,-0.012 0.026,-0.018 0.043,-0.018c0.017,0 0.031,0.006 0.044,0.018c0.012,0.011 0.018,0.027 0.018,0.048c0,0.021 -0.006,0.038 -0.018,0.05c-0.013,0.011 -0.027,0.017 -0.044,0.017Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1509.76,352.594)"><path d="M0.582,-0.25l-0.273,0.265l-0.042,-0.046l0.201,-0.187l-0.439,0l0,-0.068l0.439,0l-0.201,-0.187l0.042,-0.046l0.273,0.265l0,0.004Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1629.76,352.594)"><path d="M0.079,-0.656l0.084,0l0,0.41c0,0.034 0.004,0.063 0.011,0.086c0.006,0.024 0.016,0.043 0.028,0.057c0.013,0.015 0.027,0.025 0.044,0.032c0.017,0.007 0.035,0.01 0.055,0.01c0.02,0 0.038,-0.003 0.055,-0.01c0.017,-0.007 0.031,-0.017 0.044,-0.032c0.013,-0.014 0.023,-0.033 0.03,-0.057c0.007,-0.023 0.01,-0.052 0.01,-0.086l0,-0.41l0.081,0l0,0.408c0,0.047 -0.005,0.087 -0.016,0.12c-0.011,0.033 -0.027,0.059 -0.046,0.081c-0.019,0.021 -0.042,0.036 -0.069,0.045c-0.027,0.009 -0.057,0.014 -0.089,0.014c-0.032,0 -0.062,-0.005 -0.089,-0.014c-0.027,-0.009 -0.051,-0.024 -0.07,-0.046c-0.02,-0.021 -0.035,-0.047 -0.046,-0.08c-0.011,-0.033 -0.017,-0.073 -0.017,-0.12l0,-0.408Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1689.76,352.594)"><path d="M0.267,-0.299l-0.182,0l0,-0.062l0.182,0l0,-0.195l0.066,0l0,0.195l0.182,0l0,0.062l-0.182,0l0,0.195l-0.066,0l0,-0.195Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1749.76,352.594)"><path d="M0.099,-0.132c0.021,0.02 0.047,0.038 0.077,0.053c0.029,0.015 0.065,0.023 0.106,0.023c0.022,0 0.042,-0.003 0.061,-0.008c0.019,-0.006 0.035,-0.014 0.049,-0.024c0.013,-0.01 0.024,-0.022 0.032,-0.036c0.007,-0.015 0.011,-0.031 0.011,-0.049c0,-0.019 -0.004,-0.036 -0.012,-0.051c-0.009,-0.016 -0.022,-0.03 -0.041,-0.041c-0.019,-0.011 -0.043,-0.02 -0.072,-0.026c-0.029,-0.006 -0.065,-0.009 -0.107,-0.009l0,-0.063c0.038,0 0.07,-0.003 0.097,-0.009c0.026,-0.006 0.047,-0.014 0.064,-0.025c0.017,-0.011 0.029,-0.023 0.037,-0.038c0.007,-0.015 0.011,-0.03 0.011,-0.047c0,-0.031 -0.012,-0.056 -0.035,-0.074c-0.024,-0.018 -0.056,-0.027 -0.095,-0.027c-0.03,0 -0.058,0.006 -0.085,0.018c-0.027,0.012 -0.051,0.028 -0.072,0.047l-0.044,-0.052c0.027,-0.023 0.057,-0.042 0.091,-0.057c0.034,-0.015 0.072,-0.023 0.113,-0.023c0.03,0 0.058,0.004 0.084,0.011c0.025,0.007 0.048,0.018 0.067,0.032c0.019,0.013 0.033,0.03 0.044,0.05c0.011,0.02 0.016,0.043 0.016,0.069c0,0.039 -0.013,0.07 -0.038,0.095c-0.025,0.025 -0.058,0.044 -0.098,0.057l0,0.004c0.021,0.005 0.042,0.012 0.061,0.021c0.019,0.009 0.035,0.02 0.05,0.033c0.015,0.014 0.026,0.03 0.035,0.048c0.008,0.018 0.012,0.038 0.012,0.06c0,0.028 -0.006,0.053 -0.018,0.076c-0.012,0.023 -0.028,0.042 -0.049,0.058c-0.021,0.015 -0.046,0.027 -0.074,0.036c-0.028,0.008 -0.058,0.012 -0.09,0.012c-0.055,0 -0.102,-0.009 -0.139,-0.027c-0.037,-0.019 -0.068,-0.04 -0.091,-0.063l0.042,-0.054Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1809.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1869.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1929.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,1989.76,352.594)"><path d="M0.135,-0.656l0.401,0l0,0.07l-0.318,0l0,0.222l0.269,0l0,0.07l-0.269,0l0,0.294l-0.083,0l0,-0.656Z" style="fill:#2d2d2d;fill-rule:nonzero;"/></g></g><path d="M26.595,132.839c-1.552,0 -2.76,-0.688 -3.624,-2.064c-0.864,-1.376 -1.296,-3.352 -1.296,-5.928c0,-2.576 0.432,-4.536 1.296,-5.88c0.864,-1.344 2.072,-2.016 3.624,-2.016c1.536,0 2.736,0.672 3.6,2.016c0.864,1.344 1.296,3.304 1.296,5.88c0,2.576 -0.432,4.552 -1.296,5.928c-0.864,1.376 -2.064,2.064 -3.6,2.064Zm0,-1.584c0.448,0 0.852,-0.124 1.212,-0.372c0.36,-0.248 0.672,-0.632 0.936,-1.152c0.264,-0.52 0.468,-1.184 0.612,-1.992c0.144,-0.808 0.216,-1.772 0.216,-2.892c0,-1.12 -0.072,-2.08 -0.216,-2.88c-0.144,-0.8 -0.348,-1.452 -0.612,-1.956c-0.264,-0.504 -0.576,-0.876 -0.936,-1.116c-0.36,-0.24 -0.764,-0.36 -1.212,-0.36c-0.448,0 -0.856,0.12 -1.224,0.36c-0.368,0.24 -0.684,0.612 -0.948,1.116c-0.264,0.504 -0.468,1.156 -0.612,1.956c-0.144,0.8 -0.216,1.76 -0.216,2.88c0,2.24 0.276,3.868 0.828,4.884c0.552,1.016 1.276,1.524 2.172,1.524Z" style="fill-rule:nonzero;"/><path d="M22.851,218.34l3.504,0l0,-11.28l-2.784,0l0,-1.272c0.704,-0.128 1.316,-0.284 1.836,-0.468c0.52,-0.184 0.988,-0.404 1.404,-0.66l1.512,0l0,13.68l3.168,0l0,1.632l-8.64,0l0,-1.632Z" style="fill-rule:nonzero;"/><path d="M21.603,306.362c1.152,-1.152 2.176,-2.192 3.072,-3.12c0.896,-0.928 1.648,-1.788 2.256,-2.58c0.608,-0.792 1.072,-1.52 1.392,-2.184c0.32,-0.664 0.48,-1.308 0.48,-1.932c0,-0.88 -0.24,-1.6 -0.72,-2.16c-0.48,-0.56 -1.208,-0.84 -2.184,-0.84c-0.64,0 -1.232,0.18 -1.776,0.54c-0.544,0.36 -1.04,0.796 -1.488,1.308l-1.128,-1.128c0.64,-0.704 1.32,-1.268 2.04,-1.692c0.72,-0.424 1.584,-0.636 2.592,-0.636c1.424,0 2.544,0.412 3.36,1.236c0.816,0.824 1.224,1.916 1.224,3.276c0,0.72 -0.156,1.444 -0.468,2.172c-0.312,0.728 -0.744,1.48 -1.296,2.256c-0.552,0.776 -1.208,1.584 -1.968,2.424c-0.76,0.84 -1.596,1.732 -2.508,2.676c0.416,-0.032 0.848,-0.064 1.296,-0.096c0.448,-0.032 0.872,-0.048 1.272,-0.048l4.44,0l0,1.704l-9.888,0l0,-1.176Z" style="fill-rule:nonzero;"/><path d="M22.419,391.647c0.464,0.48 1.004,0.904 1.62,1.272c0.616,0.368 1.38,0.552 2.292,0.552c0.928,0 1.688,-0.252 2.28,-0.756c0.592,-0.504 0.888,-1.188 0.888,-2.052c0,-0.448 -0.084,-0.86 -0.252,-1.236c-0.168,-0.376 -0.444,-0.7 -0.828,-0.972c-0.384,-0.272 -0.888,-0.48 -1.512,-0.624c-0.624,-0.144 -1.392,-0.216 -2.304,-0.216l0,-1.512c0.816,0 1.5,-0.072 2.052,-0.216c0.552,-0.144 1,-0.344 1.344,-0.6c0.344,-0.256 0.588,-0.56 0.732,-0.912c0.144,-0.352 0.216,-0.728 0.216,-1.128c0,-0.752 -0.236,-1.344 -0.708,-1.776c-0.472,-0.432 -1.116,-0.648 -1.932,-0.648c-0.64,0 -1.228,0.144 -1.764,0.432c-0.536,0.288 -1.036,0.664 -1.5,1.128l-1.056,-1.248c0.592,-0.56 1.244,-1.02 1.956,-1.38c0.712,-0.36 1.524,-0.54 2.436,-0.54c0.672,0 1.288,0.088 1.848,0.264c0.56,0.176 1.044,0.428 1.452,0.756c0.408,0.328 0.724,0.732 0.948,1.212c0.224,0.48 0.336,1.032 0.336,1.656c0,0.928 -0.256,1.688 -0.768,2.28c-0.512,0.592 -1.184,1.048 -2.016,1.368l0,0.096c0.464,0.112 0.896,0.276 1.296,0.492c0.4,0.216 0.752,0.488 1.056,0.816c0.304,0.328 0.54,0.708 0.708,1.14c0.168,0.432 0.252,0.912 0.252,1.44c0,0.672 -0.132,1.28 -0.396,1.824c-0.264,0.544 -0.624,1.004 -1.08,1.38c-0.456,0.376 -0.988,0.664 -1.596,0.864c-0.608,0.2 -1.264,0.3 -1.968,0.3c-0.608,0 -1.164,-0.06 -1.668,-0.18c-0.504,-0.12 -0.964,-0.28 -1.38,-0.48c-0.416,-0.2 -0.788,-0.428 -1.116,-0.684c-0.328,-0.256 -0.62,-0.528 -0.876,-0.816l1.008,-1.296Z" style="fill-rule:nonzero;"/><path d="M25.395,543.735l-4.44,0.001c-0.416,0 -0.908,-0.012 -1.476,-0.036c-0.568,-0.024 -1.06,-0.052 -1.476,-0.084l0,0.096c0.368,0.192 0.728,0.392 1.08,0.6c0.352,0.208 0.712,0.424 1.08,0.648l5.232,3.575l0,-4.8Zm1.583,-3.96l0,2.088l4.224,0l0.001,1.872l-4.224,0l0,6.888l-1.296,0l-9.792,-6.551l-0.001,-2.208l9.504,-0.001l0,-2.088l1.584,0Z" style="fill:#cfcfcf;fill-rule:nonzero;"/><path d="M24.434,533.271l-0.001,-5.52l1.512,0l0.001,5.52l-1.512,0Z" style="fill:#cfcfcf;fill-rule:nonzero;"/><path d="M29.568,520.047l0,-3.504l-11.28,0.001l0,2.784l-1.272,0c-0.128,-0.704 -0.284,-1.316 -0.468,-1.836c-0.184,-0.52 -0.404,-0.988 -0.66,-1.404l0,-1.512l13.68,-0.001l-0.001,-3.168l1.632,0l0.001,8.64l-1.632,0Z" style="fill:#cfcfcf;fill-rule:nonzero;"/><path d="M28.031,508.383c0.48,-0.464 0.904,-1.004 1.272,-1.62c0.368,-0.616 0.552,-1.38 0.552,-2.292c-0.001,-0.928 -0.253,-1.688 -0.757,-2.28c-0.504,-0.592 -1.188,-0.888 -2.052,-0.888c-0.448,0 -0.86,0.084 -1.236,0.252c-0.376,0.168 -0.7,0.444 -0.972,0.828c-0.272,0.384 -0.48,0.888 -0.624,1.512c-0.143,0.624 -0.215,1.392 -0.215,2.304l-1.512,0.001c0,-0.816 -0.072,-1.5 -0.216,-2.052c-0.145,-0.552 -0.345,-1 -0.601,-1.344c-0.256,-0.344 -0.56,-0.588 -0.912,-0.732c-0.352,-0.144 -0.728,-0.216 -1.128,-0.216c-0.752,0 -1.344,0.236 -1.776,0.708c-0.432,0.472 -0.648,1.116 -0.647,1.932c0,0.64 0.144,1.228 0.432,1.764c0.288,0.536 0.664,1.036 1.128,1.5l-1.248,1.056c-0.56,-0.592 -1.02,-1.244 -1.38,-1.956c-0.36,-0.712 -0.54,-1.524 -0.54,-2.436c-0.001,-0.672 0.087,-1.288 0.263,-1.848c0.176,-0.56 0.428,-1.044 0.756,-1.452c0.328,-0.408 0.732,-0.724 1.212,-0.948c0.48,-0.224 1.032,-0.336 1.656,-0.336c0.928,0 1.688,0.256 2.28,0.768c0.592,0.512 1.048,1.184 1.368,2.016l0.096,0c0.112,-0.464 0.276,-0.897 0.492,-1.297c0.216,-0.4 0.488,-0.752 0.816,-1.056c0.328,-0.304 0.708,-0.54 1.14,-0.708c0.432,-0.168 0.912,-0.252 1.44,-0.252c0.672,0 1.28,0.132 1.824,0.396c0.544,0.264 1.004,0.624 1.38,1.08c0.376,0.456 0.664,0.988 0.864,1.596c0.2,0.608 0.3,1.264 0.301,1.968c0,0.608 -0.06,1.164 -0.18,1.668c-0.12,0.504 -0.28,0.964 -0.48,1.38c-0.2,0.416 -0.428,0.788 -0.684,1.116c-0.256,0.328 -0.528,0.62 -0.816,0.876l-1.296,-1.008Z" style="fill:#cfcfcf;fill-rule:nonzero;"/><path d="M10.203,652.996l3.504,0l0,-11.28l-2.784,0l0,-1.272c0.704,-0.128 1.316,-0.284 1.836,-0.468c0.52,-0.184 0.988,-0.404 1.404,-0.66l1.512,0l0,13.68l3.168,0l0,1.632l-8.64,0l0,-1.632Z" style="fill-rule:nonzero;"/><path d="M27.531,648.82l0,-4.44c0,-0.416 0.012,-0.908 0.036,-1.476c0.024,-0.568 0.052,-1.06 0.084,-1.476l-0.096,0c-0.192,0.368 -0.392,0.728 -0.6,1.08c-0.208,0.352 -0.424,0.712 -0.648,1.08l-3.576,5.232l4.8,0Zm3.96,1.584l-2.088,0l0,4.224l-1.872,0l0,-4.224l-6.888,0l0,-1.296l6.552,-9.792l2.208,0l0,9.504l2.088,0l0,1.584Z" style="fill-rule:nonzero;"/><path d="M10.683,697.661l3.504,0l0,-11.28l-2.784,0l0,-1.272c0.704,-0.128 1.316,-0.284 1.836,-0.468c0.52,-0.184 0.988,-0.404 1.404,-0.66l1.512,0l0,13.68l3.168,0l0,1.632l-8.64,0l0,-1.632Z" style="fill-rule:nonzero;"/><path d="M22.275,696.197c0.448,0.464 0.98,0.872 1.596,1.224c0.616,0.352 1.372,0.528 2.268,0.528c0.464,0 0.9,-0.084 1.308,-0.252c0.408,-0.168 0.764,-0.404 1.068,-0.708c0.304,-0.304 0.544,-0.672 0.72,-1.104c0.176,-0.432 0.264,-0.912 0.264,-1.44c0,-1.056 -0.296,-1.88 -0.888,-2.472c-0.592,-0.592 -1.384,-0.888 -2.376,-0.888c-0.528,0 -0.98,0.08 -1.356,0.24c-0.376,0.16 -0.796,0.392 -1.26,0.696l-1.056,-0.672l0.504,-7.368l7.656,0l0,1.704l-5.928,0l-0.408,4.536c0.368,-0.192 0.736,-0.344 1.104,-0.456c0.368,-0.112 0.784,-0.168 1.248,-0.168c0.656,0 1.272,0.096 1.848,0.288c0.576,0.192 1.08,0.484 1.512,0.876c0.432,0.392 0.772,0.888 1.02,1.488c0.248,0.6 0.372,1.316 0.372,2.148c0,0.832 -0.144,1.568 -0.432,2.208c-0.288,0.64 -0.672,1.18 -1.152,1.62c-0.48,0.44 -1.028,0.776 -1.644,1.008c-0.616,0.232 -1.26,0.348 -1.932,0.348c-0.608,0 -1.164,-0.06 -1.668,-0.18c-0.504,-0.12 -0.96,-0.276 -1.368,-0.468c-0.408,-0.192 -0.776,-0.412 -1.104,-0.66c-0.328,-0.248 -0.62,-0.508 -0.876,-0.78l0.96,-1.296Z" style="fill-rule:nonzero;"/><path d="M10.491,733.161l3.504,0l0,-11.28l-2.784,0l0,-1.272c0.704,-0.128 1.316,-0.284 1.836,-0.468c0.52,-0.184 0.988,-0.404 1.404,-0.66l1.512,0l0,13.68l3.168,0l0,1.632l-8.64,0l0,-1.632Z" style="fill-rule:nonzero;"/><path d="M26.955,733.521c0.384,0 0.736,-0.08 1.056,-0.24c0.32,-0.16 0.6,-0.388 0.84,-0.684c0.24,-0.296 0.428,-0.648 0.564,-1.056c0.136,-0.408 0.204,-0.868 0.204,-1.38c0,-1.008 -0.232,-1.8 -0.696,-2.376c-0.464,-0.576 -1.176,-0.864 -2.136,-0.864c-0.48,0 -1.004,0.156 -1.572,0.468c-0.568,0.312 -1.108,0.828 -1.62,1.548c0.128,1.504 0.476,2.644 1.044,3.42c0.568,0.776 1.34,1.164 2.316,1.164Zm3.144,-11.472c-0.32,-0.368 -0.7,-0.66 -1.14,-0.876c-0.44,-0.216 -0.9,-0.324 -1.38,-0.324c-0.528,0 -1.032,0.112 -1.512,0.336c-0.48,0.224 -0.904,0.592 -1.272,1.104c-0.368,0.512 -0.664,1.18 -0.888,2.004c-0.224,0.824 -0.344,1.844 -0.36,3.06c0.48,-0.592 1.04,-1.06 1.68,-1.404c0.64,-0.344 1.272,-0.516 1.896,-0.516c1.328,0 2.388,0.392 3.18,1.176c0.792,0.784 1.188,1.968 1.188,3.552c0,0.736 -0.12,1.404 -0.36,2.004c-0.24,0.6 -0.568,1.116 -0.984,1.548c-0.416,0.432 -0.896,0.768 -1.44,1.008c-0.544,0.24 -1.128,0.36 -1.752,0.36c-0.752,0 -1.448,-0.152 -2.088,-0.456c-0.64,-0.304 -1.196,-0.764 -1.668,-1.38c-0.472,-0.616 -0.844,-1.384 -1.116,-2.304c-0.272,-0.92 -0.408,-1.996 -0.408,-3.228c0,-1.536 0.16,-2.844 0.48,-3.924c0.32,-1.08 0.752,-1.96 1.296,-2.64c0.544,-0.68 1.164,-1.176 1.86,-1.488c0.696,-0.312 1.428,-0.468 2.196,-0.468c0.832,0 1.548,0.156 2.148,0.468c0.6,0.312 1.116,0.7 1.548,1.164l-1.104,1.224Z" style="fill-rule:nonzero;"/><g transform="matrix(0.24,0,0,0.24,11.8223,1.83551)"><g transform="matrix(100,0,0,100,2424.51,297.899)"><path d="M0.09,-0.656l0.195,0c0.033,0 0.064,0.003 0.091,0.009c0.028,0.006 0.052,0.015 0.072,0.028c0.019,0.013 0.034,0.029 0.045,0.049c0.012,0.021 0.017,0.045 0.017,0.074c0,0.033 -0.009,0.062 -0.028,0.088c-0.019,0.027 -0.047,0.045 -0.086,0.055l0,0.004c0.048,0.007 0.085,0.024 0.112,0.05c0.027,0.026 0.04,0.062 0.04,0.107c0,0.032 -0.006,0.06 -0.018,0.084c-0.012,0.024 -0.029,0.044 -0.051,0.06c-0.022,0.016 -0.048,0.028 -0.079,0.036c-0.031,0.008 -0.064,0.012 -0.101,0.012l-0.209,0l0,-0.656Zm0.18,0.28c0.057,0 0.097,-0.01 0.122,-0.029c0.024,-0.019 0.036,-0.047 0.036,-0.084c0,-0.036 -0.013,-0.062 -0.039,-0.078c-0.025,-0.015 -0.064,-0.023 -0.115,-0.023l-0.101,0l0,0.214l0.097,0Zm0.017,0.31c0.057,0 0.101,-0.01 0.132,-0.032c0.031,-0.021 0.047,-0.053 0.047,-0.098c0,-0.041 -0.015,-0.071 -0.046,-0.09c-0.031,-0.018 -0.075,-0.028 -0.133,-0.028l-0.114,0l0,0.248l0.114,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2483.31,297.899)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2534.51,297.899)"><path d="M0.069,-0.11c0.021,0.017 0.043,0.031 0.066,0.042c0.022,0.011 0.048,0.016 0.077,0.016c0.032,0 0.056,-0.007 0.072,-0.022c0.016,-0.015 0.024,-0.033 0.024,-0.054c0,-0.013 -0.003,-0.024 -0.01,-0.033c-0.007,-0.009 -0.015,-0.018 -0.026,-0.024c-0.01,-0.008 -0.022,-0.014 -0.035,-0.019c-0.013,-0.005 -0.027,-0.011 -0.04,-0.016c-0.017,-0.006 -0.035,-0.013 -0.052,-0.021c-0.017,-0.007 -0.033,-0.017 -0.047,-0.028c-0.013,-0.011 -0.024,-0.023 -0.033,-0.038c-0.009,-0.015 -0.013,-0.032 -0.013,-0.053c0,-0.019 0.004,-0.038 0.011,-0.055c0.008,-0.017 0.019,-0.031 0.033,-0.044c0.015,-0.012 0.032,-0.022 0.053,-0.029c0.021,-0.007 0.044,-0.01 0.07,-0.01c0.031,0 0.059,0.005 0.084,0.016c0.026,0.011 0.048,0.024 0.067,0.039l-0.039,0.052c-0.017,-0.013 -0.034,-0.023 -0.052,-0.031c-0.018,-0.008 -0.038,-0.012 -0.059,-0.012c-0.031,0 -0.053,0.007 -0.068,0.021c-0.014,0.014 -0.021,0.03 -0.021,0.049c0,0.011 0.003,0.021 0.009,0.029c0.006,0.009 0.014,0.016 0.024,0.022c0.01,0.007 0.021,0.012 0.034,0.017c0.013,0.005 0.027,0.011 0.041,0.016c0.017,0.007 0.035,0.014 0.052,0.021c0.018,0.007 0.034,0.016 0.048,0.027c0.014,0.011 0.025,0.025 0.034,0.041c0.009,0.016 0.014,0.035 0.014,0.058c0,0.02 -0.004,0.039 -0.012,0.056c-0.007,0.017 -0.019,0.033 -0.034,0.046c-0.015,0.013 -0.033,0.024 -0.056,0.031c-0.022,0.008 -0.047,0.012 -0.076,0.012c-0.035,0 -0.068,-0.006 -0.099,-0.019c-0.031,-0.013 -0.059,-0.029 -0.082,-0.048l0.041,-0.055Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2576.41,297.899)"><path d="M0.124,-0.586c-0.016,0 -0.029,-0.005 -0.04,-0.015c-0.011,-0.01 -0.017,-0.023 -0.017,-0.038c0,-0.016 0.006,-0.029 0.017,-0.038c0.011,-0.01 0.024,-0.015 0.04,-0.015c0.016,0 0.029,0.005 0.041,0.015c0.01,0.009 0.016,0.022 0.016,0.038c0,0.015 -0.006,0.028 -0.016,0.038c-0.011,0.01 -0.025,0.015 -0.041,0.015Zm-0.042,0.1l0.082,0l0,0.486l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2601.01,297.899)"><path d="M0.046,-0.242c0,-0.041 0.006,-0.077 0.019,-0.109c0.013,-0.031 0.03,-0.058 0.051,-0.08c0.021,-0.022 0.046,-0.039 0.075,-0.05c0.028,-0.011 0.058,-0.017 0.089,-0.017c0.032,0 0.059,0.006 0.082,0.018c0.023,0.011 0.043,0.025 0.06,0.04l-0.041,0.053c-0.015,-0.013 -0.03,-0.023 -0.046,-0.031c-0.015,-0.008 -0.033,-0.012 -0.052,-0.012c-0.022,0 -0.042,0.005 -0.061,0.014c-0.019,0.009 -0.035,0.021 -0.048,0.038c-0.013,0.017 -0.024,0.037 -0.032,0.06c-0.007,0.023 -0.011,0.048 -0.011,0.076c0,0.028 0.004,0.053 0.011,0.076c0.007,0.023 0.017,0.042 0.03,0.059c0.013,0.016 0.029,0.029 0.048,0.038c0.019,0.009 0.039,0.013 0.061,0.013c0.023,0 0.044,-0.005 0.063,-0.014c0.019,-0.01 0.036,-0.022 0.051,-0.035l0.037,0.054c-0.022,0.019 -0.047,0.035 -0.074,0.046c-0.027,0.011 -0.055,0.017 -0.084,0.017c-0.032,0 -0.062,-0.006 -0.09,-0.017c-0.028,-0.011 -0.052,-0.028 -0.073,-0.049c-0.02,-0.022 -0.036,-0.049 -0.048,-0.08c-0.011,-0.032 -0.017,-0.068 -0.017,-0.108Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2666.81,297.899)"><path d="M0.09,-0.656l0.098,0l0.127,0.352l0.048,0.134l0.004,0l0.046,-0.134l0.126,-0.352l0.098,0l0,0.656l-0.079,0l0,-0.361c0,-0.029 0.001,-0.062 0.004,-0.097c0.002,-0.035 0.004,-0.068 0.007,-0.097l-0.004,0l-0.053,0.146l-0.126,0.343l-0.047,0l-0.127,-0.343l-0.052,-0.146l-0.004,0c0.002,0.029 0.004,0.062 0.007,0.097c0.003,0.035 0.004,0.068 0.004,0.097l0,0.361l-0.077,0l0,-0.656Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2739.51,297.899)"><path d="M0.075,-0.486l0.083,0l0,0.297c0,0.046 0.007,0.079 0.021,0.1c0.015,0.02 0.038,0.03 0.07,0.03c0.025,0 0.048,-0.007 0.067,-0.02c0.019,-0.013 0.041,-0.033 0.064,-0.062l0,-0.345l0.082,0l0,0.486l-0.068,0l-0.007,-0.076l-0.003,0c-0.023,0.027 -0.046,0.048 -0.072,0.064c-0.024,0.016 -0.054,0.024 -0.088,0.024c-0.052,0 -0.09,-0.016 -0.114,-0.048c-0.023,-0.032 -0.035,-0.079 -0.035,-0.142l0,-0.308Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2793.91,297.899)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2819.41,297.899)"><path d="M0.096,-0.419l-0.072,0l0,-0.062l0.076,-0.005l0.01,-0.136l0.069,0l0,0.136l0.131,0l0,0.067l-0.131,0l0,0.27c0,0.03 0.006,0.053 0.017,0.069c0.01,0.017 0.03,0.025 0.058,0.025c0.009,0 0.018,-0.001 0.028,-0.004c0.01,-0.003 0.019,-0.006 0.027,-0.009l0.016,0.062c-0.013,0.005 -0.028,0.009 -0.044,0.012c-0.015,0.004 -0.031,0.006 -0.046,0.006c-0.026,0 -0.048,-0.004 -0.066,-0.012c-0.017,-0.008 -0.032,-0.019 -0.043,-0.033c-0.011,-0.014 -0.018,-0.031 -0.023,-0.051c-0.005,-0.02 -0.007,-0.042 -0.007,-0.066l0,-0.269Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2853.21,297.899)"><path d="M0.124,-0.586c-0.016,0 -0.029,-0.005 -0.04,-0.015c-0.011,-0.01 -0.017,-0.023 -0.017,-0.038c0,-0.016 0.006,-0.029 0.017,-0.038c0.011,-0.01 0.024,-0.015 0.04,-0.015c0.016,0 0.029,0.005 0.041,0.015c0.01,0.009 0.016,0.022 0.016,0.038c0,0.015 -0.006,0.028 -0.016,0.038c-0.011,0.01 -0.025,0.015 -0.041,0.015Zm-0.042,0.1l0.082,0l0,0.486l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2877.81,297.899)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2903.31,297.899)"><path d="M0.124,-0.586c-0.016,0 -0.029,-0.005 -0.04,-0.015c-0.011,-0.01 -0.017,-0.023 -0.017,-0.038c0,-0.016 0.006,-0.029 0.017,-0.038c0.011,-0.01 0.024,-0.015 0.04,-0.015c0.016,0 0.029,0.005 0.041,0.015c0.01,0.009 0.016,0.022 0.016,0.038c0,0.015 -0.006,0.028 -0.016,0.038c-0.011,0.01 -0.025,0.015 -0.041,0.015Zm-0.042,0.1l0.082,0l0,0.486l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2927.91,297.899)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2982.61,297.899)"><path d="M0.117,0.082c0,0.026 0.012,0.047 0.037,0.062c0.025,0.015 0.06,0.023 0.104,0.023c0.023,0 0.044,-0.003 0.064,-0.009c0.019,-0.005 0.035,-0.013 0.048,-0.021c0.013,-0.01 0.024,-0.02 0.031,-0.032c0.007,-0.012 0.011,-0.024 0.011,-0.037c0,-0.023 -0.008,-0.038 -0.025,-0.047c-0.017,-0.009 -0.041,-0.013 -0.073,-0.013l-0.084,0c-0.009,0 -0.019,-0.001 -0.03,-0.002c-0.011,-0.001 -0.022,-0.003 -0.033,-0.006c-0.017,0.013 -0.03,0.026 -0.038,0.04c-0.008,0.014 -0.012,0.028 -0.012,0.042Zm-0.072,0.011c0,-0.021 0.006,-0.04 0.019,-0.059c0.013,-0.019 0.03,-0.036 0.052,-0.051l0,-0.004c-0.012,-0.007 -0.022,-0.018 -0.03,-0.031c-0.009,-0.013 -0.013,-0.029 -0.013,-0.048c0,-0.021 0.006,-0.039 0.017,-0.054c0.011,-0.015 0.023,-0.027 0.036,-0.036l0,-0.004c-0.016,-0.013 -0.03,-0.031 -0.043,-0.053c-0.013,-0.023 -0.02,-0.049 -0.02,-0.078c0,-0.027 0.005,-0.051 0.015,-0.072c0.009,-0.021 0.022,-0.039 0.039,-0.054c0.017,-0.016 0.036,-0.027 0.059,-0.035c0.022,-0.008 0.045,-0.012 0.07,-0.012c0.013,0 0.026,0.001 0.038,0.004c0.011,0.002 0.022,0.005 0.031,0.008l0.169,0l0,0.063l-0.1,0c0.011,0.011 0.021,0.026 0.029,0.043c0.007,0.017 0.011,0.036 0.011,0.057c0,0.026 -0.005,0.049 -0.014,0.071c-0.009,0.02 -0.022,0.038 -0.038,0.052c-0.016,0.015 -0.035,0.026 -0.057,0.034c-0.021,0.008 -0.044,0.012 -0.069,0.012c-0.012,0 -0.024,-0.002 -0.037,-0.005c-0.013,-0.003 -0.025,-0.007 -0.036,-0.012c-0.009,0.007 -0.016,0.016 -0.022,0.025c-0.006,0.009 -0.009,0.02 -0.009,0.033c0,0.015 0.006,0.028 0.018,0.038c0.012,0.01 0.035,0.015 0.068,0.015l0.094,0c0.057,0 0.099,0.009 0.127,0.028c0.029,0.018 0.043,0.047 0.043,0.088c0,0.023 -0.006,0.044 -0.017,0.065c-0.011,0.02 -0.028,0.038 -0.049,0.053c-0.021,0.015 -0.047,0.028 -0.078,0.037c-0.03,0.009 -0.064,0.013 -0.102,0.013c-0.03,0 -0.057,-0.003 -0.082,-0.009c-0.025,-0.005 -0.046,-0.014 -0.064,-0.025c-0.017,-0.011 -0.031,-0.025 -0.041,-0.041c-0.009,-0.016 -0.014,-0.035 -0.014,-0.056Zm0.201,-0.302c0.014,0 0.027,-0.003 0.039,-0.008c0.013,-0.005 0.024,-0.013 0.033,-0.023c0.01,-0.01 0.018,-0.022 0.023,-0.037c0.005,-0.014 0.008,-0.03 0.008,-0.048c0,-0.036 -0.01,-0.064 -0.03,-0.084c-0.02,-0.019 -0.044,-0.029 -0.073,-0.029c-0.029,0 -0.053,0.01 -0.073,0.029c-0.02,0.02 -0.03,0.048 -0.03,0.084c0,0.018 0.003,0.034 0.008,0.048c0.005,0.015 0.013,0.027 0.022,0.037c0.01,0.01 0.021,0.018 0.033,0.023c0.013,0.005 0.026,0.008 0.04,0.008Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3033.01,297.899)"><path d="M0.075,-0.486l0.083,0l0,0.297c0,0.046 0.007,0.079 0.021,0.1c0.015,0.02 0.038,0.03 0.07,0.03c0.025,0 0.048,-0.007 0.067,-0.02c0.019,-0.013 0.041,-0.033 0.064,-0.062l0,-0.345l0.082,0l0,0.486l-0.068,0l-0.007,-0.076l-0.003,0c-0.023,0.027 -0.046,0.048 -0.072,0.064c-0.024,0.016 -0.054,0.024 -0.088,0.024c-0.052,0 -0.09,-0.016 -0.114,-0.048c-0.023,-0.032 -0.035,-0.079 -0.035,-0.142l0,-0.308Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3087.41,297.899)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3138.61,297.899)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2925.51,397.899)"><path d="M0.09,-0.656l0.201,0c0.036,0 0.069,0.003 0.099,0.01c0.03,0.007 0.055,0.018 0.077,0.032c0.02,0.015 0.037,0.035 0.048,0.06c0.012,0.025 0.018,0.055 0.018,0.091c0,0.035 -0.006,0.065 -0.018,0.09c-0.011,0.025 -0.028,0.046 -0.049,0.063c-0.021,0.017 -0.047,0.029 -0.077,0.038c-0.029,0.008 -0.062,0.012 -0.098,0.012l-0.118,0l0,0.26l-0.083,0l0,-0.656Zm0.191,0.328c0.057,0 0.1,-0.011 0.128,-0.032c0.027,-0.022 0.041,-0.056 0.041,-0.103c0,-0.047 -0.014,-0.08 -0.042,-0.098c-0.028,-0.019 -0.07,-0.028 -0.127,-0.028l-0.108,0l0,0.261l0.108,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2983.11,397.899)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3008.61,397.899)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3059.81,397.899)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3114.51,397.899)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g></g><g transform="matrix(0.24,0,0,0.24,-28.1857,83.6811)"><g transform="matrix(100,0,0,100,2165.71,297.899)"><path d="M0.092,-0.143c0.023,0.025 0.051,0.045 0.083,0.06c0.031,0.015 0.064,0.022 0.098,0.022c0.043,0 0.077,-0.01 0.101,-0.029c0.024,-0.02 0.036,-0.046 0.036,-0.078c0,-0.017 -0.003,-0.031 -0.009,-0.042c-0.005,-0.012 -0.013,-0.022 -0.023,-0.03c-0.009,-0.009 -0.021,-0.016 -0.034,-0.023c-0.013,-0.007 -0.028,-0.014 -0.043,-0.021l-0.094,-0.041c-0.015,-0.007 -0.031,-0.015 -0.047,-0.024c-0.016,-0.009 -0.03,-0.021 -0.043,-0.034c-0.013,-0.013 -0.023,-0.029 -0.031,-0.047c-0.008,-0.019 -0.012,-0.04 -0.012,-0.064c0,-0.025 0.005,-0.048 0.016,-0.069c0.01,-0.021 0.024,-0.04 0.043,-0.055c0.018,-0.016 0.04,-0.028 0.065,-0.037c0.025,-0.009 0.052,-0.013 0.082,-0.013c0.039,0 0.076,0.008 0.109,0.023c0.033,0.015 0.062,0.034 0.085,0.058l-0.045,0.054c-0.02,-0.019 -0.042,-0.034 -0.067,-0.045c-0.024,-0.011 -0.051,-0.017 -0.082,-0.017c-0.037,0 -0.066,0.009 -0.088,0.026c-0.023,0.017 -0.034,0.04 -0.034,0.07c0,0.016 0.003,0.03 0.01,0.041c0.006,0.011 0.014,0.02 0.025,0.029c0.011,0.008 0.022,0.015 0.035,0.022c0.013,0.006 0.026,0.012 0.039,0.017l0.093,0.04c0.019,0.008 0.036,0.017 0.053,0.028c0.017,0.01 0.031,0.022 0.043,0.036c0.012,0.013 0.022,0.029 0.029,0.048c0.007,0.018 0.01,0.039 0.01,0.063c0,0.026 -0.005,0.05 -0.015,0.073c-0.011,0.023 -0.026,0.043 -0.045,0.06c-0.019,0.017 -0.043,0.03 -0.07,0.04c-0.027,0.009 -0.058,0.014 -0.093,0.014c-0.046,0 -0.089,-0.009 -0.128,-0.026c-0.039,-0.017 -0.073,-0.041 -0.102,-0.071l0.05,-0.058Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2219.11,297.899)"><path d="M0.075,-0.486l0.083,0l0,0.297c0,0.046 0.007,0.079 0.021,0.1c0.015,0.02 0.038,0.03 0.07,0.03c0.025,0 0.048,-0.007 0.067,-0.02c0.019,-0.013 0.041,-0.033 0.064,-0.062l0,-0.345l0.082,0l0,0.486l-0.068,0l-0.007,-0.076l-0.003,0c-0.023,0.027 -0.046,0.048 -0.072,0.064c-0.024,0.016 -0.054,0.024 -0.088,0.024c-0.052,0 -0.09,-0.016 -0.114,-0.048c-0.023,-0.032 -0.035,-0.079 -0.035,-0.142l0,-0.308Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2273.51,297.899)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2329.01,297.899)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2384.51,297.899)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2410.01,297.899)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2459.61,297.899)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.021,-0.023 0.044,-0.043 0.069,-0.059c0.025,-0.015 0.053,-0.023 0.082,-0.023c0.037,0 0.066,0.008 0.087,0.024c0.021,0.017 0.037,0.04 0.047,0.069c0.025,-0.028 0.051,-0.051 0.076,-0.068c0.026,-0.017 0.054,-0.025 0.084,-0.025c0.05,0 0.087,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.037,-0.03 -0.068,-0.03c-0.037,0 -0.077,0.025 -0.122,0.075l0,0.352l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.099c-0.015,-0.021 -0.038,-0.031 -0.069,-0.031c-0.037,0 -0.077,0.025 -0.122,0.075l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2542.51,297.899)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2592.11,297.899)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2646.81,297.899)"><path d="M0.096,-0.419l-0.072,0l0,-0.062l0.076,-0.005l0.01,-0.136l0.069,0l0,0.136l0.131,0l0,0.067l-0.131,0l0,0.27c0,0.03 0.006,0.053 0.017,0.069c0.01,0.017 0.03,0.025 0.058,0.025c0.009,0 0.018,-0.001 0.028,-0.004c0.01,-0.003 0.019,-0.006 0.027,-0.009l0.016,0.062c-0.013,0.005 -0.028,0.009 -0.044,0.012c-0.015,0.004 -0.031,0.006 -0.046,0.006c-0.026,0 -0.048,-0.004 -0.066,-0.012c-0.017,-0.008 -0.032,-0.019 -0.043,-0.033c-0.011,-0.014 -0.018,-0.031 -0.023,-0.051c-0.005,-0.02 -0.007,-0.042 -0.007,-0.066l0,-0.269Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2678.81,297.899)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2730.01,297.899)"><path d="M0.082,-0.486l0.068,0l0.007,0.088l0.003,0c0.017,-0.031 0.037,-0.055 0.06,-0.073c0.024,-0.018 0.05,-0.027 0.078,-0.027c0.019,0 0.037,0.003 0.052,0.01l-0.016,0.072c-0.008,-0.003 -0.015,-0.005 -0.022,-0.006c-0.007,-0.001 -0.015,-0.002 -0.025,-0.002c-0.021,0 -0.042,0.008 -0.064,0.025c-0.023,0.017 -0.042,0.046 -0.059,0.087l0,0.312l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2766.61,297.899)"><path d="M0.049,0.134c0.005,0.001 0.011,0.003 0.018,0.005c0.007,0.001 0.013,0.002 0.019,0.002c0.028,0 0.051,-0.01 0.068,-0.03c0.018,-0.019 0.032,-0.044 0.042,-0.074l0.011,-0.036l-0.195,-0.487l0.085,0l0.099,0.269c0.007,0.021 0.015,0.044 0.023,0.067c0.009,0.024 0.017,0.047 0.024,0.07l0.004,0c0.007,-0.022 0.014,-0.045 0.021,-0.069c0.007,-0.024 0.013,-0.047 0.02,-0.068l0.087,-0.269l0.08,0l-0.183,0.526c-0.009,0.024 -0.018,0.046 -0.029,0.067c-0.011,0.021 -0.023,0.038 -0.038,0.053c-0.015,0.015 -0.031,0.027 -0.05,0.036c-0.019,0.009 -0.04,0.013 -0.065,0.013c-0.011,0 -0.022,-0.001 -0.031,-0.003c-0.009,-0.001 -0.018,-0.004 -0.026,-0.007l0.016,-0.065Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2833.51,297.899)"><path d="M0.09,-0.656l0.098,0l0.127,0.352l0.048,0.134l0.004,0l0.046,-0.134l0.126,-0.352l0.098,0l0,0.656l-0.079,0l0,-0.361c0,-0.029 0.001,-0.062 0.004,-0.097c0.002,-0.035 0.004,-0.068 0.007,-0.097l-0.004,0l-0.053,0.146l-0.126,0.343l-0.047,0l-0.127,-0.343l-0.052,-0.146l-0.004,0c0.002,0.029 0.004,0.062 0.007,0.097c0.003,0.035 0.004,0.068 0.004,0.097l0,0.361l-0.077,0l0,-0.656Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2906.21,297.899)"><path d="M0.075,-0.486l0.083,0l0,0.297c0,0.046 0.007,0.079 0.021,0.1c0.015,0.02 0.038,0.03 0.07,0.03c0.025,0 0.048,-0.007 0.067,-0.02c0.019,-0.013 0.041,-0.033 0.064,-0.062l0,-0.345l0.082,0l0,0.486l-0.068,0l-0.007,-0.076l-0.003,0c-0.023,0.027 -0.046,0.048 -0.072,0.064c-0.024,0.016 -0.054,0.024 -0.088,0.024c-0.052,0 -0.09,-0.016 -0.114,-0.048c-0.023,-0.032 -0.035,-0.079 -0.035,-0.142l0,-0.308Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2960.61,297.899)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2986.11,297.899)"><path d="M0.096,-0.419l-0.072,0l0,-0.062l0.076,-0.005l0.01,-0.136l0.069,0l0,0.136l0.131,0l0,0.067l-0.131,0l0,0.27c0,0.03 0.006,0.053 0.017,0.069c0.01,0.017 0.03,0.025 0.058,0.025c0.009,0 0.018,-0.001 0.028,-0.004c0.01,-0.003 0.019,-0.006 0.027,-0.009l0.016,0.062c-0.013,0.005 -0.028,0.009 -0.044,0.012c-0.015,0.004 -0.031,0.006 -0.046,0.006c-0.026,0 -0.048,-0.004 -0.066,-0.012c-0.017,-0.008 -0.032,-0.019 -0.043,-0.033c-0.011,-0.014 -0.018,-0.031 -0.023,-0.051c-0.005,-0.02 -0.007,-0.042 -0.007,-0.066l0,-0.269Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3019.91,297.899)"><path d="M0.124,-0.586c-0.016,0 -0.029,-0.005 -0.04,-0.015c-0.011,-0.01 -0.017,-0.023 -0.017,-0.038c0,-0.016 0.006,-0.029 0.017,-0.038c0.011,-0.01 0.024,-0.015 0.04,-0.015c0.016,0 0.029,0.005 0.041,0.015c0.01,0.009 0.016,0.022 0.016,0.038c0,0.015 -0.006,0.028 -0.016,0.038c-0.011,0.01 -0.025,0.015 -0.041,0.015Zm-0.042,0.1l0.082,0l0,0.486l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3044.51,297.899)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3070.01,297.899)"><path d="M0.124,-0.586c-0.016,0 -0.029,-0.005 -0.04,-0.015c-0.011,-0.01 -0.017,-0.023 -0.017,-0.038c0,-0.016 0.006,-0.029 0.017,-0.038c0.011,-0.01 0.024,-0.015 0.04,-0.015c0.016,0 0.029,0.005 0.041,0.015c0.01,0.009 0.016,0.022 0.016,0.038c0,0.015 -0.006,0.028 -0.016,0.038c-0.011,0.01 -0.025,0.015 -0.041,0.015Zm-0.042,0.1l0.082,0l0,0.486l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3094.61,297.899)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3149.31,297.899)"><path d="M0.117,0.082c0,0.026 0.012,0.047 0.037,0.062c0.025,0.015 0.06,0.023 0.104,0.023c0.023,0 0.044,-0.003 0.064,-0.009c0.019,-0.005 0.035,-0.013 0.048,-0.021c0.013,-0.01 0.024,-0.02 0.031,-0.032c0.007,-0.012 0.011,-0.024 0.011,-0.037c0,-0.023 -0.008,-0.038 -0.025,-0.047c-0.017,-0.009 -0.041,-0.013 -0.073,-0.013l-0.084,0c-0.009,0 -0.019,-0.001 -0.03,-0.002c-0.011,-0.001 -0.022,-0.003 -0.033,-0.006c-0.017,0.013 -0.03,0.026 -0.038,0.04c-0.008,0.014 -0.012,0.028 -0.012,0.042Zm-0.072,0.011c0,-0.021 0.006,-0.04 0.019,-0.059c0.013,-0.019 0.03,-0.036 0.052,-0.051l0,-0.004c-0.012,-0.007 -0.022,-0.018 -0.03,-0.031c-0.009,-0.013 -0.013,-0.029 -0.013,-0.048c0,-0.021 0.006,-0.039 0.017,-0.054c0.011,-0.015 0.023,-0.027 0.036,-0.036l0,-0.004c-0.016,-0.013 -0.03,-0.031 -0.043,-0.053c-0.013,-0.023 -0.02,-0.049 -0.02,-0.078c0,-0.027 0.005,-0.051 0.015,-0.072c0.009,-0.021 0.022,-0.039 0.039,-0.054c0.017,-0.016 0.036,-0.027 0.059,-0.035c0.022,-0.008 0.045,-0.012 0.07,-0.012c0.013,0 0.026,0.001 0.038,0.004c0.011,0.002 0.022,0.005 0.031,0.008l0.169,0l0,0.063l-0.1,0c0.011,0.011 0.021,0.026 0.029,0.043c0.007,0.017 0.011,0.036 0.011,0.057c0,0.026 -0.005,0.049 -0.014,0.071c-0.009,0.02 -0.022,0.038 -0.038,0.052c-0.016,0.015 -0.035,0.026 -0.057,0.034c-0.021,0.008 -0.044,0.012 -0.069,0.012c-0.012,0 -0.024,-0.002 -0.037,-0.005c-0.013,-0.003 -0.025,-0.007 -0.036,-0.012c-0.009,0.007 -0.016,0.016 -0.022,0.025c-0.006,0.009 -0.009,0.02 -0.009,0.033c0,0.015 0.006,0.028 0.018,0.038c0.012,0.01 0.035,0.015 0.068,0.015l0.094,0c0.057,0 0.099,0.009 0.127,0.028c0.029,0.018 0.043,0.047 0.043,0.088c0,0.023 -0.006,0.044 -0.017,0.065c-0.011,0.02 -0.028,0.038 -0.049,0.053c-0.021,0.015 -0.047,0.028 -0.078,0.037c-0.03,0.009 -0.064,0.013 -0.102,0.013c-0.03,0 -0.057,-0.003 -0.082,-0.009c-0.025,-0.005 -0.046,-0.014 -0.064,-0.025c-0.017,-0.011 -0.031,-0.025 -0.041,-0.041c-0.009,-0.016 -0.014,-0.035 -0.014,-0.056Zm0.201,-0.302c0.014,0 0.027,-0.003 0.039,-0.008c0.013,-0.005 0.024,-0.013 0.033,-0.023c0.01,-0.01 0.018,-0.022 0.023,-0.037c0.005,-0.014 0.008,-0.03 0.008,-0.048c0,-0.036 -0.01,-0.064 -0.03,-0.084c-0.02,-0.019 -0.044,-0.029 -0.073,-0.029c-0.029,0 -0.053,0.01 -0.073,0.029c-0.02,0.02 -0.03,0.048 -0.03,0.084c0,0.018 0.003,0.034 0.008,0.048c0.005,0.015 0.013,0.027 0.022,0.037c0.01,0.01 0.021,0.018 0.033,0.023c0.013,0.005 0.026,0.008 0.04,0.008Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3199.71,297.899)"><path d="M0.075,-0.486l0.083,0l0,0.297c0,0.046 0.007,0.079 0.021,0.1c0.015,0.02 0.038,0.03 0.07,0.03c0.025,0 0.048,-0.007 0.067,-0.02c0.019,-0.013 0.041,-0.033 0.064,-0.062l0,-0.345l0.082,0l0,0.486l-0.068,0l-0.007,-0.076l-0.003,0c-0.023,0.027 -0.046,0.048 -0.072,0.064c-0.024,0.016 -0.054,0.024 -0.088,0.024c-0.052,0 -0.09,-0.016 -0.114,-0.048c-0.023,-0.032 -0.035,-0.079 -0.035,-0.142l0,-0.308Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3254.11,297.899)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3305.31,297.899)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3092.21,397.899)"><path d="M0.09,-0.656l0.201,0c0.036,0 0.069,0.003 0.099,0.01c0.03,0.007 0.055,0.018 0.077,0.032c0.02,0.015 0.037,0.035 0.048,0.06c0.012,0.025 0.018,0.055 0.018,0.091c0,0.035 -0.006,0.065 -0.018,0.09c-0.011,0.025 -0.028,0.046 -0.049,0.063c-0.021,0.017 -0.047,0.029 -0.077,0.038c-0.029,0.008 -0.062,0.012 -0.098,0.012l-0.118,0l0,0.26l-0.083,0l0,-0.656Zm0.191,0.328c0.057,0 0.1,-0.011 0.128,-0.032c0.027,-0.022 0.041,-0.056 0.041,-0.103c0,-0.047 -0.014,-0.08 -0.042,-0.098c-0.028,-0.019 -0.07,-0.028 -0.127,-0.028l-0.108,0l0,0.261l0.108,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3149.81,397.899)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3175.31,397.899)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3226.51,397.899)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3281.21,397.899)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g></g><g transform="matrix(0.24,0,0,0.24,-84.7759,-17.5316)"><g transform="matrix(100,0,0,100,2397.91,1078.64)"><path d="M0.092,-0.143c0.023,0.025 0.051,0.045 0.083,0.06c0.031,0.015 0.064,0.022 0.098,0.022c0.043,0 0.077,-0.01 0.101,-0.029c0.024,-0.02 0.036,-0.046 0.036,-0.078c0,-0.017 -0.003,-0.031 -0.009,-0.042c-0.005,-0.012 -0.013,-0.022 -0.023,-0.03c-0.009,-0.009 -0.021,-0.016 -0.034,-0.023c-0.013,-0.007 -0.028,-0.014 -0.043,-0.021l-0.094,-0.041c-0.015,-0.007 -0.031,-0.015 -0.047,-0.024c-0.016,-0.009 -0.03,-0.021 -0.043,-0.034c-0.013,-0.013 -0.023,-0.029 -0.031,-0.047c-0.008,-0.019 -0.012,-0.04 -0.012,-0.064c0,-0.025 0.005,-0.048 0.016,-0.069c0.01,-0.021 0.024,-0.04 0.043,-0.055c0.018,-0.016 0.04,-0.028 0.065,-0.037c0.025,-0.009 0.052,-0.013 0.082,-0.013c0.039,0 0.076,0.008 0.109,0.023c0.033,0.015 0.062,0.034 0.085,0.058l-0.045,0.054c-0.02,-0.019 -0.042,-0.034 -0.067,-0.045c-0.024,-0.011 -0.051,-0.017 -0.082,-0.017c-0.037,0 -0.066,0.009 -0.088,0.026c-0.023,0.017 -0.034,0.04 -0.034,0.07c0,0.016 0.003,0.03 0.01,0.041c0.006,0.011 0.014,0.02 0.025,0.029c0.011,0.008 0.022,0.015 0.035,0.022c0.013,0.006 0.026,0.012 0.039,0.017l0.093,0.04c0.019,0.008 0.036,0.017 0.053,0.028c0.017,0.01 0.031,0.022 0.043,0.036c0.012,0.013 0.022,0.029 0.029,0.048c0.007,0.018 0.01,0.039 0.01,0.063c0,0.026 -0.005,0.05 -0.015,0.073c-0.011,0.023 -0.026,0.043 -0.045,0.06c-0.019,0.017 -0.043,0.03 -0.07,0.04c-0.027,0.009 -0.058,0.014 -0.093,0.014c-0.046,0 -0.089,-0.009 -0.128,-0.026c-0.039,-0.017 -0.073,-0.041 -0.102,-0.071l0.05,-0.058Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2451.31,1078.64)"><path d="M0.075,-0.486l0.083,0l0,0.297c0,0.046 0.007,0.079 0.021,0.1c0.015,0.02 0.038,0.03 0.07,0.03c0.025,0 0.048,-0.007 0.067,-0.02c0.019,-0.013 0.041,-0.033 0.064,-0.062l0,-0.345l0.082,0l0,0.486l-0.068,0l-0.007,-0.076l-0.003,0c-0.023,0.027 -0.046,0.048 -0.072,0.064c-0.024,0.016 -0.054,0.024 -0.088,0.024c-0.052,0 -0.09,-0.016 -0.114,-0.048c-0.023,-0.032 -0.035,-0.079 -0.035,-0.142l0,-0.308Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2505.71,1078.64)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2561.21,1078.64)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2616.71,1078.64)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2642.21,1078.64)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2691.81,1078.64)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.021,-0.023 0.044,-0.043 0.069,-0.059c0.025,-0.015 0.053,-0.023 0.082,-0.023c0.037,0 0.066,0.008 0.087,0.024c0.021,0.017 0.037,0.04 0.047,0.069c0.025,-0.028 0.051,-0.051 0.076,-0.068c0.026,-0.017 0.054,-0.025 0.084,-0.025c0.05,0 0.087,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.037,-0.03 -0.068,-0.03c-0.037,0 -0.077,0.025 -0.122,0.075l0,0.352l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.099c-0.015,-0.021 -0.038,-0.031 -0.069,-0.031c-0.037,0 -0.077,0.025 -0.122,0.075l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2774.71,1078.64)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2824.31,1078.64)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2879.01,1078.64)"><path d="M0.096,-0.419l-0.072,0l0,-0.062l0.076,-0.005l0.01,-0.136l0.069,0l0,0.136l0.131,0l0,0.067l-0.131,0l0,0.27c0,0.03 0.006,0.053 0.017,0.069c0.01,0.017 0.03,0.025 0.058,0.025c0.009,0 0.018,-0.001 0.028,-0.004c0.01,-0.003 0.019,-0.006 0.027,-0.009l0.016,0.062c-0.013,0.005 -0.028,0.009 -0.044,0.012c-0.015,0.004 -0.031,0.006 -0.046,0.006c-0.026,0 -0.048,-0.004 -0.066,-0.012c-0.017,-0.008 -0.032,-0.019 -0.043,-0.033c-0.011,-0.014 -0.018,-0.031 -0.023,-0.051c-0.005,-0.02 -0.007,-0.042 -0.007,-0.066l0,-0.269Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2911.01,1078.64)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2962.21,1078.64)"><path d="M0.082,-0.486l0.068,0l0.007,0.088l0.003,0c0.017,-0.031 0.037,-0.055 0.06,-0.073c0.024,-0.018 0.05,-0.027 0.078,-0.027c0.019,0 0.037,0.003 0.052,0.01l-0.016,0.072c-0.008,-0.003 -0.015,-0.005 -0.022,-0.006c-0.007,-0.001 -0.015,-0.002 -0.025,-0.002c-0.021,0 -0.042,0.008 -0.064,0.025c-0.023,0.017 -0.042,0.046 -0.059,0.087l0,0.312l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,2998.81,1078.64)"><path d="M0.049,0.134c0.005,0.001 0.011,0.003 0.018,0.005c0.007,0.001 0.013,0.002 0.019,0.002c0.028,0 0.051,-0.01 0.068,-0.03c0.018,-0.019 0.032,-0.044 0.042,-0.074l0.011,-0.036l-0.195,-0.487l0.085,0l0.099,0.269c0.007,0.021 0.015,0.044 0.023,0.067c0.009,0.024 0.017,0.047 0.024,0.07l0.004,0c0.007,-0.022 0.014,-0.045 0.021,-0.069c0.007,-0.024 0.013,-0.047 0.02,-0.068l0.087,-0.269l0.08,0l-0.183,0.526c-0.009,0.024 -0.018,0.046 -0.029,0.067c-0.011,0.021 -0.023,0.038 -0.038,0.053c-0.015,0.015 -0.031,0.027 -0.05,0.036c-0.019,0.009 -0.04,0.013 -0.065,0.013c-0.011,0 -0.022,-0.001 -0.031,-0.003c-0.009,-0.001 -0.018,-0.004 -0.026,-0.007l0.016,-0.065Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3065.71,1078.64)"><rect x="0.09" y="-0.656" width="0.083" height="0.656" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3092.01,1078.64)"><path d="M0.047,-0.242c0,-0.039 0.006,-0.075 0.018,-0.107c0.011,-0.031 0.027,-0.058 0.046,-0.08c0.019,-0.022 0.042,-0.039 0.067,-0.051c0.025,-0.012 0.052,-0.018 0.08,-0.018c0.028,0 0.052,0.005 0.073,0.015c0.021,0.01 0.042,0.024 0.063,0.041l-0.004,-0.083l0,-0.187l0.083,0l0,0.712l-0.068,0l-0.007,-0.057l-0.003,0c-0.019,0.019 -0.042,0.035 -0.067,0.049c-0.025,0.013 -0.051,0.02 -0.08,0.02c-0.061,0 -0.11,-0.022 -0.147,-0.066c-0.036,-0.044 -0.054,-0.107 -0.054,-0.188Zm0.085,-0.001c0,0.059 0.012,0.104 0.035,0.137c0.023,0.033 0.056,0.049 0.099,0.049c0.023,0 0.044,-0.006 0.064,-0.017c0.02,-0.011 0.04,-0.027 0.06,-0.05l0,-0.254c-0.021,-0.019 -0.041,-0.032 -0.059,-0.039c-0.02,-0.008 -0.039,-0.012 -0.059,-0.012c-0.019,0 -0.038,0.004 -0.055,0.013c-0.017,0.009 -0.031,0.022 -0.044,0.038c-0.013,0.017 -0.023,0.036 -0.03,0.059c-0.007,0.023 -0.011,0.048 -0.011,0.076Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3147.51,1078.64)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3197.11,1078.64)"><path d="M0.046,-0.242c0,-0.041 0.006,-0.077 0.019,-0.109c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.021,-0.022 0.045,-0.039 0.071,-0.05c0.027,-0.011 0.056,-0.017 0.086,-0.017c0.03,0 0.058,0.006 0.085,0.017c0.027,0.011 0.051,0.028 0.072,0.05c0.021,0.022 0.037,0.049 0.049,0.08c0.013,0.032 0.019,0.068 0.019,0.109c0,0.04 -0.006,0.076 -0.019,0.107c-0.012,0.032 -0.028,0.059 -0.049,0.081c-0.021,0.021 -0.045,0.038 -0.072,0.049c-0.027,0.011 -0.055,0.017 -0.085,0.017c-0.03,0 -0.059,-0.006 -0.086,-0.017c-0.026,-0.011 -0.05,-0.028 -0.071,-0.049c-0.021,-0.022 -0.037,-0.049 -0.049,-0.081c-0.013,-0.031 -0.019,-0.067 -0.019,-0.107Zm0.085,0c0,0.028 0.003,0.053 0.01,0.076c0.007,0.023 0.016,0.042 0.028,0.058c0.013,0.017 0.028,0.029 0.045,0.038c0.017,0.009 0.036,0.014 0.057,0.014c0.021,0 0.04,-0.005 0.057,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.035 0.029,-0.058c0.007,-0.023 0.01,-0.048 0.01,-0.076c0,-0.028 -0.003,-0.054 -0.01,-0.077c-0.007,-0.022 -0.016,-0.042 -0.029,-0.059c-0.012,-0.017 -0.027,-0.03 -0.044,-0.038c-0.017,-0.01 -0.036,-0.014 -0.057,-0.014c-0.021,0 -0.04,0.005 -0.057,0.014c-0.017,0.008 -0.032,0.021 -0.045,0.038c-0.012,0.017 -0.021,0.037 -0.028,0.059c-0.007,0.023 -0.01,0.049 -0.01,0.077Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3251.31,1078.64)"><path d="M0.117,0.082c0,0.026 0.012,0.047 0.037,0.062c0.025,0.015 0.06,0.023 0.104,0.023c0.023,0 0.044,-0.003 0.064,-0.009c0.019,-0.005 0.035,-0.013 0.048,-0.021c0.013,-0.01 0.024,-0.02 0.031,-0.032c0.007,-0.012 0.011,-0.024 0.011,-0.037c0,-0.023 -0.008,-0.038 -0.025,-0.047c-0.017,-0.009 -0.041,-0.013 -0.073,-0.013l-0.084,0c-0.009,0 -0.019,-0.001 -0.03,-0.002c-0.011,-0.001 -0.022,-0.003 -0.033,-0.006c-0.017,0.013 -0.03,0.026 -0.038,0.04c-0.008,0.014 -0.012,0.028 -0.012,0.042Zm-0.072,0.011c0,-0.021 0.006,-0.04 0.019,-0.059c0.013,-0.019 0.03,-0.036 0.052,-0.051l0,-0.004c-0.012,-0.007 -0.022,-0.018 -0.03,-0.031c-0.009,-0.013 -0.013,-0.029 -0.013,-0.048c0,-0.021 0.006,-0.039 0.017,-0.054c0.011,-0.015 0.023,-0.027 0.036,-0.036l0,-0.004c-0.016,-0.013 -0.03,-0.031 -0.043,-0.053c-0.013,-0.023 -0.02,-0.049 -0.02,-0.078c0,-0.027 0.005,-0.051 0.015,-0.072c0.009,-0.021 0.022,-0.039 0.039,-0.054c0.017,-0.016 0.036,-0.027 0.059,-0.035c0.022,-0.008 0.045,-0.012 0.07,-0.012c0.013,0 0.026,0.001 0.038,0.004c0.011,0.002 0.022,0.005 0.031,0.008l0.169,0l0,0.063l-0.1,0c0.011,0.011 0.021,0.026 0.029,0.043c0.007,0.017 0.011,0.036 0.011,0.057c0,0.026 -0.005,0.049 -0.014,0.071c-0.009,0.02 -0.022,0.038 -0.038,0.052c-0.016,0.015 -0.035,0.026 -0.057,0.034c-0.021,0.008 -0.044,0.012 -0.069,0.012c-0.012,0 -0.024,-0.002 -0.037,-0.005c-0.013,-0.003 -0.025,-0.007 -0.036,-0.012c-0.009,0.007 -0.016,0.016 -0.022,0.025c-0.006,0.009 -0.009,0.02 -0.009,0.033c0,0.015 0.006,0.028 0.018,0.038c0.012,0.01 0.035,0.015 0.068,0.015l0.094,0c0.057,0 0.099,0.009 0.127,0.028c0.029,0.018 0.043,0.047 0.043,0.088c0,0.023 -0.006,0.044 -0.017,0.065c-0.011,0.02 -0.028,0.038 -0.049,0.053c-0.021,0.015 -0.047,0.028 -0.078,0.037c-0.03,0.009 -0.064,0.013 -0.102,0.013c-0.03,0 -0.057,-0.003 -0.082,-0.009c-0.025,-0.005 -0.046,-0.014 -0.064,-0.025c-0.017,-0.011 -0.031,-0.025 -0.041,-0.041c-0.009,-0.016 -0.014,-0.035 -0.014,-0.056Zm0.201,-0.302c0.014,0 0.027,-0.003 0.039,-0.008c0.013,-0.005 0.024,-0.013 0.033,-0.023c0.01,-0.01 0.018,-0.022 0.023,-0.037c0.005,-0.014 0.008,-0.03 0.008,-0.048c0,-0.036 -0.01,-0.064 -0.03,-0.084c-0.02,-0.019 -0.044,-0.029 -0.073,-0.029c-0.029,0 -0.053,0.01 -0.073,0.029c-0.02,0.02 -0.03,0.048 -0.03,0.084c0,0.018 0.003,0.034 0.008,0.048c0.005,0.015 0.013,0.027 0.022,0.037c0.01,0.01 0.021,0.018 0.033,0.023c0.013,0.005 0.026,0.008 0.04,0.008Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3301.71,1078.64)"><path d="M0.082,-0.486l0.068,0l0.007,0.088l0.003,0c0.017,-0.031 0.037,-0.055 0.06,-0.073c0.024,-0.018 0.05,-0.027 0.078,-0.027c0.019,0 0.037,0.003 0.052,0.01l-0.016,0.072c-0.008,-0.003 -0.015,-0.005 -0.022,-0.006c-0.007,-0.001 -0.015,-0.002 -0.025,-0.002c-0.021,0 -0.042,0.008 -0.064,0.025c-0.023,0.017 -0.042,0.046 -0.059,0.087l0,0.312l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3333.91,1078.64)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3385.11,1078.64)"><path d="M0.164,0.041l0,0.164l-0.082,0l0,-0.691l0.068,0l0.007,0.056l0.003,0c0.022,-0.019 0.046,-0.035 0.072,-0.048c0.027,-0.013 0.054,-0.02 0.083,-0.02c0.031,0 0.059,0.006 0.083,0.018c0.024,0.011 0.044,0.028 0.06,0.05c0.016,0.021 0.028,0.047 0.036,0.078c0.009,0.03 0.013,0.064 0.013,0.102c0,0.041 -0.006,0.078 -0.017,0.11c-0.011,0.033 -0.027,0.06 -0.046,0.083c-0.019,0.023 -0.042,0.04 -0.067,0.052c-0.025,0.011 -0.052,0.017 -0.08,0.017c-0.023,0 -0.045,-0.005 -0.068,-0.015c-0.022,-0.01 -0.044,-0.024 -0.067,-0.041l0.002,0.085Zm0,-0.149c0.022,0.019 0.043,0.032 0.064,0.039c0.021,0.008 0.039,0.012 0.055,0.012c0.02,0 0.038,-0.005 0.055,-0.014c0.017,-0.009 0.032,-0.021 0.044,-0.038c0.013,-0.016 0.022,-0.036 0.029,-0.06c0.007,-0.024 0.011,-0.051 0.011,-0.081c0,-0.027 -0.002,-0.051 -0.007,-0.073c-0.005,-0.022 -0.012,-0.041 -0.023,-0.056c-0.01,-0.016 -0.023,-0.028 -0.04,-0.037c-0.016,-0.009 -0.035,-0.013 -0.058,-0.013c-0.021,0 -0.042,0.006 -0.063,0.017c-0.021,0.011 -0.043,0.028 -0.067,0.049l0,0.255Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3440.61,1078.64)"><path d="M0.082,-0.712l0.082,0l0,0.194l-0.003,0.1c0.023,-0.022 0.048,-0.041 0.073,-0.056c0.025,-0.016 0.055,-0.024 0.089,-0.024c0.051,0 0.089,0.016 0.113,0.048c0.023,0.032 0.035,0.079 0.035,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.099c-0.015,-0.021 -0.038,-0.031 -0.07,-0.031c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.712Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3495.01,1078.64)"><path d="M0.124,-0.586c-0.016,0 -0.029,-0.005 -0.04,-0.015c-0.011,-0.01 -0.017,-0.023 -0.017,-0.038c0,-0.016 0.006,-0.029 0.017,-0.038c0.011,-0.01 0.024,-0.015 0.04,-0.015c0.016,0 0.029,0.005 0.041,0.015c0.01,0.009 0.016,0.022 0.016,0.038c0,0.015 -0.006,0.028 -0.016,0.038c-0.011,0.01 -0.025,0.015 -0.041,0.015Zm-0.042,0.1l0.082,0l0,0.486l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3519.61,1078.64)"><path d="M0.046,-0.242c0,-0.041 0.006,-0.077 0.019,-0.109c0.013,-0.031 0.03,-0.058 0.051,-0.08c0.021,-0.022 0.046,-0.039 0.075,-0.05c0.028,-0.011 0.058,-0.017 0.089,-0.017c0.032,0 0.059,0.006 0.082,0.018c0.023,0.011 0.043,0.025 0.06,0.04l-0.041,0.053c-0.015,-0.013 -0.03,-0.023 -0.046,-0.031c-0.015,-0.008 -0.033,-0.012 -0.052,-0.012c-0.022,0 -0.042,0.005 -0.061,0.014c-0.019,0.009 -0.035,0.021 -0.048,0.038c-0.013,0.017 -0.024,0.037 -0.032,0.06c-0.007,0.023 -0.011,0.048 -0.011,0.076c0,0.028 0.004,0.053 0.011,0.076c0.007,0.023 0.017,0.042 0.03,0.059c0.013,0.016 0.029,0.029 0.048,0.038c0.019,0.009 0.039,0.013 0.061,0.013c0.023,0 0.044,-0.005 0.063,-0.014c0.019,-0.01 0.036,-0.022 0.051,-0.035l0.037,0.054c-0.022,0.019 -0.047,0.035 -0.074,0.046c-0.027,0.011 -0.055,0.017 -0.084,0.017c-0.032,0 -0.062,-0.006 -0.09,-0.017c-0.028,-0.011 -0.052,-0.028 -0.073,-0.049c-0.02,-0.022 -0.036,-0.049 -0.048,-0.08c-0.011,-0.032 -0.017,-0.068 -0.017,-0.108Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3326.61,1178.64)"><path d="M0.09,-0.656l0.201,0c0.036,0 0.069,0.003 0.099,0.01c0.03,0.007 0.055,0.018 0.077,0.032c0.02,0.015 0.037,0.035 0.048,0.06c0.012,0.025 0.018,0.055 0.018,0.091c0,0.035 -0.006,0.065 -0.018,0.09c-0.011,0.025 -0.028,0.046 -0.049,0.063c-0.021,0.017 -0.047,0.029 -0.077,0.038c-0.029,0.008 -0.062,0.012 -0.098,0.012l-0.118,0l0,0.26l-0.083,0l0,-0.656Zm0.191,0.328c0.057,0 0.1,-0.011 0.128,-0.032c0.027,-0.022 0.041,-0.056 0.041,-0.103c0,-0.047 -0.014,-0.08 -0.042,-0.098c-0.028,-0.019 -0.07,-0.028 -0.127,-0.028l-0.108,0l0,0.261l0.108,0Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3384.21,1178.64)"><path d="M0.082,-0.712l0.082,0l0,0.62c0,0.013 0.002,0.023 0.007,0.028c0.005,0.005 0.01,0.008 0.016,0.008l0.008,0c0.002,0 0.005,-0.001 0.01,-0.002l0.011,0.062c-0.005,0.003 -0.012,0.005 -0.019,0.006c-0.007,0.001 -0.017,0.002 -0.028,0.002c-0.031,0 -0.054,-0.009 -0.067,-0.028c-0.013,-0.019 -0.02,-0.046 -0.02,-0.082l0,-0.614Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3409.71,1178.64)"><path d="M0.058,-0.126c0,-0.053 0.024,-0.094 0.072,-0.123c0.047,-0.028 0.123,-0.048 0.227,-0.059c0,-0.015 -0.002,-0.03 -0.005,-0.045c-0.003,-0.015 -0.008,-0.028 -0.015,-0.039c-0.008,-0.011 -0.018,-0.021 -0.031,-0.028c-0.013,-0.007 -0.029,-0.01 -0.049,-0.01c-0.029,0 -0.055,0.005 -0.079,0.016c-0.025,0.011 -0.047,0.023 -0.066,0.036l-0.033,-0.057c0.023,-0.015 0.05,-0.029 0.083,-0.043c0.033,-0.013 0.069,-0.02 0.108,-0.02c0.059,0 0.102,0.018 0.129,0.054c0.027,0.037 0.04,0.085 0.04,0.146l0,0.298l-0.068,0l-0.007,-0.058l-0.002,0c-0.023,0.019 -0.048,0.036 -0.075,0.05c-0.027,0.013 -0.056,0.02 -0.086,0.02c-0.041,0 -0.075,-0.012 -0.102,-0.036c-0.027,-0.024 -0.041,-0.058 -0.041,-0.102Zm0.081,-0.006c0,0.028 0.008,0.048 0.025,0.06c0.016,0.012 0.036,0.018 0.06,0.018c0.023,0 0.046,-0.005 0.067,-0.016c0.021,-0.011 0.043,-0.028 0.066,-0.049l0,-0.135c-0.041,0.005 -0.075,0.012 -0.103,0.019c-0.028,0.007 -0.05,0.016 -0.067,0.026c-0.017,0.01 -0.03,0.022 -0.037,0.035c-0.007,0.013 -0.011,0.027 -0.011,0.042Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3460.91,1178.64)"><path d="M0.082,-0.486l0.068,0l0.007,0.07l0.003,0c0.023,-0.023 0.048,-0.043 0.073,-0.059c0.026,-0.015 0.056,-0.023 0.09,-0.023c0.051,0 0.089,0.016 0.112,0.048c0.024,0.032 0.036,0.079 0.036,0.142l0,0.308l-0.082,0l0,-0.297c0,-0.046 -0.007,-0.079 -0.022,-0.1c-0.015,-0.02 -0.038,-0.03 -0.07,-0.03c-0.025,0 -0.048,0.006 -0.067,0.019c-0.019,0.013 -0.041,0.031 -0.066,0.056l0,0.352l-0.082,0l0,-0.486Z" style="fill-rule:nonzero;"/></g><g transform="matrix(100,0,0,100,3515.61,1178.64)"><path d="M0.046,-0.242c0,-0.04 0.006,-0.076 0.019,-0.108c0.012,-0.031 0.028,-0.058 0.049,-0.08c0.02,-0.022 0.043,-0.039 0.069,-0.05c0.026,-0.012 0.053,-0.018 0.081,-0.018c0.031,0 0.058,0.005 0.083,0.016c0.024,0.011 0.044,0.026 0.061,0.046c0.016,0.02 0.028,0.044 0.037,0.072c0.009,0.028 0.013,0.059 0.013,0.094c0,0.018 -0.001,0.033 -0.003,0.045l-0.328,0c0.003,0.053 0.019,0.094 0.049,0.125c0.029,0.031 0.066,0.046 0.113,0.046c0.023,0 0.045,-0.003 0.065,-0.01c0.019,-0.007 0.038,-0.017 0.056,-0.028l0.029,0.054c-0.021,0.013 -0.045,0.025 -0.071,0.035c-0.026,0.01 -0.056,0.015 -0.089,0.015c-0.033,0 -0.063,-0.006 -0.092,-0.017c-0.028,-0.012 -0.053,-0.029 -0.074,-0.05c-0.021,-0.022 -0.037,-0.049 -0.049,-0.08c-0.012,-0.031 -0.018,-0.067 -0.018,-0.107Zm0.34,-0.037c0,-0.05 -0.011,-0.088 -0.032,-0.114c-0.021,-0.027 -0.05,-0.04 -0.088,-0.04c-0.017,0 -0.034,0.004 -0.05,0.011c-0.015,0.006 -0.029,0.016 -0.042,0.029c-0.013,0.013 -0.023,0.029 -0.032,0.048c-0.008,0.019 -0.013,0.041 -0.016,0.066l0.26,0Z" style="fill-rule:nonzero;"/></g></g><path d="M498.672,535.845c4.608,0 7.68,-1.296 9.216,-3.888c1.536,-2.592 2.304,-6.48 2.304,-11.664c0,-4.8 -0.144,-9.36 -0.432,-13.68c-0.288,-4.32 -0.432,-9.168 -0.432,-14.544c0,-3.936 0.456,-7.152 1.368,-9.648c0.912,-2.496 2.76,-4.176 5.544,-5.04l0,-0.576c-2.784,-0.864 -4.632,-2.52 -5.544,-4.968c-0.912,-2.448 -1.368,-5.688 -1.368,-9.72c0,-5.376 0.144,-10.224 0.432,-14.544c0.288,-4.32 0.432,-8.88 0.432,-13.68c0,-5.184 -0.768,-9.072 -2.304,-11.664c-1.536,-2.592 -4.608,-3.888 -9.216,-3.888l-4.608,0l0,-3.168l4.32,0c2.592,0 4.848,0.264 6.768,0.792c1.92,0.528 3.528,1.488 4.824,2.88c1.296,1.392 2.28,3.264 2.952,5.616c0.672,2.352 1.008,5.304 1.008,8.856c0,5.376 -0.192,10.512 -0.576,15.408c-0.384,4.896 -0.576,9.936 -0.576,15.12c0,1.44 0.168,2.856 0.504,4.248c0.336,1.392 0.96,2.616 1.872,3.672c0.912,1.056 2.184,1.92 3.816,2.592c1.632,0.672 3.696,1.008 6.192,1.008l0,3.456c-2.496,0 -4.56,0.336 -6.192,1.008c-1.632,0.672 -2.904,1.56 -3.816,2.664c-0.912,1.104 -1.536,2.352 -1.872,3.744c-0.336,1.392 -0.504,2.856 -0.504,4.392c0,5.088 0.192,10.056 0.576,14.904c0.384,4.848 0.576,9.96 0.576,15.336c0,3.648 -0.336,6.624 -1.008,8.928c-0.672,2.304 -1.656,4.152 -2.952,5.544c-1.296,1.392 -2.904,2.352 -4.824,2.88c-1.92,0.528 -4.176,0.792 -6.768,0.792l-4.32,0l0,-3.168l4.608,0Z" style="fill-rule:nonzero;"/></svg>
  


<h3 id="addresses-and-names">Addresses and names</h3>
<p>Second, Unicode defined an addressing scheme. In previous character sets, there was an immediate equivalence between the character and the bytes you used for representing that character. In contrast to that approach, the Unicode character set only concerns itself with giving each character an address in the array (its <code>U+</code> number) and a name.</p>
<p>The number and the name define what is called a code point. All code points are created equal — some have semantics but from an addressing standpoint, there is no fundamental difference between characters such as U+006B <code>LATIN SMALL LETTER K</code> (k), symbols such as U+27A4 <code>BLACK RIGHTWARDS ARROWHEAD</code> (➤) and emojis such as U+1F63B <code>smiling cat face with heart-shaped eyes</code> (😻).</p>
<p>It&rsquo;s in the Unicode mission statement:</p>
<blockquote>
<p>Unicode provides a unique number for every character</p>
</blockquote>
<h3 id="code-points-bonanza">Code points bonanza</h3>
<p>Unicode defines over a hundred thousand code points that cover over a hundred scripts (a script is a writing system such as Arabic, Cyrillic, ancient Greek, Hebrew, Latin, etc…). Because there is so much room to grow, Unicode also defines characters that are used in <a href="https://en.wikipedia.org/wiki/Musical_Symbols_(Unicode_block)">music</a> or in <a href="https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode">mathematics</a>.</p>
<p>Because there is so much space available, Unicode can afford to define code points that resemble one another but that have different semantics. U+03A3 <code>GREEK CAPITAL LETTER SIGMA</code> (Σ) and U+1D6BA <code>MATHEMATICAL BOLD CAPITAL SIGMA</code> (𝚺) are different code points even though the latter stems from the former.</p>
<p>Look-alike characters also get distinct code points: U+0430 <code>CYRILLIC SMALL LETTER A</code> (а) is a different character than U+0061 <code>LATIN SMALL LETTER A</code> (a). Same goes for U+03B2 <code>GREEK SMALL LETTER BETA</code> (β) and U+00DF <code>LATIN SMALL LETTER SHARP S</code> (ß). In other words, Unicode doesn&rsquo;t concern itself with the <em>shape</em> of a character, it concerns itself with its formal definition and its function. And since there&rsquo;s plenty of room, Unicode can be extremely specific to define all the variations of what might otherwise pass for the same character.</p>
<p>The minutiae can go quite far. An interesting example is that the Western latin script and its numbering system is fairly prevalent in the world, and it is common that other scripts (Arabic, Cyrillic, Hebrew, etc…) need to use latin characters in contexts where it mixed with local ones.</p>
<p>For mostly aesthetic reasons, the Japanese and Chinese languages have defined a different mode for writing those, where, in order to match the natural width of ideographs, the physical width of the glyph (the space taken by the character on the screen) is bigger than it normally would be.</p>
<p>Unicode defines those as separate code points from the original one they are based on. For instance, U+FF43 <code>FULLWIDTH LATIN SMALL LETTER C</code> (ｃ) is intrinsically the same as U+0063 <code>LATIN SMALL LETTER C</code> (c) but it is defined separately from the standpoint of Unicode.</p>
<p>Conversely, there is a also a set of Katakana characters that are defined as &ldquo;half-width&rdquo; (e.g. U+FF76 <code>HALFWIDTH KATAKANA LETTER KA</code> ｶ) compared to their natural full-width base (U+30AB <code>KATAKANA LETTER KA</code> カ).</p>
<h3 id="versions">Versions</h3>
<p>Lastly, Unicode took care of defining versions of its character set. As of this writing, the most recent version of Unicode is 13, and it defines 143,859 code points. Unlike other character sets, Unicode planned ahead to allow for the character set to grow and for these changes to roll-out in a way that is backwards-compatible.</p>
<p>When new characters such as emojis came around, all that needed to happen is to assign each of them a U+ number and a name, and that was that.</p>



  
    
      
      <img src="/codes/i-love-unicode-character-set/versions_hu7ab1dd742a6411a730de8ba7ae8abd3f_271320_1000x0_resize_box_3.png" alt="Chart of scripts and code points defined in various Unicode versions"/>
    
  


<h3 id="fonts-and-rendering">Fonts and rendering</h3>
<p>After new code points are defined in a Unicode release, two more steps need to be taken for the end user to actually be able to benefit from it:</p>
<ul>
<li>OS vendors (Apple for macOS, Google for Android, etc…) need to bump up their Unicode version to include support for those characters</li>
<li>Font vendors (e.g. <a href="https://twemoji.twitter.com/">Twitter</a>, Microsoft, Apple, <a href="https://www.google.com/get/noto">Google</a>) need to add glyphs (graphical symbols) to represent those characters.</li>
</ul>
<p>As mentioned before, Unicode doesn&rsquo;t focus on character shapes but end users need that! Fonts embed the data for converting Unicode code points into <em>glyphs</em>, which are what you see on your screen. They are orthogonal to the Unicode standard but they are critical to the user experience of the Unicode character set.</p>
<p>A &ldquo;missing character&rdquo; in a string you see on screen might be because the operating system doesn&rsquo;t recognize it, or because there&rsquo;s no available font that knows what to make of that code point (or sequence of code points). No single font can represent all Unicode code points because of size limits with popular font file formats. As a result, vendors segment their font files by script or sometimes regions.</p>
<p>If you were to use an old version of, e.g. Android, newer emojis would not render correctly but would also not crash your system: the Unicode implementation would just see a code point it doesn&rsquo;t know about and handles it</p>
<ul>
<li>If this is an issue with the underlying encoding, the character should be replaced U+FFFD <code>REPLACEMENT CHARACTER</code> (�)</li>
<li>If there is no available font to render the code point, the system should use a generic replacement glyph, e.g. &ldquo;󰀀&rdquo;</li>
</ul>
]]></content>
        </entry>
    
        <entry>
            <title>I � Unicode</title>
            <link href="https://www.eiggen.co/codes/i-love-unicode/"/>
            <updated>2020-03-17T00:00:00+0000</updated>
            <id>https://www.eiggen.co/codes/i-love-unicode/</id>
            <content type="html"><![CDATA[ <h2 id="introduction">Introduction</h2>
<p>If you work in computer science, the sentence &ldquo;It&rsquo;s probably just a Unicode character&rdquo; is probably one that you have heard thrown around more than once in your career. It&rsquo;s one after which the people in the room generally shrug it off as one of those inevitable quirks of working with computers and move on with their day because, well, what else is there to do today?</p>
<p>In another instance, you might have found yourself trying make sense of a blob of bytes content using various flavors and combinations of ASCII and then UTF-8 and then converting back to binary without always understanding what went on and how you got it working. But that email parsing functionality you were tasked to deliver is working now, at least until you start shipping your software in Bulgaria or Uzbekistan, at which point you&rsquo;ll hopefully be two jobs further along in your career.</p>
<p>And there is this set of JIRA tickets, all carefully labelled <code>i18n</code> by your predecessor, where your users report being unable to get the right search results when they search for the content they have hosted in the CMS you sell them. Some of them even provide reproducible examples of issues with your software&rsquo;s indexing. But there&rsquo;s few enough of them that you brush it off as an edge case: &ldquo;It&rsquo;s probably just a Unicode character or something like that&rdquo;. You decide to further label all tickets with <code>intern</code> and <code>starter-task</code>.</p>
<h2 id="a-primer-on-unicode">A primer on Unicode</h2>
<p>Joking aside, this series is intended as a moderately advanced explainer for people who want to educate themselves about what Unicode is. The reason for it to be is that there are very few places on the Internet that strike the right balance between Joel Spolsky&rsquo;s <a href="https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/">Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
</a> (which is an absolute must-read) and the <a href="http://unicode.org/main.html">technical portal</a> on the official Unicode website (that homepage got a welcome revamp in 2020, let&rsquo;s hope it will expand to the documentation sections too)</p>
<p>Unicode is <em>a lot</em> of different things to different people. It&rsquo;s easier to work backwards from what the goal of Unicode is: enable everyone to use their own language on any digital platform. That&rsquo;s a lofty goal, especially at the time it was formulated all the way back in the early 1990&rsquo;s.</p>
<p>However, and unlike most standards and specifications that came in the wake of dozen others, Unicode has actually risen to be the prevailing set of modern standards for managing text on billions of computers and phones. Since there&rsquo;s a XKCD for everything, there&rsquo;s also an anti-XKCD for everything:</p>
<p><img src="https://imgs.xkcd.com/comics/standards.png" alt="Standards" title="Fortunately, the charging one has been solved now that we've all standardized on mini-USB. Or is it micro-USB? Shit."></p>
<p>I will repeat myself: Unicode is <em>a lot</em> of different things to different people. That&rsquo;s because the Unicode standard is a vast and complex one: it attempts to formalize the complexities and intricacies of text, which is a thorny and culturally touchy domain. It seeks to bridge the gap between computers and programmers, who expect rules and structures, and languages and humans, who are messy and history-rich.</p>
<p>For this series, I will focus on three aspects of the Unicode standard:</p>
<ul>
<li><a href="/codes/i-love-unicode-character-set">The character set</a>: what is the Unicode character set and how does it differ from ones that came before?</li>
<li><a href="/codes/i-love-unicode-encodings">The encodings</a>: what exactly is an encoding and why it is a requirement for Unicode I/O?</li>
<li><a href="/codes/i-love-unicode-algorithms">The algorithms</a>: beyond characters and codepoints, what higher-level problems does the Unicode standard consider and address?</li>
</ul>
<h2 id="code-and-examples">Code and examples</h2>
<p>The code used to generate the tables in this series (and more) can be found on GitHub at <a href="https://github.com/jsilland/unicode">jsilland/unicode</a>. The examples are in Java but are intended to demonstrate concepts that are applicable and accessible in most languages that have access to a port of CLDR. Contributions and examples in other programming languages are welcome.</p>
]]></content>
        </entry>
    
        <entry>
            <title>I find your lack of 🎉 disturbing</title>
            <link href="https://www.eiggen.co/codes/i-find-your-lack-of-disturbing/"/>
            <updated>2020-02-27T00:00:00+0000</updated>
            <id>https://www.eiggen.co/codes/i-find-your-lack-of-disturbing/</id>
            <content type="html"><![CDATA[ <p>This story dates back from when I worked at <a href="https://strava.com">Strava</a>. At the time, Strava ran its main web and API service on Ruby on Rails v3 (which has since been <a href="https://medium.com/strava-engineering/upgrading-strava-to-rails-5-0-f42e7ac939e4">upgraded</a>) and stored most of the data in MySQL.</p>
<p>Despite its status as the go-to social network for millions of athletes, Strava was missing support for emojis until the second half of 2017. This wasn&rsquo;t even something that came on our radar as a feature request from users, but the content on Strava looked flat compared to other places where users are free to type in text. Facebook, Twitter, Slack and even GitHub are places where emojis have taken on like wildfire: it&rsquo;s just part of the world&rsquo;s vocabulary and Strava users were left behind.</p>
<p>But even before the engineering team looked seriously into supporting emojis, one of my coworkers asked why the caption of a picture taken on another employee&rsquo;s activity showed signs that we actually did: specifically, the caption simply read as two red hearts: &ldquo;❤️❤️&rdquo;</p>
<h2 id="the-persistence-layer">The persistence layer</h2>
<p>Most entities at Strava are persisted in MySQL databases. The main instance encoded most string using <a href="https://dev.mysql.com/doc/refman/5.7/en/charset-unicode-utf8.html"><code>utf8</code></a>, which is an incredibly misleading name in the context of MySQL. As you can see in the linked documentation, this encoding cannot actually encode a large portion of the Unicode codepoints:</p>
<ul>
<li>&ldquo;No support for supplementary characters (BMP characters only)&rdquo;</li>
<li>&ldquo;A maximum of three bytes per multibyte character&rdquo;</li>
</ul>
<p>Strava&rsquo;s core database was set up before MySQL introduced the <a href="https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html"><code>utf8mb4</code></a> character set, which extends the support of UTF-8-encoded text to the actual full range of all codepoints defined Unicode.</p>
<p>However, pictures (and their captions) are managed by a separate backend, which has its own database. The captions persisted in that database can contain emojis because the column was explicitly set to support it. As a matter of fact, one could easily <code>INSERT</code> values that contained any codepoint and retrieve them later, as long as this was done from the MySQL CLI.</p>
<h2 id="the-serving-layer">The serving layer</h2>
<p>Now that we know that the data in the database <em>may</em> be an emoji, let&rsquo;s try to see how it is returned to the client. Using <a href="https://github.com/jkbrzt/httpie">httpie</a> and <a href="https://stedolan.github.io/jq/">jq</a>, we can specifically look at that field in an API response and examine the bytes<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>:</p>
<pre tabindex="0"><code>$ http &quot;https://www.strava.com/api/v3/activities/&lt;redacted&gt;/photos?photo_sources=true&quot; \
  'Authorization: Bearer &lt;redacted&gt;' | jq '.[8].caption' | xxd
00000000: 22e2 9da4 efb8 8fe2 9da4 efb8 8f22 0a    &quot;............&quot;.
</code></pre><p>We see the same sequence of bytes, repeated twice: <code>e29da4efb88f</code>. This is the raw hexadecimal representation of content that is UTF-8 encoded. <a href="https://software.hixie.ch/utilities/cgi/unicode-decoder/utf8-decoder">Decoding that sequence</a> to the Unicode codepoints yields two of them:</p>
<ul>
<li><code>U+2764 HEAVY BLACK HEART</code>: this character is actually not in the <a href="https://en.wikipedia.org/wiki/Emoticons_%28Unicode_block%29">Emoji block</a> (range: U+1F600..U+1F64F) but in the <a href="https://en.wikipedia.org/wiki/Dingbat#Unicode">Dingbats block</a> (range: U+2700..U+27BF)</li>
<li><code>U+FE0F VARIATION SELECTOR-16</code>: this is a <a href="https://en.wikipedia.org/wiki/Variation_Selectors_%28Unicode_block%29">variant selector</a> - it specifies a variant of the previous character&rsquo;s glyph, and, in this case, I assume it changes the color to red.</li>
</ul>
<p>What&rsquo;s interesting is that the heart codepoint actually appears in the <a href="http://unicode.org/emoji/charts/full-emoji-list.html#2764">exhaustive list</a> of Emoji codepoints on the Unicode website. The character, which was originally defined in 1995, was grandfathered into the emoji range despite having a codepoint in a very different range than other emojis.</p>
<p>We&rsquo;ve asserted that the content is actually not an emoji, and can therefore be rendered properly by Rails v3. Problem solved. However, the premise of my coworker&rsquo;s question was that emojis simply do not work and it&rsquo;s worth exploring why that is the case.</p>
<h2 id="-but-no-">❤️ but no 🎉</h2>
<p>At the time I worked there, Strava&rsquo;s main frontend was a relatively vanilla Rails setup running v3.2. Let&rsquo;s look into how that version of Rails encodes strings in JSON - the code below is a simplified version of <a href="https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/json/encoding.rb#L121-L136"><code>activesupport/lib/active_support/json/encoding.rb</code></a><sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="n">string</span> <span class="o">=</span> <span class="s2">&#34;\u2764\uFE0F&#34;</span>
<span class="n">string</span> <span class="o">=</span> <span class="n">string</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="o">::</span><span class="no">Encoding</span><span class="o">::</span><span class="no">UTF_8</span><span class="p">,</span> <span class="ss">:undef</span> <span class="o">=&gt;</span> <span class="ss">:replace</span><span class="p">)</span><span class="o">.</span><span class="n">force_encoding</span><span class="p">(</span><span class="o">::</span><span class="no">Encoding</span><span class="o">::</span><span class="no">BINARY</span><span class="p">)</span>
<span class="n">json</span> <span class="o">=</span> <span class="n">string</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="n">escape_regex</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">s</span><span class="o">|</span> <span class="no">ESCAPED_CHARS</span><span class="o">[</span><span class="n">s</span><span class="o">]</span> <span class="p">}</span>
<span class="n">json</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/([\xC0-\xDF][\x80-\xBF]|
</span><span class="sr">                   [\xE0-\xEF][\x80-\xBF]{2}|
</span><span class="sr">                   [\xF0-\xF7][\x80-\xBF]{3})+/nx</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">s</span><span class="o">|</span>
            <span class="n">s</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="s2">&#34;U*&#34;</span><span class="p">)</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s2">&#34;n*&#34;</span><span class="p">)</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="s2">&#34;H*&#34;</span><span class="p">)</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/.{4}/n</span><span class="p">,</span> <span class="s1">&#39;\\\\u\&amp;&#39;</span><span class="p">)</span>
          <span class="p">}</span>
<span class="n">json</span> <span class="o">=</span> <span class="sx">%(&#34;</span><span class="si">#{</span><span class="n">json</span><span class="si">}</span><span class="sx">&#34;)</span>
<span class="n">json</span><span class="o">.</span><span class="n">force_encoding</span><span class="p">(</span><span class="o">::</span><span class="no">Encoding</span><span class="o">::</span><span class="no">UTF_8</span><span class="p">)</span>
</code></pre></div><p>Making sense of this logic is not easy, to say the least:</p>
<ol>
<li>The string is first encoded to UTF-8 (undefined characters are replaced with the <a href="https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character">replacement character</a>) and then force-encoded to binary. This will enable the rest of the code to dig into the binary representation of the text encoded in UTF-8</li>
<li>A first round of escaping takes place:</li>
</ol>
<ul>
<li><code>gsub</code> is a method on Ruby strings that takes in a regular expression and yields each match in the receiver to a block which is tasked with determining the string to replace the match with.</li>
<li><code>escape_regex</code> is essentially <code>[\x00-\x1F&quot;\\]</code>, i.e. bytes <code>0x00</code> to <code>0x1F</code>, the double quote (reserved character in JSON) and the backslash.</li>
<li><code>ESCAPED_CHARS</code> is a mapping that contains the escaped version of these, e.g. <code>\x17</code> → <code>\u0017</code>.</li>
</ul>
<ol start="3">
<li>A second round of replacement takes place, again using <code>gsub</code></li>
</ol>
<ul>
<li>The code first attempts to chunk the string in groups of two, three or four bytes depending on the range of the leading byte:
<ul>
<li><code>0xC0</code>-<code>0xDF</code> → 2 bytes</li>
<li><code>0xE0</code>-<code>0xEF</code> → 3 bytes</li>
<li><code>0xF0</code>-<code>0xF7</code> → 4 bytes</li>
</ul>
</li>
<li>Each chunk of bytes then goes through another conversion pipeline that uses Ruby&rsquo;s <a href="https://apidock.com/ruby/Array/pack"><code>pack</code></a> and <a href="https://apidock.com/ruby/String/unpack"><code>unpack</code></a> methods
<ul>
<li>decoded as a UTF-8 character (<code>unpack(&quot;U*&quot;)</code>)</li>
<li>converted into big-endian 16-bit values (<code>pack(&quot;n*&quot;)</code>)</li>
<li>finally converted into a hexadecimal string (<code>unpack(&quot;H*&quot;)</code>)</li>
</ul>
</li>
</ul>
<p>The chunking in 2/3/4 bytes is done based on the correct bytes prefixes for UTF-8, where codepoints are encoded on 1-4 bytes</p>
<table>
<thead>
<tr>
<th>Number of bytes</th>
<th>Bits for codepoint</th>
<th>First codepoint</th>
<th>Last codepoint</th>
<th>Byte 1</th>
<th>Byte 2</th>
<th>Byte 3</th>
<th>Byte 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>7</td>
<td>U+0000</td>
<td>U+0070</td>
<td>0xxxxxxx</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>11</td>
<td>U+0080</td>
<td>U+07FF</td>
<td>110xxxxx (0xC0)</td>
<td>10xxxxxx</td>
<td></td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>16</td>
<td>U+0800</td>
<td>U+FFFF</td>
<td>1110xxxx (0xE0)</td>
<td>10xxxxxx</td>
<td>10xxxxxx</td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>21</td>
<td>U+10000</td>
<td>U+10FFFF</td>
<td>11110xxx (0xF0)</td>
<td>10xxxxxx</td>
<td>10xxxxxx</td>
<td>10xxxxxx</td>
</tr>
</tbody>
</table>
<p>As one might suspect from the complicated logic implemented here, the final conversion pipeline is why Rails doesn&rsquo;t support emojis out of the box. All responses to XHRs and the entirety of the API downstream traffic go through this JSON encoder. This block of code was once <a href="https://github.com/rails/rails/commit/815a9431ab61376a7e8e1bdff21f87bc557992f8">removed</a> and then <a href="https://github.com/rails/rails/commit/c910388587220e962682b0b9187e79b8f1641c17">re-added</a> because the fix was deemed to be changing the behavior of a stable version (later versions of Rails do not have that issue).</p>
<p>Interestingly, rendering an emoji character in an HTML context does work even in v3.2 because the encoding path is completely independent ¯\_(ツ)_/¯. But what actually happens? Knowing the escaping logic is faulty, we&rsquo;d expect the dingbat character to go through that phase unscathed, while a &ldquo;real&rdquo; emoji will come out mangled:</p>
<ul>
<li>For &ldquo;❤️&rdquo; as an input (<code>string = &quot;\u2764\uFE0F&quot;</code>), the return value is <code>&quot;\&quot;\\u2764\\ufe0f\&quot;&quot;</code>.</li>
<li>For &ldquo;🎉&rdquo; as an input (<code>string = &quot;\u{1F389}&quot;</code>), which is a character in the Emoji block, this returns <code>&quot;\&quot;\\uf389\&quot;&quot;</code>.</li>
</ul>
<p>The outputs here seems does not fully allow us to blame the JSON encoder: the two outputs look roughly similar and it&rsquo;s unclear if either or both of them are good or faulty.</p>
<h2 id="api-clients">API clients</h2>
<p>To understand why the output of the second call is actually an issue, we need to look into what happens on the receiving end of it. JSON stands for &ldquo;JavaScript Object Notation&rdquo;: a data representation which is proper to JavaScript and we should therefore continue to investigate in that context. Using the Chrome inspector, it&rsquo;s trivial to convert our content from JSON into JavaScript strings:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="s2">&#34;\&#34;\\u2764\\ufe0f\&#34;&#34;</span><span class="p">)</span>
<span class="s2">&#34;❤️&#34;</span>
<span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="s2">&#34;\&#34;\\uf389\&#34;&#34;</span><span class="p">)</span>
<span class="s2">&#34;&#34;</span>
</code></pre></div><p>This is the evidence we were looking for all along. It took going all the way to the client but we finally know the issue is real: only one of the two characters is failing to be unescaped correctly by a real-world JSON parser.</p>
<h2 id="to-the-json-rfc">To the JSON RFC…</h2>
<p>Now that we now that the encoder is faulty, we should look into the root cause of the issue—and specifically understanding why there is such a triple conversion at the last step. That will require a dive in the <a href="http://www.ietf.org/rfc/rfc4627.txt">JSON RFC</a>:</p>
<blockquote>
<p>Any character may be escaped.  If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF), then it may be represented as a six-character sequence: a reverse solidus, followed by the lowercase letter u, followed by four hexadecimal digits that encode the character&rsquo;s code point.  The hexadecimal letters A though F can be upper or lowercase.  So, for example, a string containing only a single reverse solidus character may be represented as &ldquo;\u005C&rdquo;.</p>
</blockquote>
<p>The heart character is in the BMP, the <a href="https://en.wikipedia.org/wiki/Plane_%28Unicode%29#Basic_Multilingual_Plane">Basic Multilingual Plane</a> (range: U+0000..U+FFFF), so that section applies and the output of the escaper makes sense.</p>
<h2 id="and-back-again">…And back again</h2>
<p>What does the spec have to say about characters that are not in the BMP, however?</p>
<blockquote>
<p>To escape an extended character that is not in the Basic Multilingual Plane, the character is represented as a twelve-character sequence, encoding the UTF-16 surrogate pair.</p>
</blockquote>
<p>That should be the case for the the party popper character (U+1F389) but the JSON encoder shipping with with Rails 3 doesn&rsquo;t do that. It did escape the character but actually stripped the leading <code>1</code>, which is kind of important 😕. As per the spec, characters may be encoded in UTF-16 and represented using the two resulting bytes. <a href="http://macchiato.com/unicode/convert.html">Converting</a> 🎉 to UTF-16 yields &ldquo;D83C DF89&rdquo;, so let&rsquo;s try that:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="s2">&#34;\&#34;\uD83C\uDF89\&#34;&#34;</span><span class="p">)</span>
<span class="s2">&#34;🎉&#34;</span>
</code></pre></div><p>We have our first step towards a fix: if we can get the encoder to to spit out the correct UTF-16 bytes representing the &ldquo;🎉&rdquo; character, we could mitigate the issue. But it seems like a fairly painful mitigation: do we really need to jump through all those hoops to just represent emojis in JSON? The sad truth is that all that escaping is not even needed to begin with. The spec also contains the following language:</p>
<blockquote>
<p>JSON text SHALL be encoded in Unicode.  The default encoding is UTF-8</p>
</blockquote>
<p>UTF-8 is just an encoding, which supports all Unicode codepoints, including emojis. And the spec didn&rsquo;t say that such characters <strong>must</strong> be escaped, it said that they <a href="https://www.ietf.org/rfc/rfc2119.txt"><em>may</em></a>. So let&rsquo;s try to be literal for one second:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="s2">&#34;\&#34;🎉\&#34;&#34;</span><span class="p">)</span>
<span class="s2">&#34;🎉&#34;</span>
</code></pre></div><p>This is exactly the path taken by the JSON escaper in Rails 4+: it mostly became a passthrough for text content which is already encoded in UTF-8.</p>
<h2 id="step-by-step">Step by step</h2>
<p>The full solution to supporting emojis on Rails 3 and MySQL 5 is as follows:</p>
<ol>
<li>Convert your MySQL <code>VARCHAR</code> and <code>TEXT</code> columns to use <code>utf8mb4</code> as an encoding. Depending on the volume of data you have, this may take a while.</li>
<li>Set <code>utf8mb4</code> as an encoding in your database connection settings.</li>
<li>Monkey-patch the default Rails JSON encoder — you can do that in an initializer, e.g. <code>config/emoji_support.rb</code>. <a href="https://github.com/rails/rails/commit/815a9431ab61376a7e8e1bdff21f87bc557992f8">This commit</a> which was proposed in the 3.2 branch to fix this very issue is a good place to start.</li>
<li>Test, test, test. Depending on the age of your Rails application, there can be subtle bugs that have never manifested with the lower range of Unicode codepoints. One that wasn&rsquo;t caught in time for Strava is <a href="https://www.eiggen.co/codes/on-string-lengths/">this one</a>.</li>
</ol>
<section class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1" role="doc-endnote">
<p>You may object that this command is not useful because it doesn&rsquo;t actually expose the raw bytes as returned by the server: both <code>httpie</code> and <code>jq</code> have built-in JSON parsers, which unescape the real data sent from the server. The actual content can be observed by piping the output of <code>http</code> directly into <code>xxd</code>. Unsurprisingly, <code>&quot;\u2764\ufe0f&quot;</code> appears in it:</p>
<pre tabindex="0"><code>000012e0: 6361 7074 696f 6e22 3a22 5c75 3237 3634  caption&quot;:&quot;\u2764
000012f0: 5c75 6665 3066 5c75 3237 3634 5c75 6665  \ufe0f\u2764\ufe
00001300: 3066 222c 2274 7970 6522 3a6e 756c 6c2c  0f&quot;,&quot;type&quot;:null,
</code></pre><p>This is a valid point – with that said, and independently of the findings presented here, the mechanisms defined by the JSON RFC are meant to be transparent. What really matters to the user isn&rsquo;t what&rsquo;s on the wire, it&rsquo;s the decoded, unescaped data, which the initial command does actually surface.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>With <code>ESCAPED_CHARS</code> declared as per the constant in <a href="https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/json/encoding.rb#L84-L103">the source</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</section>
]]></content>
        </entry>
    
        <entry>
            <title>On string lengths</title>
            <link href="https://www.eiggen.co/codes/on-string-lengths/"/>
            <updated>2020-02-22T00:00:00+0000</updated>
            <id>https://www.eiggen.co/codes/on-string-lengths/</id>
            <content type="html"><![CDATA[ <p>This story dates back from when I worked at <a href="https://strava.com">Strava</a>.</p>
<p>The Strava app has a feature where users can <em>mention</em> each other in comment boxes: when you start typing someone&rsquo;s name, it triggers an autocomplete box to let you pick a friend&rsquo;s name, and then bolds and links the text to the profile of the user being mentioned. At the time the mentioning feature was launched, the app didn&rsquo;t support the full range of Unicode codepoints (practically speaking: emojis were excluded from Strava).</p>
<p>A short while after adding support for emojis, we observed an issue when users would use both mentions and emojis in the same comment:</p>



  
    
      <img src="/codes/on-string-lengths/mention-steve.png" alt="Example of user mention with bolding being off by one"/>
    
  


<p>The bolding was <em>off</em> - and the faulty offset was apparently related to the number of emojis preceding the mention:</p>



  
    
      <img src="/codes/on-string-lengths/mention-scott.png" alt="Example of user mention with bolding being off by five"/>
    
  


<h2 id="digging-deep">Digging Deep</h2>
<p>The issue occurred on both our official Android and iOS clients, which hinted at a server-side issue. Hours were spent digging into the mentions logic on the server but no obvious flaws were found. And at the API level, the response returned by the server looked legit:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="p">{</span>
  <span class="nt">&#34;text&#34;</span><span class="p">:</span> <span class="s2">&#34;👏👏👏👏👏 Jason Milliron Julien Silland&#34;</span><span class="p">,</span>
  <span class="nt">&#34;mentions_metadata&#34;</span><span class="p">:</span> <span class="p">[{</span>
    <span class="nt">&#34;uri&#34;</span><span class="p">:</span> <span class="s2">&#34;strava://athletes/6527&#34;</span><span class="p">,</span>
    <span class="nt">&#34;start&#34;</span><span class="p">:</span> <span class="mi">6</span><span class="p">,</span>
    <span class="nt">&#34;end&#34;</span><span class="p">:</span> <span class="mi">19</span>
  <span class="p">},</span> <span class="p">{</span>
    <span class="nt">&#34;uri&#34;</span><span class="p">:</span> <span class="s2">&#34;strava://athletes/136697&#34;</span><span class="p">,</span>
    <span class="nt">&#34;start&#34;</span><span class="p">:</span> <span class="mi">21</span><span class="p">,</span>
    <span class="nt">&#34;end&#34;</span><span class="p">:</span> <span class="mi">34</span>
  <span class="p">}]</span>
<span class="p">}</span></code></pre></div>
<p>For backwards compatibility, mentions were added to the comment object as a <code>mentions_metadata</code> field, an array of objects that contain the start and end index of a single mention, and the target of the link to go to when the link is clicked. The indices in that response are correct: the first mention begins at character 6 and ends at character 19, the second one starts at character 21 and ends at 34:</p>
<table>
  <tr>
    <td>Sections</td><td>👏👏👏👏👏</td><td> </td><td><code>Jason Milliron</code></td><td> </td><td><code>Julien Silland</code></td>
  </tr>
  </tr>
    <td>Indices</td><td>0 – 4</td><td>5</td><td>6 – 19</td><td>20</td><td>21 – 34</td>
  </tr>
</table>
<p>On the wire, this string was encoded in UTF-8 – for future reference, here&rsquo;s the hex version of the raw UTF-8 bytes:</p>
<table>
  <tr><td>0xF0</td><td>0x9F</td><td>0x91</td><td>0x8F</td><td>0xF0</td><td>0x9F</td><td>0x91</td><td>0x8F</td></tr>
  <tr><td>0xF0</td><td>0x9F</td><td>0x91</td><td>0x8F</td><td>0xF0</td><td>0x9F</td><td>0x91</td><td>0x8F</td></tr>
  <tr><td>0xF0</td><td>0x9F</td><td>0x91</td><td>0x8F</td><td>0x20</td><td>0x4A</td><td>0x61</td><td>0x73</td></tr>
  <tr><td>0x6F</td><td>0x6E</td><td>0x20</td><td>0x4D</td><td>0x69</td><td>0x6C</td><td>0x6C</td><td>0x69</td></tr>
  <tr><td>0x72</td><td>0x6F</td><td>0x6E</td><td>0x20</td><td>0x4A</td><td>0x75</td><td>0x6C</td><td>0x69</td></tr>
  <tr><td>0x65</td><td>0x6E</td><td>0x20</td><td>0x53</td><td>0x69</td><td>0x6C</td><td>0x6C</td><td>0x61</td></tr>
  <tr><td>0x6E</td><td>0x64</td></tr>
</table>
<p>On the client side, the bytes were decoded into the native string type and decorated using the routines proper to their platform, in Java on Android:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="n">String</span> <span class="n">comment</span> <span class="o">=</span> <span class="k">new</span> <span class="n">String</span><span class="o">(</span><span class="n">bytes</span><span class="o">,</span> <span class="n">StandardCharsets</span><span class="o">.</span><span class="na">UTF_8</span><span class="o">);</span>
<span class="n">SpannableString</span> <span class="n">stylable</span> <span class="o">=</span> <span class="k">new</span> <span class="n">SpannableString</span><span class="o">(</span><span class="n">comment</span><span class="o">);</span>
<span class="n">stylable</span><span class="o">.</span><span class="na">setSpan</span><span class="o">(</span><span class="k">new</span> <span class="n">StyleSpan</span><span class="o">(</span><span class="n">Typeface</span><span class="o">.</span><span class="na">BOLD</span><span class="o">),</span> <span class="n">mention</span><span class="o">.</span><span class="na">start</span><span class="o">,</span> <span class="n">mention</span><span class="o">.</span><span class="na">end</span><span class="o">,</span> <span class="err">…</span><span class="o">);</span></code></pre></div>
<p>And in Objective-C on iOS:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="n">NSString</span> <span class="o">*</span><span class="n">comment</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSString</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithData</span><span class="p">:</span><span class="n">bytes</span>
                                          <span class="nl">encoding</span><span class="p">:</span><span class="n">NSUTF8StringEncoding</span><span class="p">];</span>
<span class="n">stylable</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSMutableAttributedString</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithString</span><span class="p">:</span><span class="n">comment</span><span class="p">];</span> 
<span class="p">[</span><span class="n">stylable</span> <span class="nl">addAttribute</span><span class="p">:(</span><span class="n">NSString</span> <span class="o">*</span><span class="p">)</span><span class="n">kCTFontAttributeName</span>
                 <span class="nl">value</span><span class="p">:(</span><span class="k">__bridge</span> <span class="kt">id</span><span class="p">)</span><span class="n">font</span>
                 <span class="nl">range</span><span class="p">:</span><span class="n">mention</span><span class="p">.</span><span class="n">range</span><span class="p">];</span></code></pre></div>
<p>The code on both platforms is legible and straightforward, and doesn&rsquo;t look to be flawed with an off-by-x index issue. It&rsquo;s a wild guess but since the API response looks correct, and the client code looks correct, we should look at a deeper level to understand the discrepancy.</p>
<p>As it turns out, Java and Objective-C have striking similarities in how they represent strings. Both have good Unicode support but both are also relatively ancient: Java&rsquo;s JDK 1.0 was released in 1995 and Cocoa&rsquo;s Foundation Kit (which contains <code>NSString</code>) was developed for NeXTSTEP 3.0, which shipped in 1992. Unicode 1.0 was published in 1992 and played a role in how the standard libraries of each language would encode strings.</p>
<p>With fewer than 65K codepoints defined at the time, it made sense to encode strings using UCS-2, a precursor to <a href="https://en.wikipedia.org/wiki/UTF-16">UTF-16</a>: strings would be backed by an array of fixed 16-bit chunks. This was both forward-looking and practical: although there would be a memory penalty when representing ASCII-compatible text (which would generally fit on 8-bit chunks), opting for 16-bit chunks opened up compatibility with most of the world&rsquo;s scripts and made character iteration fast and easy.</p>
<p>However, this direct equivalence between characters and items in the backing array breaks for emojis and other characters that take more than a single chunk to represent.</p>
<h2 id="different-strokes">Different Strokes</h2>
<p>When a human thinks about string length and indices, they generally reason about characters they can see on-screen. A programming language will generally reasons in the length of the underlying structure that stores the string. What is supposed to be an implementation detail becomes a leaky abstraction. As it turns out, most languages are leaky by default and few of them do the intuitive thing when computing the length of a string.</p>
<p>The following table lists the result of computing the length of the string &ldquo;👏👏👏👏👏 Jason Milliron Julien Silland&rdquo; across a few popular languages:</p>
<table>
<thead>
<tr>
<th>Language</th>
<th>Result</th>
<th>Method</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://gist.github.com/jsilland/d4e3fb779b3c274752b7b24e3c727f55#file-length-java">Java</a></td>
<td>40</td>
<td><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#length--"><code>String.length()</code></a></td>
</tr>
<tr>
<td><a href="https://gist.github.com/jsilland/d4e3fb779b3c274752b7b24e3c727f55#file-length-rb">Ruby</a></td>
<td>35</td>
<td><a href="https://ruby-doc.org/core-2.6/String.html#method-i-length"><code>String.length</code></a></td>
</tr>
<tr>
<td><a href="https://play.golang.org/p/07T9oOS6If8">Go</a></td>
<td>50</td>
<td><a href="https://golang.org/pkg/builtin/#len"><code>len(…)</code></a></td>
</tr>
<tr>
<td><a href="https://gist.github.com/jsilland/d4e3fb779b3c274752b7b24e3c727f55#file-length-m">Obective-C</a></td>
<td>40</td>
<td><a href="https://developer.apple.com/documentation/foundation/nsstring/1414212-length"><code>NSString length</code></a></td>
</tr>
<tr>
<td><a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=c6eb24e6358fb437f93f238a1656d29c">Rust</a></td>
<td>50</td>
<td><a href="https://doc.rust-lang.org/std/string/struct.String.html#method.len"><code>std::string::String.len()</code></a></td>
</tr>
<tr>
<td><a href="https://gist.github.com/jsilland/d4e3fb779b3c274752b7b24e3c727f55#file-length-js">JavaScript</a></td>
<td>40</td>
<td><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length"><code>String length</code></a></td>
</tr>
<tr>
<td><a href="https://gist.github.com/jsilland/d4e3fb779b3c274752b7b24e3c727f55#file-length-swift">Swift 3</a></td>
<td>35</td>
<td>This was using the now deprecated <code>.characters</code> view</td>
</tr>
<tr>
<td><a href="https://gist.github.com/jsilland/d4e3fb779b3c274752b7b24e3c727f55#file-length-swift4">Swift 4+</a></td>
<td>35</td>
<td><a href="https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html#ID297">String.count</a></td>
</tr>
<tr>
<td><a href="https://gist.github.com/jsilland/d4e3fb779b3c274752b7b24e3c727f55#file-length-py">Python 2</a></td>
<td>40</td>
<td><a href="https://docs.python.org/2/library/functions.html#len"><code>len(…)</code></a></td>
</tr>
<tr>
<td><a href="https://gist.github.com/jsilland/d4e3fb779b3c274752b7b24e3c727f55#file-length-py">Python 3</a></td>
<td>35</td>
<td><a href="https://docs.python.org/3/library/functions.html#len"><code>len(…)</code></a></td>
</tr>
</tbody>
</table>
<ul>
<li>Java, Objective-C and JavaScript all use UCS-2 for their strings: the first 5 &lsquo;👏&rsquo; each occupy 2 elements in the array, and the remaining 30 codepoints each occupy one: (5 × 2) + 30 = 40</li>
<li>Ruby and Swift operate at the <em>grapheme cluster</em> level and each return 35</li>
<li>Go and Rust represent strings as an array of UTF-8 bytes: the first 5 &lsquo;👏&rsquo; occupy 4 elements each, and the remaining 30 codepoints each occupy 1: (5 × 4) + 30 = 50</li>
<li>Strings in Python 3 are strongly typed as such, but they were raw byte arrays in Python 2 and lower</li>
</ul>
<table>
  <tr>
    <td></td><td>👏👏👏👏👏</td><td> </td><td><code>Jason Milliron</code></td><td> </td><td><code>Julien Silland</code></td><td> </td>
  </tr>
  <tr>
    <td>UCS-2</td><td>5 × 2</td><td>1</td><td>14</td><td>1</td><td>14</td><td>40</td>
  </tr>
  <tr>
    <td>UTF-8</td><td>5 × 4</td><td>1</td><td>14</td><td>1</td><td>14</td><td>50</td>
  </tr>
  <tr>
    <td>Human</td><td>5</td><td>1</td><td>14</td><td>1</td><td>14</td><td>35</td>
  </tr>
</table>
<p>The root cause of the rendering issue is that the indices returned from API operate in terms of human characters whereas both clients use them to index an array of 16-bit chunks. When a character such as 👏 takes 32 bits to represent, the indices are off. It&rsquo;s clear from this example that <strong>you should be skeptical of the commonly available methods to obtain the length of a string</strong>. There are only a handful of situations where it can be relied on:</p>
<ul>
<li>You are positively certain that it measures what you are seeking to measure</li>
<li>You will never need to assert the equivalence of the same string across multiple programming languages</li>
<li>You strongly guard against the presence of any character that would throw the calculation off</li>
</ul>
<p>A more realist stance is that if your code operates on strings (measuring length, indexing, trimming, splitting), it should be ready to handle the complexity that comes with it - this is espcially important for content that is user-submitted.</p>
<h2 id="digging-deeper">Digging Deeper</h2>
<p>The solution here is to break down what is really a string of bytes into chunks that make sense for humans – these are called &ldquo;grapheme clusters&rdquo; in the Unicode specification. However, doing so isn&rsquo;t a simple matter of accounting for characters that take twice or four times the length of characters in the ASCII range. Unicode defines <a href="https://emojipedia.org/modifiers/">modifiers</a> and <a href="https://emojipedia.org/zero-width-joiner/">zero width joiners</a> which are used to modify and link the semantics of another codepoint.</p>
<p>For instance, the single emoji 👨🏿‍🦲is actually a combination of <em>three</em> different codepoints and one &ldquo;joiner&rdquo; character that serves as an hint to implementors that the codepoints on either side of it participate to the same cluster:</p>
<table>
  <tr><td>Character</td><td colspan="4">👨🏿‍🦲</td></tr>
  <tr><td>Codepoints</td><td>Man</td><td>Dark Skin Tone</td><td>Zero Width Joiner</td><td>Bald</td></tr>
  <tr><td>Values</td><td>U+1F468</td><td>U+1F3FF</td><td>U+200D</td><td>U+1F9B2</td></tr>
  <tr><td>UTF-8 hex</td><td>F0 9F 91 A8</td><td>F0 9F 8F BF</td><td>E2 80 8D</td><td>F0 9F A6 B2</td></tr>
</table>
<p>In a language such as Go, this single character would be reported as having a <a href="https://play.golang.org/p/-6E5Vl7o6JY">length of 15</a>!</p>
<p>Unicode defines <a href="https://unicode.org/reports/tr29/">grapheme clusters</a> as part of the standard: these are rules for segmenting strings into chunks that map well to what a human would consider to be characters in a string. Most high-level languages such as Java, Objective-C and Swift expose this higher-level abstraction:</p>
<ul>
<li>Java&rsquo;s documentation on <a href="https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#unicode">character representations</a>, and especially <a href="https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#codePointAt(int)"><code>String.codepointAt(index)</code></a>, <a href="https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#isHighSurrogate(char)"><code>Character.isHighSurrogate</code></a>, <a href="https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#isLowSurrogate(char)"><code>isLowSurrogate</code></a>, <a href="https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#isSupplementaryCodePoint(int)"><code>isSupplementaryCodePoint</code></a></li>
<li>Objective-C&rsquo;s <a href="https://developer.apple.com/documentation/foundation/nsstring">NSString</a> and especially <a href="https://developer.apple.com/documentation/foundation/nsstring/1416036-rangeofcomposedcharactersequence?language=objc"><code>rangeOfComposedCharacterSequenceAtIndex</code></a></li>
<li>Swift&rsquo;s documentation on strings and characters <a href="https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html">documentation</a></li>
<li>Go documentation on <a href="https://blog.golang.org/strings">strings</a> and <a href="https://blog.golang.org/normalization">normalization</a></li>
</ul>
]]></content>
        </entry>
    
</feed>