<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Maëlle&#39;s R blog on Maëlle Salmon&#39;s personal website</title>
    <link>https://masalmon.eu/post/</link>
    <description>Recent content in Maëlle&#39;s R blog on Maëlle Salmon&#39;s personal website</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>Licence: &lt;a href=&#34;https://creativecommons.org/licenses/by-sa/2.0/&#34;&gt;CC BY-SA&lt;/a&gt;</copyright>
    <lastBuildDate>Tue, 19 May 2026 00:00:00 +0000</lastBuildDate>
    
        <atom:link href="https://masalmon.eu/post/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>More crochet/programming thoughts</title>
      <link>https://masalmon.eu/2026/05/19/crochet-again/</link>
      <pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2026/05/19/crochet-again/</guid>
      <description>&lt;p&gt;Here I am again, writing about crochet and programming!
I’ve continued creating &lt;a href=&#34;https://masalmon.eu/2026/01/26/amigurumi/#the-importance-of-practice&#34;&gt;&lt;del&gt;my tons of shitty stitches&lt;/del&gt;&lt;/a&gt; cute creatures.&lt;/p&gt;
&lt;h2 id=&#34;new-git-analogy-the-crochet-lifeline&#34;&gt;New Git analogy! The crochet lifeline&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&#34;https://masalmon.eu/2026/02/15/stitch-markers-git-commits/&#34;&gt;First Git/crochet analogy&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I read a great crochet book about creating your own amigurumi patterns: &lt;a href=&#34;https://www.editions-eyrolles.com/livre/creer-ses-propres-modeles-d-amigurumis-au-crochet&#34;&gt;&lt;em&gt;Créer ses propres modèles d&amp;rsquo;amigurumis au crochet&lt;/em&gt;&lt;/a&gt; by Clotilde Massot and Lise Grandjonc.
One of its authors (Clotilde Massot) is a software developer who, among other things, published an octocat pattern that I bought and &lt;a href=&#34;https://bsky.app/profile/masalmon.eu/post/3mjw2zxta2k2z&#34;&gt;used&lt;/a&gt;…
Anyway in the book they explain that when you create a pattern, you will probably have to undo your work several times.
Undoing a round is easy if you have a stitch marker in the first stitch of the current/last round: you undo until you hit that stitch marker.
But what about undoing several rounds?
In that case, you’ll be better off if instead of using a stitch marker at the beginning of the current round, you use contrasting yarn stuck &lt;em&gt;under the first stitch of each round&lt;/em&gt;.
That yarn creates what the authors of the book call your &lt;strong&gt;lifeline&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;Now, if that’s not a great analogy for commits and the ability to reset…&lt;/p&gt;
&lt;h2 id=&#34;communities-of-practice&#34;&gt;Communities of practice&lt;/h2&gt;
&lt;p&gt;If you’ve had the opportunity to attend or watch the wonderful &lt;a href=&#34;https://yabellini.netlify.app/talk/2025_user2025/&#34;&gt;useR! 2025 keynote talk of my rOpenSci colleague Yanina Bellini Saibene&lt;/a&gt;, you’ve heard of communities of practice.
In her talk, Yani quoted Etienne Wenger who defined communities of practice as &lt;em&gt;“groups of people who share a passion for something that they know how to do, and who interact regularly in order to learn how to do it better“&lt;/em&gt;.
Yani mentioned her swimming team and English conversation club.
Well, I found a community of practice for crochet: a stitch club at a local café!
Participants meet up to crochet side by side, talking a lot about crochet: comparing yarns, exchanging tips, etc.
The first time I went, we even started with a round of introductions where we said what each of us would work on during that meeting, which reminded me of &lt;a href=&#34;https://ropensci.org/coworking/&#34;&gt;rOpenSci coworking sessions&lt;/a&gt; where participants do exactly that.&lt;/p&gt;
&lt;h2 id=&#34;usefulness-of-seeing-others-work&#34;&gt;Usefulness of seeing others’ work&lt;/h2&gt;
&lt;p&gt;I’ve worked on some patterns by Yan Schenkel a.k.a. &lt;a href=&#34;https://picapauyan.com/&#34;&gt;Pica Pau&lt;/a&gt;.
One cool aspect of the patterns is that they include a link to a gallery where anyone can upload pics of their take on each creature.
So you can look at them, maybe seeing a crucial (to you) angle that’s absent from the pattern, noticing whether some “flaw” of your own project is present in others’ projects, comparing variations and picking what you prefer before you start, etc.
For instance I stared at many pics of &lt;a href=&#34;https://www.amigurumi.com/forum/Animal-Friends-of-Pica-Pau-3/Alberto-Seagull/&#34;&gt;Alberto Seagull&lt;/a&gt; before making the legs for mine.&lt;/p&gt;
&lt;p&gt;The usefulness of seeing others’ crocheted animals reminds me of how reading and reviewing open-source, or our colleagues’, code helps us (and LLMs, I suppose) learn how to do, or not to do, some things, how it help us refine our taste!
Ironically, I do publish most of my code, but I haven&amp;rsquo;t had interest in doing that for my crocheting yet. 😸&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In summary, I keep finding excuses to talk about crochet. My pink octocat approves!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Git worktrees are now cool</title>
      <link>https://masalmon.eu/2026/04/23/git-worktree-again/</link>
      <pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2026/04/23/git-worktree-again/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m not mad when current AI tools or tips&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; make Git look cool and important.
Something old and stable to cling to! 🤗
In particular, it&amp;rsquo;s now trendy to have agents work on different tickets in the same project in parallel by using &lt;em&gt;Git worktrees&lt;/em&gt;.
Git worktrees are even useful for us humans, even if we should probably not work on a dozen things at the same time.&lt;/p&gt;
&lt;p&gt;I had learnt about Git worktrees a while ago, but only viewed them as a way to open a read-only view of a past version of a repository:
I have written about &lt;a href=&#34;https://masalmon.eu/2024/01/23/git-worktree/&#34;&gt;loading different R package versions at once with git worktree&lt;/a&gt;.
The exercise about worktrees I added to the saperlipopette R package is very much about &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_worktree.html&#34;&gt;reading too&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let me sum up what I learnt about Git worktrees in the last weeks&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;git-worktrees-are-for-any-work-not-only-reading&#34;&gt;Git worktrees are for any work, not only reading&lt;/h2&gt;
&lt;p&gt;Let me first admit I have trouble getting used to the idea of a &amp;ldquo;working tree&amp;rdquo;.
What Git calls a &amp;ldquo;working tree&amp;rdquo; I call &amp;ldquo;my files&amp;rdquo; (my &lt;em&gt;precious&lt;/em&gt; files).
But knowing what a &amp;ldquo;working tree&amp;rdquo; is makes it easier to get used to a &amp;ldquo;worktree&amp;rdquo;, which is a working tree with some metadata.&lt;/p&gt;
&lt;p&gt;You can init/clone your Git repository once and then from there sprout as many working trees as you need.
Only the main one has a fully-fledged &lt;code&gt;.git&lt;/code&gt; folder, the others have a &lt;code&gt;.git&lt;/code&gt; &lt;em&gt;file&lt;/em&gt; with a line like &amp;ldquo;gitdir: /path-to-the-main-worktree/.git/worktrees/current-worktree&amp;rdquo; in it.&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
But from any worktrees you can run any Git commands.
You can for instance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;have a worktree where you fix a bug and another worktree where you write docs.&lt;/li&gt;
&lt;li&gt;create commits and push from either one.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From reading &lt;a href=&#34;https://wizardzines.com/comics/git-worktree/&#34;&gt;Julia Evans&amp;rsquo; bonus comic about Git worktrees&lt;/a&gt;, I learnt that an advantage of using worktrees rather than cloning the same repo several times is that it&amp;rsquo;s faster, because of the worktrees&amp;rsquo; sharing a &lt;code&gt;.git&lt;/code&gt; folder.&lt;/p&gt;
&lt;h2 id=&#34;creating-a-worktree-for-a-brand-new-branch-is-easy&#34;&gt;Creating a worktree for a brand-new branch is easy&lt;/h2&gt;
&lt;p&gt;If you want to create a new worktree for a new branch &lt;code&gt;feat-bla&lt;/code&gt;, do not run&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git branch -c feat-bla
git worktree add ../feat-bla feat-bla
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can simply run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git worktree add ../feat-bla
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I learnt that from reading the &lt;a href=&#34;https://git-scm.com/docs/git-worktree&#34;&gt;manual page for git worktrees&lt;/a&gt;, who&amp;rsquo;d have thought reading docs was useful? 🫠&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Git worktrees are cool, and they&amp;rsquo;re not even fancy,
even if your AI service or orchestrator might manage them for you.
They&amp;rsquo;re sort of a&amp;hellip; low-hanging fruit I guess. 🙊&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;For instance, the post &lt;a href=&#34;https://deadsimpletech.com/blog/ai_proof_engineer&#34;&gt;&amp;ldquo;Becoming an AI-proof software engineer&amp;rdquo;&lt;/a&gt; by Iris Meredith states &amp;ldquo;Being an effective user of git makes software development much less painful and importantly allows you to collaborate with other developers&amp;rdquo;. It also recommends writing. 😸 &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I am very proud of having gone inside &lt;code&gt;.git&lt;/code&gt; to prep this post. 🫡 &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Better Git diff with difftastic</title>
      <link>https://masalmon.eu/2026/03/30/difftastic/</link>
      <pubDate>Mon, 30 Mar 2026 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2026/03/30/difftastic/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m currently on a quest to better know and understand treesitter-based tooling for R.
To make it short, treesitter is a tool for parsing code, for instance recognizing what is a function, an argument, a logical in a string of code.
With tools built upon treesitter you can &lt;a href=&#34;https://emilhvitfeldt.com/post/ast-grep-r-claude-code/&#34;&gt;search&lt;/a&gt;, &lt;a href=&#34;https://posit-dev.github.io/air/&#34;&gt;reformat&lt;/a&gt;, &lt;a href=&#34;https://jarl.etiennebacher.com/&#34;&gt;lint and fix&lt;/a&gt;, etc. your code.
Exciting stuff, running locally and deterministically on your machine.&lt;/p&gt;
&lt;p&gt;Speaking of &amp;ldquo;etc.&amp;rdquo;, &lt;a href=&#34;https://www.etiennebacher.com/&#34;&gt;Etienne Bacher&lt;/a&gt; helpfully suggested I also look at treesitter-based tooling for &lt;em&gt;other languages&lt;/em&gt; to see what&amp;rsquo;s still missing in our ecosystem.
This is how I stumbled upon difftastic by Wilfred Hughes, &amp;ldquo;a structural diff tool that understands syntax&amp;rdquo;. ✨
This means that difftastic doesn&amp;rsquo;t only compare line or &amp;ldquo;words&amp;rdquo; but actual syntax by looking at lines around the lines that changed (by default, 3),
Even better, it understands R out of the box&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to Etienne Bacher not only for making me discover difftastic but also for useful feedback on this post!&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;installing-difftastic&#34;&gt;Installing difftastic&lt;/h2&gt;
&lt;p&gt;To install difftastic I downloaded a binary file for my system from the releases of the GitHub repository,
as &lt;a href=&#34;https://difftastic.wilfred.me.uk/installation.html&#34;&gt;documented in the manual&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;difftastic-on-two-files&#34;&gt;difftastic on two files&lt;/h2&gt;
&lt;p&gt;You can run difftastic on two files, a bit like you would use the &lt;a href=&#34;https://waldo.r-lib.org/&#34;&gt;waldo&lt;/a&gt; R package on two objects.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s compare:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;a &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bad&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;good&amp;#34;&lt;/span&gt;, x)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;a &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(x, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bad&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;good&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;respectedly saved in &lt;code&gt;old.R&lt;/code&gt; and &lt;code&gt;new.R&lt;/code&gt;.
The CLI is called difft not difftastic.
I use the &amp;ldquo;inline&amp;rdquo; display rather than the two columns default in order to save horizontal space.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;difft old.R new.R --display inline
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;d get to this nice looking diff:&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;oldnew.png&#34;
         alt=&#34;diff of the two lines of code, where &amp;#39;gsub&amp;#39; and &amp;#39;, x&amp;#39; are in red then &amp;#39;strinrr::str_replace&amp;#39; and &amp;#39;x&amp;#39; in green&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;The parentheses and &lt;code&gt;&amp;quot;bad&amp;quot;&lt;/code&gt; and &lt;code&gt;&amp;quot;good&amp;quot;&lt;/code&gt; arguments are ignored.&lt;/p&gt;
&lt;p&gt;We can also get the JSON version of this diff, which is an unstable feature which usage requires setting an environment variable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;color:#007020&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#bb60d5&#34;&gt;DFT_UNSTABLE&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;yes
difft old.R new.R --display json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This gets us&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;aligned_lines&amp;#34;&lt;/span&gt;:[[&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;],[&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;]],&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;chunks&amp;#34;&lt;/span&gt;:[[{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;lhs&amp;#34;&lt;/span&gt;:{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;line_number&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;changes&amp;#34;&lt;/span&gt;:[{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;9&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;gsub&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;highlight&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;normal&amp;#34;&lt;/span&gt;},{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;23&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;24&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;highlight&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;normal&amp;#34;&lt;/span&gt;},{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;25&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;26&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;highlight&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;normal&amp;#34;&lt;/span&gt;}]},&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;rhs&amp;#34;&lt;/span&gt;:{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;line_number&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;changes&amp;#34;&lt;/span&gt;:[{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;stringr&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;highlight&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;normal&amp;#34;&lt;/span&gt;},{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;14&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;::&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;highlight&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;keyword&amp;#34;&lt;/span&gt;},{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;14&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;25&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;str_replace&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;highlight&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;normal&amp;#34;&lt;/span&gt;},{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;26&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;27&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;highlight&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;normal&amp;#34;&lt;/span&gt;},{&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;27&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#40a070&#34;&gt;28&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;highlight&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;normal&amp;#34;&lt;/span&gt;}]}}]],&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;language&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;R&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;content/post/2026-03-26-difftastic/new.R&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;&amp;#34;status&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;changed&amp;#34;&lt;/span&gt;}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, none of this isn&amp;rsquo;t very useful because I would never compare files in this way&amp;hellip;
I use version control!&lt;/p&gt;
&lt;h2 id=&#34;difftastic-with-git&#34;&gt;difftastic with Git&lt;/h2&gt;
&lt;p&gt;We can set difftastic as the external diff tool for Git globally or for the current project.&lt;/p&gt;
&lt;p&gt;For instance with the gert R package, to set it locally:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;gert&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;git_config_set&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;diff.external&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;difft&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If I want to use the inline display I&amp;rsquo;d set:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;gert&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;git_config_set&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;diff.external&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;difft --display inline&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then &lt;code&gt;git diff&lt;/code&gt; will by default use difftastic.
Most interestingly for me, &lt;code&gt;git show --ext-diff&lt;/code&gt; will use difftastic.
I never use &lt;code&gt;git diff&lt;/code&gt; directly but I do look at more or less recent commits a lot.&lt;/p&gt;
&lt;p&gt;Say I am interested in the &lt;a href=&#34;https://github.com/r-lib/roxygen2/commit/7a1dd39866699a2b0a034bb15244c07698a1e2e7&#34;&gt;commit&lt;/a&gt; that removed roxygen2&amp;rsquo;s dependency on stringi, I&amp;rsquo;ll run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;git show 7a1dd39866699a2b0a034bb15244c07698a1e2e7 --ext-diff
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and get:&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;strwrap.png&#34;
         alt=&#34;diff where the parentheses of a nested call are nicely highlighted&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;This isn&amp;rsquo;t spectacular because this is a small diff, but I enjoy the highlighting of the parentheses of the removed nested call, and of the logical.&lt;/p&gt;
&lt;h2 id=&#34;cool-features-of-difftastic&#34;&gt;Cool features of difftastic&lt;/h2&gt;
&lt;p&gt;Building on two examples of the &lt;a href=&#34;https://difftastic.wilfred.me.uk/&#34;&gt;difftastic homepage&lt;/a&gt;&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;ignoring-formatting-changes&#34;&gt;Ignoring formatting changes&lt;/h3&gt;
&lt;p&gt;Since formatters can so helpfully apply your formatting preferences,
reviewing formatting changes in a patch that&amp;rsquo;s about something else entirely is useless and annoying.
Imagine having a function definition that fits on a single line, then adding one argument to it.&lt;/p&gt;
&lt;p&gt;Going from&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;f &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(myarg1 &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; foo, myarg2 &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; bar) {}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;f &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(
  myarg1 &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; foo,
  myarg2 &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; bar,
  myarg3 &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; baz
) {}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Because the definition is now longer than 80 characters, your formatter might switch the definition to be on multiple lines.
But the actually interesting change is the addition of one argument.&lt;/p&gt;
&lt;p&gt;Native Git diff&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; would show:&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;args.png&#34;
         alt=&#34;diff where all lines are highlighted because the function was reformatted, not only complemented with one argument&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;Git with difftastic would show:&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;args-better.png&#34;
         alt=&#34;diff where only the comma after `bar` and the line with the new argument are highlighted&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;The matching of delimiters is why I found the difftastic&amp;rsquo;s display of the roxygen2 commit more pleasing.&lt;/p&gt;
&lt;h3 id=&#34;matching-delimiters-in-wrappers&#34;&gt;Matching delimiters in wrappers&lt;/h3&gt;
&lt;p&gt;The Git diff can look a bit ugly when you simply move code from one function to the other.&lt;/p&gt;
&lt;p&gt;Say we go from&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;f &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;() {
  &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;f &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;() {
  &lt;span style=&#34;color:#06287e&#34;&gt;g&lt;/span&gt;()
}

g &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;() {
  &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Git diff would show:&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;wrappers-bad.png&#34;
         alt=&#34;uncool diff that shows lines modified in both the wrapper and the function without matching delimiters&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;Whereas Git with difftastic would show:&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;wrappers-good.png&#34;
         alt=&#34;cool diff that shows `g` as a new function by highlighting its name and the left arrow, whereas the entire definiton of `f` is marked as changed.&#34;/&gt; 
&lt;/figure&gt;

&lt;h2 id=&#34;will-i-use-difftastic&#34;&gt;Will I use difftastic?&lt;/h2&gt;
&lt;p&gt;I really like the concept behind difftastic and the few Git commits I looked at with it rendered nicely.
Now, what&amp;rsquo;s &lt;a href=&#34;https://github.com/Wilfred/difftastic#does-difftastic-integrate-with-my-favourite-tool&#34;&gt;missing&lt;/a&gt; for me to use difftastic a lot is its integration with the tools where I actually use Git:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Positron including the GitLens extension;&lt;/li&gt;
&lt;li&gt;GitHub Pull Request Files tab.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In any case, I&amp;rsquo;ll continue learning about tools based on treesitter, some of which like &lt;a href=&#34;https://posit-dev.github.io/air/&#34;&gt;Air&lt;/a&gt; and &lt;a href=&#34;https://jarl.etiennebacher.com/&#34;&gt;Jarl&lt;/a&gt; I can already use directly from my IDE. 😸&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;It&amp;rsquo;s not every day we R developers look at the &lt;a href=&#34;https://difftastic.wilfred.me.uk/&#34;&gt;homepage&lt;/a&gt; of a tool and see the R logo among the logos of other languages! &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;To get the diff that Git would show me I ran &lt;code&gt;git diff --no-index old-args.R new-args.R --no-ext-diff&lt;/code&gt;, cool trick I didn&amp;rsquo;t know about! Very glad I didn&amp;rsquo;t have to create a fake Git repo just for this. (&lt;code&gt;--no-ext-diff&lt;/code&gt; because my diff in this repo would use difftastic by default!) &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Zut, Git ! Porting {saperlipopette} to the terminal with Claude</title>
      <link>https://masalmon.eu/2026/02/27/zut-saperlipopette-claude/</link>
      <pubDate>Fri, 27 Feb 2026 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2026/02/27/zut-saperlipopette-claude/</guid>
      <description>&lt;p&gt;A while ago, I decided to learn some Rust.
I bought a book, opened it months later and started a small side-project: porting my R package saperlipopette to the terminal by writing a CLI with Rust.
I then lost steam and discarded the project.
Now, teaching more Git with &lt;a href=&#34;https://docs.ropensci.org/saperlipopette&#34;&gt;saperlipopette&lt;/a&gt; has me itching to do the same outside of R, to reach more learners.
And in the meantime, even though I have &lt;a href=&#34;https://ropensci.org/blog/2026/02/26/ropensci-ai-policy/&#34;&gt;conflicting feelings&lt;/a&gt; about it, I realized that using an LLM, specifically Claude Code (Opus 4.6), would help me take my CLI over the finishing line!&lt;/p&gt;
&lt;h2 id=&#34;what-my-cli-already-had&#34;&gt;What my CLI already had&lt;/h2&gt;
&lt;p&gt;The CLI project already had a few exercises, all the “Oh shit, Git!” exercises from saperlipopette.
It had a bad name: ohcrabgit, a pun based on “Oh crap, Git!” and on Rust’s logo being a crab.
Definitely not something you want to be typing in a terminal again and again.&lt;/p&gt;
&lt;p&gt;Its interface was the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You’d create an exercise in a folder by typing a command in the terminal.&lt;/li&gt;
&lt;li&gt;You’d then open that folder, and read the file &lt;code&gt;instructions.txt&lt;/code&gt; to know what to do, then the file &lt;code&gt;tip.txt&lt;/code&gt; in case you needed hints.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That interface I wanted to keep, because it’s fairly simple and would work no matter what people usually use to work with Git.
Surely they use Git somewhere where they can read text files.&lt;/p&gt;
&lt;p&gt;It had some internal infrastructure: for instance a file called &lt;code&gt;git.rs&lt;/code&gt; that had some utility functions such as &lt;code&gt;init_playground&lt;/code&gt; or &lt;code&gt;create_branch&lt;/code&gt;.
It used the Rust crate git2 in particular, for the Git aspects.&lt;/p&gt;
&lt;p&gt;Each line had been painstakingly written by me, with the help of a search engine and of the helpful error messages from the compiler. 😅&lt;/p&gt;
&lt;h2 id=&#34;what-i-wanted-for-the-cli&#34;&gt;What I wanted for the CLI&lt;/h2&gt;
&lt;p&gt;I wasn’t so interested any more in writing Rust code myself.
Maybe one day that’ll be relevant for my work, but it isn’t right now.
I wanted to grow the CLI for it to match the features of saperlipopette: more exercises, and translations of the instructions/tips in French and Spanish.
With that end product, I should be able to teach the same workshops as before, but using the CLI instead of saperlipopette if my audience were not R users only.&lt;/p&gt;
&lt;p&gt;I also wanted to improve the formatting of the help, and the installation instructions.&lt;/p&gt;
&lt;p&gt;The project went well!
I have a Claude Code subscription, I call Claude from the terminal, from within Positron IDE.
Note that I reached the rate limit of a session right before it was time for my Pilates class so it wasn’t too bad to just wait. 🧘&lt;/p&gt;
&lt;p&gt;Here’s what was produced in &lt;a href=&#34;https://github.com/maelle/zut&#34;&gt;zut source code&lt;/a&gt;, and reviewed by me the Rust newbie, therefore not extremely deeply:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Improvements of the help formatting. I pushed back on ANSI strings in the code, and asked for more accessible colors (not sure they’re the best choice). &lt;a href=&#34;https://github.com/maelle/zut/commit/a0be5dda82c93663904d07d31e22003f114e561e&#34;&gt;Commit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I chose a better name for the CLI, the French curseword “zut” (“darn”). Claude did the renaming everywhere, which was especially lazy from me. &lt;a href=&#34;https://github.com/maelle/zut/commit/3679fbf50807a971125ab430f1441ed295d78e3c&#34;&gt;Commit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The installation instructions are now to run &lt;code&gt;cargo install --git https://github.com/maelle/zut&lt;/code&gt;, suggestion by Claude, since the audience for my tool should mostly be developers. I guess I’ll see what the pain points are when people do try to install it on different platforms&amp;hellip; &lt;a href=&#34;https://github.com/maelle/zut/commit/92afceca8198233084d11bc914bdbbfe14d5bb06#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5&#34;&gt;Commit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The CLI now outputs instructions and tips in different languages based on the system locale, an environment variable, or a flag. I asked for the system locale to be the default. In that same stream of work, Claude added more unit tests, which I didn’t even request, and integration tests, which I did request after seeing the tests folder was empty. &lt;a href=&#34;https://github.com/maelle/zut/commit/30519918ebfb2316f47d25acb5945f869c938f48&#34;&gt;Commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;All new exercises from saperlipopette were ported to zut in French, English and Spanish, and they were categorized in the help output as well as the docs (which at the moment is… the README). I tried running them, which lead to small tweaks (empty lines at the end of files) and bigger tweaks (for instance the git bisect exercise in saperlipopette has you run an R script, but it needed to become a shell script for it to make sense in zut). &lt;a href=&#34;https://github.com/maelle/zut/commit/4587ca6df38cb5371ceed45faf086f7161746dea&#34;&gt;Commit&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A bug fix, since zut only worked&amp;hellip; from the folder containing its source. 🤦 &lt;a href=&#34;https://github.com/maelle/zut/commit/a2d3eb9fb991a425ca9823132ddc4bebad889ab3&#34;&gt;Commit&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-state-of-zut&#34;&gt;The state of zut&lt;/h2&gt;
&lt;p&gt;To install zut:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;cargo install --git https://github.com/maelle/zut
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To view help:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;zut --help
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;whose output is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;Create example Git messes to solve, inspired by https://ohshitgit.com/

Usage: zut &amp;lt;EXO&amp;gt;&lt;span style=&#34;color:#666&#34;&gt;[&lt;/span&gt;TARGET&lt;span style=&#34;color:#666&#34;&gt;]&lt;/span&gt;. In the exercise folder, open instructions.txt.

Arguments:
  &amp;lt;EXO&amp;gt;
          Name of the exercise

          Possible values:
          - time-machine:       Oh shit, I did something terribly wrong, please tell me git has a magic &lt;span style=&#34;color:#007020&#34;&gt;time&lt;/span&gt; machine!?!
          - small-change:       Oh shit, I committed and immediately realized I need to make one small change!
          - latest-message:     Oh shit, I need to change the message on my last commit!
          - committed-to-main:  Oh shit, I accidentally committed something to main that should have been on a brand new branch!
          - committed-to-wrong: Oh shit, I accidentally committed to the wrong branch!
          - undo-commit:        Oh shit, I need to undo a commit from like &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt; commits ago!
          - undo-file:          Oh shit, I need to undo my changes to a file!
          - split-changes:      Hey I&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;d like to split these changes to the same file into several commits!
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          - clean-dir:          Hey, how do I remove all my debugging left-over stuff at once?
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          - conflict:           Hey I&amp;#39;&lt;/span&gt;d like to see what merge conflicts look like!
          - rebase-i:           Hey I&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;d like to make my commits in a branch look informative and smart! (interactive rebase)
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          - reset:              Hey I&amp;#39;&lt;/span&gt;d like to restart from scratch and reorganize my commits! &lt;span style=&#34;color:#666&#34;&gt;(&lt;/span&gt;git reset --mixed&lt;span style=&#34;color:#666&#34;&gt;)&lt;/span&gt;
          - bisect:             Hey I&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;d like to find which commit introduced a bug!
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          - log-deleted-file:   I want to find which commit deleted a file!
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          - log-deleted-line:   I want to find which commit deleted a line!
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          - revparse:           I want to understand ancestry references like HEAD~5 and HEAD^^!
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          - blame:              I want to find who added a specific line and when!
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          - worktree:           I need to see what the project looked like at a certain version!
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;  [TARGET]
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          Where to create the exercise directory. Default: temporary directory
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          [default: tempdir]
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;Options:
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;      --lang &amp;lt;LANG&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          Language (default: auto-detected from system locale)
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          [possible values: en, fr, es]
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;  -h, --help
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;          Print help (see a summary with &amp;#39;&lt;/span&gt;-h&lt;span style=&#34;&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;)&lt;/span&gt;

  -V, --version
          Print version

Examples:

  zut small-change  creates the small-change exercise folder in a temporary folder.
  zut latest-message ..  creates the latest-message exercise folder in the parent of the current folder.

Categories:

  Oh shit, Git!:
    time-machine, small-change, latest-message, committed-to-main,
    committed-to-wrong, undo-commit, undo-file

  Clean history:
    split-changes, clean-dir, conflict, rebase-i, reset

  Use history:
    bisect, log-deleted-file, log-deleted-line, revparse, blame, worktree
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To create the time machine exercise in a temporary folder:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;zut time-machine
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The path to the folder is printed to screen so you can open it, read &lt;code&gt;instructions.txt&lt;/code&gt; there and get working:
in that challenge a &lt;code&gt;git reset --hard&lt;/code&gt; too many was run so you need &lt;code&gt;git reflog&lt;/code&gt; to rescue an important commit.&lt;/p&gt;
&lt;p&gt;To create the blame exercise in a folder above the current one, in French:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;zut blame .. --lang fr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In that challenge, you need to find who committed a given line in a script.
Dr Jekyll or Mr Hyde? &lt;code&gt;git blame&lt;/code&gt; will help!&lt;/p&gt;
&lt;p&gt;Last but not least, if you try creating an exercise somewhere where it exists:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;zut blame .. --lang fr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;you get:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;Exercise folder already exists: ../exo-blame — delete it or choose a different target.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;conclusion-future-work&#34;&gt;Conclusion: future work&lt;/h2&gt;
&lt;p&gt;Using Claude Code helped me port the features of the saperlipopette R package to the zut CLI.
The next steps are for me to actually use zut more beyond the tests I did, to catch further problems.
Say I need to teach &lt;a href=&#34;https://masalmon.eu/talks/2025-11-24-git-history/&#34;&gt;“Painlessly Improve Your Git History”&lt;/a&gt; again, I’d do all the exercises again in a row. I would do that in the human language of the workshop.&lt;/p&gt;
&lt;p&gt;I could also improve the code of the CLI based on user’s feedback and on, say, feedback from Claude Code using the &lt;a href=&#34;https://github.com/posit-dev/skills/blob/97b0d388f24ccb500fd06ddd01116e427c5aa65f/posit-dev/critical-code-reviewer/SKILL.md?plain=1#L2&#34;&gt;posit-dev/critical-code-reviewer skill&lt;/a&gt; (thanks to &lt;a href=&#34;https://drmowinckels.io/&#34;&gt;Mo&lt;/a&gt; for telling me about it!).
The documentation could also use some work, compared to saperlipopette, but as a companion to workshops it might be ok.&lt;/p&gt;
&lt;p&gt;The saperlipopette package itself has been submitted to &lt;a href=&#34;github.com/ropensci/software-review/issues/754&#34;&gt;rOpenSci software peer-review&lt;/a&gt; so I expect it to change for the better. When I need to port over those changes, depending on what they are I might resort to Claude Code again.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Git commits: please mark your stitches!</title>
      <link>https://masalmon.eu/2026/02/15/stitch-markers-git-commits/</link>
      <pubDate>Sun, 15 Feb 2026 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2026/02/15/stitch-markers-git-commits/</guid>
      <description>&lt;p&gt;In which I share a crochet analogy for Git commits…&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://serve.podhome.fm/episodepage/r-weekly-highlights/222&#34;&gt;R Weekly highlights podcast&lt;/a&gt; hosted by Eric Nantz and Mike Thomas.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;dont-forget-your-stitch-markers&#34;&gt;Don’t forget your stitch markers!&lt;/h2&gt;
&lt;p&gt;I am happily continuing my &lt;a href=&#34;https://masalmon.eu/2026/01/26/amigurumi/&#34;&gt;crochet learning journey&lt;/a&gt;.
One lesson I have now internalised is that I should never ever forget or neglect to use stitch markers.
Stitch markers are sort of small, not spiky, safety pins.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;markers.jpg&#34;
         alt=&#34;A crochet project featuring several stitch markers (beginning of a Snorlax from Lee Sartori&amp;amp;rsquo;s Pokemon crochet book)&#34; width=&#34;400&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;A crochet project featuring several stitch markers (beginning of a Snorlax from Lee Sartori&amp;rsquo;s Pokemon crochet book)&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Stitch markers should be used:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;at the beginning of a round to not forget where it started – in amigurumi you often crochet in a spiral so it’s hard to know where a round started,&lt;/li&gt;
&lt;li&gt;every multiple of stitches to not have to count stitches above 12 even if you happen to have a PhD in counting&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. Many crochet patterns will have you, say, “increase by two stitches every 8th stitch”, then “increase by two stitches every 9th stitch” so having your markers every 9 then 10 stitches will be most helpful.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have sometimes forgotten to place my stitch marker at the beginning of a round, and really regretted my lack of concentration.
Furthermore, I used to think that adding more stitch markers was too much work (Opening the marker! Putting it under a stitch! Closing the marker! Could I be any lazier?!) which is absolutely wrong.
Stitch markers bring peace of mind.
They spark joy.&lt;/p&gt;
&lt;h2 id=&#34;dont-forget-your-git-commits&#34;&gt;Don’t forget your Git commits!&lt;/h2&gt;
&lt;p&gt;Well, Git commits are just like stitch markers.
Putting them regularly along your strand of work will only help you in the future. It is well worth the small annoyance of making them.
With good commits, you can undo your work up to a certain point. You can understand what was done when and why.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&#34;https://masalmon.eu/2024/01/18/saperlipopette-package-practice-git/&#34;&gt;saperlipopette R package&lt;/a&gt; I’ve recently added exercises related to using history:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_log_deleted_file.html&#34;&gt;&amp;ldquo;I want to find which commit deleted a file!&amp;quot;&lt;/a&gt; (&lt;code&gt;git log -- &amp;lt;path&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_log_deleted_line.html&#34;&gt;&amp;ldquo;I want to find which commit deleted a line!&amp;quot;&lt;/a&gt; (&lt;code&gt;git log -S&amp;lt;string&amp;gt;&lt;/code&gt;, &lt;code&gt;git log -G&amp;lt;regex&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_revparse.html&#34;&gt;&amp;ldquo;I want to understand ancestry references!&amp;quot;&lt;/a&gt; (&lt;code&gt;git show&lt;/code&gt;, &lt;code&gt;git rev-parse&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_blame.html&#34;&gt;&amp;ldquo;I want to find who added a specific line!&amp;quot;&lt;/a&gt; (&lt;code&gt;git blame&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_worktree.html&#34;&gt;&amp;ldquo;I need to see what the project looked like at a certain version!&amp;quot;&lt;/a&gt; (&lt;code&gt;git worktree&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;An older exercise: &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_bisect.html&#34;&gt;&amp;ldquo;Hey I&amp;rsquo;d like to find which commit introduced a bug!&amp;quot;&lt;/a&gt; (&lt;code&gt;git bisect&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most of those exercises teach you the skill of obtaining a Git commit ID in answer to a question.
How useful that is depends on how good the commit history is: big commits with uninformative messages are not great.
If the exercises related to using the history seem relevant to you, try &lt;a href=&#34;https://masalmon.eu/2024/06/11/rewrite-git-history/&#34;&gt;improving your commit history&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;conventional.png&#34;
         alt=&#34;Screenshot of commits on saperlipopette&amp;#39;s GitHub repo where each type of commit gets a colored label, e.g. &amp;#39;docs&amp;#39; or &amp;#39;feature&amp;#39;&#34; width=&#34;300&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;Note that you use &lt;a href=&#34;https://www.conventionalcommits.org/en/v1.0.0/&#34;&gt;conventional commits&lt;/a&gt;, you might even get nice colours for them, just as if you were using stitch markers!
The above is due to RefinedGitHub, a browser extension for GitHub, but I&amp;rsquo;m sure similar functionality exist for other Git platforms and in IDEs.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In conclusion, I firmly believe good Git commits can change your life for the better, just like stitch markers.
Don’t learn the lesson the hard way!&lt;/p&gt;
&lt;p&gt;Besides, if you’re interested in learning how to recover from common Git mistakes such as a commit made on the wrong branch, consider registering to my upcoming workshop at Workshops for Ukraine:
&lt;a href=&#34;https://sites.google.com/view/dariia-mykhailyshyna/main/r-workshops-for-ukraine#h.r3evto8phau7&#34;&gt;&amp;ldquo;Oops, Git! How to recover from common mistakes&amp;rdquo;&lt;/a&gt;,
Thursday, March 19th, 14:00 - 16:00 CET (Rome, Berlin, Paris timezone).
All proceeds going to support Ukraine. (After the workshop, &lt;a href=&#34;https://sites.google.com/view/dariia-mykhailyshyna/main/r-workshops-for-ukraine#h.wqbtxn2ugxva&#34;&gt;making a donation gets you access to the recording&lt;/a&gt;)&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Also called PhD in statistics! &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Parallel strands between learning crochet and learning programming</title>
      <link>https://masalmon.eu/2026/01/26/amigurumi/</link>
      <pubDate>Mon, 26 Jan 2026 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2026/01/26/amigurumi/</guid>
      <description>&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&#34;https://drmowinckels.io/&#34;&gt;Athanasia Mo Mowinckel&lt;/a&gt; for reviewing this post!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;One goal of mine this year is to learn how to crochet &lt;a href=&#34;https://en.wikipedia.org/wiki/Amigurumi&#34;&gt;amigurumi&lt;/a&gt;, that is to say, cute creatures.
When working on my first project, a cat toy made out of yarn left-over from knitting projects, I thought of some similarities between this activity and being a beginner in programming.
Here they are!&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;bee.jpg&#34;
         alt=&#34;A light yellow and dark blue bee&#34;/&gt; &lt;figcaption&gt;
            &lt;p&gt;This poor bee has heart wings&amp;hellip; mounted the wrong way so won&amp;rsquo;t be able to flee the cat it was gifted to. &lt;a href=&#34;https://en.wikipedia.org/wiki/Empire_of_AI&#34;&gt;Unrelated excellent book in the background&lt;/a&gt;.&lt;/p&gt;
        &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&#34;importance-of-instruction-quality&#34;&gt;Importance of instruction quality&lt;/h2&gt;
&lt;p&gt;I bought an amigurumi kit that came with horrible instructions.
Probably a bad translation to English but even assuming that, I can’t even think what crappy explanations it was translated from. 😅
I’m so grateful for the possibility to search for tutorials or videos that “click”!
Even among good explanations, some of them didn’t work for me, so I guess writing yet another tutorial on something isn’t necessarily a waste of time as your own voice might unstuck someone.&lt;/p&gt;
&lt;h2 id=&#34;frustration-is-part-of-the-process&#34;&gt;Frustration is part of the process&lt;/h2&gt;
&lt;p&gt;I’ve seen a reddit thread where someone said learning how to make a magic ring, the very first step of many (all?) amigurumi patterns, made them cry.
Well this intersects with finding instructions that resonate, but even so, having to frog (undo&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;) your project over and over again is normal.
Just like you might have to try and try again something in programming… Even beyond one’s beginner’s days actually.
We have to work on our endurance.&lt;/p&gt;
&lt;h2 id=&#34;thanks-for-tech&#34;&gt;Thanks for tech&lt;/h2&gt;
&lt;p&gt;Very much like learning can be helped by technical tools (software for webinars!), I am thankful in general for the internet and computers and cameras and in particular for tools that help creators mirror their videos or photos so that I, a left-handed crochet learner, don’t need to add to my overwhelm by having to mirror things in my head.&lt;/p&gt;
&lt;h2 id=&#34;the-importance-of-practice&#34;&gt;The importance of practice&lt;/h2&gt;
&lt;p&gt;I am getting better at crochet because of practice. There’s no magical shortcut. Just like this quote of &lt;a href=&#34;https://mastodon.social/@hadleywickham@fosstodon.org/112021309114549465&#34;&gt;Hadley Wickham’s&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Periodic reminder: The only way to write good code is to write tons of shitty code first. Feeling shame about bad code stops you from getting to good code.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I am working on my tons of shitty stitches. 😸&lt;/p&gt;
&lt;h2 id=&#34;the-importance-of-scrap-yarn&#34;&gt;The importance of scrap yarn&lt;/h2&gt;
&lt;p&gt;My first kit is cheap.
I even started with left-over yarn, which is even less valuable&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.
This gave me so much freedom!
In programming, I also believe in the importance of low pressure to learn.
If you practice Git with my &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/&#34;&gt;saperlipopette&lt;/a&gt; package, you can do so in temporary folders that are very much like scrap yarn: good for learning, fine to throw away.&lt;/p&gt;
&lt;h2 id=&#34;silly-conventions&#34;&gt;Silly conventions&lt;/h2&gt;
&lt;p&gt;R starts indexing from 1, Python from 0. Well in crochet, a French &lt;em&gt;maille serrée&lt;/em&gt; is single crochet in US patterns and a double crochet in UK patterns. 😵‍💫&lt;/p&gt;
&lt;h2 id=&#34;so-many-pitfalls&#34;&gt;So many pitfalls&lt;/h2&gt;
&lt;p&gt;Even beyond those silly conventions, there are so many pitfalls as a beginner!
For some of the things I regularly do at work, I have internalized many rules and risks thanks to practice, but in crochet, I can get so overwhelmed.
You have to count (harder than it sounds),
you&amp;rsquo;ll be in hell if you forget to place your stitch marker at the beginning of a row,
the tension is important (not too loose, not too tight),
it’s hard to see what you’re doing with dark yarn,
set up (the magic ring that doesn’t magically appear!) is a chore and difficult, etc.
The list goes on and on.
I guess they don’t say for nothing that it’s good to be a beginner: it will increase my empathy as an instructor!&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I summarized some common points between being a beginner in crochet and programming.
I’d better follow my own advice and continue practicing crochet regularly. 🙂&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Called frogging apparently because the sound of undoing your stitches resembles the sound of a frog? &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Even if I love that yarn because it is not made of several strands, it is a sturdy chain I can&amp;rsquo;t undo! So handy when you’re bad at orientating your crochet! &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>How to open files, folders, websites in R</title>
      <link>https://masalmon.eu/2025/06/25/open-files-folders-websites/</link>
      <pubDate>Wed, 25 Jun 2025 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2025/06/25/open-files-folders-websites/</guid>
      <description>&lt;p&gt;Coming to you from France, a post about &lt;a href=&#34;https://en.wikipedia.org/wiki/Mise_en_place&#34;&gt;&lt;em&gt;Mise en place&lt;/em&gt;&lt;/a&gt; for R projects. In a less francophone phrasing: to get to work on something you have to open that thing, be it a script or a project or a website. The easier that is, the faster you get to work. In this post I&amp;rsquo;ll show a roundup of R functions and related tools for opening scripts, projects and websites for yourself or on behalf of the users of your code.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to &lt;a href=&#34;https://www.frick.ws/&#34;&gt;Hannah Frick&lt;/a&gt; for providing inspiration for some items of this post, and for reviewing it!&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;open-any-file-in-the-editor-utilsfileedit-or-styling-with-cli&#34;&gt;Open any file in the editor: &lt;code&gt;utils::file.edit()&lt;/code&gt; or styling with &lt;code&gt;{cli}&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;If you write code that creates a file at &lt;code&gt;path&lt;/code&gt; and then is supposed to open it for the user, there is no need for you to use, say, &lt;code&gt;rstudioapi::documentOpen(path)&lt;/code&gt; that only works in &lt;a href=&#34;https://posit.co/products/open-source/rstudio/&#34;&gt;RStudio IDE&lt;/a&gt;. You can use a base R function, &lt;a href=&#34;https://rdrr.io/r/utils/file.edit.html&#34;&gt;&lt;code&gt;utils::file.edit()&lt;/code&gt;&lt;/a&gt;! It will open the path in the default editor. Without me setting up anything, that is the RStudio IDE when I&amp;rsquo;m already in RStudio and &lt;a href=&#34;https://drmowinckels.io/blog/2025/positron-debugging/&#34;&gt;Positron&lt;/a&gt; when I&amp;rsquo;m already in Positron. From an R session in the terminal&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, that is the default editor of my system&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;I was surprised to see that &lt;a href=&#34;https://usethis.r-lib.org/reference/edit_file.html&#34;&gt;&lt;code&gt;usethis::edit_file()&lt;/code&gt;&lt;/a&gt; uses an RStudio specific function when available:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# https://github.com/r-lib/usethis/blob/4aa55e72ccca131df2d98fcd84fff66724d6250a/R/edit.R#L32C1-L36C4&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;kr&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;rstudio_available&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;rstudioapi&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rstudio.github.io/rstudioapi/reference/hasFun.html&#39;&gt;hasFun&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;navigateToFile&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;rstudioapi&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rstudio.github.io/rstudioapi/reference/navigateToFile.html&#39;&gt;navigateToFile&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;else&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;utils&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/utils/file.edit.html&#39;&gt;file.edit&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;According to the &lt;a href=&#34;https://github.com/r-lib/usethis/commit/9ab2582980f0f4a8a1d565dba00345ac7aa7e2a2&#34;&gt;commit that added this logic&lt;/a&gt; more than 7 years ago, &amp;ldquo;utils::file.edit opens in dialog&amp;rdquo; which I do not understand. Maybe it&amp;rsquo;s different depending on the OS? Maybe RStudio changed in the meantime? Please tell me if you have any more information on this. 🙏&lt;/p&gt;
&lt;p&gt;In any case, I really enjoy &lt;a href=&#34;https://rdrr.io/r/utils/file.edit.html&#34;&gt;&lt;code&gt;file.edit()&lt;/code&gt;&lt;/a&gt; in code bases. Interactively, I do not use is as often as, say, Positron&amp;rsquo;s shortcut for navigating to files (Ctrl+P on my machine).&lt;/p&gt;
&lt;p&gt;Last but not least, if you want to make it easy for the user to open a file, without opening it on their behalf, in messages emitted through the &lt;a href=&#34;https://blog.r-hub.io/2023/11/30/cliff-notes-about-cli/&#34;&gt;cli package&lt;/a&gt; you can use the &lt;a href=&#34;https://cli.r-lib.org/reference/inline-markup.html#classes&#34;&gt;file class&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;cli&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://cli.r-lib.org/reference/cli_alert.html&#39;&gt;cli_alert_success&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;Hey go edit &amp;#123;.file config.toml&amp;#125; please!&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;ldquo;If the terminal supports ANSI hyperlinks (e.g. RStudio, iTerm2, etc.), then cli creates a clickable link that opens the file in RStudio or with the default app for the file type.&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;open-the-script-or-test-file-of-a-script-test-pair-usethisuse_r-and-usethisuse_test&#34;&gt;Open the script or test file of a script-test pair: &lt;code&gt;usethis::use_r()&lt;/code&gt; and &lt;code&gt;usethis::use_test()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Coming back to the wonderful usethis package, when you name your test files after your scripts as you should, running &lt;a href=&#34;https://r-pkgs.org/testing-basics.html#create-a-test&#34;&gt;&lt;code&gt;usethis::use_test()&lt;/code&gt;&lt;/a&gt; when focussed on an R script will open its test file, and conversely &lt;a href=&#34;https://usethis.r-lib.org/reference/use_r.html&#34;&gt;&lt;code&gt;usethis::use_r()&lt;/code&gt;&lt;/a&gt; when focussed on a test file. This is still how I switch between the two even if inside Positron.&lt;/p&gt;
&lt;h2 id=&#34;open-a-project-positron-project-launcher-usethis&#34;&gt;Open a project: &lt;code&gt;positron&lt;/code&gt;, project launcher, {usethis}&lt;/h2&gt;
&lt;p&gt;This is all very good when within a project, but how do you enter your IDE in the first place? How sad would it be to lose momentum before even launching a project?&lt;/p&gt;
&lt;p&gt;When I used the RStudio IDE, I would navigate to the folder of interest, then double-click on the &lt;code&gt;.Rproj&lt;/code&gt; file. Hannah Frick inspired me, when demoing Positron to me, to think a bit harder about how much I click. 😅 I have adopted a more keyboard-based workflow since I switched to Positron, which I could have done with RStudio IDE.&lt;/p&gt;
&lt;p&gt;One thing in particular that Hannah showed me that looks cool is the use of a &lt;a href=&#34;https://positron.posit.co/rstudio-rproj-file.html#use-an-application-launcher&#34;&gt;project launcher&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, I myself still use the terminal. For instance if I clone a repository&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;, I&amp;rsquo;ll then open it with the &lt;code&gt;positron&lt;/code&gt; command. If that command does not work for you yet on macOS or Windows, you might need to &lt;a href=&#34;https://positron.posit.co/add-to-path.html&#34;&gt;add Positron to your PATH&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another way to open projects that I use a lot, in Positron and RStudio, is to click on the recent projects when the IDE is already up and running. Unfortunately, I created and &lt;a href=&#34;https://stateofther.netlify.app/post/saperlipopette/&#34;&gt;currently&lt;/a&gt; &lt;a href=&#34;https://www.meetup.com/rbuenosaires/events/308338205/&#34;&gt;often&lt;/a&gt; use the &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/&#34;&gt;saperlipopette&lt;/a&gt; package that creates throwaway folders for practicing Git. This makes the list of recent projects utter rubbish. 🙃&lt;/p&gt;
&lt;p&gt;Within saperlipopette itself, to create and open the exercise folder on behalf of the user, I use &lt;a href=&#34;https://usethis.r-lib.org/reference/create_package.html&#34;&gt;&lt;code&gt;usethis::create_project()&lt;/code&gt;&lt;/a&gt;, which handily opens it in Positron when run in Positron and in RStudio when run in RStudio.&lt;/p&gt;
&lt;h2 id=&#34;open-an-url-in-the-browser-browseurl-or-styling-with-cli&#34;&gt;Open an URL in the browser: &lt;code&gt;browseURL()&lt;/code&gt; or styling with {cli}&lt;/h2&gt;
&lt;p&gt;Sometimes you want the user of some code of yours to go admire or read a web page.&lt;/p&gt;
&lt;p&gt;To open an URL in the default browser, you can use &lt;a href=&#34;https://rdrr.io/r/utils/browseURL.html&#34;&gt;&lt;code&gt;utils::browseURL()&lt;/code&gt;&lt;/a&gt;. In all of the &lt;code&gt;usethis::browse_&lt;/code&gt; functions, &lt;a href=&#34;https://rdrr.io/r/utils/browseURL.html&#34;&gt;&lt;code&gt;utils::browseURL()&lt;/code&gt;&lt;/a&gt; is what&amp;rsquo;s used under the hood. For instance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/utils/browseURL.html&#39;&gt;browseURL&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;https://masalmon.eu/post&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To make it easy to open an URL from a message, you can use the &lt;a href=&#34;https://cli.r-lib.org/reference/inline-markup.html#classes&#34;&gt;URL class&lt;/a&gt; of the cli package. For instance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;cli&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://cli.r-lib.org/reference/cli_alert.html&#39;&gt;cli_alert_info&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;Go read that blog! &amp;#123;.url https://masalmon.eu/post&amp;#125;!&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;When getting that message, the user will simply have to click on the link to follow it (after trusting the domain in Positron).&lt;/p&gt;
&lt;h2 id=&#34;open-only-in-interactive-sessions-interactive-rlangis_interactive&#34;&gt;Open only in interactive sessions: &lt;code&gt;interactive()&lt;/code&gt;, &lt;code&gt;rlang::is_interactive()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;If you use &lt;a href=&#34;https://rdrr.io/r/utils/file.edit.html&#34;&gt;&lt;code&gt;utils::file.edit()&lt;/code&gt;&lt;/a&gt; or &lt;a href=&#34;https://rdrr.io/r/utils/browseURL.html&#34;&gt;&lt;code&gt;utils::browseURL()&lt;/code&gt;&lt;/a&gt; in your code, you need to ensure the session is interactive.&lt;/p&gt;
&lt;p&gt;Either&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;kr&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/interactive.html&#39;&gt;interactive&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/utils/file.edit.html&#39;&gt;file.edit&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;config.toml&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Or&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;kr&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/is_interactive.html&#39;&gt;is_interactive&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/utils/file.edit.html&#39;&gt;file.edit&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;config.toml&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Compared to &lt;a href=&#34;https://rdrr.io/r/base/interactive.html&#34;&gt;&lt;code&gt;interactive()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://rlang.r-lib.org/reference/is_interactive.html&#34;&gt;&lt;code&gt;rlang::is_interactive()&lt;/code&gt;&lt;/a&gt; also checks whether knitr or testthat are in progress, and provides an escape hatch through the &lt;code&gt;rlang_interactive&lt;/code&gt; option.&lt;/p&gt;
&lt;p&gt;All of the usethis functions that try to open or browse something on behalf of the user behave differently based on &lt;a href=&#34;https://rlang.r-lib.org/reference/is_interactive.html&#34;&gt;&lt;code&gt;rlang::is_interactive()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/r-lib/usethis/blob/4aa55e72ccca131df2d98fcd84fff66724d6250a/R/edit.R#L20&#34;&gt;&lt;code&gt;usethis::edit_file()&lt;/code&gt;&#39;s source&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/r-lib/usethis/blob/4aa55e72ccca131df2d98fcd84fff66724d6250a/R/helpers.R#L107&#34;&gt;&lt;code&gt;usethis::view_url()&lt;/code&gt;&#39;s source&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I summarized some tools for opening scripts, projects, and URLs - for yourself or on behalf of your user. I&amp;rsquo;d like to add some words of conclusion beyond the summary table below, but after so much talk of opening, I have trouble &lt;strong&gt;closing&lt;/strong&gt; this post. 😁&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Target to open&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Audience&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;File&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://rdrr.io/r/utils/file.edit.html&#34;&gt;&lt;code&gt;utils::file.edit()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Users of your code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;IDE&amp;rsquo;s shortcut&lt;/td&gt;
&lt;td&gt;You &amp;ndash; get to know your IDE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://cli.r-lib.org/reference/inline-markup.html#classes&#34;&gt;&lt;code&gt;.file&lt;/code&gt; class of cli message&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Users of your code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;R script from test file&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://usethis.r-lib.org/reference/use_r.html&#34;&gt;&lt;code&gt;usethis::use_r()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;IDE&amp;rsquo;s shortcut&lt;/td&gt;
&lt;td&gt;You &amp;ndash; get to know your IDE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test file from R script&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://usethis.r-lib.org/reference/use_r.html&#34;&gt;&lt;code&gt;usethis::use_test()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;IDE&amp;rsquo;s shortcut&lt;/td&gt;
&lt;td&gt;You &amp;ndash; get to know your IDE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Project (folder)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.Rproj&lt;/code&gt; file&lt;/td&gt;
&lt;td&gt;RStudio IDE users who like clicking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;List of recent projects within the IDE&lt;/td&gt;
&lt;td&gt;You when the IDE is already launched&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;code&gt;rstudio&lt;/code&gt;, &lt;code&gt;positron&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Terminal dwellers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://positron.posit.co/rstudio-rproj-file.html#use-an-application-launcher&#34;&gt;Project launcher&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Positron users on macOS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://usethis.r-lib.org/reference/create_package.html&#34;&gt;&lt;code&gt;usethis::create_project()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Users of your code that created a project&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;URL&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://rdrr.io/r/utils/browseURL.html&#34;&gt;&lt;code&gt;utils::browseURL()&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Users of your code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;a href=&#34;https://cli.r-lib.org/reference/inline-markup.html#classes&#34;&gt;&lt;code&gt;.url&lt;/code&gt; class of cli message&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Users of your code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Look how adventurous I was when preparing this post! Running R from a terminal! &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Which is&amp;hellip; &lt;a href=&#34;https://en.wikipedia.org/wiki/Atom_(text_editor)&#34;&gt;Atom&lt;/a&gt;, meaning I live in the past since its end-of-life occurred a few years ago. 👻 I actually rarely use it. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I know I could use &lt;a href=&#34;https://usethis.r-lib.org/reference/create_from_github.html&#34;&gt;&lt;code&gt;usethis::create_from_github()&lt;/code&gt;&lt;/a&gt; and sometimes do but not always&amp;hellip; Maybe the message of this post is that my workflows are a big mess. &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Cover and modify, some tips for R package development</title>
      <link>https://masalmon.eu/2024/09/24/cover-modify-r-packages/</link>
      <pubDate>Tue, 24 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/09/24/cover-modify-r-packages/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve recently been dealing with legacy code refactoring both in theory and in practice: while I&amp;rsquo;m continuing some work on the igraph R package, I&amp;rsquo;ve started reading &lt;a href=&#34;https://www.oreilly.com/library/view/working-effectively-with/0131177052/&#34;&gt;Working Effectively with Legacy Code by Michael Feathers&lt;/a&gt;, that had been in my to-read pile for months. In this post, I&amp;rsquo;ll summarize some ideas from both the book and my work.&lt;/p&gt;
&lt;h2 id=&#34;cover-and-modify-with-characterization-tests&#34;&gt;&amp;ldquo;Cover and modify&amp;rdquo; with &amp;ldquo;characterization tests&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;When you start modifying your &lt;a href=&#34;https://masalmon.eu/talks/2024-07-10-user-2024-rusty-code/&#34;&gt;rusty code&lt;/a&gt;, how do you ensure you do not break existing and important behaviour inadvertently? In his book, Michael Feathers advocates for &lt;strong&gt;&amp;ldquo;cover and modify&amp;rdquo;&lt;/strong&gt; (test, then amend) rather than &lt;strong&gt;&amp;ldquo;edit and pray&amp;rdquo;&lt;/strong&gt; (that you&amp;rsquo;re not breaking anyone&amp;rsquo;s script or reverse dependency). Not necessarily brand-new ideas but nice phrases. 😁&lt;/p&gt;
&lt;p&gt;In igraph for instance, when I have to add tests for a function that does not have any test yet, I tend to use code from examples as a starting point. I run the code in an unit test and add expectations that seem relevant to me, and to collaborators more knowledgeable about graphs. Part of this work is very mechanical and probably also very common: running the code to figure out its output, codify its output as expectation. For instance if &lt;code&gt;f()&lt;/code&gt; returns a numeric of value 0.42, I&amp;rsquo;ll add something like &lt;code&gt;testthat::expect_type(output, &amp;quot;double&amp;quot;)&lt;/code&gt; and &lt;code&gt;testthat::expect_equal(output, 0.42)&lt;/code&gt;. It turns out such tests have a name in the book, which made me very happy: they are &lt;strong&gt;&amp;ldquo;characterization tests&amp;rdquo;&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&#34;how-to-characterize-the-output&#34;&gt;How to characterize the output&lt;/h2&gt;
&lt;p&gt;Three tips on how to characterize the output:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You can use &lt;a href=&#34;https://rdrr.io/r/base/typeof.html&#34;&gt;&lt;code&gt;typeof()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://sloop.r-lib.org/reference/otype.html&#34;&gt;&lt;code&gt;sloop::otype()&lt;/code&gt;&lt;/a&gt; to help you find out which &lt;a href=&#34;https://testthat.r-lib.org/reference/inheritance-expectations.html&#34;&gt;testthat type/class expectation&lt;/a&gt; you should use. The latter is linked from a chapter in Hadley Wickham&amp;rsquo;s Advanced R that in turn is linked from the testthat docs. I am mildly embarrassed about even needing the former. 😂&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can use &lt;a href=&#34;https://cynkra.github.io/constructive/reference/construct.html&#34;&gt;&lt;code&gt;constructive::construct()&lt;/code&gt;&lt;/a&gt; to record an expected value in a more readable way than with &lt;a href=&#34;https://rdrr.io/r/base/dput.html&#34;&gt;&lt;code&gt;dput()&lt;/code&gt;&lt;/a&gt; &amp;ndash; for use in snapshot tests or even directly in &lt;a href=&#34;https://testthat.r-lib.org/reference/equality-expectations.html&#34;&gt;&lt;code&gt;testthat::expect_equal()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Michael Feathers notes that characterization tests are a form of documentation, so &amp;ldquo;you have to think about what will be important to the reader&amp;rdquo;. I try to order expectations logically, and&amp;hellip; I request a review on my pull requests so there might actually be another reader involved in the short term. 😇&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;how-to-check-coverage&#34;&gt;How to check coverage&lt;/h2&gt;
&lt;p&gt;To know whether you&amp;rsquo;ve covered the code you&amp;rsquo;re about to modify, you have to assess your tests.&lt;/p&gt;
&lt;p&gt;For some (historical I suppose) reason, in Michael Feathers&amp;rsquo; book code coverage tooling seems absent. I&amp;rsquo;ve instead read about &amp;ldquo;sensing variables&amp;rdquo; and using the debugger to step through the code.&lt;/p&gt;
&lt;p&gt;In R when using devtools we can rely on &lt;a href=&#34;https://devtools.r-lib.org/reference/test.html&#34;&gt;&lt;code&gt;devtools::test_coverage_active_file()&lt;/code&gt;&lt;/a&gt; (including showing you an interactive report!).&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; It&amp;rsquo;s allowed me to see some branches my tests weren&amp;rsquo;t hitting yet. Running it again and again and seeing more lines in green is very satisfying.&lt;/p&gt;
&lt;p&gt;The code coverage might be a part of the continuous integration workflows but in the case of igraph it only runs after all other checks (so not quickly).&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I&amp;rsquo;ve presented some ideas around &amp;ldquo;covering&amp;rdquo; R code with tests before you &amp;ldquo;modify&amp;rdquo; it. Do you have any insight to share that I haven&amp;rsquo;t&amp;hellip; covered? 😅&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I first used a few lines that did the same thing (but obviously not as well) because I had forgotten about this function. Don&amp;rsquo;t do like me! &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Create and use a custom roxygen2 tag</title>
      <link>https://masalmon.eu/2024/09/03/roxygen2-custom-tag/</link>
      <pubDate>Tue, 03 Sep 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/09/03/roxygen2-custom-tag/</guid>
      <description>&lt;p&gt;&lt;strong&gt;This post contains mistakes! No need for a roclet for custom tags! Use the &lt;a href=&#34;https://roxygen2.r-lib.org/reference/load_options.html&#34;&gt;&lt;code&gt;packages&lt;/code&gt; load option&lt;/a&gt;. Refer to the &lt;a href=&#34;https://roxygen2.r-lib.org/dev/articles/extending.html&#34;&gt;roxygen2 vignette&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://serve.podhome.fm/episodepage/r-weekly-highlights/178&#34;&gt;R Weekly highlights podcast&lt;/a&gt; hosted by Eric Nantz and Mike Thomas.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You might know that it&amp;rsquo;s possible to extend &lt;a href=&#34;https://roxygen2.r-lib.org/&#34;&gt;roxygen2&lt;/a&gt; to do all sorts of cool things including but not limited to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;documenting your internal functions for developers only (that&amp;rsquo;s &lt;a href=&#34;https://github.com/moodymudskipper/devtag&#34;&gt;devtag by my cynkra colleague Antoine Fabri&lt;/a&gt;),&lt;/li&gt;
&lt;li&gt;recording your following statistical software standards (that&amp;rsquo;s &lt;a href=&#34;https://github.com/ropensci-review-tools/srr&#34;&gt;srr by my rOpenSci colleague Mark Padgham&lt;/a&gt;),&lt;/li&gt;
&lt;li&gt;writing tests from within R scripts (that&amp;rsquo;s &lt;a href=&#34;https://github.com/mikldk/roxytest&#34;&gt;roxytest by Mikkel Meyer Andersen&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I did something much more basic but still challenging to me: creating a custom tag that adds a new section to a manual page. In this post I&amp;rsquo;ll summarize how to go about that.&lt;/p&gt;
&lt;h2 id=&#34;context-need-for-a-custom-tag-in-the-igraph-r-package&#34;&gt;Context: need for a custom tag in the igraph R package&lt;/h2&gt;
&lt;p&gt;The igraph R package outsources a lot of its work to the igraph C library. Sometimes, the R package docs therefore have to try and catch up with the C library docs. One idea we&amp;rsquo;ve had when thinking about the problem is to link to relevant C docs from each R manual page: if a function called &lt;a href=&#34;https://r.igraph.org/reference/make_empty_graph.html&#34;&gt;&lt;code&gt;igraph::empty_graph()&lt;/code&gt;&lt;/a&gt; uses &lt;code&gt;igraph_empty&lt;/code&gt; under the hood, then its manual page should link to &lt;a href=&#34;https://igraph.org/c/doc/igraph-Basic.html#igraph_empty&#34;&gt;https://igraph.org/c/doc/igraph-Basic.html#igraph_empty&lt;/a&gt;. It means the users would be able to easily browse the C docs, and as a side-effect they&amp;rsquo;d be aware of what part of the C library supports what functionality in the R package.&lt;/p&gt;
&lt;p&gt;A workflow to make that happen is the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;have a sitemap of the C docs at hand (we &lt;a href=&#34;https://github.com/igraph/igraph.r2cdocs/blob/main/data-raw/c-links.R&#34;&gt;parse the index page of the C docs&lt;/a&gt;);&lt;/li&gt;
&lt;li&gt;add &lt;code&gt;@cdocs&lt;/code&gt; tags in the source of the R package, for instance &lt;code&gt;@cdocs igraph_empty&lt;/code&gt; near the function definition (adding them semi-automatically will be a topic for another day 😅);&lt;/li&gt;
&lt;li&gt;have &lt;strong&gt;some roxygen2 machinery parsing the &lt;code&gt;@cdocs&lt;/code&gt;&lt;/strong&gt; into links in the manual page when we call &lt;code&gt;document()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This blog post is about the roxygen2 machinery as I had to piece together several things I saw online.&lt;/p&gt;
&lt;h2 id=&#34;minimal-example&#34;&gt;Minimal example&lt;/h2&gt;
&lt;h3 id=&#34;create-our-minimal-r-package&#34;&gt;Create our minimal R package&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/maelle/hgb&#34;&gt;R package hgb&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The hgb package has one script whose docs use a custom &lt;code&gt;@custom&lt;/code&gt; tag:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; A function messaging a thing&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @custom Hello I am here&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @return Nothing, print thing&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @export&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @examples&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; thing()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/message.html&#39;&gt;message&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;thing&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id=&#34;create-a-package-holding-the-custom-tag&#34;&gt;Create a package holding the custom tag&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/maelle/myroxy&#34;&gt;R package myroxy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In a script I have the following lines that mostly come from an &lt;a href=&#34;https://roxygen2.r-lib.org/articles/extending.html&#34;&gt;roxygen2 vignette&lt;/a&gt;, in which the creation of a custom tag is well documented (its usage less so 😅).&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a method &lt;code&gt;roxy_tag_parse.roxy_tag_custom()&lt;/code&gt; telling roxygen2 how to parse the tag, a method &lt;code&gt;roxy_tag_rd.roxy_tag_custom&lt;/code&gt; telling roxygen2 what to do with the value: a special &amp;ldquo;custom&amp;rdquo; section. Then there&amp;rsquo;s a method &lt;code&gt;format.rd_section_custom()&lt;/code&gt; telling roxygen2 how to build the &amp;ldquo;custom&amp;rdquo; section. Here it&amp;rsquo;s just pasting. In my real use case I defined a helper function to identify the C docs link corresponding to a given tag value.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @importFrom roxygen2 roxy_tag_parse&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @importFrom roxygen2 roxy_tag_rd&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;kc&#39;&gt;NULL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @export&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# same as https://roxygen2.r-lib.org/articles/extending.html&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;roxy_tag_parse.roxy_tag_custom&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;roxygen2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://roxygen2.r-lib.org/reference/tag_parsers.html&#39;&gt;tag_markdown&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @export&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# same as https://roxygen2.r-lib.org/articles/extending.html&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;roxy_tag_rd.roxy_tag_custom&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;base_path&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;env&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;roxygen2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://roxygen2.r-lib.org/reference/rd_section.html&#39;&gt;rd_section&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;custom&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;val&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @export&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# same as https://roxygen2.r-lib.org/articles/extending.html&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;format.rd_section_custom&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;...&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/paste.html&#39;&gt;paste0&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;s&#39;&gt;&#34;\\section&amp;#123;Custom section&amp;#125;&amp;#123;\n&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;s&#39;&gt;&#34;\\itemize&amp;#123;\n&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/paste.html&#39;&gt;paste0&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;  \\item &#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;value&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;\n&#34;&lt;/span&gt;, collapse &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;s&#39;&gt;&#34;&amp;#125;\n&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;s&#39;&gt;&#34;&amp;#125;\n&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id=&#34;create-a-roclet-for-sharing-the-custom-tag&#34;&gt;Create a roclet for sharing the custom tag&lt;/h3&gt;
&lt;p&gt;Even if all we do is creating a custom roxygen2 tag, we need to define a roclet as it&amp;rsquo;ll be the vessel by which another package can use the custom tag. You can have a custom tag defined inside a package without a roclet if you use the custom tag &lt;em&gt;within the same package&lt;/em&gt;. But to cross package boundaries you need a roclet.&lt;/p&gt;
&lt;p&gt;Further in the same script I have those lines:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @export&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# https://github.com/shahronak47/informationtag&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;custom_roclet&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;roxygen2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://roxygen2.r-lib.org/reference/roclet.html&#39;&gt;roclet&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;custom&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @importFrom roxygen2 block_get_tags roclet_process&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @method roclet_process roclet_custom&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @export&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# https://github.com/shahronak47/informationtag&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;roclet_process.roclet_custom&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;blocks&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;env&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;base_path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @export&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&#39; @importFrom roxygen2 block_get_tags roclet_output&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;roclet_output.roclet_custom&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;results&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;base_path&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;...&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You&amp;rsquo;ll notice we defined something called &amp;ldquo;custom_roclet&amp;rdquo; but now the methods are for &amp;ldquo;roclet_custom&amp;rdquo; (inverted word order). This confused me at first. Furthermore, I had no idea what the process and output methods were supposed to do, so I used the &lt;a href=&#34;https://github.com/shahronak47/informationtag&#34;&gt;demo by Ronak Shah&lt;/a&gt;. Lastly, the roxygen2 tags used in that demo didn&amp;rsquo;t work for me so I stole the ones used by Antoine Fabri in &lt;a href=&#34;https://github.com/moodymudskipper/devtag/blob/61098a12545b34c3bba4e516f29c71da56a7d49d/R/roxygen.R#L20&#34;&gt;devtag&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;build-the-package-holding-the-custom-tag&#34;&gt;Build the package holding the custom tag&lt;/h3&gt;
&lt;p&gt;By that I mean running &lt;code&gt;document()&lt;/code&gt; and installing the myroxy package on my machine to try it.&lt;/p&gt;
&lt;h3 id=&#34;register-the-roclet-in-our-minimal-package&#34;&gt;Register the roclet in our minimal package&lt;/h3&gt;
&lt;p&gt;I added the following lines to the &lt;code&gt;DESCRIPTION&lt;/code&gt; of the hgb package to indicate to roxygen2 that there&amp;rsquo;s another package to use when documenting my package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;Roxygen&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;list(markdown&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;TRUE,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;roclets&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;c(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;collate&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rd&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;namespace&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;myroxy::custom_roclet&amp;#34;&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;packages&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;myroxy&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I also added these lines so that fellow developers might know where to get myroxy from&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;Config/Needs/build&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;roxygen2,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;devtools,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;maelle/myroxy&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;try-it&#34;&gt;Try it&lt;/h3&gt;
&lt;p&gt;If all goes well, running &lt;code&gt;document()&lt;/code&gt; in the hgb package works without any error. The manual page for &lt;code&gt;?thing&lt;/code&gt; has the &lt;a href=&#34;https://github.com/maelle/hgb/blob/c75682742bcaa29efa74f8a7ee055c65640b0aa0/man/thing.Rd#L18&#34;&gt;custom section&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;do-i-need-an-external-package&#34;&gt;Do I need an external package?&lt;/h2&gt;
&lt;p&gt;The roxygen2 extensions I mentioned in the introduction (devtag, srr, roxytag) are standalone packages that you can use when building your own package, because their use case is fairly general. Here, I am developing a custom tag for igraph only. So in theory, the infrastructure could live inside the R package itself.&lt;/p&gt;
&lt;p&gt;I actually started by implementing the custom tag within the igraph package but I was not a fan of the clutter it created in &lt;code&gt;data-raw&lt;/code&gt;, &lt;code&gt;R&lt;/code&gt;, the &lt;code&gt;NAMESPACE&lt;/code&gt;, etc. It was great to start this way as it was much easier (no roclet!), but I ended up factoring out the roxygen2 code in a distinct GitHub-only package called &lt;code&gt;igraph.r2cdocs&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;sources&#34;&gt;Sources&lt;/h2&gt;
&lt;p&gt;I am very thankful to the authors of roxygen2 obviously, and to the authors of the following resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://roxygen2.r-lib.org/articles/extending.html&#34;&gt;roxygen2 vignette &amp;ldquo;Extending roxygen2&amp;rdquo;&lt;/a&gt; that says of itself that it&amp;rsquo;s &amp;ldquo;very rough&amp;rdquo;. For me the missing part was understanding what goes in what package (the package where you define the tags, the package where you use the tags); and I&amp;rsquo;d have obviously liked some explanations on roclets that are just there for a basic custom tag, as opposed to printing content / saving information in other files. I want docs just for me. 😉&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stackoverflow.com/questions/77865500/how-can-i-create-custom-roxygen2-tags-for-a-package&#34;&gt;Stack Overflow post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=AcibRDNSfoM&#34;&gt;Video&lt;/a&gt; by Ronak Shah that I didn&amp;rsquo;t watch and related repositories that I did stare at a lot: &lt;a href=&#34;https://github.com/shahronak47/informationtag&#34;&gt;informationtag&lt;/a&gt; and &lt;a href=&#34;https://github.com/shahronak47/infotagdemo&#34;&gt;infotagdemo&lt;/a&gt;. This is how I understood what the &amp;ldquo;process&amp;rdquo; and &amp;ldquo;output&amp;rdquo; methods of my roclet had to look like.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/moodymudskipper/devtag/blob/61098a12545b34c3bba4e516f29c71da56a7d49d/R/roxygen.R#L17&#34;&gt;devtag source&lt;/a&gt; which is where I got the necessary roxygen2 tags for the &amp;ldquo;process&amp;rdquo; and &amp;ldquo;output&amp;rdquo; methods of my roclet (the ones from the aforementioned demo didn&amp;rsquo;t work for me).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I explained the creation and usage of a custom roxygen2 tag, with a minimal example. If you&amp;rsquo;re curious about the igraph use case, find the &lt;a href=&#34;https://github.com/igraph/rigraph/pull/1484/files&#34;&gt;demo PR to igraph&lt;/a&gt; and the &lt;a href=&#34;https://github.com/igraph/igraph.r2cdocs/&#34;&gt;igraph.r2cdocs package&lt;/a&gt;. Have you ever extended roxygen2? What were the difficulties in your experience?&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;This is a &lt;a href=&#34;https://r-pkgs.org/description.html#sec-description-custom-fields&#34;&gt;custom&amp;hellip; &lt;code&gt;DESCRIPTION&lt;/code&gt; field&lt;/a&gt;. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Does my test really validate a bug fix? Check it with git cherry-pick</title>
      <link>https://masalmon.eu/2024/08/29/cherrypick-test/</link>
      <pubDate>Thu, 29 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/08/29/cherrypick-test/</guid>
      <description>&lt;p&gt;Earlier this year I wrote a post about &lt;a href=&#34;https://masalmon.eu/2024/01/23/git-worktree/&#34;&gt;git worktree&lt;/a&gt; that allows you to load different versions of an R package at once on your computer. To keep with the &amp;ldquo;juggle between versions of a codebase with Git plant-related commands&amp;rdquo; theme, let me show you how I use cherry-pick to assess the quality of an unit test.&lt;/p&gt;
&lt;h2 id=&#34;scenario-you-fix-a-bug-in-a-branch&#34;&gt;Scenario: you fix a bug in a branch&lt;/h2&gt;
&lt;p&gt;In a perfect world, the bug you&amp;rsquo;re working on is paired with a ✨ &lt;a href=&#34;https://reprex.tidyverse.org/&#34;&gt;reprex&lt;/a&gt; ✨, and you even start your work by adding a test case for it. The test case fails at first, then you fix the bug in the code so that the test case succeeds.&lt;/p&gt;
&lt;p&gt;You might even push the test in a first commit, so that on continuous integration you get a failure then a success in later commits on the branch. Note that merging the commits in this order without &lt;a href=&#34;https://masalmon.eu/2024/06/11/rewrite-git-history/&#34;&gt;rewriting history&lt;/a&gt; means that &lt;a href=&#34;https://masalmon.eu/2024/06/03/small-commits/#all-was-well-3-days-ago-now-my-thing-is-broken&#34;&gt;debugging with git bisect&lt;/a&gt; later on might be problematic, as the codebase at the commit that added the test had, well, failing tests. Thanks &lt;a href=&#34;https://github.com/krlmlr/&#34;&gt;Kirill&lt;/a&gt; for that useful reminder.&lt;/p&gt;
&lt;h2 id=&#34;problem-you-add-a-test-after-the-fix-not-before-the-fix&#34;&gt;Problem: you add a test after the fix, not before the fix&lt;/h2&gt;
&lt;p&gt;Now, sometimes things are less than optimal and you add the test case after the fact. So you have a commit or several ones fixing the bug, then a commit adding a passing test. Maybe there was not even a reprex so you&amp;rsquo;re not really sure what the same code snippet returned before the bug fix. How can you ensure the new test was failing before you added the fix?&lt;/p&gt;
&lt;p&gt;Without undoing the bug fix using code comments, that is. 😉&lt;/p&gt;
&lt;h2 id=&#34;solution-a-throwaway-branch-and-git-cherry-pick&#34;&gt;Solution: a throwaway branch and git cherry-pick&lt;/h2&gt;
&lt;p&gt;What I&amp;rsquo;ve done a few times now (so clearly an expert workflow 😅) is&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;getting the hash of the commit that added the test.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;returning to the main branch, for instance with &lt;code&gt;gert::git_branch_checkout(&amp;quot;main&amp;quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;creating a throwaway branch, for instance with &lt;code&gt;gert::git_branch_create(&amp;quot;deleteme&amp;quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;putting the test on that branch with git cherry-pick, for instance with &lt;code&gt;gert::git_cherry_pick(&amp;quot;&amp;lt;commit-hash&amp;gt;&amp;quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;running the test. It is so validating when it does fail on the main branch! It&amp;rsquo;s a good test! 🎉&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;returning to the main (or the bug-fix) branch, for instance with &lt;code&gt;gert::git_branch_checkout(&amp;quot;main&amp;quot;)&lt;/code&gt; (or &lt;code&gt;gert::git_branch_checkout(&amp;quot;bug-fix&amp;quot;)&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;deleting the throwaway branch, for instance with &lt;code&gt;gert::git_branch_delete(&amp;quot;deleteme&amp;quot;)&lt;/code&gt;. 😇&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I&amp;rsquo;ve explained a small git workflow I enjoy for checking a test of a bug fix is a good test for it: failing without the bug fix, succeeding with the bug fix. I find this process a nice use case for cherry-pick, beside &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_committed_to_wrong.html&#34;&gt;moving a commit that was made on the wrong branch&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Get your codebase lint-free forever with lintr</title>
      <link>https://masalmon.eu/2024/08/28/lintr-3-steps/</link>
      <pubDate>Wed, 28 Aug 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/08/28/lintr-3-steps/</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://serve.podhome.fm/episodepage/r-weekly-highlights/177&#34;&gt;R Weekly highlights podcast&lt;/a&gt; hosted by Eric Nantz and Mike Thomas.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Writing good code is hard. Some aspects get easier with experience &amp;ndash; although I observe that I consistently forget some things. 🙈 Other aspects can be tackled through code review &amp;ndash; although your reviewer&amp;rsquo;s time will be better spent on design questions than on nitpicks. 💅 Static code analysis can help with code quality.&lt;/p&gt;
&lt;p&gt;In this post I will show how I set up packages to benefit from the &lt;a href=&#34;https://lintr.r-lib.org/&#34;&gt;lintr&lt;/a&gt; R package for static code analysis.&lt;/p&gt;
&lt;h2 id=&#34;step-1-add-a-lintr-configuration-file&#34;&gt;Step 1: Add a lintr configuration file&lt;/h2&gt;
&lt;p&gt;I start by creating (and &lt;a href=&#34;https://blog.r-hub.io/2020/05/20/rbuildignore/&#34;&gt;.Rbuildignoring&lt;/a&gt;) a &lt;code&gt;.lintr&lt;/code&gt; file at the root of my package with contents indicating I want to run &lt;a href=&#34;https://lintr.r-lib.org/reference/index.html&#34;&gt;all available linters&lt;/a&gt; (there are so many wonderful linters!).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;linters&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;lintr::linters_with_tags(tags&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;NULL)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;encoding&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the hard work can start&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;step-2-run-lintr-fix-or-skip-or-configure-until-done&#34;&gt;Step 2: Run lintr, fix or skip or configure until done&lt;/h2&gt;
&lt;p&gt;I then run &lt;a href=&#34;https://lintr.r-lib.org/reference/lint.html&#34;&gt;&lt;code&gt;lintr::lint_package()&lt;/code&gt;&lt;/a&gt; and have a look at the output. It can be quite humbling. 😅&lt;/p&gt;
&lt;p&gt;For each marker, I can&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;fix-the-problem&#34;&gt;Fix the problem&lt;/h3&gt;
&lt;p&gt;For instance if a line is too long, I might split it into two, going from&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;config_lines &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; brio&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_lines&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;&amp;lt;&lt;/span&gt;super&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;long&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;path&lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;config_path &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;&lt;/span&gt;super&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;long&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;path&lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt;
config_lines &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; brio&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_lines&lt;/span&gt;(config_path)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I can also change function calls &lt;a href=&#34;https://github.com/lionel-/codegrip&#34;&gt;from long to wide&lt;/a&gt;, create helper functions, etc.&lt;/p&gt;
&lt;p&gt;I might notice some linters come up especially often which makes me vow to try and remember about them, for instance writing explicit integers (&lt;code&gt;2L&lt;/code&gt;) rathen than implicit ones (&lt;code&gt;2&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id=&#34;skip-a-linter-for-a-line&#34;&gt;Skip a linter for a line&lt;/h3&gt;
&lt;p&gt;For some marked lines that I view as non problematic or as a false positive, I will add a &lt;a href=&#34;https://lintr.r-lib.org/articles/lintr.html#excluding-only-some-linters&#34;&gt;&lt;code&gt;nolint: &amp;lt;name-of-the-linter&amp;gt;&lt;/code&gt; exclusion&lt;/a&gt; to the specific line.&lt;/p&gt;
&lt;h3 id=&#34;configure-lintr&#34;&gt;Configure lintr&lt;/h3&gt;
&lt;p&gt;I might also decide to &lt;a href=&#34;https://lintr.r-lib.org/articles/lintr.html#configuring-linters&#34;&gt;stop using some linters&lt;/a&gt;, like the complicated indentation one, or to &lt;a href=&#34;https://lintr.r-lib.org/articles/lintr.html#excluding-files-completely&#34;&gt;exclude whole files&lt;/a&gt;, like &lt;code&gt;tests/testthat.R&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For instance in a package the &lt;code&gt;.lintr&lt;/code&gt; might end up looking like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;linters&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;lintr::linters_with_tags(tags&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;NULL,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;indentation_linter&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;=&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;NULL)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;encoding&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;exclusions&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;list(&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# excluded from all lints:&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tests/testthat.R&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;repeat-until-a-clean-output&#34;&gt;Repeat until a clean output&lt;/h3&gt;
&lt;p&gt;After a few (or more, let&amp;rsquo;s be honest) cycles of running lintr and responding to part of the output, lintr has nothing left to complain about! The codebase is in a good shape. 🎉&lt;/p&gt;
&lt;h2 id=&#34;step-3-set-up-lintr-on-continuous-integration&#34;&gt;Step 3: Set up lintr on continuous integration&lt;/h2&gt;
&lt;p&gt;At this point I call &lt;a href=&#34;https://usethis.r-lib.org/reference/use_github_action.html&#34;&gt;&lt;code&gt;usethis::use_github_action(&amp;quot;lint-changed-files&amp;quot;)&lt;/code&gt;&lt;/a&gt; that will download a &lt;a href=&#34;https://github.com/r-lib/actions/blob/v2-branch/examples/lint-changed-files.yaml&#34;&gt;GitHub Actions workflow&lt;/a&gt; for me. This workflow tells GitHub Actions to run lintr in pull requests, &lt;strong&gt;only for files changed in the pull request&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Having this safeguard means that I&amp;rsquo;ll never have to run step 2 ever again, as problems in new code will be flagged (and hopefully addressed) continuously. I might only have to run step 2 again because of newly released linters.&lt;/p&gt;
&lt;p&gt;An alternative approach might be to use &lt;a href=&#34;https://datawookie.dev/blog/2022/09/enforcing-style-in-an-r-project/&#34;&gt;pre-commit&lt;/a&gt; to run lintr before making any commit.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I explained how I set up lintr safeguards in packages where I decide to get serious about code quality:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;first creating a basic lintr configuration file,&lt;/li&gt;
&lt;li&gt;then running lintr, editing my code and lintr configuration over and over again until lintr marks nothing,&lt;/li&gt;
&lt;li&gt;adding a continuous integration workflow that will run lintr on files changed by every pull request.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks to lintr maintainer Michael Chirico and to all other lintr authors and contributors. 🙏&lt;/p&gt;
&lt;p&gt;How do &lt;em&gt;you&lt;/em&gt; use lintr? Have you heard of &lt;a href=&#34;https://flint.etiennebacher.com/reference/&#34;&gt;flint&lt;/a&gt; by Etienne Bacher, that does not only flags problems but also fixes them, for a subset of lintr&amp;rsquo;s linters?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Extracting names of functions defined in a script with treesitter</title>
      <link>https://masalmon.eu/2024/07/18/extract-function-names-treesitter/</link>
      <pubDate>Thu, 18 Jul 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/07/18/extract-function-names-treesitter/</guid>
      <description>&lt;p&gt;Coming back from a conference, we might be excited to install and try out the cool things we have heard about. I, going against the stream 🐟, decided to experiment with a tool I have &lt;em&gt;not&lt;/em&gt; heard about last week, as I unfortunately missed &lt;a href=&#34;https://www.youtube.com/watch?v=Gm0ikRBAfwc&#34;&gt;Davis Vaughan&amp;rsquo;s talk about treesitter&lt;/a&gt;. Nonetheless, I caught the idea that treesitter is a parser of code, R code in particular. The treesitter &lt;em&gt;R package&lt;/em&gt; uses the tree-sitter &lt;em&gt;C library&lt;/em&gt;. There are awesome applications of treesitter among which ✨ code search for R on GitHub ✨ but I learnt to know a bit of treesitter by solving a boring use case.&lt;/p&gt;
&lt;h2 id=&#34;my-use-case-i-wont-copy-paste-these-function-names&#34;&gt;My use case: I won&amp;rsquo;t copy-paste these function names&lt;/h2&gt;
&lt;p&gt;Have you noticed this nice error message you get if you try to use &lt;a href=&#34;https://dplyr.tidyverse.org/reference/across.html&#34;&gt;&lt;code&gt;dplyr::across()&lt;/code&gt;&lt;/a&gt; directly?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;dplyr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://dplyr.tidyverse.org/reference/across.html&#39;&gt;across&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #BBBB00; font-weight: bold;&#39;&gt;Error&lt;/span&gt;&lt;span style=&#39;font-weight: bold;&#39;&gt; in `dplyr::across()`:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #BBBB00;&#39;&gt;!&lt;/span&gt; Must only be used inside data-masking verbs like `mutate()`,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   `filter()`, and `group_by()`.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Kirill Müller got the idea to offer a similar behaviour to some igraph functions that exist only for use only within the square operator. Therefore I had to find all functions defined &lt;em&gt;within&lt;/em&gt; this function (whose body has been simplified here):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;`[.igraph.vs` &amp;lt;- function(...) {
  # some code
  bla &amp;lt;- function(...) {
    # some code
  }
  blop &amp;lt;- function(...) {
    # some code
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the script outline I get on the right of my script in RStudio IDE&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, I can see the function names (that would be &lt;code&gt;bla()&lt;/code&gt; and &lt;code&gt;blop()&lt;/code&gt; in the simplified chunk above) but not copy-paste from there.&lt;/p&gt;
&lt;p&gt;I would know how to extract them with &lt;a href=&#34;https://masalmon.eu/2024/05/15/refactoring-xml/&#34;&gt;xmlparsedata&lt;/a&gt; but I thought it might be an opportunity for me to have a look at treesitter. I went through different emotions as a beginner, not all of them positive 😭, but I did get the function names in the end! 💪&lt;/p&gt;
&lt;h2 id=&#34;get-the-whole-tree-from-the-script&#34;&gt;Get the whole tree from the script&lt;/h2&gt;
&lt;p&gt;Below, I dutifully followed the example on the &lt;a href=&#34;https://davisvaughan.github.io/r-tree-sitter/index.html#example&#34;&gt;package homepage&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;load the R language from the treesitter.r package, as far as I understand the only language available at this point for the R package.&lt;/li&gt;
&lt;li&gt;load the parser for that language.&lt;/li&gt;
&lt;li&gt;read in the text.&lt;/li&gt;
&lt;li&gt;parse the text.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A last step is getting the tree root node as node, because I will query the whole script, and you can only query &lt;em&gt;nodes&lt;/em&gt;, not &lt;em&gt;trees&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;language&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;treesitter.r&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter.r/man/language.html&#39;&gt;language&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;parser&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;treesitter&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter/man/parser.html&#39;&gt;parser&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;language&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;text&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/read_lines.html&#39;&gt;read_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;/home/maelle/Documents/rigraph/R/iterators.R&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/paste.html&#39;&gt;paste&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;collapse &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;\n&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;tree&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;treesitter&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter/man/parser-parse.html&#39;&gt;parser_parse&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parser&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;text&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;node&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;treesitter&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter/man/tree_root_node.html&#39;&gt;tree_root_node&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;tree&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id=&#34;find-the-node-of-the-parent-function-of-interest&#34;&gt;Find the node of the parent function of interest&lt;/h2&gt;
&lt;p&gt;The documentation page of &lt;a href=&#34;https://davisvaughan.github.io/r-tree-sitter/reference/query.html&#34;&gt;&lt;code&gt;treesitter::query()&lt;/code&gt;&lt;/a&gt; recommends reading the documentation of tree-sitter about the &lt;a href=&#34;https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax&#34;&gt;query syntax&lt;/a&gt;. That documentation features very useful examples.&lt;/p&gt;
&lt;p&gt;Below I am looking for &amp;ldquo;binary_operator&amp;rdquo; whose left hand side is an identifier that I capture as &amp;ldquo;name&amp;rdquo;, and whose right hand side is a &amp;ldquo;function_definition&amp;rdquo; I capture as &amp;ldquo;def&amp;rdquo;. For some reason if I did not capture &amp;ldquo;def&amp;rdquo; then I got less information about the node. 🤷 I also use a predicate: the name of the function has to be equal to &amp;ldquo;&lt;code&gt;[.igraph.vs&lt;/code&gt;&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;To find out I was after a &amp;ldquo;function_definition&amp;rdquo;, I parsed a few lines of made-up code to study the resulting tree.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;square_bracket_thing&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;((binary_operator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;  lhs: (identifier) @name&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;  rhs: (function_definition)) @def&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;  (#eq? @name &#34;`[.igraph.vs`&#34;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;square_bracket_query&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;treesitter&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter/man/query.html&#39;&gt;query&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;language&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;square_bracket_thing&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then I executed the query and extracted the node. In reality this took a bit more trial and error.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;square_bracket_thing_captures&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;treesitter&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter/man/query-matches-and-captures.html&#39;&gt;query_captures&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;square_bracket_query&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;node&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;square_bracket_thing_captures&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $name&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;def&#34;  &#34;name&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[1]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; `[.igraph.vs` &amp;lt;- function(x, ..., na_ok = FALSE) &amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   args &amp;lt;- lazy_dots(..., .follow_symbols = FALSE)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   ## If indexing has no argument at all, then we still get one,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   ## but it is &#34;empty&#34;, a name that is  &#34;&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   ## Special case, no argument (but we might get an artificial&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   ## empty one&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   if (length(args) &amp;lt; 1 ||&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     (length(args) == 1 &amp;amp;&amp;amp; inherits(args[[1]]$expr, &#34;name&#34;) &amp;amp;&amp;amp;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       as.character(args[[1]]$expr) == &#34;&#34;)) &amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     return(x)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   ## Special case: single numeric argument&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   if (length(args) == 1 &amp;amp;&amp;amp; inherits(args[[1]]$expr, &#34;numeric&#34;)) &amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     res &amp;lt;- simple_vs_index(x, args[[1]]$expr, na_ok)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     return(add_vses_graph_ref(res, get_vs_graph(x)))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   ## Special case: single symbol argument, no such attribute&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   if (length(args) == 1 &amp;amp;&amp;amp; inherits(args[[1]]$expr, &#34;name&#34;)) &amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     graph &amp;lt;- get_vs_graph(x)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     if (!(as.character(args[[1]]$expr) %in% vertex_attr_names(graph))) &amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       res &amp;lt;- simple_vs_index(x, lazy_eval(args[[1]]), na_ok)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;font-style: italic;&#39;&gt;&amp;lt;truncated&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;binary_operator &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 0), (637, 1)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   lhs: &lt;span style=&#39;color: #00BB00;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 0), (479, 13)]&lt;/span&gt;&lt;span style=&#39;color: #00BB00;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   operator: &#34;&amp;lt;-&#34; &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 14), (479, 16)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   rhs: &lt;span style=&#39;color: #00BB00;&#39;&gt;(&lt;/span&gt;function_definition &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 17), (637, 1)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     name: &#34;function&#34; &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 17), (479, 25)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     parameters: &lt;span style=&#39;color: #BB0000;&#39;&gt;(&lt;/span&gt;parameters &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 25), (479, 48)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       open: &#34;(&#34; &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 25), (479, 26)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       parameter: &lt;span style=&#39;color: #00BBBB;&#39;&gt;(&lt;/span&gt;parameter &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 26), (479, 27)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;         name: &lt;span style=&#39;color: #BBBB00;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 26), (479, 27)]&lt;/span&gt;&lt;span style=&#39;color: #BBBB00;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &lt;span style=&#39;color: #00BBBB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &lt;span style=&#39;color: #00BBBB;&#39;&gt;(&lt;/span&gt;comma &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 27), (479, 28)]&lt;/span&gt;&lt;span style=&#39;color: #00BBBB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       parameter: &lt;span style=&#39;color: #00BBBB;&#39;&gt;(&lt;/span&gt;parameter &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 29), (479, 32)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;         name: &lt;span style=&#39;color: #BBBB00;&#39;&gt;(&lt;/span&gt;dots &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 29), (479, 32)]&lt;/span&gt;&lt;span style=&#39;color: #BBBB00;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &lt;span style=&#39;color: #00BBBB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &lt;span style=&#39;color: #00BBBB;&#39;&gt;(&lt;/span&gt;comma &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 32), (479, 33)]&lt;/span&gt;&lt;span style=&#39;color: #00BBBB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       parameter: &lt;span style=&#39;color: #00BBBB;&#39;&gt;(&lt;/span&gt;parameter &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 34), (479, 47)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;         name: &lt;span style=&#39;color: #BBBB00;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 34), (479, 39)]&lt;/span&gt;&lt;span style=&#39;color: #BBBB00;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;         &#34;=&#34; &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 40), (479, 41)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;         default: &lt;span style=&#39;color: #BBBB00;&#39;&gt;(&lt;/span&gt;false &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 42), (479, 47)]&lt;/span&gt;&lt;span style=&#39;color: #BBBB00;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &lt;span style=&#39;color: #00BBBB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       close: &#34;)&#34; &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 47), (479, 48)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &lt;span style=&#39;color: #BB0000;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     body: &lt;span style=&#39;color: #BB0000;&#39;&gt;(&lt;/span&gt;braced_expression &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 49), (637, 1)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       open: &#34;&amp;#123;&#34; &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 49), (479, 50)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       body: &lt;span style=&#39;color: #00BBBB;&#39;&gt;(&lt;/span&gt;binary_operator &lt;span style=&#39;color: #555555;&#39;&gt;[(480, 2), (480, 49)]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;font-style: italic;&#39;&gt;&amp;lt;truncated&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[2]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; `[.igraph.vs`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(479, 0), (479, 13)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;square_fn&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;square_bracket_thing_captures&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;node&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;At this point I was already very proud of my tiny win but I did not have the &amp;ldquo;children functions&amp;rdquo; yet!&lt;/p&gt;
&lt;h2 id=&#34;find-the-functions-defined-within-the-parent&#34;&gt;Find the functions defined within the parent&lt;/h2&gt;
&lt;p&gt;I first considered creating a complicated nested query but I found no example of that. I did see someone telling StackOverflow they did a recursive query and for some reason that gave me the idea of parsing the text of the node, then look for functions in that text.&lt;/p&gt;
&lt;p&gt;The query was simpler: looking for function definitions, only capturing the names on the left hand side.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;square_tree&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;treesitter&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter/man/parser-parse.html&#39;&gt;parser_parse&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parser&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;treesitter&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter/man/node_text.html&#39;&gt;node_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;square_fn&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;square_node&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;treesitter&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter/man/tree_root_node.html&#39;&gt;tree_root_node&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;square_tree&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;kiddos_source&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;(binary_operator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;  lhs: (identifier) @name&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;  rhs: (function_definition))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;s&#39;&gt;&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;kiddos_query&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;treesitter&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter/man/query.html&#39;&gt;query&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;language&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;kiddos_source&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;square_bracket_thing_captures&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;treesitter&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter/man/query-matches-and-captures.html&#39;&gt;query_captures&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;kiddos_query&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;square_node&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/utils/head.html&#39;&gt;head&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;square_bracket_thing_captures&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $name&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [1] &#34;name&#34; &#34;name&#34; &#34;name&#34; &#34;name&#34; &#34;name&#34; &#34;name&#34; &#34;name&#34; &#34;name&#34; &#34;name&#34; &#34;name&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [11] &#34;name&#34; &#34;name&#34; &#34;name&#34; &#34;name&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[1]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; `[.igraph.vs`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(0, 0), (0, 13)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[2]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; .nei&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(29, 2), (29, 6)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[3]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; nei&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(50, 2), (50, 5)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[4]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; .innei&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(53, 2), (53, 8)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[5]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; innei&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(56, 2), (56, 7)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[6]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; .outnei&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(59, 2), (59, 9)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[7]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; outnei&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(62, 2), (62, 8)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[8]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; .inc&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(65, 2), (65, 6)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[9]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; inc&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(78, 2), (78, 5)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[10]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; adj&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(81, 2), (81, 5)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[11]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; .from&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(84, 2), (84, 7)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[12]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; from&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(96, 2), (96, 6)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[13]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; .to&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(99, 2), (99, 5)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $node[[14]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;tree_sitter_node&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── Text ────────────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; to&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ── S-Expression ────────────────────────────────────────────────────────────────&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB;&#39;&gt;(&lt;/span&gt;identifier &lt;span style=&#39;color: #555555;&#39;&gt;[(111, 2), (111, 4)]&lt;/span&gt;&lt;span style=&#39;color: #0000BB;&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;After that I was able to get the &lt;em&gt;names&lt;/em&gt; of the children functions! I was actually only interested in those whose names start with a dot as all the other ones are deprecated anyway.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;kiddos_functions&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/map.html&#39;&gt;map_chr&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;square_bracket_thing_captures&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;node&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;treesitter&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/treesitter/man/node_text.html&#39;&gt;node_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;kiddos_functions&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/startsWith.html&#39;&gt;startsWith&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;kiddos_functions&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;.&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;.nei&#34;    &#34;.innei&#34;  &#34;.outnei&#34; &#34;.inc&#34;    &#34;.from&#34;   &#34;.to&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Tada! Now I can go fix the issue I was tasked with.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I report on my first encounter with the treesitter package for parsing R code. Copy-pasting the few function names would surely have been faster, but sometimes you&amp;rsquo;ve got to sit and &lt;a href=&#34;https://www.pipinghotdata.com/posts/2022-11-02-regular-intentional-and-time-boxed-yak-shaving/&#34;&gt;learn something new&lt;/a&gt;. ☺️&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;No, I have not installed Positron yet. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Extracting all links from my slidedeck</title>
      <link>https://masalmon.eu/2024/07/16/extract-links-from-md/</link>
      <pubDate>Tue, 16 Jul 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/07/16/extract-links-from-md/</guid>
      <description>&lt;p&gt;Last week after my &lt;a href=&#34;https://masalmon.eu/talks/2024-07-10-user-2024-rusty-code/&#34;&gt;useR! talk&lt;/a&gt;, someone I had met at the R-Ladies dinner asked me for a list of all the links in my slides. I said I&amp;rsquo;d prepare it, not because I&amp;rsquo;m a nice person, but because I knew it&amp;rsquo;d be an use case where the great tinkr package would shine! 😈&lt;/p&gt;
&lt;h2 id=&#34;what-is-tinkr&#34;&gt;What is tinkr?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.ropensci.org/tinkr/&#34;&gt;tinkr&lt;/a&gt; is an R package I &lt;a href=&#34;https://ropensci.org/blog/2018/10/01/tinkr/&#34;&gt;created&lt;/a&gt;, and that its current maintainer &lt;a href=&#34;https://zkamvar.netlify.app/&#34;&gt;Zhian Kamvar&lt;/a&gt; took much further that I&amp;rsquo;d ever would have. tinkr can transform Markdown into XML and back.&lt;/p&gt;
&lt;p&gt;Under the hood, tinkr uses&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://docs.ropensci.org/commonmark/&#34;&gt;commonmark&lt;/a&gt; for the Markdown-to-XML conversion. CommonMark, in the form of its cmark implementation, is the C library that GitHub for instance uses to display your Markdown comments as HTML. The commonmark package is also what powers &lt;a href=&#34;https://roxygen2.r-lib.org/articles/rd-formatting.html&#34;&gt;Markdown support in roxygen2&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.ropensci.org/xslt/&#34;&gt;xslt&lt;/a&gt; for the XML-to-Markdown conversion. XSLT is a templating language for XML.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anyway, enough said, let&amp;rsquo;s go back to today&amp;rsquo;s use case.&lt;/p&gt;
&lt;h2 id=&#34;extract-and-format-links-from-indexqmd&#34;&gt;Extract and format links from &lt;code&gt;index.qmd&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;With tinkr I can use XPath, the query language for XML or HTML, to extract links from my slidedeck source. Then I will format them as a list.&lt;/p&gt;
&lt;p&gt;First, I create a yarn object from my slidedeck source.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;talk_yarn&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;tinkr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/tinkr/reference/yarn.html&#39;&gt;yarn&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;new&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;/home/maelle/Documents/conferences/user2024/index.qmd&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;talk_yarn&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;yarn&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   Public:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     add_md: function (md, where = 0L) &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     body: xml_document, xml_node&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     clone: function (deep = FALSE) &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     get_protected: function (type = NULL) &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     head: function (n = 6L, stylesheet_path = stylesheet()) &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     initialize: function (path = NULL, encoding = &#34;UTF-8&#34;, sourcepos = FALSE, &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     md_vec: function (xpath = NULL, stylesheet_path = stylesheet()) &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     ns: http://commonmark.org/xml/1.0&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     path: /home/maelle/Documents/conferences/user2024/index.qmd&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     protect_curly: function () &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     protect_math: function () &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     protect_unescaped: function () &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     reset: function () &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     show: function (lines = TRUE, stylesheet_path = stylesheet()) &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     tail: function (n = 6L, stylesheet_path = stylesheet()) &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     write: function (path = NULL, stylesheet_path = stylesheet()) &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     yaml: --- format:   revealjs:       highlight-style: a11y      ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   Private:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     encoding: UTF-8&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     md_lines: function (path = NULL, stylesheet = NULL) &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     sourcepos: FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then I extract all links.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;links&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_find_all.html&#39;&gt;xml_find_all&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;talk_yarn&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;body&lt;/span&gt;, &lt;/span&gt;
&lt;span&gt;  xpath &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;.//md:link&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  ns &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;talk_yarn&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;ns&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/utils/head.html&#39;&gt;head&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;links&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;#123;xml_nodeset (6)&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &amp;lt;link destination=&#34;https://user-maelle.netlify.app&#34; title=&#34;&#34;&amp;gt;\n  &amp;lt;text xm ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [2] &amp;lt;link destination=&#34;https://www.pexels.com/photo/old-cargo-ship-on-sea-207 ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [3] &amp;lt;link destination=&#34;https://www.pexels.com/photo/the-word-louise-is-spelle ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [4] &amp;lt;link destination=&#34;https://www.pexels.com/photo/gray-rotary-telephone-on- ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [5] &amp;lt;link destination=&#34;https://www.pexels.com/photo/close-up-photography-of-y ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [6] &amp;lt;link destination=&#34;https://www.r-consortium.org/all-projects/call-for-pro ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I then throw away the links to the great website Pexels, because these are image credits rather than information useful to do R stuff.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;links&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/keep.html&#39;&gt;discard&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;links&lt;/span&gt;, &lt;/span&gt;
&lt;span&gt;  \&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/startsWith.html&#39;&gt;startsWith&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_attr.html&#39;&gt;xml_attr&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;destination&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;https://www.pexels&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/utils/head.html&#39;&gt;head&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;links&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;#123;xml_nodeset (6)&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &amp;lt;link destination=&#34;https://user-maelle.netlify.app&#34; title=&#34;&#34;&amp;gt;\n  &amp;lt;text xm ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [2] &amp;lt;link destination=&#34;https://www.r-consortium.org/all-projects/call-for-pro ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [3] &amp;lt;link destination=&#34;https://www.r-consortium.org/all-projects/call-for-pro ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [4] &amp;lt;link destination=&#34;https://www.heltweg.org/posts/who-wrote-this-shit/&#34; ti ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [5] &amp;lt;link destination=&#34;https://fosstodon.org/@hadleywickham/11202130903588421 ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [6] &amp;lt;link destination=&#34;https://nostarch.com/kill-it-fire&#34; title=&#34;&#34;&amp;gt;\n  &amp;lt;text  ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;After that I can format the links and display them here using an &lt;a href=&#34;https://bookdown.org/yihui/rmarkdown-cookbook/results-asis.html&#34;&gt;&amp;ldquo;asis&amp;rdquo; chunk&lt;/a&gt;. Yes, my slidedeck uses Quarto but this blog is still powered by R Markdown, &lt;a href=&#34;https://hugodown.r-lib.org/&#34;&gt;hugodown&lt;/a&gt; to be precise.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m using the formatting as an opportunity to only keep distinct links: sometimes I had very similar slides in a row, with repeated information.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;format_link&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;link&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;url&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_attr.html&#39;&gt;xml_attr&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;link&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;destination&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;text&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;link&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/sprintf.html&#39;&gt;sprintf&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;* [%s](%s)&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;text&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;url&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;formatted_links&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/map.html&#39;&gt;map_chr&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;links&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;format_link&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;formatted_links&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/unique.html&#39;&gt;unique&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;formatted_links&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;formatted_links&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/paste.html&#39;&gt;paste&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;collapse &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;\n&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/cat.html&#39;&gt;cat&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://user-maelle.netlify.app&#34;&gt;https://user-maelle.netlify.app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.r-consortium.org/all-projects/call-for-proposals&#34;&gt;R Consortium ISC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.heltweg.org/posts/who-wrote-this-shit/&#34;&gt;https://www.heltweg.org/posts/who-wrote-this-shit/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://fosstodon.org/@hadleywickham/112021309035884210&#34;&gt;https://fosstodon.org/@hadleywickham/112021309035884210&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://nostarch.com/kill-it-fire&#34;&gt;https://nostarch.com/kill-it-fire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.geepawhill.org/2019/03/03/refactoring-pro-tip-easiest-nearest-owwie-first/&#34;&gt;&amp;ldquo;Refactoring Pro-Tip: Easiest Nearest Owwie First&amp;rdquo;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://styler.r-lib.org/&#34;&gt;https://styler.r-lib.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://masalmon.eu/2024/05/23/refactoring-tests/&#34;&gt;https://masalmon.eu/2024/05/23/refactoring-tests/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://lintr.r-lib.org/&#34;&gt;{lintr} itself&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://lintr.r-lib.org/reference/index.html&#34;&gt;reference index&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/r-lib/actions/tree/v2-branch/examples&#34;&gt;continuous integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://masalmon.eu/2024/05/15/refactoring-xml/&#34;&gt;https://masalmon.eu/2024/05/15/refactoring-xml/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://code-review.tidyverse.org/&#34;&gt;Tidyteam code review principles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://developer-success-lab.gitbook.io/code-review-anxiety-workbook-1&#34;&gt;The Code Review Anxiety Workbook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ropensci.org/software-review/&#34;&gt;General science lifecycle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ropensci.org/stat-software-review/&#34;&gt;Statistical software&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rstats-wtf/wtf-version-control-slides&#34;&gt;now&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rstudio-conf-2022/wtf-rstats/tree/main/materials&#34;&gt;then&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://happygitwithr.com/&#34;&gt;Happy Git and GitHub for the useR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wizardzines.com/zines/oh-shit-git/&#34;&gt;&amp;ldquo;Oh shit, Git!&amp;quot;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://wizardzines.com/zines/git/&#34;&gt;&amp;ldquo;How Git works&amp;rdquo;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://masalmon.eu/2024/06/03/small-commits/&#34;&gt;Why you need small, informative Git commits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://masalmon.eu/2023/12/07/two-phases-git-branches/&#34;&gt;The two phases of commits in a Git branch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://masalmon.eu/2024/06/11/rewrite-git-history/&#34;&gt;Hack your way to a good Git history&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.ropensci.org/saperlipopette/&#34;&gt;{saperlipopette}&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ohshitgit.com/&#34;&gt;Oh shit, Git!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://unmaintained.tech/&#34;&gt;No Maintenance Intended&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ropensci.org/blog/2023/02/07/what-does-it-mean-to-maintain-a-package/&#34;&gt;What Does It Mean to Maintain a Package?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://yabellini.netlify.app/blog/2023-10-13-three-payments/&#34;&gt;Three currencies of payment for our work&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://devguide.ropensci.org/maintenance_cheatsheet.html&#34;&gt;Package maintainer cheatsheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://devguide.ropensci.org/&#34;&gt;dev guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ropensci.org/blog&#34;&gt;blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ropensci.org/news&#34;&gt;Package Development Corner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://contributing.ropensci.org/&#34;&gt;paths of participation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ropensci.org/news&#34;&gt;Monthly newsletter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ropensci.org/blog&#34;&gt;Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.r-universe.dev/&#34;&gt;R-universe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ropensci.org/help-wanted&#34;&gt;https://ropensci.org/help-wanted&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ropensci.org/news&#34;&gt;https://ropensci.org/news&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://devguide.ropensci.org/maintenance_evolution.html#archivalguidance&#34;&gt;https://devguide.ropensci.org/maintenance_evolution.html#archivalguidance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ropensci.org/commcalls/apr2021-pkg-community/&#34;&gt;2021 community call&lt;/a&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Using tinkr, XPath and &lt;a href=&#34;https://masalmon.eu/2023/09/29/three-functions/&#34;&gt;&lt;code&gt;sprintf()&lt;/code&gt;&lt;/a&gt;, I was able to create a list of all the links shared in my useR! slidedeck. Some of them have no text, meaning that the URL is used as text for the link; or text that only makes sense in the context of the paragraph they were a part of; others are slightly more informative; but at least none of them is a &lt;a href=&#34;https://dap.berkeley.edu/learn/concepts/links&#34;&gt;&amp;ldquo;click here&amp;rdquo; link&lt;/a&gt;. 😅&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Hack your way to a good Git history</title>
      <link>https://masalmon.eu/2024/06/11/rewrite-git-history/</link>
      <pubDate>Tue, 11 Jun 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/06/11/rewrite-git-history/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve now explained on this blog why it&amp;rsquo;s important to have &lt;a href=&#34;https://masalmon.eu/2024/06/03/small-commits/&#34;&gt;small, informative Git commits&lt;/a&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; and how I&amp;rsquo;ve realized that polishing history can happen in a &lt;a href=&#34;https://masalmon.eu/2023/12/07/two-phases-git-branches/&#34;&gt;second phase of work in a branch&lt;/a&gt;. However, I&amp;rsquo;ve more or less glossed over &lt;em&gt;how&lt;/em&gt; to craft the history in a branch once you&amp;rsquo;re done with the work.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve entitled this post &lt;em&gt;&amp;ldquo;Hack your way to a good Git history&amp;rdquo;&lt;/em&gt; because writing the history after the fact can feel like cheating, but it&amp;rsquo;s not!&lt;/p&gt;
&lt;h2 id=&#34;to-branch-or-not-to-branch&#34;&gt;To branch or not to branch&lt;/h2&gt;
&lt;p&gt;With the second method of re-writing history I&amp;rsquo;ll present, you could get away with working on the default branch as long as you do not push. However, I&amp;rsquo;d really recommend creating a branch before you start working on whatever task you&amp;rsquo;ve assigned yourself, be it a bug fix, new feature or some refactoring. It feels safer, and it&amp;rsquo;s a good habit to take.&lt;/p&gt;
&lt;p&gt;On the default branch, you can&amp;rsquo;t force push, whereas in your own branch, you can push regularly as your work, as a backup of sorts, then rewrite history, then force push.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s assume you did a bunch of changes in a branch: adding a bug fix to a script, as well as refactoring part of it, adding a test to ensure the bug never reappears, updating the changelog&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. You have a dozen of commits because actually fixing the commit took more than one try, and you first got your test wrong so it took you 3 commits.&lt;/p&gt;
&lt;h2 id=&#34;squash-and-merge-click-the-right-githubgitlab-button&#34;&gt;&amp;ldquo;Squash and merge&amp;rdquo;: click the right GitHub/GitLab button&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re fine with all your changes being reduced to a single commit, you can &lt;em&gt;squash&lt;/em&gt; merge all the changes from your branch into a single commit on the default branch.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--squash&lt;/code&gt; is an option of &lt;a href=&#34;https://git-scm.com/docs/git-merge&#34;&gt;&lt;code&gt;git merge&lt;/code&gt;&lt;/a&gt; but to be honest, I always merge branches through the GitHub pull requests interface. You can easily perform a &amp;ldquo;squash and merge&amp;rdquo; on &lt;a href=&#34;https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#squash-and-merge-your-commits&#34;&gt;GitHub&lt;/a&gt; and &lt;a href=&#34;https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html&#34;&gt;GitLab&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s really the easiest method to get a good Git history that does not include your desperate intermediary steps, but it does not allow for more granularity than one commit. It also means that if someone reviews your pull request, they do it without the benefit of a story in the form of an informative succession of Git commits.&lt;/p&gt;
&lt;h2 id=&#34;the-repeated-amend-git-commit---amend&#34;&gt;&amp;ldquo;The repeated amend&amp;quot;™️: &lt;code&gt;git commit --amend&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Thanks to Jenny Bryan for describing this workflow and for &lt;a href=&#34;https://fosstodon.org/@jennybryan/111540760887095683&#34;&gt;pointing it to me&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This second method comes from the excellent &lt;a href=&#34;https://happygitwithr.com/repeated-amend&#34;&gt;Happy Git and GitHub for the useR by Jenny Bryan&lt;/a&gt;. The idea is than when fixing a bug in your script for instance, you make a first change, create a commit with the message &amp;ldquo;fix: fix indentation bug&amp;rdquo; or so, then do more changes and &lt;em&gt;amend the commit&lt;/em&gt; with &lt;code&gt;git commit --amend&lt;/code&gt; instead of creating a new one.&lt;/p&gt;
&lt;p&gt;This way, you &amp;lsquo;build up a &amp;ldquo;good&amp;rdquo; commit gradually&amp;rsquo;.&lt;/p&gt;
&lt;p&gt;You can use this method on the default branch, if you don&amp;rsquo;t push before the commit is really done. If you use this method on a branch of yours, you can force push. I really enjoy this method, when writing blog posts for instance!&lt;/p&gt;
&lt;p&gt;This method does allow for granularity, as you can first &amp;ldquo;repeat amend&amp;rdquo; a refactoring commit, then &amp;ldquo;repeat amend&amp;rdquo; a bug fix commit, then &amp;ldquo;repeat amend&amp;rdquo; a new test commit, etc.&lt;/p&gt;
&lt;p&gt;You can practice &lt;code&gt;git commit --amend&lt;/code&gt; with those exercises of the saperlipopette package: &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_one_small_change.html&#34;&gt;&amp;ldquo;Oh shit, I committed and immediately realized I need to make one small change!&amp;quot;&lt;/a&gt; and &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_latest_message.html&#34;&gt;&amp;ldquo;Oh shit, I need to change the message on my last commit!&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;start-from-scratch-git-reset---soft--git-add---patch&#34;&gt;&amp;ldquo;Start from scratch&amp;rdquo;: &lt;code&gt;git reset --soft&lt;/code&gt; + &lt;code&gt;git add&lt;/code&gt; (&lt;code&gt;--patch&lt;/code&gt;)&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Thanks to &lt;a href=&#34;https://hugogruson.fr/&#34;&gt;Hugo Gruson&lt;/a&gt; for introducing me to this workflow.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So, you have all the changes in three places (R script, test file, &lt;code&gt;NEWS.md&lt;/code&gt;) and a dozen commits, let&amp;rsquo;s say 12.&lt;/p&gt;
&lt;p&gt;With this method you first reset the Git history to how it was before it started, without removing the changes to the files: &lt;code&gt;git reset --soft HEAD~12&lt;/code&gt;. Now you will gradually create the 4 commits you want:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;refactor: stop using useless comments&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;fix: fix indentation bug&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;test: add test for indentation bug&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;docs: update changelog&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the first commit, you run &lt;code&gt;git add --patch R/script.R&lt;/code&gt; to only pick the refactoring changes you made to the script, then &lt;code&gt;git commit -m &amp;quot;refactor: stop using useless comments&amp;quot;&lt;/code&gt;. For the other commits, you should be able to use &lt;code&gt;git add&lt;/code&gt; without the patch option.&lt;/p&gt;
&lt;p&gt;Then, you force push to your branch (not the default branch!).&lt;/p&gt;
&lt;p&gt;You can practice &lt;code&gt;git add --patch&lt;/code&gt; with this exercise of the saperlipopette package: &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_split_changes.html&#34;&gt;&amp;ldquo;Hey I&amp;rsquo;d like to split these changes to the same file into several commits!&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;mix-and-match-your-commits-git-rebase--i&#34;&gt;&amp;ldquo;Mix and match your commits&amp;rdquo;: &lt;code&gt;git rebase -i&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;With this method, instead of throwing away the commits, you will be able to combine them into a commit (squash), change their message (reword), edit them (edit), delete them, change their order.&lt;/p&gt;
&lt;p&gt;Say you start from&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fix: fix indentation bug
try again
ok like this?!!
pff so hard
found the actual bug!
ah no
found it
refactor: stop using useless comments
test: add test for indentation bug
oops, forgot a quote
actually follow our own standards
docs: update changelog
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;git rebase -i&lt;/code&gt; will get you to something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pick &amp;lt;hash&amp;gt; fix: fix indentation bug
pick &amp;lt;hash&amp;gt; try again
pick &amp;lt;hash&amp;gt; ok like this?!!
pick &amp;lt;hash&amp;gt; pff so hard
pick &amp;lt;hash&amp;gt; found the actual bug!
pick &amp;lt;hash&amp;gt; ah no
pick &amp;lt;hash&amp;gt; found it
pick &amp;lt;hash&amp;gt; refactor: stop using useless comments
pick &amp;lt;hash&amp;gt; test: add test for indentation bug
pick &amp;lt;hash&amp;gt; oops, forgot a quote
pick &amp;lt;hash&amp;gt; actually follow our own standards
pick &amp;lt;hash&amp;gt; docs: update changelog
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That you edit to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pick &amp;lt;hash&amp;gt; refactor: stop using useless comments
pick &amp;lt;hash&amp;gt; fix: fix indentation bug
squash &amp;lt;hash&amp;gt; try again
squash &amp;lt;hash&amp;gt; ok like this?!!
squash &amp;lt;hash&amp;gt; pff so hard
squash &amp;lt;hash&amp;gt; found the actual bug!
squash &amp;lt;hash&amp;gt; ah no
squash &amp;lt;hash&amp;gt; found it
pick &amp;lt;hash&amp;gt; test: add test for indentation bug
squash &amp;lt;hash&amp;gt; oops, forgot a quote
squash &amp;lt;hash&amp;gt; actually follow our own standards
pick &amp;lt;hash&amp;gt; docs: update changelog
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to get your history to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;refactor: stop using useless comments
fix: fix indentation bug
test: add test for indentation bug
docs: update changelog
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I wrote &lt;code&gt;git rebase -i&lt;/code&gt; but it actually needs an argument: the commit from which to rebase. Usually I run&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git merge-base my-branch main
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to get that commit and copy-paste it to my next command. In theory I could &lt;em&gt;count&lt;/em&gt; commits and use something à la &lt;code&gt;HEAD~n&lt;/code&gt; but for some reason it makes me more nervous.&lt;/p&gt;
&lt;p&gt;After that, you can force push to your branch.&lt;/p&gt;
&lt;p&gt;You can practice &lt;code&gt;git rebase -i&lt;/code&gt; with this exercise of the saperlipopette package: &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_rebase_i.html&#34;&gt;&amp;ldquo;Hey I&amp;rsquo;d like to make my commits in a branch look informative and smart!&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Beside practicing, a really important thing is to configure your Git editor. I do not remember how I did it but now my Git editor is Atom, which I find easier to deal with than Vim&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Do not miss &lt;a href=&#34;https://wizardzines.com/comics/rules-for-rebasing/&#34;&gt;Julia Evans&amp;rsquo; rules for rebasing&lt;/a&gt;. One of them is to not do more than one thing (for instance not reordering and squashing like we did above 😅), you can instead do several &lt;code&gt;git rebase -i&lt;/code&gt; in a row!&lt;/p&gt;
&lt;h2 id=&#34;how-to-merge-if-you-have-1-nice-commits&#34;&gt;How to merge if you have &amp;gt;1 nice commits&lt;/h2&gt;
&lt;p&gt;If your branch features more than one nice commits and you don&amp;rsquo;t squash it, then, you can &lt;a href=&#34;https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#rebase-and-merge-your-commits&#34;&gt;rebase and merge it&lt;/a&gt; so that no merge commits is created. This way, your default branch has a nice readable history.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post, I explained everything I know about creating a good Git history. Please do not look at the commits I end up pushing to default branches, I&amp;rsquo;m still learning. 😁 I&amp;rsquo;m doing my best to rewrite history as often as I can, to follow Martin Fowler&amp;rsquo;s principle &lt;a href=&#34;https://martinfowler.com/bliki/FrequencyReducesDifficulty.html&#34;&gt;&amp;ldquo;if it hurts, do it more often&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I should also have added &amp;ldquo;atomic&amp;rdquo;, because if you can&amp;rsquo;t load your project at a given commit because of a missing parenthesis, then you can&amp;rsquo;t run Git bisect for instance. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;If you find updating the changelog manually is a bit of a faff, check out the &lt;a href=&#34;https://fledge.cynkra.com/dev/&#34;&gt;fledge package&lt;/a&gt;. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Although I suppose I could one day try and get better at Vim&amp;hellip; Baby steps&amp;hellip; &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Why you need small, informative Git commits</title>
      <link>https://masalmon.eu/2024/06/03/small-commits/</link>
      <pubDate>Mon, 03 Jun 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/06/03/small-commits/</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://serve.podhome.fm/episodepage/r-weekly-highlights/issue-2024-w24-highlights&#34;&gt;R Weekly highlights podcast&lt;/a&gt; hosted by Eric Nantz and Mike Thomas.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Make small Git commits with informative messages&amp;rdquo; is a piece of advice we hear a lot when learning Git. That&amp;rsquo;s why we might want to sometimes &lt;a href=&#34;https://masalmon.eu/2023/12/07/two-phases-git-branches/&#34;&gt;rewrite history in a branch&lt;/a&gt;. In this post, I&amp;rsquo;d like to underline three main (😉) reasons why you&amp;rsquo;ll be happy you, or someone else, made small and informative Git commits in a codebase.&lt;/p&gt;
&lt;p&gt;A disclaimer: these three reasons are only valid if you do not write perfectly working and readable code all the time. If you do, you won&amp;rsquo;t need to use your Git log for debugging and undoing purposes, so who cares about your Git commits?&lt;/p&gt;
&lt;h2 id=&#34;a-mysterious-line-of-code-git-blame&#34;&gt;A mysterious line of code (Git blame)&lt;/h2&gt;
&lt;p&gt;Imagine you encounter a mysterious line of code in a script that either someone else or yourself wrote a while ago.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;figure&gt;
    &lt;img src=&#34;mystery.png&#34;
         alt=&#34;An R script with a line &amp;#39;x &amp;lt;- x - 1&amp;#39;&#34; width=&#34;400&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;As luck will have it, there is no comment explaining the line around it. How can you guess the intent of that line?&lt;/p&gt;
&lt;p&gt;A Git command might help you: Git blame! It&amp;rsquo;d better be called Git explain, as blaming is a &lt;a href=&#34;https://www.heltweg.org/posts/who-wrote-this-shit/&#34;&gt;bad idea&lt;/a&gt;. Anyway, it&amp;rsquo;s a tool for seeing the code with more context. For each line, you get to see when it was added or last modified, by whom, and when.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;blame.png&#34;
         alt=&#34;simplified diagram of Git blame: for each line in a script on the left we see who added it, when, with what commit message.&#34; width=&#34;500&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;For instance, I added or modified the 2 lines at the top and the the two lines in the middle, that are highlighted in yellow, a few years ago. The line that is interesting to me, &lt;code&gt;x &amp;lt;- x - 1&lt;/code&gt;, was added by ropenscibot in 2017.&lt;/p&gt;
&lt;p&gt;Now, I can try and display more information about the Git commit that last modified, or added that mysterious line. The person who last touch the line chose our adventure&amp;hellip;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If we&amp;rsquo;re unlucky, we get a Git commit whose message is &amp;lsquo;&amp;ldquo;Commit a bunch of files before lunch 🍝&amp;rdquo;&amp;rsquo; and whose diff shows 145 changed files with 2,624 additions and 2,209 deletions. Not exactly helpful, we&amp;rsquo;re still stuck.&lt;/li&gt;
&lt;li&gt;If we&amp;rsquo;re lucky, we get a Git commit whose message is &amp;lsquo;&amp;ldquo;fix: adapt code to tool&amp;rsquo;s 0-indexing&amp;rdquo;&amp;rsquo; and whose diff shows 2 changed files with 3 additions and 2 deletions. Now we know why x was modified this way! We can add an explaining &lt;a href=&#34;https://blog.r-hub.io/2023/01/26/code-comments-self-explaining-code/&#34;&gt;comment&lt;/a&gt; to make the code more readable for later, and continue with our work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Git blame is a built-in Git thing, but for me, it&amp;rsquo;s first and foremost a &lt;a href=&#34;https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#viewing-the-line-by-line-revision-history-for-a-file&#34;&gt;button&lt;/a&gt; in the Github interface for any file. Use Git blame as you prefer.&lt;/p&gt;
&lt;h2 id=&#34;a-bad-idea-7-commits-ago-git-revert&#34;&gt;A bad idea 7 commits ago (Git revert)&lt;/h2&gt;
&lt;p&gt;Oh no, that idea from 7 commits ago is bad! Do we&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Manually remove the change;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Simply revert the commit that added the change?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once again, the quality and granularity of the commits will decide for you. If the snapshot from 7 commits ago included many different unrelated changes, it will be easier to manually undo the changes yourself by going into the files and deleting or amending stuff. If the snapshot from 7 commits ago was small enough, you can use Git revert with that commit ID, that will create a new commit undoing that commit.&lt;/p&gt;
&lt;p&gt;You can try out Git revert in an &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_revert_file.html&#34;&gt;exercise of the saperlipopette package&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;all-was-well-3-days-ago-now-my-thing-is-broken&#34;&gt;All was well 3 days ago, now my thing is broken&lt;/h2&gt;
&lt;p&gt;Imagine you were doing something with your somewhat complex R project 3 days ago, and that all was well.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;cool.png&#34;
         alt=&#34;a bunch of scripts, on them an emoji of a happy face wearing sunglasses.&#34; width=&#34;200&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;Now, after a bunch of changes to your still complex R project, you set out to do the same thing, and&amp;hellip; it no longer works.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;sob.png&#34;
         alt=&#34;a bunch of scripts, on them an emoji of a sobbing face.&#34; width=&#34;200&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;To add insult to injury, your usual &lt;a href=&#34;https://www.pipinghotdata.com/talks/2022-11-11-debugging/&#34;&gt;debugging&lt;/a&gt; tools aren&amp;rsquo;t helping you for some reasons. Is all hope lost? No!&lt;/p&gt;
&lt;p&gt;Git has a tool to help you go over the Git history between now and then (3 days ago, 100 commits ago) in an optimal way: Git bisect. Git bisect will make you try some commits to help pinpoint which change, which commit exactly, introduced the bug you&amp;rsquo;re now observing.&lt;/p&gt;
&lt;p&gt;Your Git history looks something like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a commit at which you know the thing worked,&lt;/li&gt;
&lt;li&gt;a commit at which it no longer works,&lt;/li&gt;
&lt;li&gt;with commits in between about which you have no information because you were not doing or testing the thing, so at some point you introduced a bug.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
    &lt;img src=&#34;graph.png&#34;
         alt=&#34;a series of emoji, the first one a cool face, then sleeping faces, then a sobbing face.&#34; width=&#34;700&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;You tell Git bisect which commit was for sure good, and which commit is bad, and it starts putting your project in the state it was at a given commit, let&amp;rsquo;s say the third commit:&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;commit1.png&#34;
         alt=&#34;arrow above a sleeping face&#34; width=&#34;700&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;You have to tell Git bisect whether that commit is good or bad (no complex vocabulary for once). Let&amp;rsquo;s say your thing seems to work at that point.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;commit1good.png&#34;
         alt=&#34;all faces until the arrow are now cool faces&#34; width=&#34;700&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;Git bisect will assume all commits up to that commit were good.&lt;/p&gt;
&lt;p&gt;It now makes you explore another commit.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;commit2.png&#34;
         alt=&#34;arrow above a different sleeping face&#34; width=&#34;700&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;You try your thing, it does not work. Therefore this commit, and the following ones, are bad.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;commit2bad.png&#34;
         alt=&#34;all faces after the arrow are now sobbing&#34; width=&#34;700&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;You&amp;rsquo;re in luck, after only a few steps you get to the last commit to try out.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;commit3.png&#34;
         alt=&#34;arrow on last sleeping face&#34; width=&#34;700&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;Again a bad one, your thing does not work for your project in that state.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&#34;commit3bad.png&#34;
         alt=&#34;last sleeping face now sobbing&#34; width=&#34;700&#34;/&gt; 
&lt;/figure&gt;

&lt;p&gt;It&amp;rsquo;s the first bad commit, so it&amp;rsquo;s the one that introduced the breaking change!&lt;/p&gt;
&lt;p&gt;Now, again, the person who made that commit chose our adventure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If we&amp;rsquo;re unlucky, we get a Git commit whose message is &amp;lsquo;&amp;ldquo;Commit a bunch of files before workout 💪&amp;rdquo;&amp;rsquo; and whose diff shows 145 changed files with 2,624 additions and 2,209 deletions. Nooo, that&amp;rsquo;s still a ton of code to read.&lt;/li&gt;
&lt;li&gt;If we&amp;rsquo;re lucky, we get a Git commit whose message is &amp;lsquo;&amp;ldquo;refactor: start using YAML&amp;rdquo;&amp;rsquo; and whose diff shows 2 changed files with 3 additions and 2 deletions. Ah, YAML, what an idea! We can now search where we forgot to add quotes in a YAML file. 😉&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can practice Git bisect in an &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_bisect.html&#34;&gt;exercise of the saperlipopette package&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;two-bonus-reasons&#34;&gt;Two bonus reasons&lt;/h2&gt;
&lt;h3 id=&#34;easier-review&#34;&gt;Easier review&lt;/h3&gt;
&lt;p&gt;Small commits will be easier to review by another human. Ideally, it means the code that ends up in the codebase is better, so that there&amp;rsquo;ll be less future need of debugging and undoing. 😁&lt;/p&gt;
&lt;h3 id=&#34;better-automatic-changelog-generation&#34;&gt;Better automatic changelog generation&lt;/h3&gt;
&lt;p&gt;If you use a tool like the R package &lt;a href=&#34;https://fledge.cynkra.com/dev/&#34;&gt;fledge&lt;/a&gt; for generating your changelog or changelog draft, that uses Git commits as input data&amp;hellip; you&amp;rsquo;ll get a better starting changelog if your commits are good.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I showed three main reasons for making small and informative Git commits, all related to debugging or undoing some bad changes. So, creating small, informative Git commits will help someone in the future in trying times. I hope it can inspire myself in particular to pay attention to the Git history I create. 😁&lt;/p&gt;
&lt;p&gt;The saperlipopette package contains a few &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/index.html&#34;&gt;exercises&lt;/a&gt; that can help write a better Git history, including: &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_one_small_change.html&#34;&gt;&amp;ldquo;Oh shit, I committed and immediately realized I need to make one small change!&amp;quot;&lt;/a&gt;, &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_split_changes.html&#34;&gt;&amp;ldquo;Hey I&amp;rsquo;d like to split these changes to the same file into several commits!&amp;quot;&lt;/a&gt;, &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_rebase_i.html&#34;&gt;&amp;ldquo;Hey I&amp;rsquo;d like to make my commits in a branch look informative and smart!&amp;quot;&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What I edit when refactoring a test file</title>
      <link>https://masalmon.eu/2024/05/23/refactoring-tests/</link>
      <pubDate>Thu, 23 May 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/05/23/refactoring-tests/</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://serve.podhome.fm/episodepage/r-weekly-highlights/issue-2024-w22-highlights&#34;&gt;R Weekly highlights podcast&lt;/a&gt; hosted by Eric Nantz and Mike Thomas.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m currently refactoring test files in a package. Beside some &lt;a href=&#34;https://masalmon.eu/2024/05/15/refactoring-xml/&#34;&gt;automatic refactoring&lt;/a&gt;, I am also manually updating lines of code. Here are some tips (or pet peeves, based on how I look at it / how tired I am 😁)&lt;/p&gt;
&lt;h2 id=&#34;prequel-please-read-the-r-packages-book&#34;&gt;Prequel: please read the R packages book&lt;/h2&gt;
&lt;p&gt;The new edition of the R Packages book by Hadley Wickham and Jenny Bryan features three chapters on testing, all well worth a read. The &lt;a href=&#34;https://r-pkgs.org/testing-design.html#sec-testing-design-principles&#34;&gt;&amp;ldquo;High-level principles for testing&amp;rdquo;&lt;/a&gt; in particular are good to keep in mind.&lt;/p&gt;
&lt;h2 id=&#34;use-informative-variable-or-function-names&#34;&gt;Use informative variable or function names&lt;/h2&gt;
&lt;p&gt;If your test is&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;test_that&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;function_maelle_does_not_know_well() works&#34;&lt;/span&gt;, &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;q&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;function_maelle_does_not_know_well&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;ab&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nv&#39;&gt;y&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Log.html&#39;&gt;exp&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;+&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;42&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;7&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Round.html&#39;&gt;round&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Log.html&#39;&gt;log&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;y&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;/&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;50&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_equal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;q&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;ab&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;6&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;you might want to rename &lt;code&gt;q&lt;/code&gt; and &lt;code&gt;ab&lt;/code&gt; to something more informative. Note that this is a fictional example, it does not make any mathematical sense.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;test_that&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;function_maelle_does_not_know_well() works&#34;&lt;/span&gt;, &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;transformed_vector&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;function_maelle_does_not_know_well&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;crude_transformation_approximation&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nv&#39;&gt;y&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Log.html&#39;&gt;exp&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;+&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;42&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;-&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;7&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Round.html&#39;&gt;round&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Log.html&#39;&gt;log&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;y&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;/&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;50&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_equal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;transformed_vector&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;crude_transformation_approximation&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;6&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Imagine it will be me reading your test file, and I know &lt;em&gt;nothing&lt;/em&gt; about your use case. More seriously, that&amp;rsquo;s one of the numerous aspects &lt;a href=&#34;https://code-review.tidyverse.org/&#34;&gt;code review&lt;/a&gt; can help with.&lt;/p&gt;
&lt;h2 id=&#34;vary-variable-names-within-tests&#34;&gt;Vary variable names within tests&lt;/h2&gt;
&lt;p&gt;To prevent copy-pasting mistakes and reading fatigue,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;test_that&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;awesome_function() works&#34;&lt;/span&gt;, &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;easy&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;5&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;medium&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;15&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;hard&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;25&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;is in my opinion better as&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;test_that&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;awesome_function() works&#34;&lt;/span&gt;, &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;easy_output&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;easy&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;easy_output&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;easy_output&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;5&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;medium_output&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;medium&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;medium_output&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;medium_output&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;15&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;hard_output&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;hard&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;hard_output&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;hard_output&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;25&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I do not hate it when several tests use the same variable names though.&lt;/p&gt;
&lt;h2 id=&#34;put-the-object-as-close-as-possible-to-the-related-expectations&#34;&gt;Put the object as close as possible to the related expectation(s)&lt;/h2&gt;
&lt;p&gt;Imagine I made the code chunk from above&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;test_that&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;awesome_function() works&#34;&lt;/span&gt;, &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;easy_output&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;easy&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;medium_output&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;medium&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;hard_output&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;hard&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;easy_output&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;easy_output&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;5&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;medium_output&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;medium_output&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;15&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;hard_output&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;hard_output&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;25&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I much prefer the version&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;test_that&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;awesome_function() works&#34;&lt;/span&gt;, &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;easy_output&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;easy&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;easy_output&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;easy_output&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;5&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;medium_output&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;medium&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;medium_output&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;medium_output&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;15&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;hard_output&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;awesome_function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;10&lt;/span&gt;, method &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;hard&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_typeof&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;hard_output&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;double&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;hard_output&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;25&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;because reading the expectations doesn&amp;rsquo;t require me to go too far back or to remember too much.&lt;/p&gt;
&lt;p&gt;In some cases, if the object creation is simple, and it is used in one expectation only, why not put it &lt;em&gt;inside&lt;/em&gt; the expectation rather than having to assign it to an object with an informative name?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;the_log&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Log.html&#39;&gt;log&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;the_log&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;vs.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;expect_gt&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Log.html&#39;&gt;log&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id=&#34;split-the-tests-as-needed-navigate-them-seamlessly&#34;&gt;Split the tests as needed, navigate them seamlessly&lt;/h2&gt;
&lt;p&gt;Splitting the tests (into several &lt;code&gt;test_that()&lt;/code&gt;) means each one is more focused, easier to read, easier to investigate when failing (tests tend to fail).&lt;/p&gt;
&lt;p&gt;In &lt;a href=&#34;https://github.com/rstudio/rstudio/pull/11108&#34;&gt;RStudio IDE&lt;/a&gt;, each &lt;code&gt;test_that()&lt;/code&gt; calls is shown in the script outline (the table of contents on the right) so you can hop from one to the other at will.&lt;/p&gt;
&lt;h2 id=&#34;use-a-bug-summary-not-number-as-test-name&#34;&gt;Use a bug summary, not number, as test name&lt;/h2&gt;
&lt;p&gt;Instead of&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test_that(&amp;quot;Bug #666 is fixed&amp;quot;, {
  ...
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I prefer&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test_that(&amp;quot;awesome_function() does not remove the ordering&amp;quot;, {
  # &amp;lt;link-to-bug-report&amp;gt;
  ...
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I can understand what the test is about without clicking the link;&lt;/li&gt;
&lt;li&gt;If your repository moved for instance from a monorepo to a regular repository, the hyperlink added by RStudio IDE might no longer be valid.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I summarized my testing preferences &lt;em&gt;du jour&lt;/em&gt;. Do you have any tips for refactoring test scripts?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Automate code refactoring with {xmlparsedata} and {brio}</title>
      <link>https://masalmon.eu/2024/05/15/refactoring-xml/</link>
      <pubDate>Wed, 15 May 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/05/15/refactoring-xml/</guid>
      <description>&lt;p&gt;Once again a post &lt;a href=&#34;https://masalmon.eu/2022/04/08/xml-xpath/&#34;&gt;praising XML&lt;/a&gt;. 😇 These are notes from a quite particular use case: what if you want to replace the usage of a function with another one in many scripts, without manual edits and without touching lines that do not contain a call to replace?&lt;/p&gt;
&lt;p&gt;The real life example that inspired this post is the replacement of all calls to &lt;code&gt;expect_that(..., equals(...))&lt;/code&gt;, like &lt;code&gt;expect_that(a, equals(1))&lt;/code&gt;, in igraph tests with &lt;code&gt;expect_equal()&lt;/code&gt;. If you&amp;rsquo;re a newer package developer who grew up with testthat&amp;rsquo;s third edition, you&amp;rsquo;ve probably never heard of that &lt;a href=&#34;https://testthat.r-lib.org/reference/oldskool.html&#34;&gt;cutesy old-school testing style&lt;/a&gt;. 😉&lt;/p&gt;
&lt;h2 id=&#34;why-automate-where-i-subjectively-justify-my-choice&#34;&gt;Why automate? Where I subjectively justify my choice&lt;/h2&gt;
&lt;p&gt;As brilliantly explained by &lt;a href=&#34;https://xkcd.com/1205/&#34;&gt;XKCD 1205&lt;/a&gt;, automation is not necessary worth the time. In the case that motivated this post, automation was worth it because there were many test files, and because being able to regenerate all edits meant we can recreate the changes after merging other edits to the main branch, without any conflict.&lt;/p&gt;
&lt;h2 id=&#34;parse-the-code-to-xml-detect-problematic-calls&#34;&gt;Parse the code to XML, detect problematic calls&lt;/h2&gt;
&lt;p&gt;For any &lt;code&gt;path&lt;/code&gt;, we detect function calls to &lt;code&gt;expect_that()&lt;/code&gt;. The code is parsed using the &lt;a href=&#34;https://rdrr.io/r/base/parse.html&#34;&gt;&lt;code&gt;parse()&lt;/code&gt;&lt;/a&gt; function, digested into XML with &lt;a href=&#34;https://github.com/r-lib/xmlparsedata&#34;&gt;{xmlparsedata}&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;xml&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/parse.html&#39;&gt;parse&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;keep.source &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;xmlparsedata&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/xmlparsedata/man/xml_parse_data.html&#39;&gt;xml_parse_data&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;pretty &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/read_xml.html&#39;&gt;read_xml&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;deprecated&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_find_all.html&#39;&gt;xml_find_all&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;xml&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;.//SYMBOL_FUNCTION_CALL[text()=&#39;expect_that&#39;]&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;deprecated&lt;/code&gt; object contains all the nodes we need to amend.&lt;/p&gt;
&lt;p&gt;For info, here&amp;rsquo;s how code parsed to XML looks like (yes, it is big despite representing two short lines of code):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/parse.html&#39;&gt;parse&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;text &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;1+1\nsum(c(2,2))&#34;&lt;/span&gt;, keep.source &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;xmlparsedata&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/xmlparsedata/man/xml_parse_data.html&#39;&gt;xml_parse_data&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;pretty &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/cat.html&#39;&gt;cat&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; standalone=&#34;yes&#34; ?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;exprlist&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &amp;lt;expr line1=&#34;1&#34; col1=&#34;1&#34; line2=&#34;1&#34; col2=&#34;3&#34; start=&#34;13&#34; end=&#34;15&#34;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;expr line1=&#34;1&#34; col1=&#34;1&#34; line2=&#34;1&#34; col2=&#34;1&#34; start=&#34;13&#34; end=&#34;13&#34;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;NUM_CONST line1=&#34;1&#34; col1=&#34;1&#34; line2=&#34;1&#34; col2=&#34;1&#34; start=&#34;13&#34; end=&#34;13&#34;&amp;gt;1&amp;lt;/NUM_CONST&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;/expr&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;OP-PLUS line1=&#34;1&#34; col1=&#34;2&#34; line2=&#34;1&#34; col2=&#34;2&#34; start=&#34;14&#34; end=&#34;14&#34;&amp;gt;+&amp;lt;/OP-PLUS&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;expr line1=&#34;1&#34; col1=&#34;3&#34; line2=&#34;1&#34; col2=&#34;3&#34; start=&#34;15&#34; end=&#34;15&#34;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;NUM_CONST line1=&#34;1&#34; col1=&#34;3&#34; line2=&#34;1&#34; col2=&#34;3&#34; start=&#34;15&#34; end=&#34;15&#34;&amp;gt;1&amp;lt;/NUM_CONST&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;/expr&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &amp;lt;/expr&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &amp;lt;expr line1=&#34;2&#34; col1=&#34;1&#34; line2=&#34;2&#34; col2=&#34;11&#34; start=&#34;25&#34; end=&#34;35&#34;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;expr line1=&#34;2&#34; col1=&#34;1&#34; line2=&#34;2&#34; col2=&#34;3&#34; start=&#34;25&#34; end=&#34;27&#34;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;SYMBOL_FUNCTION_CALL line1=&#34;2&#34; col1=&#34;1&#34; line2=&#34;2&#34; col2=&#34;3&#34; start=&#34;25&#34; end=&#34;27&#34;&amp;gt;sum&amp;lt;/SYMBOL_FUNCTION_CALL&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;/expr&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;OP-LEFT-PAREN line1=&#34;2&#34; col1=&#34;4&#34; line2=&#34;2&#34; col2=&#34;4&#34; start=&#34;28&#34; end=&#34;28&#34;&amp;gt;(&amp;lt;/OP-LEFT-PAREN&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;expr line1=&#34;2&#34; col1=&#34;5&#34; line2=&#34;2&#34; col2=&#34;10&#34; start=&#34;29&#34; end=&#34;34&#34;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;expr line1=&#34;2&#34; col1=&#34;5&#34; line2=&#34;2&#34; col2=&#34;5&#34; start=&#34;29&#34; end=&#34;29&#34;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;         &amp;lt;SYMBOL_FUNCTION_CALL line1=&#34;2&#34; col1=&#34;5&#34; line2=&#34;2&#34; col2=&#34;5&#34; start=&#34;29&#34; end=&#34;29&#34;&amp;gt;c&amp;lt;/SYMBOL_FUNCTION_CALL&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;/expr&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;OP-LEFT-PAREN line1=&#34;2&#34; col1=&#34;6&#34; line2=&#34;2&#34; col2=&#34;6&#34; start=&#34;30&#34; end=&#34;30&#34;&amp;gt;(&amp;lt;/OP-LEFT-PAREN&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;expr line1=&#34;2&#34; col1=&#34;7&#34; line2=&#34;2&#34; col2=&#34;7&#34; start=&#34;31&#34; end=&#34;31&#34;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;         &amp;lt;NUM_CONST line1=&#34;2&#34; col1=&#34;7&#34; line2=&#34;2&#34; col2=&#34;7&#34; start=&#34;31&#34; end=&#34;31&#34;&amp;gt;2&amp;lt;/NUM_CONST&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;/expr&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;OP-COMMA line1=&#34;2&#34; col1=&#34;8&#34; line2=&#34;2&#34; col2=&#34;8&#34; start=&#34;32&#34; end=&#34;32&#34;&amp;gt;,&amp;lt;/OP-COMMA&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;expr line1=&#34;2&#34; col1=&#34;9&#34; line2=&#34;2&#34; col2=&#34;9&#34; start=&#34;33&#34; end=&#34;33&#34;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;         &amp;lt;NUM_CONST line1=&#34;2&#34; col1=&#34;9&#34; line2=&#34;2&#34; col2=&#34;9&#34; start=&#34;33&#34; end=&#34;33&#34;&amp;gt;2&amp;lt;/NUM_CONST&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;/expr&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;OP-RIGHT-PAREN line1=&#34;2&#34; col1=&#34;10&#34; line2=&#34;2&#34; col2=&#34;10&#34; start=&#34;34&#34; end=&#34;34&#34;&amp;gt;)&amp;lt;/OP-RIGHT-PAREN&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;/expr&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;OP-RIGHT-PAREN line1=&#34;2&#34; col1=&#34;11&#34; line2=&#34;2&#34; col2=&#34;11&#34; start=&#34;35&#34; end=&#34;35&#34;&amp;gt;)&amp;lt;/OP-RIGHT-PAREN&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &amp;lt;/expr&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;/exprlist&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id=&#34;fix-problematic-calls-in-the-xml-representation&#34;&gt;Fix problematic calls in the XML representation&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;treat_deprecated()&lt;/code&gt; function below tries to find a call to &lt;code&gt;equals()&lt;/code&gt; inside the &lt;code&gt;expect_equal()&lt;/code&gt;, since we only fix the calls to &lt;code&gt;expect_that()&lt;/code&gt; that contain &lt;code&gt;equals()&lt;/code&gt;. We return early for these other cutesy expectations, with a warning so we can go look at the scripts and get an idea of what the calls are. They will have to be fixed with another script, or manually, depending on how many of them there are.&lt;/p&gt;
&lt;p&gt;For the calls to &lt;code&gt;expect_that()&lt;/code&gt; that contain a call to &lt;code&gt;equals()&lt;/code&gt;, we&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;replace &lt;code&gt;expect_that()&lt;/code&gt; with &lt;code&gt;expect_equal()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;extract the text inside &lt;code&gt;equals()&lt;/code&gt; to put it directly as second argument of &lt;code&gt;expect_equal()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thus &lt;code&gt;expect_that(a, equals(1))&lt;/code&gt; becomes &lt;code&gt;expect_equals(a, 1)&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;treat_deprecated&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;xml&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_parent&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;xml&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_siblings&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;equal&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/grep.html&#39;&gt;grepl&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;equals\\(&#34;&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;kr&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/length.html&#39;&gt;length&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;equal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;cli&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://cli.r-lib.org/reference/cli_alert.html&#39;&gt;cli_alert_warning&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;WARNING AT &amp;#123;path&amp;#125;.&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;kr&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/function.html&#39;&gt;return&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;xml&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;expect_equal&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;text&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_contents&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;equal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;3&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_replace.html&#39;&gt;xml_remove&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_contents&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;equal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;equal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;text&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id=&#34;serialize-xml-to-character-write-back&#34;&gt;Serialize XML to character, write back&lt;/h2&gt;
&lt;p&gt;We only modify the lines of the script that need to be modified, as it will avoid spurious changes but also avoid figuring out how to serialize the whole HTML.&lt;/p&gt;
&lt;p&gt;For each call that was edited in XML, we identify the corresponding start and end lines in the original script. Below is again an example of parsing just to show that each expression has attributes called line1 and line2, the start and end lines.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/parse.html&#39;&gt;parse&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;text &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;1+1\n2+2&#34;&lt;/span&gt;, keep.source &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;xmlparsedata&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/xmlparsedata/man/xml_parse_data.html&#39;&gt;xml_parse_data&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;pretty &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/read_xml.html&#39;&gt;read_xml&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;#123;xml_document&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;exprlist&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &amp;lt;expr line1=&#34;1&#34; col1=&#34;1&#34; line2=&#34;1&#34; col2=&#34;3&#34; start=&#34;5&#34; end=&#34;7&#34;&amp;gt;\n  &amp;lt;expr l ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [2] &amp;lt;expr line1=&#34;2&#34; col1=&#34;1&#34; line2=&#34;2&#34; col2=&#34;3&#34; start=&#34;9&#34; end=&#34;11&#34;&amp;gt;\n  &amp;lt;expr  ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;There are two cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the start and end line is the same. We replace the corresponding line with the text of the grand-parent node.&lt;/li&gt;
&lt;li&gt;the start and end lines are different. We loop over them, for each of them we replace the corresponding line with the text of parent and uncles/aunts nodes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The choice of parents/siblings might seem a bit arbitrary. I made it work by putting a &lt;a href=&#34;https://rdrr.io/r/base/browser.html&#34;&gt;&lt;code&gt;browser()&lt;/code&gt;&lt;/a&gt; in my code and figuring out what level of ancestry I had to deal with thanks to random tries. I do not have a particularly good mental model of R code as XML. 😉&lt;/p&gt;
&lt;p&gt;For some reason I wrote for loops in the code below, probably because that&amp;rsquo;s what made sense to me at the time. 🤷&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;lines&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/read_lines.html&#39;&gt;read_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# code identifying deprecated calls&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/map.html&#39;&gt;walk&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;deprecated&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;treat_deprecated&lt;/span&gt;, path &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;kr&#39;&gt;for&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;deprecated_call&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;in&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;deprecated&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;parent&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_parent&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_parent&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;deprecated_call&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;line1&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/numeric.html&#39;&gt;as.numeric&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_attr.html&#39;&gt;xml_attr&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parent&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;line1&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;line2&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/numeric.html&#39;&gt;as.numeric&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_attr.html&#39;&gt;xml_attr&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parent&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;line2&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;kr&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;line1&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;line2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nv&#39;&gt;lines&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;line1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parent&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;else&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;kr&#39;&gt;for&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;line&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;in&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;line1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;line2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_children&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parent&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;nv&#39;&gt;lines&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;line&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/paste.html&#39;&gt;paste&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;        &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_attr.html&#39;&gt;xml_attr&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;line1&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;line&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;        collapse &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;lines&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;After all this, we write the &lt;code&gt;lines&lt;/code&gt;, modified and not, to the original &lt;code&gt;path&lt;/code&gt;. It&amp;rsquo;s important to first try this on a script and check the diff.&lt;/p&gt;
&lt;h2 id=&#34;put-it-all-together&#34;&gt;Put it all together&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s the all script, including automatic commit generation.&lt;/p&gt;
&lt;div class=&#39;highlight&#39;&gt;&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;parse_script&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;cli&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://cli.r-lib.org/reference/cli_alert.html&#39;&gt;cli_alert_info&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;Refactoring &amp;#123;path&amp;#125;.&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;lines&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/read_lines.html&#39;&gt;read_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;xml&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/parse.html&#39;&gt;parse&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;keep.source &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;xmlparsedata&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/xmlparsedata/man/xml_parse_data.html&#39;&gt;xml_parse_data&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;pretty &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/read_xml.html&#39;&gt;read_xml&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;deprecated&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_find_all.html&#39;&gt;xml_find_all&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nv&#39;&gt;xml&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;s&#39;&gt;&#34;.//SYMBOL_FUNCTION_CALL[text()=&#39;expect_that&#39;]&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/map.html&#39;&gt;walk&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;deprecated&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;treat_deprecated&lt;/span&gt;, path &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;kr&#39;&gt;for&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;deprecated_call&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;in&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;deprecated&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nv&#39;&gt;parent&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_parent&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_parent&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;deprecated_call&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nv&#39;&gt;line1&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/numeric.html&#39;&gt;as.numeric&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_attr.html&#39;&gt;xml_attr&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parent&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;line1&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nv&#39;&gt;line2&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/numeric.html&#39;&gt;as.numeric&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_attr.html&#39;&gt;xml_attr&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parent&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;line2&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;kr&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;line1&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;line2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;nv&#39;&gt;lines&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;line1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parent&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;else&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;kr&#39;&gt;for&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;line&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;in&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;line1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;:&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;line2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;        &lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_children&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parent&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;        &lt;span class=&#39;nv&#39;&gt;lines&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;line&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/paste.html&#39;&gt;paste&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;          &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_attr.html&#39;&gt;xml_attr&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;line1&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;line&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;          collapse &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;        &lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;lines&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;kr&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;!&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/match.html&#39;&gt;%in%&lt;/a&gt;&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_status&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;file&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;kr&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/function.html&#39;&gt;return&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/invisible.html&#39;&gt;invisible&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;styler&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://styler.r-lib.org/reference/style_file.html&#39;&gt;style_file&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_add&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_commit&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/sprintf.html&#39;&gt;sprintf&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;refactor: remove deprecated expect_that() from %s&#34;&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;fs&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://fs.r-lib.org/reference/path_file.html&#39;&gt;path_file&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;treat_deprecated&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;xml&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_parent&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;xml&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_siblings&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;equal&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/grep.html&#39;&gt;grepl&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;equals\\(&#34;&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;siblings&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;kr&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/length.html&#39;&gt;length&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;equal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;0&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;cli&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://cli.r-lib.org/reference/cli_alert.html&#39;&gt;cli_alert_warning&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;WARNING AT &amp;#123;path&amp;#125;.&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;kr&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/function.html&#39;&gt;return&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;xml&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;expect_equal&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;text&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_contents&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;equal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;3&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_replace.html&#39;&gt;xml_remove&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_children.html&#39;&gt;xml_contents&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;equal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;equal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;text&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;paths&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;fs&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://fs.r-lib.org/reference/dir_ls.html&#39;&gt;dir_ls&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;tests/testthat&#34;&lt;/span&gt;, regex &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;test-&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/map.html&#39;&gt;walk&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;paths&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;parse_script&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/igraph/rigraph/pull/1337&#34;&gt;Example PR&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I presented a strategy that served me well when refactoring igraph&amp;rsquo;s test scripts: parsing code to XML, editing it as XML, then writing back the edited lines thanks to the attributes of XML nodes that indicate their original lines in the script.&lt;/p&gt;
&lt;p&gt;Other possible approaches include styler&amp;rsquo;s parsing of code into a table and &lt;a href=&#34;https://github.com/r-lib/styler&#34;&gt;serialization&lt;/a&gt; of that table.&lt;/p&gt;
&lt;p&gt;In a more similar approach, which means it might have been wise for me to explore this codebase sooner 😅, the codegrip package uses &lt;a href=&#34;https://github.com/lionel-/codegrip/blob/82d164ed91ad819587796a4053b1df5b0385c677/R/ast.R#L1&#34;&gt;xmlparsedata&lt;/a&gt; and has &lt;a href=&#34;https://github.com/lionel-/codegrip/blob/82d164ed91ad819587796a4053b1df5b0385c677/R/ast.R#L51&#34;&gt;helpers for finding which lines a node refers to&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Do you sometimes use automatic refactoring (&lt;a href=&#34;https://styler.r-lib.org/&#34;&gt;styler&lt;/a&gt;, &lt;a href=&#34;https://github.com/lionel-/codegrip&#34;&gt;codegrip&lt;/a&gt;, etc.), or automatic diagnostics (&lt;a href=&#34;https://lintr.r-lib.org/&#34;&gt;lintr&lt;/a&gt;, &lt;a href=&#34;https://docs.ropensci.org/pkgcheck/&#34;&gt;pkgcheck&lt;/a&gt;, etc.)? Have you written any customization or standalone script to help you with that?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Reading notes on Producing open source software by Karl Fogel (First edition)</title>
      <link>https://masalmon.eu/2024/02/08/producing-oss-first-edition-karl-fogel/</link>
      <pubDate>Thu, 08 Feb 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/02/08/producing-oss-first-edition-karl-fogel/</guid>
      <description>&lt;p&gt;I recently re-read &lt;a href=&#34;https://press.stripe.com/working-in-public&#34;&gt;Nadia Eghbal&amp;rsquo;s Working in public&lt;/a&gt;. This time around, I noticed her mention of the book &lt;a href=&#34;https://producingoss.com/&#34;&gt;&amp;ldquo;Producing open source software&amp;rdquo; by Karl Fogel&lt;/a&gt;. It is a book about the people aspects of open-source projects, including money, and it reads like a sort of guide. Complying with my &lt;a href=&#34;https://masalmon.eu/2024/01/19/pro-git-scott-chacon-reading-notes/&#34;&gt;first-edition-curse&lt;/a&gt;, I did not notice there was a second edition online and soonish to be in print apparently, so I bought and read a second-hand first edition.&lt;/p&gt;
&lt;p&gt;I really enjoyed it, and found myself referring to or thinking of parts of the book at work. Kind of impressive for a 2005 book about open-source to have aged so well in at least some chapters. Here are some of my highlights!&lt;/p&gt;
&lt;h2 id=&#34;what-didnt-age-well&#34;&gt;What didn&amp;rsquo;t age well&lt;/h2&gt;
&lt;p&gt;In 2005, Git was still in development (the book author is actually a Subversion contributor). Furthermore, mailing lists were apparently big.&lt;/p&gt;
&lt;p&gt;Now, the R project still uses Subversion and has mailing lists&amp;hellip;&lt;/p&gt;
&lt;p&gt;Besides, it was nice to think of some things GitHub has, like discussions board, in general terms.&lt;/p&gt;
&lt;h2 id=&#34;the-pompeii-projects-&#34;&gt;The Pompeii projects 🌋&lt;/h2&gt;
&lt;p&gt;In the introduction, the author says it&amp;rsquo;s hard to define failures of open-source projects because often the project quietly dies.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;There may be a moment when a final change is made to the project, but those who made it usually didn&amp;rsquo;t know at the time that it was the last one.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;When visiting old repositories, I regularly have the impression I am visiting a less dramatic version of Pompeii.&lt;/p&gt;
&lt;p&gt;At rOpenSci, we strive to &lt;a href=&#34;https://devdevguide.netlify.app/maintenance_evolution#archivalguidance&#34;&gt;explicitly archive abandoned or retired packages&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;about-motivations-for-participating-in-open-source&#34;&gt;About motivations for participating in open-source&lt;/h2&gt;
&lt;p&gt;To the questions &amp;ldquo;What will persuade all these people to stick together long enough to produce something useful?&amp;rdquo;, Karl Fogel answers:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;People should feel that their connection to a project, and influence over it, is directly proportional to their contributions.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A further aspect mentioned in the book is the idea that participants have a direct interest in the project because they, or their organization, use(s) it.&lt;/p&gt;
&lt;p&gt;Later in the book, Karl Fogel also writes this about participants&amp;rsquo; motivation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;The desire to produce good software may be among those motivations, along with the challenge and educational value of working on hard problems. But humans also have a built-in desire to work with other humans, and to give and earn respect through cooperative activities.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;❤️&lt;/p&gt;
&lt;p&gt;Another quote I don&amp;rsquo;t want to forget:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Credit is the primary currency of the free software world.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(yes, there are &lt;a href=&#34;https://yabellini.netlify.app/blog/2023-10-13-three-payments/&#34;&gt;different currencies of payment&lt;/a&gt;, but it is nice to underline that credit is important)&lt;/p&gt;
&lt;h2 id=&#34;on-code-review&#34;&gt;On code review&lt;/h2&gt;
&lt;p&gt;Also related to motivation&amp;hellip;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;code review also serves an indirect purpose: it confirms to people that what they do matters, because one obviously wouldn&amp;rsquo;t take time to review a commit unless one cared about its effect.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;treat-every-user-as-a-potential-volunteer&#34;&gt;&amp;ldquo;Treat Every User as a Potential Volunteer&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;The idea is that people you meet in the issue tracker are already more involved than most users. 😉&lt;/p&gt;
&lt;h2 id=&#34;appearances-matter&#34;&gt;&amp;ldquo;Appearances matter&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;The author makes the point that by providing expected information in expected places in a nice way, you help potential users and contributors feel their time will not be wasted.&lt;/p&gt;
&lt;p&gt;To me as an R package developer, &amp;ldquo;appearances matter&amp;rdquo; means: please &lt;a href=&#34;https://pkgdown.r-lib.org/articles/customise.html#getting-started&#34;&gt;switch your pkgdown website to Bootstrap 5&lt;/a&gt;. 😸 The small font size of the former template doesn&amp;rsquo;t give me a good impression as I need to zoom! Also, creating a pkgdown website in the first place, and linking it from your Git(Hub) repository, takes very little time in general. By the way, in 2005 the author already recommended for docs to be available locally but also online for people to be able to read it without installing your thing.&lt;/p&gt;
&lt;h2 id=&#34;hacktivation-energy&#34;&gt;&amp;ldquo;Hacktivation energy&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;The &amp;ldquo;hacktivation energy&amp;rdquo; is &amp;ldquo;the amount of energy a newcomer must put before she starts getting something back&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Obviously, that is something maintainers should strive to minimize. I like catchy phrases!&lt;/p&gt;
&lt;h2 id=&#34;the-case-for-sitrep-situation-report&#34;&gt;The case for sitrep (situation report)&lt;/h2&gt;
&lt;p&gt;The sentence&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;somewhere near the beginning of the documentation, tell the user how to run some sort of diagnostic test or simple command to confirm that they&amp;rsquo;ve set things up correctly&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;reminds me of &lt;a href=&#34;https://ropensci.org/blog/2021/09/30/ropensci-news-digest-september-2021/#package-development-corner&#34;&gt;&amp;ldquo;sitrep&amp;rdquo; functions in usethis and devtools&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;developer-guidelines-vs-developer-documentation&#34;&gt;Developer guidelines vs developer documentation&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Developer guidelines tell programmers how to get along with each other; developers documentation tells them how to get along with the code itself.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;about-secrecy&#34;&gt;About secrecy&lt;/h2&gt;
&lt;p&gt;The author writes about discussions in public vs in private several times. I like the sentence below, although I guess any project can operate on a different degree of openness based on its goals:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Making important decision in private is like spraying contributions repellent on your project.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In another place in the book, the author states that of course, every organization has secrets.&lt;/p&gt;
&lt;h2 id=&#34;on-issue-trackers&#34;&gt;On issue trackers&lt;/h2&gt;
&lt;p&gt;Compared to closing off issue trackers,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;It&amp;rsquo;s better to accept that cleaning out invalid issues will always be part of the project&amp;rsquo;s routine maintenance, and to try to get as many people as possible to help.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;project-health&#34;&gt;Project health&lt;/h2&gt;
&lt;p&gt;Two more catchy phrases or words! One is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Operational health is the project&amp;rsquo;s ongoing ability to incorporate new code contributions and new developers, and to be responsive to bug reports.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And the other is a nicer synonym of &amp;ldquo;bus factor&amp;rdquo;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Survivability is the project&amp;rsquo;s ability to exist independently of any individual participant or sponsor.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To put actual numbers on those, nowadays one can use &lt;a href=&#34;https://chaoss.community/&#34;&gt;CHAOSS&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;scale&#34;&gt;Scale&lt;/h2&gt;
&lt;p&gt;I feel some ideas presented in the book, like voting systems, apply to bigger projects than what I am typically dealing with.&lt;/p&gt;
&lt;p&gt;Still, these were interesting paragraphs:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;The price of success is heavy in the open source world. As your software gets more popular, the number of people who show up looking for information increases dramatically, while the number of people able to provide information increases much more slowly.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;one side effect of continuing to use unscalable communications models as the project grows is that the average quality of both questions and answers tends to go down, which makes it look like new users are dumber that they used to be, when in fact they&amp;rsquo;re probably not. It&amp;rsquo;s just that the benefit/cost ratio of using those high-population forums goes down, so naturally those with the experience to do so start to look elsewhere for answers first.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;terse-yes-but-with-emoticlues&#34;&gt;Terse, yes, but with &amp;ldquo;emoticlues&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;Karl Fogel says that if you write a terse comment, which is acceptable,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;But at the end, sign off with something indicating that your terseness is not to be taken as coldness (&amp;hellip;) A strategically placed smiley face or emoticlue can often be enough to reassure an interlocutor, too.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I really like the made-up word &amp;ldquo;emoticlue&amp;rdquo;. 😁 Adding emojis in issue comments is something I consciously do.&lt;/p&gt;
&lt;h2 id=&#34;holy-wars&#34;&gt;Holy wars&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Each project usually has a holy war or two all its own, as well, which long-time developers will quickly become familiar with.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A pint of tidyverse-vs-base-R, anyone? 🍻&lt;/p&gt;
&lt;h2 id=&#34;releases&#34;&gt;Releases&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Stabilization&amp;rdquo; is the process of getting a release branch into a releasable state; that is, of deciding which changes will be in the release, which will not, and shaping the branch content accordingly.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;(&amp;hellip;) the process of stabilizing a release is mostly about creating mechanisms for saying &amp;lsquo;no&amp;rsquo;.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;automation&#34;&gt;Automation&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Multi-step, deterministic operations are exactly what computers were invented for, save your humans for more interesting things.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Examples of this would be &lt;a href=&#34;https://twitter.com/jennybryan/status/935562495816753153&#34;&gt;usethis&lt;/a&gt; and &lt;a href=&#34;https://ropensci.org/blog/2022/05/31/chatops-review-system-github/&#34;&gt;rOpenSci automation of software-review&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;Producing open-source software&amp;rdquo; was a nice read. I don&amp;rsquo;t want to read more things on screen given how I spend my days 😅, so I will wait for the second edition to be in print to read it, but I am glad to have already read the first. I feel it&amp;rsquo;d be a nice book to discuss with others. It reminded me of Tracy Teal&amp;rsquo;s posit conference workshop &lt;a href=&#34;https://github.com/posit-conf-2023/managing-os-project/&#34;&gt;&amp;ldquo;It&amp;rsquo;s not just code: managing an open source project&amp;rdquo;&lt;/a&gt; that I didn&amp;rsquo;t attend, but whose existence I found cool; and of an rOpenSci community call I participated it in, &lt;a href=&#34;https://ropensci.org/blog/2021/04/28/commcall-pkg-community/&#34;&gt;&amp;ldquo;Set Up Your Package to Foster a Community&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Load different R package versions at once with git worktree</title>
      <link>https://masalmon.eu/2024/01/23/git-worktree/</link>
      <pubDate>Tue, 23 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/01/23/git-worktree/</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://rweekly.fireside.fm/150?t=664&#34;&gt;R Weekly highlights podcast&lt;/a&gt; hosted by Eric Nantz and Mike Thomas.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Do you ever see &lt;a href=&#34;https://github.com/igraph/rigraph/issues/1097&#34;&gt;GitHub issue comments&lt;/a&gt; where someone posts the results of a reprex with a current package version, and then with an older one, to prove a regression? How would you go about preparing such a report? Today I learnt there is a clean way to have different versions of a codebase at once on your computer, thanks to the ever powerful Git.&lt;/p&gt;
&lt;h2 id=&#34;assumption-you-want-to-load-the-package-at-different-stages-of-its-history&#34;&gt;Assumption: you want to load the package at different stages of its history&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m not talking about &lt;em&gt;installing&lt;/em&gt; different R package versions at once, this is not a post about &lt;a href=&#34;https://rstudio.github.io/renv/articles/renv.html&#34;&gt;renv&lt;/a&gt; or Docker. 😉 I mean having the ability to quickly run &lt;a href=&#34;https://devtools.r-lib.org/reference/test.html&#34;&gt;&lt;code&gt;devtools::test()&lt;/code&gt;&lt;/a&gt; or &lt;a href=&#34;https://devtools.r-lib.org/reference/test.html&#34;&gt;&lt;code&gt;devtools::test_active_file()&lt;/code&gt;&lt;/a&gt; on two different versions of an R package source.&lt;/p&gt;
&lt;p&gt;Although I guess that for running an actual &lt;a href=&#34;https://reprex.tidyverse.org/reference/reprex.html&#34;&gt;&lt;code&gt;reprex::reprex()&lt;/code&gt;&lt;/a&gt; on your code, you&amp;rsquo;d need a quick installation in each version of the codebase.&lt;/p&gt;
&lt;h2 id=&#34;solution-git-worktree&#34;&gt;Solution: git worktree!&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;git worktree&lt;/code&gt; command tends to be introduced as an &lt;a href=&#34;https://www.gitkraken.com/learn/git/git-worktree&#34;&gt;alternative to a quick git stash when switching from feature work to a hot fix&lt;/a&gt; (well, in all three posts I read/skimmed on the topic 😅). With &lt;code&gt;git worktree&lt;/code&gt; you can create a new folder somewhere on your computer, that is at a different Git state than your current folder (other commit/branch/release &amp;ndash; aren&amp;rsquo;t all of those the same thing anyway 🤪).&lt;/p&gt;
&lt;p&gt;Say, in &lt;code&gt;Documents/rigraph&lt;/code&gt; you are working on the main branch of the &lt;a href=&#34;https://github.com/igraph/rigraph&#34;&gt;https://github.com/igraph/rigraph&lt;/a&gt; repository. Now, someone asks you &amp;ldquo;what did this code do with version 1.6.0&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Past me would have diligently installed that version of the package in the same R session, probably from CRAN or with pak, run the code, re-started my R session, re-loaded the development version or something like that.&lt;/p&gt;
&lt;p&gt;Current me would run &lt;code&gt;git worktree add ../rigraphv1.6.0 v1.6.0&lt;/code&gt; which means I now have a folder &lt;code&gt;Documents/rigraphv1.6.0&lt;/code&gt; with the rigraph repository as it was at the v1.6.0 release. Then inside that folder I can open my favorite IDE, load rigraph as it was at the time, and run the code I am curious about. I can switch between my two IDE windows to try things out with the two package versions.&lt;/p&gt;
&lt;p&gt;Once I am done, from my original rigraph folder I can run &lt;code&gt;git worktree remove rigraphv1.6.0&lt;/code&gt; (or &lt;code&gt;git worktree remove rigraphv1.6.0 --force&lt;/code&gt; if there are some changes in that folder). &lt;code&gt;git worktree list&lt;/code&gt; shows me what worktrees (folders!) there are.&lt;/p&gt;
&lt;h2 id=&#34;conclusion-git-worktree-is-great&#34;&gt;Conclusion: git worktree is great!&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m glad I learnt about &lt;a href=&#34;https://git-scm.com/docs/git-worktree&#34;&gt;&lt;code&gt;git worktree&lt;/code&gt;&lt;/a&gt;, &amp;ldquo;Manage multiple working trees&amp;rdquo; a.k.a (in my head) &amp;ldquo;Create multiple folders corresponding to a single Git repo at different states&amp;rdquo;. Do you use &lt;code&gt;git worktree&lt;/code&gt;? Did I miss something in the around 10 minutes I&amp;rsquo;ve known about it? 😅&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Reading notes on Pro Git by Scott Chacon</title>
      <link>https://masalmon.eu/2024/01/19/pro-git-scott-chacon-reading-notes/</link>
      <pubDate>Fri, 19 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/01/19/pro-git-scott-chacon-reading-notes/</guid>
      <description>&lt;p&gt;As mentioned about a million times on this blog, last year I read &lt;a href=&#34;https://masalmon.eu/2023/11/01/reading-notes-git-in-practice/&#34;&gt;Git in practice by Mike McQuaid&lt;/a&gt; and it changed my life &amp;ndash; not only giving me bragging rights about the reading itself. 😅 I decided to give &lt;a href=&#34;https://git-scm.com/book/en/v2&#34;&gt;Pro Git by Scott Chacon&lt;/a&gt; a go too. It is listed in the &lt;a href=&#34;https://happygitwithr.com/resources&#34;&gt;resources section&lt;/a&gt; of the excellent &amp;ldquo;Happy Git with R&amp;rdquo; by Jenny Bryan, Jim Hester and others. For unclear reasons I bought the first edition instead of the second one.&lt;/p&gt;
&lt;h2 id=&#34;git-as-an-improved-filesystem&#34;&gt;Git as an improved filesystem&lt;/h2&gt;
&lt;p&gt;In the Chapter 1 (Getting Started), I underlined:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;[a] mini filesystem with some incredibly powerful tools built on top of it&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;awesome-diagrams&#34;&gt;Awesome diagrams&lt;/h2&gt;
&lt;p&gt;One of my favorite parts of the book were the diagrams such as the one illustrating &amp;ldquo;Git stores data as snapshots of the project over time&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;a-reminder-of-why-we-use-git&#34;&gt;A reminder of why we use Git&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;after you commit a snapshot into Git, it is very difficult to lose, especially if you regularly push your database to another repository.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The last chapter in the book, &amp;ldquo;Git internals&amp;rdquo;, include a &amp;ldquo;Data recovery&amp;rdquo; section about &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_time_machine.html&#34;&gt;&lt;code&gt;git reflog&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://git-scm.com/docs/git-fsck&#34;&gt;&lt;code&gt;git fsck&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;one-can-negate-patterns-in-gitignore&#34;&gt;One can negate patterns in &lt;code&gt;.gitignore&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I did not know about this &lt;a href=&#34;https://git-scm.com/docs/gitignore#_pattern_format&#34;&gt;pattern format&lt;/a&gt;. In hindsight it is not particularly surprising.&lt;/p&gt;
&lt;h2 id=&#34;git-log-options&#34;&gt;&lt;code&gt;git log&lt;/code&gt; options&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;format&lt;/code&gt; option lets one tell Git how to, well, format the log. I mostly interact with the Git log through a GUI or the gert R package, but that&amp;rsquo;s good to know.&lt;/p&gt;
&lt;p&gt;The book also describes how to filter commits in the log (by date, author, committer). I also never do that with Git itself, but who knows when it might become useful.&lt;/p&gt;
&lt;h2 id=&#34;a-better-understanding-of-branches&#34;&gt;A better understanding of branches&lt;/h2&gt;
&lt;p&gt;I remember reading &amp;ldquo;branches are cheap&amp;rdquo; years ago and accepting this as fact without questioning the reason behind the statement. Now thanks to reading the &amp;ldquo;Git Branching&amp;rdquo; chapter, but also Julia Evans&amp;rsquo; blog post &lt;a href=&#34;https://jvns.ca/blog/2023/11/23/branches-intuition-reality/&#34;&gt;&amp;ldquo;git branches: intuition &amp;amp; reality&amp;rdquo;&lt;/a&gt;, I know they are cheap because they are just a pointer to a commit.&lt;/p&gt;
&lt;p&gt;Likewise, the phrase &amp;ldquo;fast forward&amp;rdquo; makes more sense after reading &amp;ldquo;Git moves the pointer forward&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;Git Branching&amp;rdquo; chapter is also a place where diagrams really shine.&lt;/p&gt;
&lt;h2 id=&#34;is-rebase-better-than-merge&#34;&gt;Is rebase better than merge&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;(&amp;hellip;) rebasing makes for a cleaner history. If you examine the log of a rebased branch, it looks like a linear history.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Rebasing replays changes from one line of work onto another in the order they were introduced, whereas merging takes the endpoints and merges them together.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Reading this reminds me of the (newish?) option for merging pull requests on GitHub, &lt;a href=&#34;https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#rebase-and-merge-your-commits&#34;&gt;&amp;ldquo;Rebase and merge your commits&amp;rdquo;&lt;/a&gt; &amp;ndash; as opposed to merge or squash&amp;amp;merge.&lt;/p&gt;
&lt;h2 id=&#34;dont-rebase-commits-and-force-push-to-a-shared-branch&#34;&gt;Don&amp;rsquo;t rebase commits and force push to a shared branch&lt;/h2&gt;
&lt;p&gt;The opportunity to plug another blog post by Julia Evans, &lt;a href=&#34;https://jvns.ca/blog/2023/11/06/rebasing-what-can-go-wrong-/&#34;&gt;&amp;ldquo;git rebase: what can go wrong?&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-chance-of-getting-the-same-sha-1-twice-in-your-repository&#34;&gt;The chance of getting the same SHA-1 twice in your repository&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;A higher probability exists that every member of your programming team will be attacked and killed by wolves in unrelated incidents on the same night.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;ancestry-references&#34;&gt;Ancestry references&lt;/h2&gt;
&lt;p&gt;The name of references with &amp;ldquo;^&amp;rdquo; or &amp;ldquo;~&amp;rdquo; (or both!) is &amp;ldquo;ancestry references&amp;rdquo;. Both &lt;code&gt;HEAD~3&lt;/code&gt; and &lt;code&gt;HEAD^^^&lt;/code&gt; are &amp;ldquo;the first parent of the first parent of the first parent&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;double-dot-and-triple-dot&#34;&gt;Double dot and triple dot&lt;/h2&gt;
&lt;p&gt;I do not intend to try and learn this but&amp;hellip;&lt;/p&gt;
&lt;p&gt;The double-dot syntax &amp;ldquo;asks Git to resolve a range of commits that are reachable from one commit but aren&amp;rsquo;t reachable from another&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The triple-dot syntax &amp;ldquo;specifies all the commits that are reachable by either of the two references but not by both of them&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;new-to-me-aspects-of-git-rebase--i&#34;&gt;New-to-me aspects of &lt;code&gt;git rebase -i&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;git rebase -i&lt;/code&gt; lists commits in the reverse order compared to &lt;code&gt;git log&lt;/code&gt;. I am not sure why I did not make a note of this before.&lt;/p&gt;
&lt;p&gt;I had not really realized one could &lt;em&gt;edit&lt;/em&gt; single commits in &lt;code&gt;git rebase -i&lt;/code&gt;. When writing &amp;ldquo;edit&amp;rdquo;, rebasing will stop at the commit one wants to edit. That strategy is actually featured in the GitHub blog post &lt;a href=&#34;https://github.blog/2022-06-30-write-better-commits-build-better-projects/&#34;&gt;&amp;ldquo;Write Better Commits, Build Better Projects&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;plumbing-vs-porcelaine&#34;&gt;Plumbing vs porcelaine&lt;/h2&gt;
&lt;p&gt;I had seen these terms before but never taken the time to look them up. &lt;em&gt;Plumbing commands&lt;/em&gt; are the low-level commands, &lt;em&gt;porcelain commands&lt;/em&gt; are the more user-friendly commands. At this stage, I do not think I need to be super familiar with plumbing commands, although I did click around in a &lt;code&gt;.git&lt;/code&gt; folder out of curiosity.&lt;/p&gt;
&lt;h2 id=&#34;removing-objects&#34;&gt;Removing objects&lt;/h2&gt;
&lt;p&gt;There is a section in the &amp;ldquo;Git internals&amp;rdquo; chapter called &amp;ldquo;Removing objects&amp;rdquo;. I might come back to it if I ever need to do that&amp;hellip; Or I&amp;rsquo;d use &lt;a href=&#34;https://github.com/tj/git-extras/blob/main/Commands.md#git-obliterate&#34;&gt;git obliterate from the git-extras utilities&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Pro Git was a good read, although I do wish I had bought the second edition. I probably missed good stuff because of this! My next (and last?) Git book purchase will be &lt;a href=&#34;https://jvns.ca/blog/2023/12/31/2023--year-in-review/#moving-slowly-is-okay&#34;&gt;Julia Evans&amp;rsquo; new Git zine&lt;/a&gt; when it&amp;rsquo;s finished. I can&amp;rsquo;t wait!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Introducing saperlipopette, a package to practice Git!</title>
      <link>https://masalmon.eu/2024/01/18/saperlipopette-package-practice-git/</link>
      <pubDate>Thu, 18 Jan 2024 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2024/01/18/saperlipopette-package-practice-git/</guid>
      <description>&lt;p&gt;I got more confident with Git since reading &lt;a href=&#34;https://masalmon.eu/2023/11/01/reading-notes-git-in-practice/&#34;&gt;Git in practice&lt;/a&gt;. This has resulted in a more enjoyable Git practice! I&amp;rsquo;m also more keen to sharing Git &amp;ldquo;tips&amp;rdquo; with others, but felt it was challenging to quickly come up with examples to demo some Git workflows. This is what motivated my creating saperlipopette, an R package containing small Git playgrounds to practice various Git commands and strategies!&lt;/p&gt;
&lt;h2 id=&#34;what-is-saperlipopette&#34;&gt;What is saperlipopette?&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/&#34;&gt;saperlipopette&lt;/a&gt; package creates Git messes, or playgrounds, that users need to solve. Part of the &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/index.html&#34;&gt;exercises&lt;/a&gt; are inspired by the wonderful website &lt;a href=&#34;https://ohshitgit.com/&#34;&gt;Oh Shit, Git!?!&lt;/a&gt; by Katie Sylor-Miller; others reflect commands that I&amp;rsquo;ve enjoyed using&amp;hellip; or that I&amp;rsquo;d like to use one day, like git bisect, so the list is partly aspirational!&lt;/p&gt;
&lt;p&gt;While saperlipopette itself makes good use of the &lt;a href=&#34;https://docs.ropensci.org/gert/&#34;&gt;gert&lt;/a&gt; package under the hood, the users can solve the Git messes any way they like, be it with some sort of Git interface, the command line, etc. The package provides no checking of solutions. You get a new folder with a Git mess inside, some tips, and you are the one defining success at the end of one try, by looking at your Git history. Because re-creating an exercise folder only demands your running a function, you can re-create the exercise as needed.&lt;/p&gt;
&lt;h2 id=&#34;why-this-name&#34;&gt;Why this name?&lt;/h2&gt;
&lt;p&gt;This package is intended to be a companion to &lt;a href=&#34;https://ohshitgit.com/&#34;&gt;https://ohshitgit.com/&lt;/a&gt;, so its name had to honour the exclamation. &amp;ldquo;saperlipopette&amp;rdquo; is an &lt;a href=&#34;https://en.wiktionary.org/wiki/saperlipopette&#34;&gt;old-fashioned French exclamation&lt;/a&gt;. You can say &amp;ldquo;Saperlipopette, Git!&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;how-to-use-saperlipopette&#34;&gt;How to use saperlipopette?&lt;/h2&gt;
&lt;h3 id=&#34;setup&#34;&gt;Setup&lt;/h3&gt;
&lt;p&gt;You can install the development version of saperlipopette like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;pak&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pak&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropensci-training/saperlipopette&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You&amp;rsquo;ll also need&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;a href=&#34;https://happygitwithr.com/install-git&#34;&gt;Git installation&lt;/a&gt;, but if you made it here you probably already use Git at least a bit.&lt;/li&gt;
&lt;li&gt;basic Git knowledge, in particular being able to examine the Git history, be it with &lt;a href=&#34;https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History&#34;&gt;git log&lt;/a&gt; or a tool in your IDE.&lt;/li&gt;
&lt;li&gt;a directory where to store the exercises folder. In all examples we use a temporary directory but if you prefer, you could use a dedicated &amp;ldquo;scratch directory&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;basic-example&#34;&gt;Basic example&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s try the &lt;a href=&#34;https://docs.ropensci.org/saperlipopette/reference/exo_one_small_change.html&#34;&gt;&lt;code&gt;saperlipopette::exo_one_small_change()&lt;/code&gt;&lt;/a&gt; that goes with &lt;a href=&#34;https://ohshitgit.com/#change-last-commit&#34;&gt;&amp;ldquo;Oh shit, I committed and immediately realized I need to make one small change!&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;kr&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/library.html&#39;&gt;library&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/saperlipopette/&#39;&gt;&#34;saperlipopette&#34;&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;parent_path&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_tempfile.html&#39;&gt;local_tempdir&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/saperlipopette/reference/exo_one_small_change.html&#39;&gt;exo_one_small_change&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parent_path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BBBB;&#39;&gt;ℹ&lt;/span&gt; Follow along in /tmp/RtmpoAeVTm/file152cb747520d9/one-small-change!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# what&#39;s in path&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;fs&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://fs.r-lib.org/reference/dir_tree.html&#39;&gt;dir_tree&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #0000BB; font-weight: bold;&#39;&gt;/tmp/RtmpoAeVTm/file152cb747520d9/one-small-change&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; ├── &lt;span style=&#39;color: #0000BB; font-weight: bold;&#39;&gt;R&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; └── bla&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# with Git in a command line: git log&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# or the gert R package&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_log&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;# A tibble: 2 × 6&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   commit                          author time                files merge message&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;*&lt;/span&gt; &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;                           &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;  &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;dttm&amp;gt;&lt;/span&gt;              &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;int&amp;gt;&lt;/span&gt; &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;lgl&amp;gt;&lt;/span&gt; &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;1&lt;/span&gt; 2ff0d31f566e68ae0ee94b6028a3fa… Jane … 2023-12-15 &lt;span style=&#39;color: #555555;&#39;&gt;16:25:00&lt;/span&gt;     1 FALSE &lt;span style=&#39;color: #555555;&#39;&gt;&#34;&lt;/span&gt;feat:…&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;2&lt;/span&gt; e227ecc55e421f70b6e30602e6a2ee… Jane … 2023-12-15 &lt;span style=&#39;color: #555555;&#39;&gt;16:25:00&lt;/span&gt;     2 FALSE &lt;span style=&#39;color: #555555;&#39;&gt;&#34;&lt;/span&gt;First…&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;At this stage, the user would open the newly created R project and launch an R session, where messages would indicate them what to do, and which URL to follow, to find the corresponding ohshitgit entry if relevant. In practice here the user would change a file, then Git add it, then run &lt;code&gt;git commit --amend --no-edit&lt;/code&gt;. The user would examine the &lt;a href=&#34;https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History&#34;&gt;Git history&lt;/a&gt; before and after this.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #BB0000;&#39;&gt;✖&lt;/span&gt; &#34;Oh shit, I committed and immediately realized I need to make one small change!&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #BB0000;&#39;&gt;✖&lt;/span&gt; I wanted to list 3 things in my bla file, not only two!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BBBB;&#39;&gt;ℹ&lt;/span&gt; See &lt;span style=&#39;color: #0000BB; font-style: italic;&#39;&gt;&amp;lt;https://ohshitgit.com/#change-last-commit&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BBBB;&#39;&gt;ℹ&lt;/span&gt; For more help use `tip()`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If they need more instructions than what is initially provided, the user can run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;tip&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; • Add &#39;thing 3&#39; to the &lt;span style=&#39;color: #0000BB;&#39;&gt;bla&lt;/span&gt; file and save it.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; • Add &#39;bla&#39; file to Git.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; • `git commit --amend --no-edit`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; • Examine Git history.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That interface relies on adding an (.gitignored!) &lt;code&gt;.Rprofile&lt;/code&gt; to the newly created project, with instructions formatted with the &lt;a href=&#34;https://blog.r-hub.io/2023/11/30/cliff-notes-about-cli/&#34;&gt;cli package&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve set the Git author, committer and date so that the automatic commits get the same hashes, which could be useful when teaching a group: everyone should be looking at the same hashes on their machine, except for those commits they create themselves.&lt;/p&gt;
&lt;h2 id=&#34;feedback-welcome&#34;&gt;Feedback welcome!&lt;/h2&gt;
&lt;p&gt;In this post I introduced the saperlipopette package whose aim is to help users practice their Git skills in a safe (because throw-away) environment! I am very grateful to Jim Gardner for &lt;a href=&#34;https://github.com/ropensci-training/saperlipopette/issues/9&#34;&gt;useful feedback&lt;/a&gt; and would love to &lt;a href=&#34;https://github.com/maelle/ropensci-training/issues&#34;&gt;hear&lt;/a&gt; from more users, if saperlipopette is of any interest to you.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Reading notes on The Pragmatic Programmer by David Thomas and Andrew Hunt</title>
      <link>https://masalmon.eu/2023/12/11/reading-notes-pragmatic-programmer/</link>
      <pubDate>Mon, 11 Dec 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/12/11/reading-notes-pragmatic-programmer/</guid>
      <description>&lt;p&gt;In my quest to having reading notes on the tech books I read, and while waiting for code to run, I recently re-read &lt;a href=&#34;https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/&#34;&gt;The Pragmatic Programmer&lt;/a&gt; by David Thomas and Andrew Hunt. That book, whose second edition was published in 2019, offers an overview of many topics useful to programmers, from the idea of taking responsability, to testing, tooling, etc.&lt;/p&gt;
&lt;h2 id=&#34;not-my-favorite-tone&#34;&gt;Not my favorite tone&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m not the biggest fan of the tone used in the book, that feels a bit patronizing to me. One example that comes to mind is that the authors recommend reading non-tech books to learn about humans, because programming is also about humans. That&amp;rsquo;s not a piece of advice I&amp;rsquo;d give, even as a book lover, because one can learn about humans outside of books (not exactly breaking news, I know), and also because I&amp;rsquo;d like reading non-tech books to be a thing one can do for enjoyment unrelated to work.&lt;/p&gt;
&lt;p&gt;I also disliked analogies that I found uselessly violent: car crashes, train wrecks, boiling frogs, not to forget &lt;a href=&#34;https://en.wikipedia.org/wiki/Broken_windows_theory#Criticism&#34;&gt;broken windows&lt;/a&gt;. There&amp;rsquo;s enough violence in the world, so I prefer further violence to inhabit my non-tech reading rather than my tech reading. 😉&lt;/p&gt;
&lt;p&gt;Now, to each their own, and I can imagine such writing being enjoyable to others.&lt;/p&gt;
&lt;h2 id=&#34;an-impressive-overview&#34;&gt;An impressive overview&lt;/h2&gt;
&lt;p&gt;The Pragmatic Programmer is rather famous. I can see why when I think about its table of contents: even if the book would not be my first recommendation for any topic it covers, it&amp;rsquo;s the only one I know that covers so many topics: version control, testing, domain-specific languages, orthogonality, decoupling, etc. Seen this way, it&amp;rsquo;s quite unique and precious.&lt;/p&gt;
&lt;p&gt;Furthermore, I can imagine productive book clubs using the questions in the book.&lt;/p&gt;
&lt;h2 id=&#34;what-value-for-me-pieces-of-wisdom-and-catchy-phrases&#34;&gt;What value for me? Pieces of wisdom and catchy phrases&lt;/h2&gt;
&lt;p&gt;I did not read The Pragmatic Programmer as an absolute beginner, so I had at least vaguely heard of many (not all!) elements in the book. However, I find some value in being exposed to concepts I didn&amp;rsquo;t know, seeing new explanations or catchy descriptions for those I was more familiar with, and thinking differently about current work projects (the two latter aspects are often the value I find in so-called &amp;ldquo;productivity books&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;For most of the notes below I&amp;rsquo;m adding links to more or less related things, which would probably make me an annoying participant of a book club about The Pragmatic Programmer. Luckily this is my blog. 😇&lt;/p&gt;
&lt;h3 id=&#34;etc&#34;&gt;ETC&lt;/h3&gt;
&lt;p&gt;The authors introduced the ETC value, as in &amp;ldquo;Easy to Change&amp;rdquo;. That made me think of &lt;a href=&#34;https://masalmon.eu/2023/10/19/reading-notes-philosophy-software-design/#complexity-in-software&#34;&gt;&amp;ldquo;A Philosophy of Software Design&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;forgo-following-fads&#34;&gt;&amp;ldquo;Forgo following fads&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;That nice alliteration reminded me of &lt;a href=&#34;https://masalmon.eu/2023/11/20/reading-notes-kill-it-with-fire-marianne-bellotti/&#34;&gt;&amp;ldquo;Kill it with fire&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;reversibility&#34;&gt;Reversibility&lt;/h3&gt;
&lt;p&gt;The paragraphs on reversibility, i.e. flexible architectures, make me feel like sharing this excellent blog post by Vicki Boykis: &lt;a href=&#34;https://vickiboykis.com/2019/02/10/commit-to-your-lock-in/&#34;&gt;&amp;ldquo;Commit to your lock-in&amp;rdquo;&lt;/a&gt; that I often think about, and that&amp;rsquo;s sort of about not thinking too much about reversibility. 😅&lt;/p&gt;
&lt;h3 id=&#34;encouragement-to-learn-more-about-the-shell&#34;&gt;Encouragement to learn more about the shell&lt;/h3&gt;
&lt;p&gt;I should learn more shell commands. Incidentally, after reading about that in the book, I had to add a &lt;a href=&#34;https://ropensci.org/blog/2021/09/13/system-calls-r-package/&#34;&gt;&lt;code&gt;system2()&lt;/code&gt;&lt;/a&gt; command to a script of mine.&lt;/p&gt;
&lt;h3 id=&#34;achieve-editor-fluency&#34;&gt;&amp;ldquo;Achieve Editor Fluency&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;Also a good piece of advice. Have you read Nick Tierney&amp;rsquo;s great post &lt;a href=&#34;https://www.njtierney.com/post/2023/12/04/get-good-type-fast/&#34;&gt;&amp;ldquo;Get Good with R: Typing Skills and Shortcuts&amp;rdquo;&lt;/a&gt;? On the other hand I&amp;rsquo;m also reminded me of the video &lt;a href=&#34;https://www.youtube.com/watch?v=dIjKJjzRX_E&#34;&gt;&amp;ldquo;What editor do you use&amp;rdquo;&lt;/a&gt;? 😁&lt;/p&gt;
&lt;h3 id=&#34;engineering-daybook&#34;&gt;Engineering daybook&lt;/h3&gt;
&lt;p&gt;The authors encourage the practice of writing down things you learn, challenges, every day. I most often have a piece of paper near me, including my sticky note for my posts about &lt;a href=&#34;https://masalmon.eu/tags/useful-functions/&#34;&gt;useful functions&lt;/a&gt;, but haven&amp;rsquo;t been able to really stick to maintaining an engineering daybook. Since I work from home I don&amp;rsquo;t observe many people at work, so have to resort to tech books to imagine people working 😉, and know that the protagonist of &lt;a href=&#34;https://itrevolution.com/product/the-unicorn-project/&#34;&gt;The Unicorn Project&lt;/a&gt; maintains one.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h3 id=&#34;act-locally&#34;&gt;&amp;ldquo;Act locally&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;The occasion for me to spread the word about the existence of the fantastic &lt;a href=&#34;https://withr.r-lib.org/&#34;&gt;withr package&lt;/a&gt; for locally changing options, environment variables, languages, etc.; for instance in examples and tests.&lt;/p&gt;
&lt;h3 id=&#34;property-based-testing&#34;&gt;Property-based testing&lt;/h3&gt;
&lt;p&gt;Do you know about Mark Padgham&amp;rsquo;s &lt;a href=&#34;https://docs.ropensci.org/autotest/&#34;&gt;autotest package&lt;/a&gt;? Using it would allow one to try out property-based testing in one&amp;rsquo;s package, by feeding random input into functions. The book says one is often surprised by the results of property-based testing. 😅&lt;/p&gt;
&lt;h3 id=&#34;build-a-test-window&#34;&gt;&amp;ldquo;Build a Test Window&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;I remember similar advice in Jenny Bryan&amp;rsquo;s fantastic talk &lt;a href=&#34;https://www.youtube.com/watch?v=vgYS-F8opgE&#34;&gt;&amp;ldquo;Object of type &amp;lsquo;closure&amp;rsquo; is not subsettable&amp;rdquo;&lt;/a&gt; (&lt;a href=&#34;https://speakerdeck.com/jennybc/object-of-type-closure-is-not-subsettable?slide=77&#34;&gt;slide 77&lt;/a&gt;).&lt;/p&gt;
&lt;h3 id=&#34;delight-your-users&#34;&gt;&amp;ldquo;Delight your Users&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;The link I&amp;rsquo;ll throw here is François Chollet&amp;rsquo;s post &lt;a href=&#34;https://blog.keras.io/user-experience-design-for-apis.html&#34;&gt;&amp;ldquo;User experience design for APIs&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;a-last-part-on-ethics&#34;&gt;A last part on ethics&lt;/h3&gt;
&lt;p&gt;The book&amp;rsquo;s second edition ends with some thoughts on responsability, with the tip &amp;ldquo;Don&amp;rsquo;t enable scumbags&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I have ambivalent thoughts about The Pragmatic Programmer: it&amp;rsquo;s an extensive reference for programmers, but not my favorite tech book. Have you read it? Do you know other similar reference books? Are you planning to write one and do you need readers of advanced copies? 😸&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Have you ever read riveting kid books about some little character &amp;ldquo;who don&amp;rsquo;t want to share&amp;rdquo;, &amp;ldquo;who bakes a cake&amp;rdquo;, or &amp;ldquo;who discovers daycare&amp;rdquo;? The Unicorn Project, and The Phoenix Project are similar books, but for adults working with tech. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>The two phases of commits in a Git branch</title>
      <link>https://masalmon.eu/2023/12/07/two-phases-git-branches/</link>
      <pubDate>Thu, 07 Dec 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/12/07/two-phases-git-branches/</guid>
      <description>&lt;p&gt;I seem to have at last entered my Git era. 🎉 Reading and applying &lt;a href=&#34;https://masalmon.eu/2023/11/01/reading-notes-git-in-practice/&#34;&gt;Git in practice&lt;/a&gt; was probably the best thing I did for my upskilling this year. One Git workflow aspect I&amp;rsquo;ve finally realized is that it&amp;rsquo;s fine to have two phases of work in a Git branch. I&amp;rsquo;ll explain it in this post.&lt;/p&gt;
&lt;h2 id=&#34;set-up-create-a-branch-for-your-work&#34;&gt;Set up: create a branch for your work!&lt;/h2&gt;
&lt;p&gt;Ideally, in most cases, when adding a feature or fixing a bug or whatever, I&amp;rsquo;ll work in a branch.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_branch.html&#39;&gt;git_branch_create&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;feature&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I really like running the code above as I feel it puts me in the right mind space. I signal my intention to work on a given issue to the universe, it can&amp;rsquo;t hurt, right. 😁&lt;/p&gt;
&lt;h2 id=&#34;phase-1-do-not-think-about-a-clean-git-history-nor-your-reputation-just-commit-all-the-time&#34;&gt;Phase 1: do not think about a clean Git history nor your reputation, just commit all the time&lt;/h2&gt;
&lt;p&gt;Now, even if I might already open a &lt;strong&gt;draft&lt;/strong&gt; PR to signal my working on a given thing, I just do the thing and try to not think about looking stupid with 1,000 commits &amp;ldquo;try to make R CMD check happy&amp;rdquo;. I absolutely do not want to lose my work so I commit (with RStudio IDE tab) and push (with &lt;a href=&#34;https://docs.ropensci.org/gert/reference/git_fetch.html&#34;&gt;&lt;code&gt;gert::git_push()&lt;/code&gt;&lt;/a&gt; or that same tab) regularly. In this phase, Git is merely my backup.&lt;/p&gt;
&lt;h2 id=&#34;phase-2-clean-up&#34;&gt;Phase 2: clean up!&lt;/h2&gt;
&lt;p&gt;That&amp;rsquo;s the phase I used to never do&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; but that I&amp;rsquo;m trying to consciously practice. I guess blogging about this will force me to keep doing it.&lt;/p&gt;
&lt;p&gt;In the comments of my &lt;a href=&#34;https://masalmon.eu/2023/11/01/reading-notes-git-in-practice/&#34;&gt;reading notes on Git in practice&lt;/a&gt;, one of my Git models, &lt;a href=&#34;https://github.com/Bisaloo&#34;&gt;Hugo Gruson&lt;/a&gt;&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, recommended the post &lt;a href=&#34;https://github.blog/2022-06-30-write-better-commits-build-better-projects/&#34;&gt;&amp;ldquo;Write Better Commits, Build Better Projects&amp;rdquo;&lt;/a&gt;. The kind of posts I used to think were for other people since I did not understand half of the Git words in it. 😉 (Have I mentioned reading a Git book was life-changing? 😅)&lt;/p&gt;
&lt;p&gt;Basically once you have your PR code ready, you have to try and create nice commits, in a nice order. It&amp;rsquo;s important both for the people that will have to review your code (which might even be just you in a few days for lack of collaborators), and for the people who might have to perform a &lt;code&gt;Git bisect&lt;/code&gt;-ion or some other form of archeology on the code base later (again, this might be you).&lt;/p&gt;
&lt;p&gt;Part of the work is thinking about what a good set of commits might be.&lt;/p&gt;
&lt;p&gt;Then in practice I&amp;rsquo;ll use&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Git rebase -i&lt;/code&gt; to squash, reorder or even drop commits and to improve commit messages;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Git reset --soft&lt;/code&gt; to remove changes from the Git history but not from the files, and then commit them incrementally in a smarter way than when I was in phase 1.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Git push -f&lt;/code&gt; which is fine since my branch is mine only until I mark the PR as ready to review. 😈&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I explained how I now think as work in a branch as happening in two phases, one phase where Git is my backup, and one phase where I try to think more about code reviewers (for the PR) and code archeologists (for later when the PR is merged). I&amp;rsquo;m still very much learning so don&amp;rsquo;t think you&amp;rsquo;ll get perfect PRs from me just yet!&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;And I was so embarrassed when a PR of mine was merged without being squashed. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;If you&amp;rsquo;ve ever reviewed a PR by Hugo you have to know what I mean! Such good story-telling in commits! &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Reading notes on Kill It with Fire by Marianne Bellotti</title>
      <link>https://masalmon.eu/2023/11/20/reading-notes-kill-it-with-fire-marianne-bellotti/</link>
      <pubDate>Mon, 20 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/11/20/reading-notes-kill-it-with-fire-marianne-bellotti/</guid>
      <description>&lt;p&gt;Another month, another long train trip enjoyed in the company of great books, among which a work-related one, &lt;a href=&#34;https://nostarch.com/kill-it-fire&#34;&gt;Kill it with fire by Marianne Bellotti&lt;/a&gt;. As indicated by its subtitle &amp;ldquo;Manage Aging Computer Systems (and Future Proof Modern Ones)&amp;rdquo;, the book deals with handling legacy computer systems. The focus is on bigger projects (including serious internal politics) than what I usually deal with, but there&amp;rsquo;s some valuable lessons for any project size in there.&lt;/p&gt;
&lt;p&gt;It was actually my second reading of the book, since I regretted not having taken notes the first time around! Some aspects had already stuck with me though.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s dive into some highlights&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;dealing-with-legacy-code-is-a-honour&#34;&gt;Dealing with legacy code is a honour&lt;/h2&gt;
&lt;p&gt;The number one thing I got out of this book is an enhanced appreciation for having to work with legacy codebases. I did not start out hating them, but still, I&amp;rsquo;m glad to now be able to refer to these two quotes for instance (although I do not work with &lt;em&gt;very&lt;/em&gt; old code!):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;legacy technology exists only if it is successful. These old programs are perhaps less efficient than they were before, but technology that isn&amp;rsquo;t used doesn&amp;rsquo;t survive decades.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;To most software engineers, legacy systems may seem like torturous dead-end work, but the reality is systems that are not used get turned off.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;why-are-older-systems-bad&#34;&gt;Why are older systems bad&lt;/h2&gt;
&lt;p&gt;Chapter 3 (&amp;ldquo;Evaluating Your Architecture&amp;rdquo;) Marianne Bellotti explains three kinds of issues that might be the reason a modernization is wished for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;tech debt&lt;/strong&gt;. It reminded me, among other things, of John Ousterhout&amp;rsquo;s &lt;a href=&#34;https://masalmon.eu/2023/10/19/reading-notes-philosophy-software-design/#tactical-vs-strategic-programming&#34;&gt;&amp;ldquo;tactical vs strategic programming&amp;rdquo;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;performance issues&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;stability issues&lt;/strong&gt; (surprising failures, due to tight coupling and/or complexity).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In Chapter 10 (&amp;ldquo;Future Proofing&amp;rdquo;) the author mentions two ways in which systems age:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;change of usage patterns&lt;/strong&gt; (scale);&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;resources that back them&lt;/strong&gt; deteriorate.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s the chapter where the idea of &lt;strong&gt;legacy modernization being an anti-pattern&lt;/strong&gt; is presented: if you maintain your system well over time, you won&amp;rsquo;t need a special operation. 😅&lt;/p&gt;
&lt;h2 id=&#34;how-people-adopt-new-software&#34;&gt;How people adopt new software&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s a lot of content about how technology gets adopted or not, including these two nuggets of wisdom:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;familiar interfaces help speed up adoption&amp;rdquo; (it reminded me of Quarto vs R Markdown);&lt;/li&gt;
&lt;li&gt;&amp;ldquo;people gain awareness of interfaces and technology through their networks, not necessarily by popularity&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The latter is not the only time that the book underlines human aspects of computer systems, far from it.&lt;/p&gt;
&lt;h2 id=&#34;lessons-for-planning-modernization-efforts&#34;&gt;Lessons for planning modernization efforts&lt;/h2&gt;
&lt;p&gt;Obviously the book is full of lessons about planning modernization efforts, but here are three of them:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;ldquo;Migrating for Value, Not for Trends&amp;rdquo;&lt;/strong&gt;. Don&amp;rsquo;t go for the next new shiny thing, pragmatically assess whether it&amp;rsquo;ll be best for the system (or just best for bragging about it to your peers 😅 See the next section of this post!)&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s important to first learn how to &lt;strong&gt;understand&lt;/strong&gt;, &lt;strong&gt;test&lt;/strong&gt; (what does not fail?), &lt;strong&gt;monitor&lt;/strong&gt; (what fails?) the codebase before one makes big changes to it.&lt;/p&gt;
&lt;p&gt;The book includes many tips on &lt;strong&gt;how to build and keep momentum of a team or organization&lt;/strong&gt; during a modernization effort (the whole chapter 5, &amp;ldquo;Building and Protecting Momentum&amp;rdquo;), as well as how to keep one&amp;rsquo;s own motivation (marking time, or I guess more generally tracking progress).&lt;/p&gt;
&lt;h2 id=&#34;the-workplacecareer-related-aspects-of-code&#34;&gt;The workplace/career related aspects of code&lt;/h2&gt;
&lt;p&gt;At several points, Marianne Bellotti underlines how the atmosphere at an organization will influence its code. For instance if there&amp;rsquo;s no well-defined career ladder at an organization, maybe people will make choices to get recognition from their peers outside of it, for instance by being the first to try out tool X for some application.&lt;/p&gt;
&lt;p&gt;This quote would pair well with some more reading on psychological safety and the like, as that&amp;rsquo;s what it made me think of:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Good technologists should focus on what brings the most benefit and highest probability of success to the table at the current moment, with the confidence of knowing they have nothing to prove.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There&amp;rsquo;s also a few pages on how people get seen, and how that influences what gets built.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&#34;use-the-codebase-and-its-context-but-not-too-much&#34;&gt;Use the codebase and its context but not too much&lt;/h2&gt;
&lt;p&gt;In my own words,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Retrieve context as much as possible.&lt;/li&gt;
&lt;li&gt;Think of the tools available at the time the system was created as that might you help understand some constraints.&lt;/li&gt;
&lt;li&gt;Respect that the system is working (otherwise it wouldn&amp;rsquo;t be used any more).&lt;/li&gt;
&lt;li&gt;However don&amp;rsquo;t make the mistake of assuming all decisions were good ones.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-tools-are-not-the-most-important-thing&#34;&gt;The tools are not the most important thing&lt;/h2&gt;
&lt;p&gt;Marianne Bellotti encourages the reader to be realistic about what automatic tools (for instance for traducing code from one language to another) will give you.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;The tools themselves are not as important as the phases of excavating, understanding, documenting, and ultimately rewriting and replacing legacy systems. Tools will come and go.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;turn-things-off-and-see-what-happens&#34;&gt;Turn things off and see what happens&lt;/h2&gt;
&lt;p&gt;I love this idea, apparently called &amp;ldquo;chaos testing&amp;rdquo;, for when someone encounters a thing one isn&amp;rsquo;t sure is used at all or where. You turn it off and wait for someone to complain. It&amp;rsquo;s in a book so it&amp;rsquo;s a legit strategy. 😸&lt;/p&gt;
&lt;h2 id=&#34;tips-on-designing-technical-conversations&#34;&gt;Tips on designing technical conversations&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t want to reproduce what&amp;rsquo;s in the book here but just to remember there are good tips around conversations in this book with exercises such as &amp;ldquo;The Saboteur&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;breaking-changes-and-users-procrastination&#34;&gt;Breaking changes and users&amp;rsquo; procrastination&lt;/h2&gt;
&lt;p&gt;In &amp;ldquo;Communicating Failure&amp;rdquo;, in Chapter 8 (&amp;ldquo;Breaking Changes&amp;rdquo;), Marianne Bellotti explains that giving too much time to users to stop using a thing to be deprecated, just leads them to procrastinate more.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;Kill It with Fire&amp;rdquo; is a great book! I really enjoyed the pragmatism and the focus on human aspects of modernization.&lt;/p&gt;
&lt;p&gt;I might re-read it when the stories of bigger projects have more value to me than being interesting stories, that is to say, if I ever participate in bigger modernization efforts!&lt;/p&gt;
&lt;p&gt;Have you read the book? Any thoughts on it or on the general topic of modernizing old computer systems?&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;These are strong pages despite citing &lt;a href=&#34;https://en.wikipedia.org/wiki/Dan_Ariely#Manipulated_data_in_an_experiment_about_dishonesty&#34;&gt;work by Dan Ariely&lt;/a&gt;. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>The current introduction to my package development workshops</title>
      <link>https://masalmon.eu/2023/11/09/r-package-development-teaching-intro/</link>
      <pubDate>Thu, 09 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/11/09/r-package-development-teaching-intro/</guid>
      <description>&lt;p&gt;I somewhat regularly teach about package development. One recent example was a &lt;a href=&#34;https://ropensci.org/blog/2023/08/04/champions-program-training/#package-development-the-mechanicshttpsrpkgdev-mechanicsnetlifyapp&#34;&gt;workshop for rOpenSci champions&lt;/a&gt;. I am improving my teaching over time (thankfully 😅) but one thing I have down by now is the intro, which is mostly my throwing together my &lt;strong&gt;favorite quotes about R package development&lt;/strong&gt;! Let me write it up.&lt;/p&gt;
&lt;h2 id=&#34;where-i-explain-why-people-shouldnt-flee-the-workshop&#34;&gt;Where I explain why people shouldn&amp;rsquo;t flee the workshop&lt;/h2&gt;
&lt;p&gt;After boasting a bit (a.k.a. sharing my package development creds to introduce myself), I answer three retorical questions:&lt;/p&gt;
&lt;h3 id=&#34;why-develop-an-r-package&#34;&gt;Why develop an R package?&lt;/h3&gt;
&lt;p&gt;Developing an R package is the easiest way to share code/data/R Markdown templates&amp;hellip; with&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;(future) you: a package for organizing your utility functions in a smart way;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;the collaborators you know: a package for your team;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;and the collaborators you don&amp;rsquo;t: a package for the whole wide world. Without needing to be a generalist tool à la ggplot2, your package could help other R users!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;why-learn-about-package-development&#34;&gt;Why learn about package development?&lt;/h3&gt;
&lt;p&gt;This is a different question! I love &lt;a href=&#34;https://joncalder.co.za/&#34;&gt;Jon Calder&lt;/a&gt;&amp;rsquo;s &lt;a href=&#34;https://github.com/iandurbach/datasci-fi/tree/master/docs/packages/slides&#34;&gt;wording about this&lt;/a&gt;. You should learn about package development&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;- To share code (and data)&amp;quot;;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which is learning about package development to develop your packages.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;- To leverage existing tooling&amp;rdquo;;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which could be learning about package development for using part of the infrastructure, like the one for testing, in your own projects.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;- To contribute to other packages&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which is learning about package development to improve packages owned by other people (in my words, being a package aunt/babysitter).&lt;/p&gt;
&lt;p&gt;So you don&amp;rsquo;t need to even have an idea or need for your own R package for that learning to be relevant.&lt;/p&gt;
&lt;h3 id=&#34;who-can-learn-about-package-development&#34;&gt;Who can learn about package development?&lt;/h3&gt;
&lt;p&gt;To answer this question I use the &lt;a href=&#34;https://github.com/susjoh/fibonacci&#34;&gt;wise words&lt;/a&gt; of &lt;a href=&#34;https://github.com/susjoh&#34;&gt;Susan Johnston&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;- Can you open R or RStudio?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;- Can you install a package?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;- Have you ever written a function in R?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;- Could you learn how to write a function in R?&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;➡️ You can write a package in R!&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&#34;side-note-where-to-learn-about-functions&#34;&gt;Side-note: where to learn about functions&lt;/h4&gt;
&lt;p&gt;Knowing vaguely what a function is a pre-requisite when I teach package development (the example functions I use are nothing fancy) but I&amp;rsquo;ve collated links for those who want to learn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/rladies-eastlansing/2021-rfunctions#writing-r-functions&#34;&gt;Materials from Stephanie Kirmer&amp;rsquo;s R-Ladies East Lansing tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://stat545.com/functions-part1.html&#34;&gt;Write your own R functions&lt;/a&gt;, stat 545 course by Jenny Bryan and The STAT 545 TAs;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://r4ds.hadley.nz/functions&#34;&gt;Chapter about functions&lt;/a&gt; in the book &amp;ldquo;R for Data Science&amp;rdquo; by Hadley Wickham, Mine Çetinkaya-Rundel, and Garrett Grolemund;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://zealous-wiles-e22e83.netlify.app/talk/funwithfunctions/&#34;&gt;Fun with Functions talk&lt;/a&gt; by Kaylea Haynes, R-Ladies Manchester.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;where-i-go-more-into-details-about-packages&#34;&gt;Where I go more into details about packages&lt;/h2&gt;
&lt;h3 id=&#34;what-is-a-package&#34;&gt;What is a package?&lt;/h3&gt;
&lt;p&gt;The author of this excellent quote (first reproduced in French) is &lt;a href=&#34;https://thinkr.fr/transformer-plusieurs-scripts-eparpilles-en-beau-package-r&#34;&gt;Sébastien Rochette&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Pour réduire ses craintes, il faut se dire que ce n&amp;rsquo;est ni plus ni moins qu&amp;rsquo;un dossier organisé d&amp;rsquo;une manière contrainte.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;To be less afraid you have to tell yourself that it&amp;rsquo;s simply a folder organized in a constrained way.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;At this point what could remain scary is, how do I remember about these constraints and rules? So here comes&amp;hellip;&lt;/p&gt;
&lt;h3 id=&#34;automation&#34;&gt;Automation!&lt;/h3&gt;
&lt;p&gt;At this point I introduce &lt;a href=&#34;https://usethis.r-lib.org/&#34;&gt;usethis&lt;/a&gt; as an &amp;ldquo;actually useful Clippy&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t necessarily use, but think of, this great &lt;a href=&#34;https://twitter.com/JennyBryan/status/935562495816753153&#34;&gt;quote&lt;/a&gt; of &lt;a href=&#34;https://github.com/jennybc&#34;&gt;Jenny Bryan&lt;/a&gt;&amp;rsquo;s:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;The usethis package implements this important principle: Automate that which can be automated. Your computer was literally born to implement rote-but-fussy stuff for you.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;why-automate&#34;&gt;Why automate?&lt;/h3&gt;
&lt;p&gt;Even in the intro I like to underline that automating package development tasks is useful not only for the regular work of package development, but also for teaching (😉) and for reproducing problems.&lt;/p&gt;
&lt;h3 id=&#34;goals-of-a-beginner-workshop&#34;&gt;Goals of a beginner workshop&lt;/h3&gt;
&lt;p&gt;At least the latest one I taught had two goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;For the learners to get to know the tools for package development that I use myself;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For the learners to learn that there is no magic, only practice and ✨ tips ✨.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I wrote up the intro that I&amp;rsquo;ve now used a few times for my package development teaching. If you&amp;rsquo;re curious, to conclude such workshops I list what I think is actually difficult: writing good code, writing a good interface, writing good docs. But even that can be learnt (still learning myself 💪). In my teaching materials I share a list of &lt;a href=&#34;https://rpkgdev-mechanics.netlify.app/resources/&#34;&gt;resources&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Useful functions for dealing with object names</title>
      <link>https://masalmon.eu/2023/11/06/functions-dealing-with-names/</link>
      <pubDate>Mon, 06 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/11/06/functions-dealing-with-names/</guid>
      <description>&lt;p&gt;My sticky note filled up quickly after I only added &lt;a href=&#34;https://rdrr.io/r/stats/setNames.html&#34;&gt;&lt;code&gt;setNames()&lt;/code&gt;&lt;/a&gt; on it, with related functions for dealing with object names, in base R and beyond!&lt;/p&gt;
&lt;h2 id=&#34;unsetting-object-names-statssetnames-unname-and-rlangset_names&#34;&gt;(Un)Setting object names: &lt;code&gt;stats::setNames()&lt;/code&gt;, &lt;code&gt;unname()&lt;/code&gt; and &lt;code&gt;rlang::set_names()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I noticed a function ending with something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;blop&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;c&#39;&gt;# code creating the df data.frame&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;c&#39;&gt;# ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/names.html&#39;&gt;names&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;df&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;col1&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;col2&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;df&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It struck me as simplifiable by:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;blop&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;c&#39;&gt;# code creating the df data.frame&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;c&#39;&gt;# ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;stats&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/stats/setNames.html&#39;&gt;setNames&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;df&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;col1&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;col2&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Interestingly the docs for &lt;a href=&#34;https://rdrr.io/r/stats/setNames.html&#34;&gt;&lt;code&gt;setNames()&lt;/code&gt;&lt;/a&gt; sound as if it were created just for this use case!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;This is a convenience function that sets the names on an object and returns the object. It is most useful at the end of a function definition where one is creating the object to be returned and would prefer not to store it under a name just so the names can be assigned.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For the opposite operation, removing the names of an object, we can use &lt;a href=&#34;https://rdrr.io/r/base/unname.html&#34;&gt;&lt;code&gt;unname()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unsurprisingly, the rlang package has its own special &lt;a href=&#34;https://rlang.r-lib.org/reference/set_names.html&#34;&gt;&lt;code&gt;rlang::set_names()&lt;/code&gt;&lt;/a&gt;, that is more or less a &lt;a href=&#34;https://rdrr.io/r/stats/setNames.html&#34;&gt;&lt;code&gt;stats::setNames()&lt;/code&gt;&lt;/a&gt; + &lt;a href=&#34;https://rdrr.io/r/base/unname.html&#34;&gt;&lt;code&gt;unname()&lt;/code&gt;&lt;/a&gt; + generic &lt;a href=&#34;https://sfirke.github.io/janitor/reference/clean_names.html&#34;&gt;&lt;code&gt;janitor::clean_names()&lt;/code&gt;&lt;/a&gt; combo!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;df&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/data.frame.html&#39;&gt;data.frame&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;5&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;7&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   c.1..2. c.5..7.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1       1       5&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 2       2       7&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/set_names.html&#39;&gt;set_names&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;df&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;a&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;b&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;c&#39;&gt;# sets names!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   a b&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 1 5&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 2 2 7&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/set_names.html&#39;&gt;set_names&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;df&lt;/span&gt;, &lt;span class=&#39;kc&#39;&gt;NULL&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;c&#39;&gt;# removes names&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;      &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 1 5&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 2 2 7&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;df2&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/set_names.html&#39;&gt;set_names&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;df&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;SHOUTING&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;LOUDLY&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;df2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   SHOUTING LOUDLY&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1        1      5&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 2        2      7&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/set_names.html&#39;&gt;set_names&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;df2&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;tolower&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;c&#39;&gt;# using a function to transform names&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   shouting loudly&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1        1      5&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 2        2      7&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Of note,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;&lt;code&gt;set_names()&lt;/code&gt; is stable and exported in purrr&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So if you prefer, you can use &lt;a href=&#34;https://rlang.r-lib.org/reference/set_names.html&#34;&gt;&lt;code&gt;purrr::set_names()&lt;/code&gt;&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;Last but not least, despite the examples above being on a data.frame, these functions can be used on lists, vectors&amp;hellip;&lt;/p&gt;
&lt;h2 id=&#34;extracting-names-names-rlangnames2&#34;&gt;Extracting names: &lt;code&gt;names()&lt;/code&gt;, &lt;code&gt;rlang::names2()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://rdrr.io/r/base/names.html&#34;&gt;&lt;code&gt;names()&lt;/code&gt;&lt;/a&gt; probably doesn&amp;rsquo;t need any introduction, but it&amp;rsquo;s interesting to mention it in contrast to &lt;a href=&#34;https://rlang.r-lib.org/reference/names2.html&#34;&gt;&lt;code&gt;rlang::names2()&lt;/code&gt;&lt;/a&gt; that &amp;quot; always returns a character vector, even when an object does not have a names attribute.&amp;rdquo;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;vector&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/names.html&#39;&gt;names&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;vector&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; NULL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/names2.html&#39;&gt;names2&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;vector&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;&#34; &#34;&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;rlang also has a replacement variant, &lt;code&gt;rlang::names2&amp;lt;-&lt;/code&gt;, that &amp;ldquo;never adds NA names and instead fills unnamed vectors with &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t know all this before skimming the list of rlang functions &lt;a href=&#34;https://rlang.r-lib.org/reference/index.html#attributes&#34;&gt;dealing with object attributes&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;checking-names&#34;&gt;Checking names&lt;/h2&gt;
&lt;h3 id=&#34;is-the-object-named-rlangis_named-rlangis_named2-rlanghave_name&#34;&gt;Is the object named: &lt;code&gt;rlang::is_named()&lt;/code&gt;, &lt;code&gt;rlang::is_named2()&lt;/code&gt;, &lt;code&gt;rlang::have_name()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://rlang.r-lib.org/reference/is_named.html&#34;&gt;&lt;code&gt;rlang::have_name()&lt;/code&gt;&lt;/a&gt; is the vectorized version of &lt;code&gt;rlang::is_name()&lt;/code&gt;, not to be confused with &lt;a href=&#34;https://rlang.r-lib.org/reference/has_name.html&#34;&gt;&lt;code&gt;rlang::has_name()&lt;/code&gt;&lt;/a&gt;. 😅&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/is_named.html&#39;&gt;is_named&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;a &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/is_named.html&#39;&gt;is_named&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kc&#39;&gt;NULL&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/is_named.html&#39;&gt;is_named2&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kc&#39;&gt;NULL&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/is_named.html&#39;&gt;have_name&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;a &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;c&#39;&gt;# the example from the manual page&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1]  TRUE FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I do not know of a base R equivalent, I mean I&amp;rsquo;d find a way to express it, but not as directly. But maybe I am missing yet another base R gem!&lt;/p&gt;
&lt;h3 id=&#34;does-the-object-have-an-element-called-x-does-the-object-have-elements-called-x-y-utilshasname-rlanghas_name&#34;&gt;Does the object have an element called X, does the object have elements called X, Y: &lt;code&gt;utils::hasName()&lt;/code&gt;, &lt;code&gt;rlang::has_name()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;If you want to check that an object contains elements with certain names, you can use &lt;a href=&#34;https://rdrr.io/r/utils/hasName.html&#34;&gt;&lt;code&gt;utils::hasName()&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;expected_names&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;pof&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;blop&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;vector1&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;pof &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;, bla &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;vector2&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;pof &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;, bla &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;, blop &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;3&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;utils&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/utils/hasName.html&#39;&gt;hasName&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;vector1&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;expected_names&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1]  TRUE FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;utils&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/utils/hasName.html&#39;&gt;hasName&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;vector2&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;expected_names&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] TRUE TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The rlang package has a similar function, &lt;a href=&#34;https://rlang.r-lib.org/reference/has_name.html&#34;&gt;&lt;code&gt;rlang::has_name()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;expected_names&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;pof&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;blop&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;vector1&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;pof &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;, bla &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;vector2&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;pof &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;, bla &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;, blop &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;3&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/has_name.html&#39;&gt;has_name&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;vector1&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;expected_names&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1]  TRUE FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;rlang&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rlang.r-lib.org/reference/has_name.html&#39;&gt;has_name&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;vector2&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;expected_names&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] TRUE TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;rsquo;m honestly not sure whether there&amp;rsquo;s any difference between the utils and rlang versions, apart from the name!&lt;/p&gt;
&lt;h3 id=&#34;in-package-tests-testthatexpect_named&#34;&gt;In package tests: &lt;code&gt;testthat::expect_named()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&#34;https://testthat.r-lib.org/reference/expect_named.html&#34;&gt;&lt;code&gt;testthat::expect_named()&lt;/code&gt;&lt;/a&gt; allows you to check that an object returned by your code has the names you expect, or simply has names. You can ignore case and order based on the arguments &lt;code&gt;ignore.case&lt;/code&gt; and &lt;code&gt;ignore.order&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;object&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;tibble&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://tibble.tidyverse.org/reference/tibble.html&#39;&gt;tibble&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;a &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;, b &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;3&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;4&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;# A tibble: 2 × 2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       a     b&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;dbl&amp;gt;&lt;/span&gt; &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;dbl&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;1&lt;/span&gt;     1     3&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;2&lt;/span&gt;     2     4&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;testthat&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://testthat.r-lib.org/reference/expect_named.html&#39;&gt;expect_named&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;object&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;unnamed_object&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/unname.html&#39;&gt;unname&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;object&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;testthat&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://testthat.r-lib.org/reference/expect_named.html&#39;&gt;expect_named&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;unnamed_object&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; Error: `unnamed_object` does not have names.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;testthat&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://testthat.r-lib.org/reference/expect_named.html&#39;&gt;expect_named&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;object&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;b&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;a&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; Error: Names of `object` (&#39;a&#39;, &#39;b&#39;) don&#39;t match &#39;b&#39;, &#39;a&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;testthat&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://testthat.r-lib.org/reference/expect_named.html&#39;&gt;expect_named&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;object&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;b&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;a&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;, ignore.order &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;testthat&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://testthat.r-lib.org/reference/expect_named.html&#39;&gt;expect_named&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;object&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;A&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;B&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; Error: Names of `object` (&#39;a&#39;, &#39;b&#39;) don&#39;t match &#39;A&#39;, &#39;B&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;testthat&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://testthat.r-lib.org/reference/expect_named.html&#39;&gt;expect_named&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;object&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;A&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;B&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;, ignore.case &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you&amp;rsquo;re not used to using this expectation yet, lintr can &lt;a href=&#34;https://lintr.r-lib.org/reference/expect_named_linter.html&#34;&gt;help you a bit&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I went through functions that deals with names: &lt;a href=&#34;https://rdrr.io/r/stats/setNames.html&#34;&gt;&lt;code&gt;stats::setNames()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://rdrr.io/r/base/unname.html&#34;&gt;&lt;code&gt;unname()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://rlang.r-lib.org/reference/set_names.html&#34;&gt;&lt;code&gt;rlang::set_names()&lt;/code&gt;&lt;/a&gt; for (un)setting names (my initial motivation for this post!); &lt;a href=&#34;https://rdrr.io/r/base/names.html&#34;&gt;&lt;code&gt;names()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://rlang.r-lib.org/reference/names2.html&#34;&gt;&lt;code&gt;rlang::names2()&lt;/code&gt;&lt;/a&gt; for extracting names; &lt;a href=&#34;https://rlang.r-lib.org/reference/is_named.html&#34;&gt;&lt;code&gt;rlang::is_named()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://rlang.r-lib.org/reference/is_named.html&#34;&gt;&lt;code&gt;rlang::is_named2()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://rlang.r-lib.org/reference/is_named.html&#34;&gt;&lt;code&gt;rlang::have_name()&lt;/code&gt;&lt;/a&gt; to find out whether an object is named; &lt;a href=&#34;https://rdrr.io/r/utils/hasName.html&#34;&gt;&lt;code&gt;utils::hasName()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://rlang.r-lib.org/reference/has_name.html&#34;&gt;&lt;code&gt;rlang::has_name()&lt;/code&gt;&lt;/a&gt; to find out whether an object contains elements of a given name; &lt;a href=&#34;https://testthat.r-lib.org/reference/expect_named.html&#34;&gt;&lt;code&gt;testthat::expect_named()&lt;/code&gt;&lt;/a&gt; for testing whether an object has names, or specific names. Any other related function that comes to mind?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Reading notes on Git in Practice by Mike McQuaid</title>
      <link>https://masalmon.eu/2023/11/01/reading-notes-git-in-practice/</link>
      <pubDate>Wed, 01 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/11/01/reading-notes-git-in-practice/</guid>
      <description>&lt;p&gt;While preparing materials for teaching Git a few months ago, I re-read Suzan Baert&amp;rsquo;s excellent &lt;a href=&#34;https://suzan.rbind.io/2018/03/reflections-4-months-of-github/&#34;&gt;post about Git and GitHub&lt;/a&gt;, where she &lt;a href=&#34;https://suzan.rbind.io/2018/03/reflections-4-months-of-github/#final-thoughts&#34;&gt;mentioned&lt;/a&gt; having read &lt;a href=&#34;https://www.manning.com/books/git-in-practice&#34;&gt;&amp;ldquo;Git in Practice&amp;rdquo; by Mike McQuaid&lt;/a&gt;. I added the book to my &lt;a href=&#34;https://en.wikipedia.org/wiki/Momox&#34;&gt;Momox&lt;/a&gt; alerts, where it got available a few weeks later. The book source is on &lt;a href=&#34;https://github.com/MikeMcQuaid/GitInPractice#readme&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The book isn&amp;rsquo;t too heavy, so I took it with me on a long train journey! 🚋&lt;/p&gt;
&lt;p&gt;Here are my reading notes, since I hope this habit of writing book learnings will stick. These notes are of limited generalizability, depending on what your own Git practice and knowledge are. Some chapter numbers are missing: they are those that were less relevant to me.&lt;/p&gt;
&lt;h2 id=&#34;first-impressions&#34;&gt;First impressions&lt;/h2&gt;
&lt;h3 id=&#34;manning-publications-book-cover&#34;&gt;Manning Publications book cover&lt;/h3&gt;
&lt;p&gt;This is the second book published by Manning that I own, the other being &lt;a href=&#34;https://www.manning.com/books/the-programmers-brain&#34;&gt;&amp;ldquo;The Programmer&amp;rsquo;s Brain&amp;rdquo; by Felienne Hermans&lt;/a&gt;. Both have covers featuring an ancient drawing of someone wearing a traditional dress, but different drawings of course, and different artists. For &amp;ldquo;Git in Practice&amp;rdquo; the cover is &amp;ldquo;A Kamtchadale in her full dress in 1768&amp;rdquo;. While the editor didn&amp;rsquo;t explain why a particular drawing was chosen, they have a general explanation&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;At a time when it is hard to tell one computer book from another, Manning celebrates the inventiveness and initiative of the computer business with book covers based on the right diversity of national costumes (&amp;hellip;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Good to know!&lt;/p&gt;
&lt;h3 id=&#34;not-a-book-for-beginners&#34;&gt;Not a book for beginners&lt;/h3&gt;
&lt;p&gt;The book is advertised for users at an &amp;ldquo;intermediate to advanced level&amp;rdquo;. One thing that clearly shows this is that the content on &amp;ldquo;Why you should use version control and how to convince others that doing so is a good idea&amp;rdquo; is an Appendix! Note that the content I&amp;rsquo;d actually use on the topic is the article &lt;a href=&#34;https://peerj.com/preprints/3159/&#34;&gt;&amp;ldquo;Excuse me, do you have a moment to talk about version control?&amp;rdquo; by Jenny Bryan&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;an-older-book&#34;&gt;An older book?&lt;/h3&gt;
&lt;p&gt;The book was published in 2015. I guess some Git things have been deprecated but I assume most of the book is still valid. What aged really bad: the screenshots from GitHub interface!&lt;/p&gt;
&lt;h3 id=&#34;66-techniques&#34;&gt;66 &amp;ldquo;techniques&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;The book cover indicates it includes 66 techniques. The first techniques are &lt;code&gt;git init&lt;/code&gt;, &lt;code&gt;git add&lt;/code&gt;, &lt;code&gt;git commit&lt;/code&gt;: calling them techniques is a bit of a stretch to me? But then the very predictable structure of the book content was actually great, so using that structure from the get go wasn&amp;rsquo;t bad at all.&lt;/p&gt;
&lt;h2 id=&#34;chapter-1-local-git&#34;&gt;Chapter 1: Local Git&lt;/h2&gt;
&lt;h3 id=&#34;clearer-understanding-of-git-add&#34;&gt;Clearer understanding of Git add&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Rather than require all changes in the working tree to make up the next commit, Git allows files to be added incrementally to the index&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, while I&amp;rsquo;ve been practicing this, I&amp;rsquo;m not sure I ever expressed the usefulness of &lt;code&gt;git add&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I also underlined a sentence explaining that &lt;code&gt;git add&lt;/code&gt; does two things:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;git add is used both to initially add a file to the Git repository and to request that changes to the fine be used in the next commit.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;garbage-in-garbage-out&#34;&gt;Garbage in, garbage out&lt;/h3&gt;
&lt;p&gt;I liked that sentence:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;How useful the history is relies a great deal on the quality of data entered into it.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then the author mentions two reasons why small commits are better:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Better readability of the history;&lt;/li&gt;
&lt;li&gt;Easier reversal of an unwanted change.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;commit-messages-are-structured-like-emails&#34;&gt;Commit messages are structured like emails&lt;/h3&gt;
&lt;p&gt;And apparently this comes from the history of Git, where commits could be sent as email. So the first line of a commit message is the subject and the rest, the body.&lt;/p&gt;
&lt;p&gt;I guess there&amp;rsquo;s also a parallel between the &lt;a href=&#34;https://www.conventionalcommits.org/en/v1.0.0/&#34;&gt;conventional commits convention&lt;/a&gt;, where you add a prefix to the subject indicating its category: &amp;ldquo;fix:&amp;rdquo; for bug fixes, &amp;ldquo;feat:&amp;rdquo; for features, is like adding a prefix to an email subject: &amp;ldquo;[ACTION REQUIRED]&amp;rdquo;.&lt;/p&gt;
&lt;h3 id=&#34;a-motivation-for-rewriting-history&#34;&gt;A motivation for rewriting history&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;there&amp;rsquo;s no need for everyone to see the mistakes you made along the way&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now let&amp;rsquo;s see if this, and other parts of the book, motivate me enough to rewrite the history of my Git branches before I mark a PR as ready for review.&lt;/p&gt;
&lt;h3 id=&#34;a-better-understanding-of-git-diff&#34;&gt;A better understanding of Git diff&lt;/h3&gt;
&lt;p&gt;I didn&amp;rsquo;t know that one could call &lt;code&gt;git diff&lt;/code&gt; without an argument, and that it&amp;rsquo;d show the diff between the working directory and the index staging area&amp;hellip; but apparently only for files that were already added, which answers my question about how different that is from &lt;code&gt;git status&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_tempfile.html&#39;&gt;local_tempdir&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_repo.html&#39;&gt;git_init&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;blop&#34;&lt;/span&gt;, path &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/file.path.html&#39;&gt;file.path&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;bla.txt&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_add&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;bla.txt&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;      file status staged&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 bla.txt    new   TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;first_commit&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_commit&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;first commit&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;bip&#34;&lt;/span&gt;, path &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/file.path.html&#39;&gt;file.path&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;other.txt&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_diff.html&#39;&gt;git_diff&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;HEAD&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   status     old     new&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1      A bla.txt bla.txt&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;                                                                                                                                patch&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 diff --git a/bla.txt b/bla.txt\nnew file mode 100644\nindex 0000000..35733a0\n--- /dev/null\n+++ b/bla.txt\n@@ -0,0 +1 @@\n+blop\n&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_diff.html&#39;&gt;git_diff&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;first_commit&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   status     old     new&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1      A bla.txt bla.txt&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;                                                                                                                                patch&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 diff --git a/bla.txt b/bla.txt\nnew file mode 100644\nindex 0000000..35733a0\n--- /dev/null\n+++ b/bla.txt\n@@ -0,0 +1 @@\n+blop\n&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_diff.html&#39;&gt;git_diff&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] status old    new    patch &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;0 rows&amp;gt; (or 0-length row.names)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_status&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;                                                              file  status&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 2  content/post/2023-01-02-reading-notes-git-in-practice/index.md deleted&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 content/post/2023-01-02-reading-notes-git-in-practice/index.Rmd deleted&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 3          content/post/2023-11-01-reading-notes-git-in-practice/     new&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   staged&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 2  FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1  FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 3  FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;bip&#34;&lt;/span&gt;, path &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/file.path.html&#39;&gt;file.path&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;bla.txt&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_diff.html&#39;&gt;git_diff&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   status     old     new&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1      M bla.txt bla.txt&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;                                                                                                                     patch&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 diff --git a/bla.txt b/bla.txt\nindex 35733a0..94652b8 100644\n--- a/bla.txt\n+++ b/bla.txt\n@@ -1 +1 @@\n-blop\n+bip\n&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_status&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;                                                              file  status&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 2  content/post/2023-01-02-reading-notes-git-in-practice/index.md deleted&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 content/post/2023-01-02-reading-notes-git-in-practice/index.Rmd deleted&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 3          content/post/2023-11-01-reading-notes-git-in-practice/     new&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   staged&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 2  FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1  FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 3  FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id=&#34;smiling-refs&#34;&gt;Smiling refs&lt;/h3&gt;
&lt;p&gt;I learnt that &lt;code&gt;main^&lt;/code&gt; is equivalent to &lt;code&gt;main~1&lt;/code&gt; and &lt;code&gt;main^^&lt;/code&gt; is equivalent to &lt;code&gt;main~2&lt;/code&gt;. ^_^&lt;/p&gt;
&lt;h3 id=&#34;git-rev-parse&#34;&gt;Git rev-parse&lt;/h3&gt;
&lt;p&gt;So if you use say &lt;code&gt;main^^&lt;/code&gt; and want to get the actual SHA, you can use &lt;code&gt;git rev-parse&lt;/code&gt;. In gert, that&amp;rsquo;s &lt;a href=&#34;https://github.com/r-lib/gert/issues/70&#34;&gt;gert::git_commit_id()&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_tempfile.html&#39;&gt;local_tempdir&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_repo.html&#39;&gt;git_init&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;blop&#34;&lt;/span&gt;, path &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/file.path.html&#39;&gt;file.path&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;bla.txt&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_add&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;bla.txt&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;      file status staged&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 bla.txt    new   TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_commit&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;first commit&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;c17a89d5682d3bab91e412aa935062c35dcdc1e2&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;blip&#34;&lt;/span&gt;, path &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/file.path.html&#39;&gt;file.path&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;bla.txt&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_add&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;bla.txt&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;      file   status staged&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 bla.txt modified   TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_commit&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;second commit&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;9a02ae19cbcd1f03bd68aba9cd414b7d83250d3d&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;blup&#34;&lt;/span&gt;, path &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/file.path.html&#39;&gt;file.path&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;bla.txt&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_add&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;bla.txt&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;      file   status staged&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 bla.txt modified   TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_commit&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;third commit&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;cd437aebe6e3f11223cdc4c4d62e3660bde56dbd&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_commit_id&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;main&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;cd437aebe6e3f11223cdc4c4d62e3660bde56dbd&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_commit_id&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;main^&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;9a02ae19cbcd1f03bd68aba9cd414b7d83250d3d&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_commit_id&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;main^^&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;git_repo&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;c17a89d5682d3bab91e412aa935062c35dcdc1e2&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id=&#34;chapter-2-remote-git&#34;&gt;Chapter 2: Remote Git&lt;/h2&gt;
&lt;p&gt;Interestingly that&amp;rsquo;s the chapter where branches are introduced.&lt;/p&gt;
&lt;h3 id=&#34;git-as-a-distributed-version-control-system&#34;&gt;Git as a distributed version control system&lt;/h3&gt;
&lt;p&gt;My first version control experience was with SVN, for a package developed on R-forge. I only remember two things: the cute tortoise of Tortoise-SVN, and the fact that instead of doing commit+push I&amp;rsquo;d only do commit. It makes sense now that I understand that Git is a distributed version control system whereas SVN is centralized, with a remote repo being the source of truth.&lt;/p&gt;
&lt;h3 id=&#34;why-git-fetch&#34;&gt;Why Git fetch?&lt;/h3&gt;
&lt;p&gt;To be honest, I&amp;rsquo;m still not sure when I would use &lt;code&gt;git fetch&lt;/code&gt;! &lt;code&gt;git fetch&lt;/code&gt; is for fetching changes from a remote without modifying local branches. I only use &lt;code&gt;git pull&lt;/code&gt; (which is fetch+merge) or &lt;code&gt;git pull --rebase&lt;/code&gt; when that fails, mostly. Note that the &lt;a href=&#34;https://happygitwithr.com/pull-tricky.html&#34;&gt;&amp;ldquo;Pull, but you have local work&amp;rdquo; chapter&lt;/a&gt; of happygitwithr by Jenny Bryan, the STAT 545 TAs, Jim Hester looks useful (I found it by searching for &amp;ldquo;fetch&amp;rdquo; in that book).&lt;/p&gt;
&lt;p&gt;Mike McQuaid wrote a paragraph &amp;ldquo;Should you use pull or fetch?&amp;rdquo; where he explains he prefers git fetch because he can incorporate remote changes when it makes sense, using a method of his choice (merging, rebasing, resetting). He also says &lt;code&gt;git fetch&lt;/code&gt; is better for working in situations with no internet connection, which was unclear to me.&lt;/p&gt;
&lt;h3 id=&#34;branch-names&#34;&gt;Branch names&lt;/h3&gt;
&lt;p&gt;Mike McQuaid recommends creating a branch name that describes &amp;ldquo;the branch&amp;rsquo;s purpose in multiple words separated by hyphens&amp;rdquo;. That&amp;rsquo;s what I tend to do, probably imitating what I saw elsewhere. Sometimes my branch names are less informative, and this makes me cringe when I open the corresponding PR.&lt;/p&gt;
&lt;h3 id=&#34;pushing-a-local-branch-remotely&#34;&gt;Pushing a local branch remotely&lt;/h3&gt;
&lt;p&gt;This section just made me very happy I push local branches with &lt;a href=&#34;https://docs.ropensci.org/gert/reference/git_fetch.html&#34;&gt;&lt;code&gt;gert::git_push()&lt;/code&gt;&lt;/a&gt;, because it sets the upstream branch automatically by default.&lt;/p&gt;
&lt;h3 id=&#34;slowly-slowly-understanding-merge-commits&#34;&gt;Slowly, slowly understanding merge commits&lt;/h3&gt;
&lt;p&gt;I learnt that merge commits are commits with multiple parents when working on the &lt;a href=&#34;https://fledge.cynkra.com/&#34;&gt;fledge package&lt;/a&gt;. When reading &amp;ldquo;Git in practice&amp;rdquo;, I at least understood &amp;ldquo;fast-forward merge&amp;rdquo; which is something I had simply ignored when Git told me it had done one.&lt;/p&gt;
&lt;p&gt;So, for my future reference&amp;hellip; If I am merging a branch A into main, and Git tells me it did a fast-forward merge, it means no merge commit was needed so none was made. The branch A commits were added to the main branch without new commit before that.&lt;/p&gt;
&lt;h3 id=&#34;conflicts-and-merge-commits&#34;&gt;Conflicts and merge commits&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;When conflicts have been resolved, a &lt;em&gt;merge commit&lt;/em&gt; can be made. This stores the two parent commits and the conflicts that were resolved so they can be inspected un the future. Unfortunately, sometimes people pick the wrong option or merge incorrectly, so it&amp;rsquo;s good to be able to later see what conflicts they had to resolve.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This was new to me, certaintly not something I had in mind when resolving conflicts.&lt;/p&gt;
&lt;h2 id=&#34;chapter-3-filesystem-interactions&#34;&gt;Chapter 3: Filesystem interactions&lt;/h2&gt;
&lt;h3 id=&#34;git-mv-git-rm&#34;&gt;Git mv, Git rm&lt;/h3&gt;
&lt;p&gt;I was never aware of &lt;code&gt;git mv&lt;/code&gt;, for renaming and moving a file. I think it&amp;rsquo;s because the RStudio IDE Git thingie was doing this for me? When I rename a file, I see the status becomes &amp;ldquo;R&amp;rdquo; once I&amp;rsquo;ve added both the file deletion (old name) and the file adding (new name).&lt;/p&gt;
&lt;p&gt;The same goes for &lt;code&gt;git rm&lt;/code&gt; for removing a file.&lt;/p&gt;
&lt;h3 id=&#34;i-should-use-git-reset-more-often&#34;&gt;I should use Git reset more often&lt;/h3&gt;
&lt;p&gt;An use case for &lt;code&gt;git reset&lt;/code&gt; that was described really resonated with me. 😅&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Perhaps you added debugging statements to files and have now commited a fix, so you want to reset all the files that haven&amp;rsquo;t been committed to their last committed state (on the current branch)&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So instead of looking at the Git diff to remember where I added &lt;a href=&#34;https://rdrr.io/r/base/browser.html&#34;&gt;&lt;code&gt;browser()&lt;/code&gt;&lt;/a&gt;, or looking for occurrences of a given debugging thing, I could use &lt;code&gt;git reset&lt;/code&gt;, now that sounds smarter!&lt;/p&gt;
&lt;h3 id=&#34;i-should-adopt-git-clean&#34;&gt;I should adopt Git clean&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;git clean&lt;/code&gt; will remove any untracked file from the filesystem. Like the previous idea, it sounds like something I could use when debugging something and creating files à la &amp;ldquo;blop.text&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Now &lt;code&gt;git clean&lt;/code&gt; can be dangerous so you can first run &lt;code&gt;git clean -n&lt;/code&gt; or &lt;code&gt;git clean --dry-run&lt;/code&gt; to see what would be removed.&lt;/p&gt;
&lt;p&gt;Note that gert doesn&amp;rsquo;t seem to support &lt;code&gt;git clean&lt;/code&gt; so I&amp;rsquo;d do this from a terminal.&lt;/p&gt;
&lt;p&gt;The book also explains the &lt;code&gt;-X&lt;/code&gt; argument of &lt;code&gt;git clean&lt;/code&gt; for removing only ignored files, compared to the lower case &lt;code&gt;-x&lt;/code&gt; argument for removing both ignored and untracked files.&lt;/p&gt;
&lt;p&gt;In conclusion I need to practice using &lt;code&gt;git clean&lt;/code&gt;, and to refer to its docs when doing so, but at least now I know it exists.&lt;/p&gt;
&lt;h3 id=&#34;could-git-stash-be-useful-to-me&#34;&gt;Could Git stash be useful to me&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;git stash save&lt;/code&gt; is a command for temporarily stashing some changes. &lt;code&gt;git stash pop&lt;/code&gt; gets them back. &lt;code&gt;git stadsh clear&lt;/code&gt; clears stashed commits.&lt;/p&gt;
&lt;p&gt;I can&amp;rsquo;t think of an use case right now but maybe I will encounter one one day?&lt;/p&gt;
&lt;h3 id=&#34;git-update-index---assume-unchanged-path&#34;&gt;Git update-index &lt;code&gt;--assume-unchanged&lt;/code&gt; &lt;path&gt;&lt;/h3&gt;
&lt;p&gt;Again an use case that resonated with me (well I don&amp;rsquo;t use Rails but still)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;I&amp;rsquo;ve found myself in a situation in the past where I wanted to test a Rails configuration file change for a week or two while continuing to do my normal work. I didn&amp;rsquo;t want to commit it because I didn&amp;rsquo;t want it to apply to servers or my coworkers, but I did want to continue testing it while I made other commits rather than change to a particular branch each time.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So in that case one can run &lt;code&gt;Git update-index --assume-unchanged &amp;lt;path&amp;gt;&lt;/code&gt;. Then you undo this by running &lt;code&gt;Git update-index --no-assume-unchanged &amp;lt;path&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;chapter-4-history-visualization&#34;&gt;Chapter 4: History visualization&lt;/h2&gt;
&lt;p&gt;Honestly most of this chapter made me happy about the GitHub interface!&lt;/p&gt;
&lt;p&gt;The other thing is that it has an explanation of &lt;code&gt;git bisect&lt;/code&gt; that I need to come back to next time I need to find which commit caused a particular bug. I tend to be scared of &lt;code&gt;git bisect&lt;/code&gt;, but the explanation made sense. Also I guess I need to focus on making small informative commits before bisect really shines in my use cases. 😇&lt;/p&gt;
&lt;p&gt;I am especially curious about &lt;code&gt;git bisect run&lt;/code&gt; for automating &lt;code&gt;git bisect&lt;/code&gt;, I wonder how that would work with a testthat unit test.&lt;/p&gt;
&lt;h2 id=&#34;chapter-5-advanced-branching&#34;&gt;Chapter 5: Advanced branching&lt;/h2&gt;
&lt;h3 id=&#34;merge-strategies&#34;&gt;Merge strategies&lt;/h3&gt;
&lt;p&gt;I learnt there&amp;rsquo;s a merge strategy, &lt;code&gt;--ours&lt;/code&gt;, that will ignore all changes from the incoming branch but still indicate it in the history. That&amp;rsquo;s supposed to be useful for when you want to keep an experiment from an experimental branch in the history.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s another interesting merge strategy, &lt;code&gt;--patience&lt;/code&gt;, that &amp;ldquo;uses a slightly more expensive git diff algorithm to try to decrease the chance of a merge conflict&amp;rdquo;. It sounds like a joke.&lt;/p&gt;
&lt;h3 id=&#34;not-useful-to-me-but-fun-name-git-rerere&#34;&gt;Not useful to me but fun name: git rerere&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;git rerere&lt;/code&gt;, Reuse Recorded Resolution, allows you to resolve each merge conflict only once.&lt;/p&gt;
&lt;p&gt;I sort of understand the use case but it doesn&amp;rsquo;t sound useful to my work:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;You may find yourself in a situation where you have a long-running branch that you have to keep merging in another branch, and you get the same merge conflict every time.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;yay-git-cherry-pick&#34;&gt;Yay git cherry-pick&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;git cherry-pick&lt;/code&gt; allows you to add a single commit to the current branch. I recently successfully used it!&lt;/p&gt;
&lt;p&gt;A collaborator had mistakenly created a new feature branch from another feature branch instead of from the main branch. After that they added their feature commit but the PR was all broken. I created a new branch from the main branch, cherry-picked the commit and then opened a new PR. It&amp;rsquo;s a small step for humanity but it was a big step for me. 😁 It was very cool to be able to say &amp;ldquo;don&amp;rsquo;t worry, I&amp;rsquo;ve got it&amp;rdquo; to that collaborator.&lt;/p&gt;
&lt;h2 id=&#34;chapter-6-rewriting-history-and-disaster-recovery&#34;&gt;Chapter 6: Rewriting history and disaster recovery&lt;/h2&gt;
&lt;h3 id=&#34;another-new-to-me-command-git-reflog&#34;&gt;Another new-to-me command: git reflog&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;git reflog&lt;/code&gt; will list &amp;ldquo;all changes including history rewrites&amp;rdquo;, for the local repository. Commits that are deleted on all branches are only kept in the reflog for 90 days.&lt;/p&gt;
&lt;h3 id=&#34;git-reset-can-take-a-list-of-paths-as-arguments&#34;&gt;Git reset can take a list of paths as arguments&lt;/h3&gt;
&lt;p&gt;An example would be &lt;code&gt;git reset HEAD^ -- path.txt&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;actually-retired-now-git-filter-branch&#34;&gt;Actually retired now: Git filter-branch&lt;/h3&gt;
&lt;p&gt;One technique presented in the book, for rewriting git repository history, is &lt;code&gt;git filter-branch&lt;/code&gt; but then I saw a &lt;a href=&#34;https://mastodon.social/deck/@kirill@fosstodon.org/111302703034532823&#34;&gt;toot by Kirill Müller&lt;/a&gt; indicating it&amp;rsquo;s retired. A replacement is &lt;a href=&#34;https://github.com/newren/git-filter-repo/&#34;&gt;git filter-repo&lt;/a&gt;, that I&amp;rsquo;d have to explore a bit more before being able to use it. The &lt;a href=&#34;https://github.com/newren/git-filter-repo/#simple-example-with-comparisons&#34;&gt;simple example&lt;/a&gt; looks convincing enough! According to the book this can be useful for some cases of disaster recovery.&lt;/p&gt;
&lt;h3 id=&#34;commit-regularly&#34;&gt;Commit regularly&lt;/h3&gt;
&lt;p&gt;This is the main message of this chapter, and it&amp;rsquo;s not an advanced technique at all, just a good habit. 😸&lt;/p&gt;
&lt;h2 id=&#34;chapter-7-personalizing-git&#34;&gt;Chapter 7: Personalizing Git&lt;/h2&gt;
&lt;h3 id=&#34;option-for-pruning-branches-automatically&#34;&gt;Option for pruning branches automatically&lt;/h3&gt;
&lt;p&gt;If you want the references to now deleted remote branches to be deleted, you can run &lt;code&gt;git remote prune origin&lt;/code&gt; or configure Git so that this will happen every time you pull or fetch.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_config.html&#39;&gt;git_config_global_set&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;fetch.prune&#34;&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 id=&#34;global-gitignore&#34;&gt;Global gitignore&lt;/h3&gt;
&lt;p&gt;I already knew about the global gitignore file thanks to the handy &lt;a href=&#34;https://usethis.r-lib.org/reference/git_vaccinate.html&#34;&gt;&lt;code&gt;usethis::git_vaccinate()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;an-option-for-autocorrecting-misspelled-commands&#34;&gt;An option for autocorrecting misspelled commands&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s a Git option for autocorrecting misspelled commands, &lt;a href=&#34;https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_help_autocorrect&#34;&gt;help.autocorrect&lt;/a&gt;. It would not help me since my most frequent typo is &amp;ldquo;gut&amp;rdquo; instead of &amp;ldquo;git&amp;rdquo;, sadly.&lt;/p&gt;
&lt;h2 id=&#34;chapter-8-vendoring-dependencies-as-submodules&#34;&gt;Chapter 8: Vendoring dependencies as submodules&lt;/h2&gt;
&lt;p&gt;If I ever have to work again with a repo that uses submodules 😭, I might go back to this chapter to see which commands to run.&lt;/p&gt;
&lt;h2 id=&#34;chapter-12-creating-a-clean-history&#34;&gt;Chapter 12: Creating a clean history&lt;/h2&gt;
&lt;h3 id=&#34;one-can-build-a-commit-from-parts-of-files&#34;&gt;One can build a commit from parts of files&lt;/h3&gt;
&lt;p&gt;Using &lt;code&gt;git add --patch &amp;lt;path&amp;gt;&lt;/code&gt;. This opens an interactive menu letting you choose which hunk(s) to add to a commit. Each hunk can be split into smaller hunks. Then one uses &lt;code&gt;git commit&lt;/code&gt; as usual.&lt;/p&gt;
&lt;p&gt;The book also mentions that &lt;code&gt;git commit --patch&lt;/code&gt; also exists. It seems less intuitive to me to do the hunk selection at that stage.&lt;/p&gt;
&lt;h2 id=&#34;chapter-13-merging-vsrebasing&#34;&gt;Chapter 13: merging vs. rebasing&lt;/h2&gt;
&lt;p&gt;This chapter compares the strategies of two projects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CMake&amp;rsquo;s branching and merging strategy.&lt;/li&gt;
&lt;li&gt;Homebrew&amp;rsquo;s rebasing and squashing strategy. &amp;ldquo;This hides merge commits, evidence of branches, and temporary commits (for example, those that fix previous commits on the same branch) from the main branch.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To me CMake history looks like a mess or even a nightmare so I guess I&amp;rsquo;m in favor of the Homebrew&amp;rsquo;s strategy!&lt;/p&gt;
&lt;p&gt;But in each project, it is worth to have a discussion about the chosen strategy, to educate contributors.&lt;/p&gt;
&lt;p&gt;I liked reading that in Homebrew, metadata is included into commit messages. For instance I enjoy the fact that GitHub automatically adds co-authors when you squash and merge a PR that add multiple contributors: &lt;a href=&#34;https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors&#34;&gt;https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;chapter-14-recommended-team-workflows&#34;&gt;Chapter 14: Recommended team workflows&lt;/h2&gt;
&lt;p&gt;Have you heard of GitHub flow, Git flow? These are &lt;em&gt;team workflows&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;The different strategies for deciding how and when to branch, merge or rebase as part of a team are called &lt;em&gt;team workflows&lt;/em&gt;.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I much prefer GitHub flow where the default branch is stable and where there is no long-lived development branch, because in my experience, having such a long-lived development branch has lead to more confusion than gains. For &lt;a href=&#34;https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors&#34;&gt;rOpenSci dev guide&lt;/a&gt; we went from some sort of Git flow to GitHub flow, where actual relases will be, well, actual releases/tags of the main branch. Changing flows was such a relief!&lt;/p&gt;
&lt;p&gt;The author also presented his own two usual flows.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&amp;ldquo;Git in practice&amp;rdquo; by Mike McQuaid was a nice train travel companion. I feared it would be too dry or obscure but found it clear and well explained. I learnt a lot, but now, I will have to&amp;hellip; practice what I learnt! 😁&lt;/p&gt;
&lt;p&gt;Did you read this book, or another Git book? How did you learn Git? Any strong opinion on any of the topics mentioned in those notes?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>3 (actually 4) neat R functions</title>
      <link>https://masalmon.eu/2023/10/20/three-neat-functions/</link>
      <pubDate>Fri, 20 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/10/20/three-neat-functions/</guid>
      <description>&lt;p&gt;Time for me to throw away my sticky note after sharing what I wrote on it!&lt;/p&gt;
&lt;h2 id=&#34;grep-not-whichgrepl&#34;&gt;&lt;code&gt;grep(...)&lt;/code&gt; not &lt;code&gt;which(grepl(...))&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Recently I caught myself using &lt;code&gt;which(grepl(...))&lt;/code&gt;,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;cat&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;bird&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;dog&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;fish&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/which.html&#39;&gt;which&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/grep.html&#39;&gt;grepl&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;i&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] 2 4&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;when the simpler alternative is&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;cat&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;bird&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;dog&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;fish&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/grep.html&#39;&gt;grep&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;i&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] 2 4&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And should I need the values instead of the indices, I know I shouldn&amp;rsquo;t write&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;cat&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;bird&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;dog&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;fish&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/grep.html&#39;&gt;grepl&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;i&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;bird&#34; &#34;fish&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;but&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;cat&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;bird&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;dog&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;fish&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/grep.html&#39;&gt;grep&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;i&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt;, value &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;bird&#34; &#34;fish&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;How to remember to use &lt;a href=&#34;https://rdrr.io/r/base/grep.html&#34;&gt;&lt;code&gt;grep()&lt;/code&gt;&lt;/a&gt;? Re-reading oneself, or having code reviewed, probably helps, but why not automate this? When I shared my note to self on Mastodon, Hugo Gruson &lt;a href=&#34;https://mastodon.social/deck/@grusonh/111181373365621067&#34;&gt;explained&lt;/a&gt; that detecting usage of &lt;code&gt;which(grepl(&lt;/code&gt; was part of planned linters to be added to lintr from &lt;a href=&#34;https://github.com/r-lib/lintr/issues/884&#34;&gt;Google linting suite&lt;/a&gt;. This is excellent news!&lt;/p&gt;
&lt;h2 id=&#34;strrep-and-other-defence-tools-against-poor-usages-of-paste&#34;&gt;&lt;code&gt;strrep()&lt;/code&gt; and other defence tools against poor usages of &lt;code&gt;paste()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Yihui Xie wrote a &lt;a href=&#34;https://yihui.org/en/2023/10/three-functions/&#34;&gt;blog post inspired by my own series&lt;/a&gt;, where one of the three presented functions was one that was on my sticky note! I&amp;rsquo;ll still present it: &lt;a href=&#34;https://rdrr.io/r/base/strrep.html&#34;&gt;&lt;code&gt;strrep()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://rdrr.io/r/base/strrep.html&#34;&gt;&lt;code&gt;strrep()&lt;/code&gt;&lt;/a&gt; means &amp;ldquo;string repeat&amp;rdquo;. Instead of writing&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/paste.html&#39;&gt;paste&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/rep.html&#39;&gt;rep&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;bla&#34;&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;3&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;, collapse &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;blablabla&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;you can, and should, write&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/strrep.html&#39;&gt;strrep&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;bla&#34;&lt;/span&gt;, &lt;span class=&#39;m&#39;&gt;3&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;blablabla&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I discovered this function because Hugo Gruson telling me about lintr inspired me to skim through lintr reference, where I saw &lt;a href=&#34;https://lintr.r-lib.org/reference/paste_linter.html&#34;&gt;&amp;ldquo;Raise lints for several common poor usages of &lt;code&gt;paste()&lt;/code&gt;&amp;rdquo;&lt;/a&gt;. That linter would also tell you when you use &lt;code&gt;paste(, sep = &amp;quot;&amp;quot;)&lt;/code&gt; instead of &lt;a href=&#34;https://rdrr.io/r/base/paste.html&#34;&gt;&lt;code&gt;paste0()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;startswith-and-endswith&#34;&gt;&lt;code&gt;startsWith()&lt;/code&gt; and &lt;code&gt;endsWith()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I learned about &lt;a href=&#34;https://rdrr.io/r/base/startsWith.html&#34;&gt;&lt;code&gt;startsWith()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://rdrr.io/r/base/startsWith.html&#34;&gt;&lt;code&gt;endsWith()&lt;/code&gt;&lt;/a&gt; by reading lintr reference but I also got notified about it when running lintr on a package I was working on. Have you ever tried &lt;a href=&#34;https://github.com/r-lib/lintr/issues/1482#issuecomment-1198590483&#34;&gt;running all linters on your code&lt;/a&gt;? Fun experience. Anyhow, one linter is &lt;a href=&#34;https://lintr.r-lib.org/reference/string_boundary_linter.html&#34;&gt;Require usage of &lt;code&gt;startsWith()&lt;/code&gt; and &lt;code&gt;endsWith()&lt;/code&gt; over &lt;code&gt;grepl()&lt;/code&gt;/&lt;code&gt;substr()&lt;/code&gt; versions&lt;/a&gt;, with an interesting Details section on missing values.&lt;/p&gt;
&lt;p&gt;Instead of writing&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;cat&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;cow&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;dog&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;fish&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/grep.html&#39;&gt;grepl&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;^c&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1]  TRUE  TRUE FALSE FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I should write&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;cat&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;cow&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;dog&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;fish&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/startsWith.html&#39;&gt;startsWith&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;c&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1]  TRUE  TRUE FALSE FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;A nice side-effect of the switch, beyond good practice for its own sake and more readability, is that the argument order is more logical in &lt;a href=&#34;https://rdrr.io/r/base/startsWith.html&#34;&gt;&lt;code&gt;startsWith()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Similarly, instead of writing&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;cat&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;cow&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;dog&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;fish&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/grep.html&#39;&gt;grepl&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;t$&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1]  TRUE FALSE FALSE FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I should write&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;cat&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;cow&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;dog&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;fish&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/startsWith.html&#39;&gt;endsWith&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;t&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1]  TRUE FALSE FALSE FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I shared about &lt;a href=&#34;https://rdrr.io/r/base/grep.html&#34;&gt;&lt;code&gt;grep()&lt;/code&gt;&lt;/a&gt; to be used in lieu of &lt;code&gt;which(grepl())&lt;/code&gt;, about &lt;a href=&#34;https://rdrr.io/r/base/strrep.html&#34;&gt;&lt;code&gt;strrep()&lt;/code&gt;&lt;/a&gt; (string repetition) to be used in lieu of &lt;code&gt;paste(rep(), collapse =&amp;quot;&amp;quot;)&lt;/code&gt; and about &lt;a href=&#34;https://rdrr.io/r/base/startsWith.html&#34;&gt;&lt;code&gt;startsWith()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://rdrr.io/r/base/startsWith.html&#34;&gt;&lt;code&gt;endsWith()&lt;/code&gt;&lt;/a&gt; to be used in lieu of some regular expressions with respectively &lt;code&gt;^&lt;/code&gt; and &lt;code&gt;$&lt;/code&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Reading notes on A Philosophy of Software Design by John Ousterhout</title>
      <link>https://masalmon.eu/2023/10/19/reading-notes-philosophy-software-design/</link>
      <pubDate>Thu, 19 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/10/19/reading-notes-philosophy-software-design/</guid>
      <description>&lt;p&gt;When I see a book recommendation somewhere, be it for work or leisure, I often either order the book or set an alert in my &lt;a href=&#34;https://www.momox-shop.fr/&#34;&gt;favorite online second-hand bookstore&lt;/a&gt;. By the time I am notified the book is available, I sometimes don&amp;rsquo;t remember why I listed it! That&amp;rsquo;s what happened for the book A Philosophy of Software Design by John Ousterhout. I decided to trust my past self and buy it. Unfortunately I got the first not the &lt;a href=&#34;https://web.stanford.edu/~ouster/cgi-bin/book.php&#34;&gt;second edition&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For a change I wrote some reading notes, reflecting what resonated more with me at this stage in my software development journey.&lt;/p&gt;
&lt;h2 id=&#34;first-and-later-impressions&#34;&gt;First and later impressions&lt;/h2&gt;
&lt;p&gt;I found the title of the book misleading: the word &amp;ldquo;philosophy&amp;rdquo; made it sound unapproachable, but it was approachable, and also rather short (about 169 pages, including examples no one will know you skipped&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;).&lt;/p&gt;
&lt;p&gt;I got a copy that was annotated. Sadly the notes didn&amp;rsquo;t provide any novel insight, but the handwriting is good and the notes repeat what&amp;rsquo;s important, perfect for future skimming.&lt;/p&gt;
&lt;p&gt;I appreciated the tone of the book which wasn&amp;rsquo;t too dogmatic compared to &lt;a href=&#34;https://qntm.org/clean&#34;&gt;other sources&lt;/a&gt; out there.&lt;/p&gt;
&lt;h2 id=&#34;complexity-in-software&#34;&gt;Complexity in software&lt;/h2&gt;
&lt;p&gt;The most important concept is the book is &lt;strong&gt;complexity&lt;/strong&gt;, what it is and how to avoid it. The author defined three manifestations of complexity:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Change amplification, meaning it&amp;rsquo;s hard to change something. It reminds me of this quote I heard from Kara Woo&amp;rsquo;s posit keynote talk: &lt;a href=&#34;https://speakerdeck.com/karawoo/r-not-only-in-production?slide=76&#34;&gt;&amp;ldquo;If you can&amp;rsquo;t make changes because you are afraid of breaking something, it&amp;rsquo;s already broken.&amp;quot;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Cognitive load, at which point I have to tell you to read &lt;a href=&#34;https://www.manning.com/books/the-programmers-brain&#34;&gt;The Programmer&amp;rsquo;s Brain by Felienne Hermans&lt;/a&gt;. I think about it regularly and see my R friends mentioning it.&lt;/li&gt;
&lt;li&gt;Unknown unknowns. 👻&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;priority-to-the-interface&#34;&gt;Priority to the interface&lt;/h2&gt;
&lt;p&gt;A point made at least twice in the book is that you should give priority to simplifying the interface of things not their implementation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;When developing a module, look for opportunities to take a little bit of extra suffering upon yourself to reduce the suffering of your users&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is also present in the author&amp;rsquo;s idea of &amp;ldquo;Define errors out of existence&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;This made me think about &lt;a href=&#34;https://blog.r-hub.io/2020/04/07/retry-wheel/&#34;&gt;retries in HTTP requests&lt;/a&gt;. When writing a function interfacing an API I could simply return the error, forcing the user to handle the error themselves, or I could add retries, that would potentially make all errors disappear. It&amp;rsquo;s not a perfect example since retries aren&amp;rsquo;t hard to add with say httr2 or httr, but that was what I was thinking of.&lt;/p&gt;
&lt;p&gt;Another point about the interface is that you only split two things if it simplifies the interface. That&amp;rsquo;s a better way to think about it than just thinking in number of lines.&lt;/p&gt;
&lt;h2 id=&#34;tactical-vs-strategic-programming&#34;&gt;Tactical vs strategic programming&lt;/h2&gt;
&lt;p&gt;The author compares two approaches to programming:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tactical programming&lt;/strong&gt; is where you squash bugs and add features while racking up tech debt, not thinking about software design.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Strategic programming&lt;/strong&gt; is where you take more time to implement things so that the software design remains good or even becomes better over time.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unsurprisingly the author defends the second approach, explaining how it pays off. The author does acknowledge it might be hard to use the second approach depending on, for instance, &lt;a href=&#34;https://enpiar.com/2023/05/30/obey-the-timer/&#34;&gt;deadlines&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Strategic programming, and the author&amp;rsquo;s insistent advice to &amp;ldquo;stay strategic&amp;rdquo; reminded me of a &lt;a href=&#34;https://code-review.tidyverse.org/reviewer/purpose.html&#34;&gt;paragraph in the Tidyverse code review guide&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;On the other hand, it is the duty of the reviewer to make sure that each PR is of such a quality that the overall code health of the package is not decreasing as time goes on. This can be tricky, because codebases often degrade through small decreases in code health over time. This isn&amp;rsquo;t necessarily anyone&amp;rsquo;s fault. It is a natural process resulting from the accumulation of technical debt over time, which must continually be fought against.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;comments&#34;&gt;Comments&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Good comments can make a big difference in the overall quality of a system.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I appreciated seeing a few chapters about comments. I wrote a &lt;a href=&#34;https://blog.r-hub.io/2023/01/26/code-comments-self-explaining-code/&#34;&gt;post on comments&lt;/a&gt; myself earlier this year.&lt;/p&gt;
&lt;p&gt;The author write that comments belong in the code, not the commit log, which is true but with the &lt;a href=&#34;https://fledge.cynkra.com/dev/&#34;&gt;fledge package&lt;/a&gt; you can transform commit messages into changelog content. Furthermore, I feel that Git blame can be useful no matter how good your comments are.&lt;/p&gt;
&lt;p&gt;The book mentions that if a piece of code is hard to comment maybe you should refactor it. I like how it&amp;rsquo;s similar to another idea in the book: if a variable is hard to name maybe it indicates some weakness of the code design.&lt;/p&gt;
&lt;h2 id=&#34;variable-names&#34;&gt;Variable names&lt;/h2&gt;
&lt;p&gt;Apart from the idea I&amp;rsquo;ve just mentioned, one piece of advice that is reported in the book resonated with me. It&amp;rsquo;s a comment by Andrew Gerrand: &amp;ldquo;The greater the distance between a name&amp;rsquo;s declaration and its uses, the longer the name should be&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;consistency&#34;&gt;Consistency&lt;/h2&gt;
&lt;p&gt;The author underlines the importance of consistency (in names, coding style, design patterns&amp;hellip;), that makes your codebase easier to grasp and contribute to. To ensure consistency you should document it which made me think of &lt;a href=&#34;https://devdevguide.netlify.app/maintenance_collaboration#contributing-guide&#34;&gt;contributing guides&lt;/a&gt;, and/or use automatic tools, which made me think of the &lt;a href=&#34;https://lintr.r-lib.org/reference/index.html&#34;&gt;lintr package&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I am glad I ordered this book past me had bookmarked! I found it was very readable, with some good advice and ways to express it. I am pretty sure I&amp;rsquo;ll skim it in the future. My first recommendation of resources about good code would remain &lt;a href=&#34;https://www.oreilly.com/library/view/the-art-of/9781449318482/&#34;&gt;The Art of Readable Code by Dustin Boswell and Trevor Foucher&lt;/a&gt;, &lt;a href=&#34;https://www.manning.com/books/the-programmers-brain&#34;&gt;The Programmer&amp;rsquo;s Brain by Felienne Hermans&lt;/a&gt;, &lt;a href=&#34;https://github.com/jennybc/code-smells-and-feels&#34;&gt;Jenny Bryan&amp;rsquo;s talk &amp;ldquo;Code Smells and Feels&amp;rdquo;&lt;/a&gt; and &lt;a href=&#34;https://tidydesign.substack.com/&#34;&gt;Hadley Wickham&amp;rsquo;s Tidy Design newsletter that goes with a book-in-progress&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you read the book, what were your take-aways? What is your favorite resource to learn how to program better?&lt;/p&gt;
&lt;h2 id=&#34;other-reviews-of--notes-on-the-book&#34;&gt;Other reviews of / notes on the book&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://johz.bearblog.dev/book-review-philosophy-software-design/&#34;&gt;https://johz.bearblog.dev/book-review-philosophy-software-design/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://blog.pragmaticengineer.com/a-philosophy-of-software-design-review/&#34;&gt;https://blog.pragmaticengineer.com/a-philosophy-of-software-design-review/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Unless you blog about it. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>The real reset button for local mess fom tests: withr::deferred_run()</title>
      <link>https://masalmon.eu/2023/10/16/test-local-mess-reset/</link>
      <pubDate>Mon, 16 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/10/16/test-local-mess-reset/</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://rweekly.fireside.fm/141&#34;&gt;R Weekly highlights podcast&lt;/a&gt; hosted by Eric Nantz and Mike Thomas.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Following &lt;a href=&#34;https://masalmon.eu/2023/10/09/test-workflow-enhancement/&#34;&gt;last week&amp;rsquo;s post on my testing workflow enhancements&lt;/a&gt;, Jenny Bryan kindly reminded me of the existence of an actual reset button when you&amp;rsquo;ve been interactively running tests that include some &amp;ldquo;local mess&amp;rdquo;: &lt;a href=&#34;https://withr.r-lib.org/reference/with_envvar.html&#34;&gt;&lt;code&gt;withr::local_envvar()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://withr.r-lib.org/reference/with_dir.html&#34;&gt;&lt;code&gt;withr::local_dir()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://usethis.r-lib.org/reference/proj_utils.html&#34;&gt;&lt;code&gt;usethis::local_project()&lt;/code&gt;&lt;/a&gt;&amp;hellip; The reset button is &lt;a href=&#34;https://withr.r-lib.org/reference/defer.html&#34;&gt;&lt;code&gt;withr::deferred_run()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is documented in Jenny&amp;rsquo;s article about &lt;a href=&#34;https://testthat.r-lib.org/articles/test-fixtures.html&#34;&gt;test fixtures&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Since the global environment isn&amp;rsquo;t perishable, like a test environment is, you have to call deferred_run() explicitly to execute the deferred events. You can also clear them, without running, with deferred_clear().&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It is also mentioned in &lt;a href=&#34;https://github.com/r-lib/withr/blob/0c5254ebc74590e80cc0056303d74b049b943920/R/defer.R#L152&#34;&gt;messages from withr&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For some reason it hadn&amp;rsquo;t clicked for me until now?! But now I know better!&lt;/p&gt;
&lt;h2 id=&#34;example-making-a-withrlocal_-mess-and-wiping-it-with-withrdeferred_run&#34;&gt;Example: making a &lt;code&gt;withr::local_&lt;/code&gt; mess and wiping it with &lt;code&gt;withr::deferred_run()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Imagine a test file&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;test_that&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;My function works&amp;#34;&lt;/span&gt;, {
  temp_dir &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; withr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;local_tempdir&lt;/span&gt;()
  withr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;local_options&lt;/span&gt;(blop &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  usethis&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;local_project&lt;/span&gt;(temp_dir, force &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  withr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;local_envvar&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;TEST_SWITCH&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;something&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;expect_something&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;my_function&lt;/span&gt;()) &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# not actual test code, you get the idea&lt;/span&gt;
})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Imagine the test fails and I run this in my R session probably after throwing a &lt;a href=&#34;https://rdrr.io/r/base/browser.html&#34;&gt;&lt;code&gt;browser()&lt;/code&gt;&lt;/a&gt;&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; somewhere and running &lt;a href=&#34;https://devtools.r-lib.org/reference/load_all.html&#34;&gt;&lt;code&gt;devtools::load_all()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;temp_dir&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_tempfile.html&#39;&gt;local_tempdir&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_options.html&#39;&gt;local_options&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;blop &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;FALSE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;usethis&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://usethis.r-lib.org/reference/proj_utils.html&#39;&gt;local_project&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;temp_dir&lt;/span&gt;, force &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BB00;&#39;&gt;✔&lt;/span&gt; Setting active project to &lt;span style=&#39;color: #0000BB;&#39;&gt;&#39;/tmp/RtmpTxY51U/file1dbe2032be39&#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_envvar.html&#39;&gt;local_envvar&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;TEST_SWITCH&#34;&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;something&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then I do the actual debugging. At the end my session is all messy!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Sys.getenv.html&#39;&gt;Sys.getenv&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;TEST_SWITCH&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;something&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/options.html&#39;&gt;getOption&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;blop&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;usethis&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://usethis.r-lib.org/reference/proj_sitrep.html&#39;&gt;proj_sitrep&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;c&#39;&gt;# cool function!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; •   working_directory: &lt;span style=&#39;color: #0000BB;&#39;&gt;&#39;/home/maelle/Documents/blog/simplymaelle/content/post/2023-10-16-deferred-run&#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; • active_usethis_proj: &lt;span style=&#39;color: #0000BB;&#39;&gt;&#39;/tmp/RtmpTxY51U/file1dbe2032be39&#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; • active_rstudio_proj: &lt;span style=&#39;color: #555555;&#39;&gt;&amp;lt;unset&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #BB0000;&#39;&gt;•&lt;/span&gt; Your working directory is not the same as the active usethis project.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   Set working directory to the project: &lt;span style=&#39;color: #555555;&#39;&gt;`setwd(proj_get())`&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   Set project to working directory:     &lt;span style=&#39;color: #555555;&#39;&gt;`proj_set(getwd())`&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Instead of fixing each thing by hand I can run&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/defer.html&#39;&gt;deferred_run&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And now all is right in my session again, you&amp;rsquo;ll have to believe me or run the example yourself: indeed, demonstrating all of this in a knitr document makes it a bit more challenging. I swear that outside of a knitr document, this all works even for code that changes the current directory!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Sys.getenv.html&#39;&gt;Sys.getenv&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;TEST_SWITCH&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/options.html&#39;&gt;getOption&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;blop&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;usethis&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://usethis.r-lib.org/reference/proj_utils.html&#39;&gt;proj_get&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;So I can go and debug the next failing test. 😸&lt;/p&gt;
&lt;h2 id=&#34;what-about-rlangs-local-mess&#34;&gt;What about rlang&amp;rsquo;s local mess?&lt;/h2&gt;
&lt;p&gt;rlang itself has &lt;a href=&#34;https://rlang.r-lib.org/reference/is_interactive.html&#34;&gt;&lt;code&gt;rlang::local_interactive()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://rlang.r-lib.org/reference/local_options.html&#34;&gt;&lt;code&gt;rlang::local_options()&lt;/code&gt;&lt;/a&gt;. Luckily they are reset by &lt;a href=&#34;https://withr.r-lib.org/reference/defer.html&#34;&gt;&lt;code&gt;withr::deferred_run()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not sure exactly where the compatibility comes from, maybe from &lt;a href=&#34;https://github.com/r-lib/rlang/blob/7a78dc3f0d5b2fb73289f820e39afb5c4d665802/R/import-standalone-defer.R&#34;&gt;the standalone defer script&lt;/a&gt;. In any case, that&amp;rsquo;s good news!&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So, in summary, if you&amp;rsquo;re running test code interactively to debug them, and this test code changed some things using &lt;a href=&#34;https://withr.r-lib.org/reference/with_.html&#34;&gt;&lt;code&gt;withr::local_&lt;/code&gt;&lt;/a&gt; or other compatible &lt;code&gt;local_&lt;/code&gt; functions, to get your session back to its initial state without restarting R, run &lt;a href=&#34;https://withr.r-lib.org/reference/defer.html&#34;&gt;&lt;code&gt;withr::deferred_run()&lt;/code&gt;&lt;/a&gt;! Thanks Jenny for the reminder!&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.r-hub.io/2023/01/23/code-switch-escape-hatch-test/&#34;&gt;Test switches&lt;/a&gt; are sooo handy. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;For better debugging advice, refer to &lt;a href=&#34;https://www.pipinghotdata.com/talks/2022-11-11-debugging/&#34;&gt;Shannon Pileggi&amp;rsquo;s materials&lt;/a&gt;! &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Two recent enhancements to my testing workflow</title>
      <link>https://masalmon.eu/2023/10/09/test-workflow-enhancement/</link>
      <pubDate>Mon, 09 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/10/09/test-workflow-enhancement/</guid>
      <description>&lt;p&gt;I spend a lot of quality time with testthat, that sometimes deigns to praise my code with emojis, sometimes has to encourage me. No one gets it right on their first try apparently?&lt;/p&gt;
&lt;p&gt;Anyway, in honor of &lt;a href=&#34;https://www.tidyverse.org/blog/2023/10/testthat-3-2-0/&#34;&gt;testthat 3.2.0 release&lt;/a&gt; 🎉 👏, I&amp;rsquo;d like to mention two small things that improved my testing workflow a whole lot!&lt;/p&gt;
&lt;h2 id=&#34;running-one-single-test-at-a-time&#34;&gt;Running one single test at a time&lt;/h2&gt;
&lt;p&gt;Under &lt;a href=&#34;https://testthat.r-lib.org/news/index.html#minor-features-and-bug-fixes-3-2-0&#34;&gt;testthat 3.2.0 minor features&lt;/a&gt; lies a small gem:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;test_file()&lt;/code&gt; gains a desc argument which allows you to run a single test from a file. &lt;a href=&#34;https://github.com/r-lib/testthat/issues/1776&#34;&gt;#1776&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is huge! When I am struggling with a single test called &amp;ldquo;My great function works&amp;rdquo;, I can now call &lt;code&gt;devtools::test_active_file(desc = &amp;quot;My great function works&amp;quot;)&lt;/code&gt;! I&amp;rsquo;m not entirely sure yet it perfectly integrates with snapshot recording, but I&amp;rsquo;m very happy nonetheless.&lt;/p&gt;
&lt;p&gt;Now if I were struggling with more tests at a time (Remember, no one gets it right on their first try 😅), I should use the handy &lt;a href=&#34;https://github.com/cynkra/lazytest&#34;&gt;lazytest&lt;/a&gt; package.&lt;/p&gt;
&lt;h2 id=&#34;getting-back-to-the-package-directory-and-project&#34;&gt;Getting back to the package directory and project&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Update on 2023-10-16: here&amp;rsquo;s a &lt;a href=&#34;https://masalmon.eu/2023/10/16/test-local-mess-reset/&#34;&gt;better, more general solution to fix local mess from a test&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I recently realized that if&amp;hellip;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;you develop a package using RStudio IDE (which I do!);&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;your package tests change the current directory / the usethis project (for &lt;a href=&#34;https://github.com/cynkra/fledge&#34;&gt;reasons&lt;/a&gt; 😅 ) for instance with &lt;a href=&#34;https://withr.r-lib.org/reference/with_dir.html&#34;&gt;&lt;code&gt;withr::local_dir()&lt;/code&gt;&lt;/a&gt;/&lt;a href=&#34;https://usethis.r-lib.org/reference/proj_utils.html&#34;&gt;&lt;code&gt;usethis::local_project()&lt;/code&gt;&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;you run test code interactively &amp;amp; thus lose your current directory/project&amp;hellip;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;the wonderful &lt;code&gt;studioapi::getActiveProject()&lt;/code&gt; function remembers where the actual project, that is your package, is, very much like clicking on the RStudio hex logo in the Files tab.&lt;/p&gt;
&lt;p&gt;Based on that knowledge I added a helper function to the tests of a package I work on, to have it at hand after running &lt;a href=&#34;https://devtools.r-lib.org/reference/load_all.html&#34;&gt;&lt;code&gt;devtools::load_all()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;back_to_start &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;() {
  current_dev_project &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt;  rstudioapi&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;getActiveProject&lt;/span&gt;()
  &lt;span style=&#34;color:#06287e&#34;&gt;setwd&lt;/span&gt;(current_dev_project)
  usethis&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;proj_set&lt;/span&gt;(current_dev_project)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So I can make a mess in my console and then run &lt;code&gt;back_to_start()&lt;/code&gt; to get back where I started.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this short post I presented two recent enhancements to my testing workflow: the adoption of the new &lt;code&gt;desc&lt;/code&gt; argument of &lt;a href=&#34;https://testthat.r-lib.org/reference/test_file.html&#34;&gt;&lt;code&gt;testthat::test_file()&lt;/code&gt;&lt;/a&gt; to run one single test at a time; and the &amp;ldquo;discovery&amp;rdquo; of a handy way to find my way back to the package directory after experimenting in temporary toy directories.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How to translate your package&#39;s messages with {potools}</title>
      <link>https://masalmon.eu/2023/10/06/potools-mwe/</link>
      <pubDate>Fri, 06 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/10/06/potools-mwe/</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://rweekly.fireside.fm/140&#34;&gt;R Weekly highlights podcast&lt;/a&gt; hosted by Eric Nantz and Mike Thomas.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In November I&amp;rsquo;ll give a talk about multilingualism in R at the &lt;a href=&#34;https://eventum.upf.edu/101896/programme/ii-conference-of-r-and-xiii-workshop-for-r-users.html&#34;&gt;Spanish R conference&lt;/a&gt; in Barcelona (😍). I can&amp;rsquo;t wait! Until then, I need to prepare my talk. 😅 I plan to present &lt;a href=&#34;https://ropensci.org/multilingual-publishing/&#34;&gt;the rOpenSci &amp;ldquo;multilingual publishing&amp;rdquo; project&lt;/a&gt; but also other related tools, like potools. In this post, I&amp;rsquo;ll walk you through a minimal example of using potools to translate messages in an R package!&lt;/p&gt;
&lt;h2 id=&#34;what-is-potools&#34;&gt;What is potools?&lt;/h2&gt;
&lt;p&gt;In R, you can provide messages in different languages by using .po, .pot and .mo files. If you provide messages in English and their translation to Spanish, an user who sets the environment variable &lt;code&gt;LANGUAGE&lt;/code&gt; to es will get to see Spanish messages rather than the default English messages.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://michaelchirico.github.io/potools/&#34;&gt;potools package by Michael Chirico&lt;/a&gt; is the roxygen2 of .po, .pot and .mo files: as you could well write Rd files by hand&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, you could write the translation files by hand&amp;hellip; but things are easier with potools.&lt;/p&gt;
&lt;h2 id=&#34;create-package&#34;&gt;Create package&lt;/h2&gt;
&lt;p&gt;I create a package called &lt;a href=&#34;https://github.com/maelle/pockage&#34;&gt;pockage&lt;/a&gt;, with my usual usethis workflow. It initially has a single function, that tries to extract the user&amp;rsquo;s name via the whoami package, and then says hello using the cli package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; Say hello&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; @return Nothing&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; @export&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; @examples&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; speak()&lt;/span&gt;
speak &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;() {
  name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; whoami&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;fullname&lt;/span&gt;(fallback &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;)
  cli&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;cli_alert_info&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Hello {name}!&amp;#34;&lt;/span&gt;)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s try it out:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;pockage&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/pockage/man/speak.html&#39;&gt;speak&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BBBB;&#39;&gt;ℹ&lt;/span&gt; Hello Maëlle Salmon!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id=&#34;install-potools&#34;&gt;Install potools&lt;/h2&gt;
&lt;p&gt;I install potools from GitHub using &lt;code&gt;pak::pak(&amp;quot;MichaelChirico/potools&amp;quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;register-potools-style-in-description&#34;&gt;Register potools style in DESCRIPTION&lt;/h2&gt;
&lt;p&gt;I shall use potools explicit style, which means it will recognize strings as translatable only if I mark them as so. Therefore I add these lines to &lt;code&gt;DESCRIPTION&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Config/potools/style: explicit
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;create-tr_-function-and-use-it&#34;&gt;Create &lt;code&gt;tr_()&lt;/code&gt; function and use it&lt;/h2&gt;
&lt;p&gt;Following &lt;a href=&#34;https://michaelchirico.github.io/potools/articles/developers.html&#34;&gt;potools&amp;rsquo; vignette for developers&lt;/a&gt;, I run &lt;code&gt;usethis::use_r(&amp;quot;utils-potools&amp;quot;)&lt;/code&gt; and paste the definition an internal function in that new file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tr_ &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;...&lt;/span&gt;) {
  &lt;span style=&#34;color:#06287e&#34;&gt;enc2utf8&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;gettext&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;...&lt;/span&gt;), domain &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;R-pockage&amp;#34;&lt;/span&gt;))
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then modify the &lt;code&gt;speak()&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; Say hello&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; @return Nothing&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; @export&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; @examples&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; speak()&lt;/span&gt;
speak &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;() {
  name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; whoami&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;fullname&lt;/span&gt;(fallback &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;)
  cli&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;cli_alert_info&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;tr_&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Hello {name}!&amp;#34;&lt;/span&gt;))
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The difference is that the string &amp;ldquo;Hello {name}!&amp;rdquo; is now marked as translatable.&lt;/p&gt;
&lt;h2 id=&#34;create-the-general-translation-file&#34;&gt;Create the general translation file&lt;/h2&gt;
&lt;p&gt;I run &lt;a href=&#34;https://michaelchirico.github.io/potools/reference/po_extract.html&#34;&gt;&lt;code&gt;potools::po_extract()&lt;/code&gt;&lt;/a&gt; to create the &lt;code&gt;po/R-pockage.pot&lt;/code&gt; file.&lt;/p&gt;
&lt;h2 id=&#34;create-the-translation-file-for-french-and-fill-it&#34;&gt;Create the translation file for French and fill it&lt;/h2&gt;
&lt;p&gt;Then I run &lt;code&gt;potools::po_create(&amp;quot;fr&amp;quot;)&lt;/code&gt; to create the file holding the translation of the string to French.&lt;/p&gt;
&lt;p&gt;I obtain this &lt;code&gt;po/R-fr.po&lt;/code&gt; file where I edit two lines (Last-Translator, and msgstr at the bottom):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;msgid &amp;quot;&amp;quot;
msgstr &amp;quot;&amp;quot;
&amp;quot;Project-Id-Version: pockage 0.0.0.9000\n&amp;quot;
&amp;quot;POT-Creation-Date: 2023-10-06 10:45+0200\n&amp;quot;
&amp;quot;PO-Revision-Date: 2023-10-06 10:33+0200\n&amp;quot;
&amp;quot;Last-Translator: Malle Salmon\n&amp;quot;
&amp;quot;Language-Team: none\n&amp;quot;
&amp;quot;Language: fr\n&amp;quot;
&amp;quot;MIME-Version: 1.0\n&amp;quot;
&amp;quot;Content-Type: text/plain; charset=ASCII\n&amp;quot;
&amp;quot;Content-Transfer-Encoding: 8bit\n&amp;quot;
&amp;quot;Plural-Forms: nplurals=2; plural=(n &amp;gt; 1);\n&amp;quot;

#: mensaje.R:9
msgid &amp;quot;user&amp;quot;
msgstr &amp;quot;utilisateur·rice&amp;quot;

#: mensaje.R:10
msgid &amp;quot;Hello {name}!&amp;quot;
msgstr &amp;quot;Salut {name} !&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;compile-the-translation&#34;&gt;Compile the translation&lt;/h2&gt;
&lt;p&gt;I compile with &lt;a href=&#34;https://michaelchirico.github.io/potools/reference/po_compile.html&#34;&gt;&lt;code&gt;potools::po_compile()&lt;/code&gt;&lt;/a&gt; which creates the &lt;code&gt;.mo&lt;/code&gt; binary for the French language in &lt;code&gt;inst/po&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;try-out-the-translation&#34;&gt;Try out the translation&lt;/h2&gt;
&lt;p&gt;I load or install&amp;amp;load the package, then I use the following code, magically using &lt;code&gt;withr&lt;/code&gt; to set the &lt;code&gt;LANGUAGE&lt;/code&gt; environment variable locally:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_language.html&#39;&gt;with_language&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;fr&#34;&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;pockage&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/pockage/man/speak.html&#39;&gt;speak&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BBBB;&#39;&gt;ℹ&lt;/span&gt; Salut Maëlle Salmon !&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# as opposed to&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;pockage&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/pockage/man/speak.html&#39;&gt;speak&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BBBB;&#39;&gt;ℹ&lt;/span&gt; Salut Maëlle Salmon !&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Quite neat, right?&lt;/p&gt;
&lt;h2 id=&#34;add-languages&#34;&gt;Add languages&lt;/h2&gt;
&lt;p&gt;I then add two other languages, unstoppable as I am now, by running &lt;code&gt;potools::po_create(c(&amp;quot;es&amp;quot;, &amp;quot;ca&amp;quot;))&lt;/code&gt;. I add the Spanish and Catalan translations of the string in respectively &lt;code&gt;po/R-es.po&lt;/code&gt; and &lt;code&gt;po/R-ca.po&lt;/code&gt;. I compile with &lt;a href=&#34;https://michaelchirico.github.io/potools/reference/po_compile.html&#34;&gt;&lt;code&gt;potools::po_compile()&lt;/code&gt;&lt;/a&gt; which creates the &lt;code&gt;.mo&lt;/code&gt; binary for the Spanish and Catalan languages in &lt;code&gt;inst/po&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After installing the pockage package again, I get:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_language.html&#39;&gt;with_language&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;fr&#34;&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;pockage&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/pockage/man/speak.html&#39;&gt;speak&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BBBB;&#39;&gt;ℹ&lt;/span&gt; Salut Maëlle Salmon !&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_language.html&#39;&gt;with_language&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;es&#34;&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;pockage&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/pockage/man/speak.html&#39;&gt;speak&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BBBB;&#39;&gt;ℹ&lt;/span&gt; Hola Maëlle Salmon!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# I swear it&#39;s pronounced differently&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_language.html&#39;&gt;with_language&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;ca&#34;&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;pockage&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/pockage/man/speak.html&#39;&gt;speak&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BBBB;&#39;&gt;ℹ&lt;/span&gt; Hola Maëlle Salmon!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id=&#34;translate-more-strings&#34;&gt;Translate more strings&lt;/h2&gt;
&lt;p&gt;Now imagine I also want to translate the fallback of the whoami function call, for the case whoami can&amp;rsquo;t identify the user.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; Say hello&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; @return Nothing&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; @export&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39;&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; @examples&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#&amp;#39; speak()&lt;/span&gt;
speak &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;() {
  name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; whoami&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;fullname&lt;/span&gt;(fallback &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tr_&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;))
  cli&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;cli_alert_info&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;tr_&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Hello {name}!&amp;#34;&lt;/span&gt;))
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I run&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://michaelchirico.github.io/potools/reference/po_extract.html&#34;&gt;&lt;code&gt;potools::po_extract()&lt;/code&gt;&lt;/a&gt; again;&lt;/li&gt;
&lt;li&gt;then &lt;a href=&#34;https://michaelchirico.github.io/potools/reference/po_update.html&#34;&gt;&lt;code&gt;potools::po_update()&lt;/code&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;after which I need to go add a msgstr under &lt;code&gt;msgid &amp;quot;user&amp;quot;&lt;/code&gt; in &lt;code&gt;po/R-fr.po&lt;/code&gt;, &lt;code&gt;po/R-es.po&lt;/code&gt;, &lt;code&gt;po/R-ca.po&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;finally I run &lt;a href=&#34;https://michaelchirico.github.io/potools/reference/po_compile.html&#34;&gt;&lt;code&gt;potools::po_compile()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Find my final pockage package on &lt;a href=&#34;https://github.com/maelle/pockage&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To translate messages with potools in the explicit style one needs to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;register the potools style in &lt;code&gt;DESCRIPTION&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;create and use a &lt;code&gt;tr_()&lt;/code&gt; internal function to wrap strings to be translated;&lt;/li&gt;
&lt;li&gt;run &lt;a href=&#34;https://michaelchirico.github.io/potools/reference/po_extract.html&#34;&gt;&lt;code&gt;potools::po_extract()&lt;/code&gt;&lt;/a&gt; at the beginning of the translation efforts and every time strings wrapped in &lt;code&gt;tr_()&lt;/code&gt; are changed, deleted, added;&lt;/li&gt;
&lt;li&gt;run &lt;a href=&#34;https://michaelchirico.github.io/potools/reference/po_create.html&#34;&gt;&lt;code&gt;potools::po_create()&lt;/code&gt;&lt;/a&gt; once per non-default language to be supported;&lt;/li&gt;
&lt;li&gt;run &lt;a href=&#34;https://michaelchirico.github.io/potools/reference/po_update.html&#34;&gt;&lt;code&gt;potools::po_update()&lt;/code&gt;&lt;/a&gt; after &lt;a href=&#34;https://michaelchirico.github.io/potools/reference/po_extract.html&#34;&gt;&lt;code&gt;potools::po_extract()&lt;/code&gt;&lt;/a&gt; every time strings wrapped in &lt;code&gt;tr_()&lt;/code&gt; are changed, deleted, added;&lt;/li&gt;
&lt;li&gt;run &lt;a href=&#34;https://michaelchirico.github.io/potools/reference/po_compile.html&#34;&gt;&lt;code&gt;potools::po_compile()&lt;/code&gt;&lt;/a&gt; every time the translation source files are changed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;potools has one vignette for &lt;a href=&#34;https://michaelchirico.github.io/potools/articles/developers.html&#34;&gt;developers&lt;/a&gt; and one for &lt;a href=&#34;https://michaelchirico.github.io/potools/articles/translators.html&#34;&gt;translators&lt;/a&gt; that I&amp;rsquo;d recommend reading, because they provide useful advice beyond the basic workflow that I illustrated here.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;which is what I first learnt to do years and years ago. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>3 R functions that I enjoy</title>
      <link>https://masalmon.eu/2023/09/29/three-functions/</link>
      <pubDate>Fri, 29 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/09/29/three-functions/</guid>
      <description>&lt;p&gt;Straight from my sticky note, three functions that I like a lot, despite their not being new at all&amp;hellip; But maybe new to some of you?&lt;/p&gt;
&lt;h2 id=&#34;sprintf-the-dependency-free-but-less-neat-glue&#34;&gt;&lt;code&gt;sprintf()&lt;/code&gt;, the dependency-free but less neat &amp;ldquo;glue&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;Imagine I want to tell you who I am.&lt;/p&gt;
&lt;p&gt;I could write&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;name&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;whoami&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/whoami/man/fullname.html&#39;&gt;fullname&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;github_username&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;whoami&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/whoami/man/gh_username.html&#39;&gt;gh_username&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;glue&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://glue.tidyverse.org/reference/glue.html&#39;&gt;glue&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;My name is &amp;#123;name&amp;#125; and you&#39;ll find me on GitHub as &amp;#123;github_username&amp;#125;!&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; My name is Maëlle Salmon and you&#39;ll find me on GitHub as maelle!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;(Maybe the &lt;a href=&#34;https://r-lib.github.io/whoami/&#34;&gt;whoami&lt;/a&gt; package by Gábor Csárdi is a sub topic of this section?! So handy!)&lt;/p&gt;
&lt;p&gt;The code above is very readable. The nice syntax with curly braces is something one finds again in the &lt;a href=&#34;https://cli.r-lib.org/&#34;&gt;cli package&lt;/a&gt;.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Now, there&amp;rsquo;s a dependency-free version of the glue code! Albeit a bit uglier 🤐&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;name&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;whoami&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/whoami/man/fullname.html&#39;&gt;fullname&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;github_username&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;whoami&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/whoami/man/gh_username.html&#39;&gt;gh_username&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/sprintf.html&#39;&gt;sprintf&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;My name is %s and you&#39;ll find me on GitHub as %s!&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;name&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;github_username&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;My name is Maëlle Salmon and you&#39;ll find me on GitHub as maelle!&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Sure it&amp;rsquo;s less readable, since the replacements are identified by their position, but I often find myself using it! I clearly remember seeing it in other people&amp;rsquo;s code and wondering what that was.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a pattern one finds in other languages: the manual page for the function states &amp;ldquo;Use C-style String Formatting Commands&amp;rdquo;, and I know the &lt;a href=&#34;https://gohugo.io/functions/printf/&#34;&gt;Hugo equivalent&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;append-and-its-after-argument&#34;&gt;&lt;code&gt;append()&lt;/code&gt; and its after argument&lt;/h2&gt;
&lt;p&gt;To append values to a vector, I mostly use &lt;a href=&#34;https://rdrr.io/r/base/c.html&#34;&gt;&lt;code&gt;c()&lt;/code&gt;&lt;/a&gt;, but I recently discovered the base R function &lt;a href=&#34;https://rdrr.io/r/base/append.html&#34;&gt;&lt;code&gt;append()&lt;/code&gt;&lt;/a&gt; and its &lt;code&gt;after&lt;/code&gt; argument that indicates where to include the new values! By default, the values are appended at the end of the vector.&lt;/p&gt;
&lt;p&gt;I most recently used &lt;a href=&#34;https://rdrr.io/r/base/append.html&#34;&gt;&lt;code&gt;append()&lt;/code&gt;&lt;/a&gt; to create a &lt;a href=&#34;https://github.com/ropensci-review-tools/babeldown/blob/8e0fe9626c8ebe7cb70839b7751dfa803789107a/tests/testthat/test-translate-hugo.R#L12&#34;&gt;test fixture&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;thing&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;stuff&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;element&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;values&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;bla&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;blop&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/append.html&#39;&gt;append&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;values&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;thing&#34;   &#34;stuff&#34;   &#34;element&#34; &#34;bla&#34;     &#34;blop&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/append.html&#39;&gt;append&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;values&lt;/span&gt;, after &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;thing&#34;   &#34;stuff&#34;   &#34;bla&#34;     &#34;blop&#34;    &#34;element&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s not a function I use every day, but it can come in handy depending on what you&amp;rsquo;re doing!&lt;/p&gt;
&lt;p&gt;For my fellow XML fans out there, it reminds me of the &lt;code&gt;.where&lt;/code&gt; argument of &lt;a href=&#34;http://xml2.r-lib.org/reference/xml_replace.html&#34;&gt;&lt;code&gt;xml2::xml_add_sibling()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;http://xml2.r-lib.org/reference/xml_replace.html&#34;&gt;&lt;code&gt;xml2::xml_add_child()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;servrhttw-to-serve-a-local-directory-as-a-website&#34;&gt;&lt;code&gt;servr::httw()&lt;/code&gt; to serve a local directory as a website&lt;/h2&gt;
&lt;p&gt;Do you know about the &lt;a href=&#34;https://github.com/yihui/servr&#34;&gt;servr package by Yihui Xie&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;Its use case is having a local directory that is the source of a website, and wanting to preview it locally in your browser as if it were served by a real server.&lt;/p&gt;
&lt;p&gt;I make use of it when working on the &lt;a href=&#34;https://docs.ropensci.org/babelquarto/&#34;&gt;babelquarto&lt;/a&gt; package for instance, that builds multilingual Quarto books or websites. In the code of the multilingual books/websites, links to the other language versions are relative so they don&amp;rsquo;t work if I simply open HTML files in my browser. So, instead, I write &lt;code&gt;servr::httw(&amp;lt;directory-with-the-website-source&amp;gt;)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can also use servr if you want to preview locally your pkgdown website and be able to use the &lt;a href=&#34;https://pkgdown.r-lib.org/articles/search.html#bootstrap-5-built-in-search&#34;&gt;search function&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s &lt;a href=&#34;https://rdrr.io/pkg/servr/man/httd.html&#34;&gt;&lt;code&gt;servr::httw()&lt;/code&gt;&lt;/a&gt; that watches changes in the directory, and the more simple &lt;a href=&#34;https://rdrr.io/pkg/servr/man/httd.html&#34;&gt;&lt;code&gt;servr::httd()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Today I shared about &lt;a href=&#34;https://rdrr.io/r/base/sprintf.html&#34;&gt;&lt;code&gt;sprintf()&lt;/code&gt;&lt;/a&gt; for glue-like functionality, &lt;a href=&#34;https://rdrr.io/r/base/append.html&#34;&gt;&lt;code&gt;append()&lt;/code&gt;&lt;/a&gt; and its &lt;code&gt;after&lt;/code&gt; argument for appending values where you want in a vector, and &lt;a href=&#34;https://rdrr.io/pkg/servr/man/httd.html&#34;&gt;&lt;code&gt;servr::httw()&lt;/code&gt;&lt;/a&gt; for serving static files.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Curious about cli? Come to this cool &lt;a href=&#34;https://ropensci.org/events/coworking-2023-10/&#34;&gt;rOpenSci coworking session next week&lt;/a&gt;! &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>R functions that shorten/filter stuff: less is more</title>
      <link>https://masalmon.eu/2023/08/31/three-shorten/</link>
      <pubDate>Thu, 31 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/08/31/three-shorten/</guid>
      <description>&lt;p&gt;My sticky note is full! And luckily all functions on it can be squeezed into a similar topic: making things smaller!&lt;/p&gt;
&lt;h2 id=&#34;make-lists-smaller-with-purrrcompact-purrrkeep-purrrdiscard&#34;&gt;Make lists smaller with &lt;code&gt;purrr::compact()&lt;/code&gt;, &lt;code&gt;purrr::keep()&lt;/code&gt;, &lt;code&gt;purrr::discard()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Once upon a time there was a list (isn&amp;rsquo;t this the beginning of all R scripts?!)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;my_list&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  name &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;Maëlle&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  city &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;Nancy&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  r_problems_encountered &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;Inf&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  python_skills &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;NULL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Imagine you want to get rid of &lt;code&gt;NULL&lt;/code&gt; elements. That&amp;rsquo;s what &lt;a href=&#34;https://purrr.tidyverse.org/reference/keep.html&#34;&gt;&lt;code&gt;purrr::compact()&lt;/code&gt;&lt;/a&gt; does!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/keep.html&#39;&gt;compact&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;my_list&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $name&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;Maëlle&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $city&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;Nancy&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $r_problems_encountered&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] Inf&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Imagine you want to only keep elements that are infinite numbers. For some unknown reason &lt;a href=&#34;https://rdrr.io/r/base/is.finite.html&#34;&gt;&lt;code&gt;is.infinite()&lt;/code&gt;&lt;/a&gt; works on strings (but not on &lt;code&gt;NULL&lt;/code&gt;) so the following works.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;my_list&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/keep.html&#39;&gt;compact&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;|&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/keep.html&#39;&gt;keep&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;is.infinite&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $r_problems_encountered&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] Inf&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Similarly, imagine you want to discard all elements that are character.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/keep.html&#39;&gt;discard&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;my_list&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;is.character&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $r_problems_encountered&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] Inf&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $python_skills&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; NULL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;We&amp;rsquo;ve only used built-in functions as predicate functions (the second argument of all these calls). You can really unleash the power of these three functions when pairing them with your own predicate functions!&lt;/p&gt;
&lt;p&gt;Related to these functions, don&amp;rsquo;t miss Jonathan Carroll&amp;rsquo;s great post &lt;a href=&#34;https://jcarroll.com.au/2023/08/30/four-filters-for-functional-programming-friends/&#34;&gt;&amp;ldquo;Four Filters for Functional (Programming) Friends&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;make-string-vectors-smaller-with-stringrstr_squish-stringrstr_subset&#34;&gt;Make string (vectors) smaller with &lt;code&gt;stringr::str_squish()&lt;/code&gt;, &lt;code&gt;stringr::str_subset()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;This week when removing stringr from the dependencies of the &lt;a href=&#34;https://github.com/lvaudor/glitter&#34;&gt;glitter&lt;/a&gt; package I discovered &lt;a href=&#34;https://stringr.tidyverse.org/reference/str_subset.html&#34;&gt;&lt;code&gt;stringr::str_subset()&lt;/code&gt;&lt;/a&gt;. It will help you keep, in purrr&amp;rsquo;s parlance, only the elements of a string vector that have a match with a pattern.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;string&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;R&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;Python&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;Julia&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;Ruby&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;stringr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://stringr.tidyverse.org/reference/str_subset.html&#39;&gt;str_subset&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;string&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;R&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;R&#34;    &#34;Ruby&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It will also help you discard them if you use the &lt;code&gt;negate&lt;/code&gt; arguments.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;stringr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://stringr.tidyverse.org/reference/str_subset.html&#39;&gt;str_subset&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;string&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;R&#34;&lt;/span&gt;, negate &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;Python&#34; &#34;Julia&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;In glitter, where I chose to write similar-looking functions for the stringr functions that we used, I replaced &lt;a href=&#34;https://stringr.tidyverse.org/reference/str_subset.html&#34;&gt;&lt;code&gt;stringr::str_subset()&lt;/code&gt;&lt;/a&gt; with&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;str_subset &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x, pattern, negate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;) {
  &lt;span style=&#34;color:#06287e&#34;&gt;grep&lt;/span&gt;(pattern, x, value &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;, invert &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; negate)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;since its docs mentioned this base R&amp;rsquo;s equivalence.&lt;/p&gt;
&lt;p&gt;Another stringr function that makes things smaller is &lt;a href=&#34;https://stringr.tidyverse.org/reference/str_trim.html&#34;&gt;&lt;code&gt;stringr::str_squish()&lt;/code&gt;&lt;/a&gt; that removes useless whitespace from a string vector: whitespace at the start and end, and repeated whitespace in the middle.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;text&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34; So much\n\n useless    whitespace    &#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;stringr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://stringr.tidyverse.org/reference/str_trim.html&#39;&gt;str_squish&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;text&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;So much useless whitespace&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s documented on the same page as &lt;a href=&#34;https://stringr.tidyverse.org/reference/str_trim.html&#34;&gt;&lt;code&gt;stringr::str_trim()&lt;/code&gt;&lt;/a&gt; which is stringr&amp;rsquo;s own &lt;a href=&#34;https://rdrr.io/r/base/trimws.html&#34;&gt;&lt;code&gt;trimws()&lt;/code&gt;&lt;/a&gt; (a base R function) that only removes whitespace from the start and end. 💇&lt;/p&gt;
&lt;h2 id=&#34;make-your-code-shorter-with-purrrpartial&#34;&gt;Make your code shorter with &lt;code&gt;purrr::partial()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I am working on a vignette for glitter where I write (well, copy-paste) the same function call over and over again.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;blablabla &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;spq_perform&lt;/span&gt;(
    endpoint &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://ld.admin.ch/query&amp;#34;&lt;/span&gt;, 
    request_type &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;body-form&amp;#34;&lt;/span&gt;
  )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From the developer&amp;rsquo;s perspective it makes me wonder whether we should add some options as default. From an user&amp;rsquo;s perspective it reminded me of &lt;a href=&#34;https://purrr.tidyverse.org/reference/partial.html&#34;&gt;&lt;code&gt;purrr::partial()&lt;/code&gt;&lt;/a&gt;! With &lt;a href=&#34;https://purrr.tidyverse.org/reference/partial.html&#34;&gt;&lt;code&gt;purrr::partial&lt;/code&gt;&lt;/a&gt; one easily creates a function that corresponds to a function with some arguments pre-filled.&lt;/p&gt;
&lt;p&gt;So, as a glitter user, I could use&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;my_spq_perform &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;partial&lt;/span&gt;(
    spq_perform,
    endpoint &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://ld.admin.ch/query&amp;#34;&lt;/span&gt;, 
    request_type &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;body-form&amp;#34;&lt;/span&gt;
)

blablabla &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  my_spq_perform
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Quite neat!&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this short (of course) post I presented functions for making lists, string vectors and code shorter by filtering or squishing them. 🔨&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Three (four?) R functions I enjoyed this week</title>
      <link>https://masalmon.eu/2023/08/30/three-r-functions/</link>
      <pubDate>Wed, 30 Aug 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/08/30/three-r-functions/</guid>
      <description>&lt;p&gt;There are already three functions of note on a piece of paper on my desk, so it&amp;rsquo;s time to blog about them!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://podverse.fm/episode/tUcOmY5AN&#34;&gt;R Weekly podcast&lt;/a&gt; by Eric Nantz and Mike Thomas.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;how-does-this-package-depend-on-this-other-package-pakpkg_deps_explainhttpspakr-liborgreferencepkg_deps_explainhtml&#34;&gt;How does this package depend on this other package? &lt;a href=&#34;https://pak.r-lib.org/reference/pkg_deps_explain.html&#34;&gt;&lt;code&gt;pak::pkg_deps_explain()&lt;/code&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&#34;https://pak.r-lib.org&#34;&gt;pak package by Gábor Csárdi&lt;/a&gt; makes installing packages easier. If I need to start working on a package, I clone it, then run &lt;a href=&#34;https://pak.r-lib.org/reference/pak.html#details&#34;&gt;&lt;code&gt;pak::pak()&lt;/code&gt;&lt;/a&gt; to install and update its dependencies. It&amp;rsquo;s a &amp;ldquo;convenience function&amp;rdquo; that is convenient for sure! Bye bye &lt;a href=&#34;https://remotes.r-lib.org/reference/install_deps.html&#34;&gt;&lt;code&gt;remotes::install_deps()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Anyway, pak is truly a treasure trove, even for challenges that happen less often. Earlier this week I was seeing an error in a GitHub Actions log due to a package that I didn&amp;rsquo;t know was a dependency of the package I was working on. It was clearly not a direct dependency, it was not listed in &lt;code&gt;DESCRIPTION&lt;/code&gt;. It was a dependency of a dependency and I couldn&amp;rsquo;t guess which one it was&amp;hellip; Luckily one doesn&amp;rsquo;t need to guess! Although I didn&amp;rsquo;t think of it right away, the &lt;a href=&#34;https://pak.r-lib.org/reference/pkg_deps_explain.html&#34;&gt;&lt;code&gt;pak::pkg_deps_explain()&lt;/code&gt;&lt;/a&gt; is my friend in such cases&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;!&lt;/p&gt;
&lt;p&gt;For instance, if you are wondering why usethis depends on httr2,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;pak&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://pak.r-lib.org/reference/pkg_deps_explain.html&#39;&gt;pkg_deps_explain&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;usethis&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;httr2&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BB00;&#39;&gt;✔&lt;/span&gt; Updated metadata database: 3.97 MB in 4 files.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BBBB;&#39;&gt;ℹ&lt;/span&gt; Updating metadata database&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #00BB00;&#39;&gt;✔&lt;/span&gt; Updating metadata database ... done&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; usethis -&amp;gt; gh -&amp;gt; httr2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;usethis depends on gh (client for GitHub API) that in turns depends on httr2.&lt;/p&gt;
&lt;p&gt;Next time I encounter a similar problem I can only hope I&amp;rsquo;ll remember about this function sooner!&lt;/p&gt;
&lt;h2 id=&#34;where-in-the-file-are-there-non-ascii-characters-toolsshownonasciifile&#34;&gt;Where in the file are there non ASCII characters? &lt;code&gt;tools::showNonASCIIfile()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;If you get the dreaded R CMD check WARNING &amp;ldquo;Found the following file with non-ASCII characters&amp;rdquo; and can&amp;rsquo;t see at once what character that is in the file, you don&amp;rsquo;t need to comb through each line of code. You can simply run &lt;code&gt;tools::showNonASCIIfile(&amp;lt;filename&amp;gt;)&lt;/code&gt;. After that an easy fix can be to replace then with the &lt;code&gt;\uxxxx&lt;/code&gt; escape as indicated in the WARNING. I&amp;rsquo;m not saying it&amp;rsquo;s always that easy but that&amp;rsquo;s what happened to me this week! I found the correct escape by using a search engine.&lt;/p&gt;
&lt;h2 id=&#34;how-do-these-two-text-files-differ-toolsrdiff-or-gertgit_diff_patch&#34;&gt;How do these two text files differ? &lt;code&gt;tools::Rdiff()&lt;/code&gt; or &lt;code&gt;gert::git_diff_patch()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m working on the &lt;a href=&#34;https://docs.ropensci.org/babeldown/&#34;&gt;babeldown R package&lt;/a&gt; that helps translate mostly Markdown files. Support for first-time automatic translation is there, but a next step is to add support for automatic update of a translation based on a git commit. Say I have a file in English and its translation in Spanish and a contributor edits part of the Spanish file. We want to have a function update the English file based on this diff. As part of that work I need to programmatically parse the difference between two text files.&lt;/p&gt;
&lt;p&gt;I saw &lt;a href=&#34;https://docs.ropensci.org/gert/reference/git_diff.html&#34;&gt;&lt;code&gt;gert::git_diff()&lt;/code&gt;&lt;/a&gt; but I didn&amp;rsquo;t find the patch to be easily parsable.&lt;/p&gt;
&lt;p&gt;I had better luck with &lt;a href=&#34;https://rdrr.io/r/tools/Rdiff.html&#34;&gt;&lt;code&gt;tools::Rdiff()&lt;/code&gt;&lt;/a&gt; especially after a GitHub search showed me an example using it with &lt;code&gt;Log = TRUE&lt;/code&gt;. Before that I was unsuccessfully trying &lt;a href=&#34;https://rdrr.io/r/utils/capture.output.html&#34;&gt;&lt;code&gt;capture.output()&lt;/code&gt;&lt;/a&gt; to capture what was printed&amp;hellip; I should have read the arguments list more carefully.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;original_lines&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;# Title&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;## Subtitle&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;Some info&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;First line of a paragraph&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;Second line of a paragraph&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;amended_lines&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;# BIG Title&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;## Subtitle&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;Some info&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;First line of a paragraph&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;Second line of a paragraph&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;More info&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;file1&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_tempfile.html&#39;&gt;local_tempfile&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;file2&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_tempfile.html&#39;&gt;local_tempfile&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;original_lines&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;file1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;amended_lines&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;file2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;diff&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;tools&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/tools/Rdiff.html&#39;&gt;Rdiff&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;file1&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;file2&lt;/span&gt;, Log &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; files differ in number of lines:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;diff&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $status&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $out&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;files differ in number of lines&#34; &#34;1c1&#34;                            &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [3] &#34;&amp;lt; # Title&#34;                       &#34;---&#34;                            &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [5] &#34;&amp;gt; # BIG Title&#34;                   &#34;8a9&#34;                            &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [7] &#34;&amp;gt; More info&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;What I especially liked in this output, is the lines &lt;code&gt;&amp;lt;line-numbers-in-original-file&amp;gt;&amp;lt;letter-indicated-status&amp;gt;&amp;lt;line-numbers-in-new-file&amp;gt;&lt;/code&gt; where the status can be a (added), d (deleted) or c (changed).&lt;/p&gt;
&lt;p&gt;In comparison here&amp;rsquo;s what gert gives me.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;dir&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_tempfile.html&#39;&gt;local_tempdir&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_repo.html&#39;&gt;git_init&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;dir&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;original_lines&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/file.path.html&#39;&gt;file.path&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;dir&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;file.txt&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_add&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;file.txt&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;dir&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       file status staged&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 file.txt    new   TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_commit&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;first commit&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;dir&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;b56a48d10dc033e4c6a3bb81be6e18d27b34032a&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;brio&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://brio.r-lib.org/reference/write_lines.html&#39;&gt;write_lines&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;amended_lines&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/file.path.html&#39;&gt;file.path&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;dir&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;file.txt&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_add&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;file.txt&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;dir&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;       file   status staged&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1 file.txt modified   TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;commit_of_interest&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_commit.html&#39;&gt;git_commit&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;second commit&#34;&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;dir&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/cat.html&#39;&gt;cat&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;gert&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/gert/reference/git_diff.html&#39;&gt;git_diff_patch&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;commit_of_interest&lt;/span&gt;, repo &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;dir&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; diff --git a/file.txt b/file.txt&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; index 6d79a01..44a4269 100644&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; --- a/file.txt&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; +++ b/file.txt&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; @@ -1,4 +1,4 @@&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; -# Title&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; +# BIG Title&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;  ## Subtitle&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; @@ -6,3 +6,4 @@ Some info&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;  First line of a paragraph&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;  Second line of a paragraph&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; +More info&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;rsquo;m not exactly sure yet whether &lt;a href=&#34;https://rdrr.io/r/tools/Rdiff.html&#34;&gt;&lt;code&gt;tools::Rdiff()&lt;/code&gt;&lt;/a&gt; will be enough for my &lt;a href=&#34;https://mastodon.social/deck/@maelle/110972627375018302&#34;&gt;use case&lt;/a&gt; but it might!&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;My sticky note mentioned &lt;a href=&#34;https://pak.r-lib.org/reference/pkg_deps_explain.html&#34;&gt;&lt;code&gt;pak::pkg_deps_explain()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://rdrr.io/r/tools/showNonASCII.html&#34;&gt;&lt;code&gt;tools::showNonASCIIfile()&lt;/code&gt;&lt;/a&gt; (what case is this 😅) and &lt;a href=&#34;https://rdrr.io/r/tools/Rdiff.html&#34;&gt;&lt;code&gt;tools::Rdiff()&lt;/code&gt;&lt;/a&gt;, that helped me make progress on R code earlier this week. Time to break out a fresh sticky note and see what ends up on it!&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I first wrote it &amp;ldquo;pak_deps_explain&amp;rdquo; instead of &amp;ldquo;pkg_deps_explain&amp;rdquo;. 😬 &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Reducing my for loop usage with purrr::reduce()</title>
      <link>https://masalmon.eu/2023/07/26/reduce/</link>
      <pubDate>Wed, 26 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/07/26/reduce/</guid>
      <description>&lt;p&gt;I (only! but luckily!) recently got introduced to the magic of &lt;a href=&#34;https://purrr.tidyverse.org/reference/reduce.html&#34;&gt;&lt;code&gt;purrr::reduce()&lt;/code&gt;&lt;/a&gt;. &lt;em&gt;Thank you, &lt;a href=&#34;https://github.com/TSchiefer&#34;&gt;Tobias&lt;/a&gt;!&lt;/em&gt; I was told about it right as I was unhappily using many for loops in a package&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, for lack of a better idea. In this post I&amp;rsquo;ll explain how &lt;a href=&#34;https://purrr.tidyverse.org/reference/reduce.html&#34;&gt;&lt;code&gt;purrr::reduce()&lt;/code&gt;&lt;/a&gt; helped me reduce my for loop usage. I also hope that if I&amp;rsquo;m doing something wrong, &lt;a href=&#34;https://xkcd.com/386/&#34;&gt;someone will come forward and tell me&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://podverse.fm/episode/1odIoSlJl&#34;&gt;R Weekly podcast&lt;/a&gt; by Eric Nantz and Mike Thomas.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;before-many-for-much-sadness&#34;&gt;Before: many for, much sadness&lt;/h2&gt;
&lt;p&gt;I was starting from a thing, that could be a list, or even a data.frame. Then for a bunch of variables, I tweaked the thing. My initial coding pattern was therefore:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;kr&#39;&gt;for&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;var&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;in&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;variables_vector&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;do_something&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;var&lt;/span&gt;, other_argument &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;other_argument&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I was iteratively changing the thing, along a &lt;code&gt;variables_vector&lt;/code&gt;, or sometimes a &lt;code&gt;variables_list&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;silly-example&#34;&gt;Silly example&lt;/h3&gt;
&lt;p&gt;Ugh, finding an example is hard, it feels very contrived but I promise my real-life adoption of &lt;code&gt;purrr::usage()&lt;/code&gt; was life-changing!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# Some basic movie information&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;tibble&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://tibble.tidyverse.org/reference/tribble.html&#39;&gt;tribble&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;o&#39;&gt;~&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;title&lt;/span&gt;, &lt;span class=&#39;o&#39;&gt;~&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;color&lt;/span&gt;, &lt;span class=&#39;o&#39;&gt;~&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;elements&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;Barbie&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;pink&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;shoes&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;Oppenheimer&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;red&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;history&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# More information to add to movies&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;info_list&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;title &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;Barbie&#34;&lt;/span&gt;, info &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;element &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;sparkles&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;title &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;Barbie&#34;&lt;/span&gt;, info &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;element &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;feminism&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;title &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;Oppenheimer&#34;&lt;/span&gt;, info &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;element &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;fire&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# Don&#39;t tell me this is weirdly formatted data,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# who never obtains weirdly formatted data?!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;info_list&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[1]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[1]]$title&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;Barbie&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[1]]$info&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[1]]$info$element&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;sparkles&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[2]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[2]]$title&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;Barbie&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[2]]$info&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[2]]$info$element&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;feminism&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[3]]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[3]]$title&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;Oppenheimer&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[3]]$info&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [[3]]$info$element&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;fire&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;add_element&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;,&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;elements&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/toString.html&#39;&gt;toString&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;,&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;elements&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;info&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now how do I add each element of the list to the original table? I could type something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;kr&#39;&gt;for&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;in&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;info_list&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;add_element&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;# A tibble: 2 × 3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   title       color elements                 &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;       &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt; &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;                    &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;1&lt;/span&gt; Barbie      pink  shoes, sparkles, feminism&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;2&lt;/span&gt; Oppenheimer red   history, fire&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s not too bad, really. But since there&amp;rsquo;s another way, we can change it.&lt;/p&gt;
&lt;h2 id=&#34;after&#34;&gt;After&lt;/h2&gt;
&lt;p&gt;With &lt;a href=&#34;https://purrr.tidyverse.org/reference/reduce.html&#34;&gt;&lt;code&gt;purrr::reduce()&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;kr&#39;&gt;for&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;var&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;in&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;variables_vector&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;do_something&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;var&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;can become&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/reduce.html&#39;&gt;reduce&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;variables_vector&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;do_something&lt;/span&gt;, .init &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And (notice the other argument),&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;kr&#39;&gt;for&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;var&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;in&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;variables_vector&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;do_something&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;var&lt;/span&gt;, other_argument &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;other_argument&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;can become&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/reduce.html&#39;&gt;reduce&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;variables_vector&lt;/span&gt;, &lt;/span&gt;
&lt;span&gt;  \&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;do_something&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, other_argument &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;other_argument&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;, &lt;/span&gt;
&lt;span&gt;  .init &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;thing&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I haven&amp;rsquo;t completely internalized the pattern above but the &lt;a href=&#34;https://purrr.tidyverse.org/reference/reduce.html#arguments&#34;&gt;documentation of &lt;code&gt;purrr::reduce()&lt;/code&gt;&lt;/a&gt; states&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;We now generally recommend against using &amp;hellip; to pass additional (constant) arguments to .f. Instead use a shorthand anonymous function:&lt;/p&gt;
&lt;p&gt;Instead of x |&amp;gt; map(f, 1, 2, collapse = &amp;ldquo;,&amp;quot;) do: x |&amp;gt; map((x) f(x, 1, 2, collapse = &amp;ldquo;,&amp;quot;)) This makes it easier to understand which arguments belong to which function and will tend to yield better error messages.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It might remind you of how things work for &lt;a href=&#34;https://dplyr.tidyverse.org/reference/across.html&#34;&gt;&lt;code&gt;dplyr::across()&lt;/code&gt;&lt;/a&gt; &lt;a href=&#34;https://mastodon.social/deck/@blasbenito@fosstodon.org/110745684166845628&#34;&gt;these days&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;back-to-our-silly-example&#34;&gt;Back to our silly example!&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# Some basic movie information&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;tibble&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://tibble.tidyverse.org/reference/tribble.html&#39;&gt;tribble&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;o&#39;&gt;~&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;title&lt;/span&gt;, &lt;span class=&#39;o&#39;&gt;~&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;color&lt;/span&gt;, &lt;span class=&#39;o&#39;&gt;~&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;elements&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;Barbie&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;pink&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;shoes&#34;&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;s&#39;&gt;&#34;Oppenheimer&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;red&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;history&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# More information to add to movies&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;info_list&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;title &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;Barbie&#34;&lt;/span&gt;, info &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;element &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;sparkles&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;title &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;Barbie&#34;&lt;/span&gt;, info &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;element &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;feminism&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;title &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;Oppenheimer&#34;&lt;/span&gt;, info &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;element &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;fire&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;add_element&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;,&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;elements&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/toString.html&#39;&gt;toString&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;,&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;elements&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;info&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/reduce.html&#39;&gt;reduce&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;info_list&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;add_element&lt;/span&gt;, .init &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;# A tibble: 2 × 3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   title       color elements                 &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;       &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt; &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;                    &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;1&lt;/span&gt; Barbie      pink  shoes, sparkles, feminism&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;2&lt;/span&gt; Oppenheimer red   history, fire&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If we tweak the &lt;code&gt;add_element()&lt;/code&gt; function to add a &lt;code&gt;separator&lt;/code&gt; argument to it,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;add_element&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;separator&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;,&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;elements&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/paste.html&#39;&gt;paste&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;title&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;,&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;elements&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;      &lt;span class=&#39;nv&#39;&gt;info&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;info&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[[&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;    &lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;, collapse &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;separator&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/reduce.html&#39;&gt;reduce&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;info_list&lt;/span&gt;, &lt;/span&gt;
&lt;span&gt;  \&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;add_element&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, separator &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34; - &#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;, &lt;/span&gt;
&lt;span&gt;  .init &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;# A tibble: 2 × 3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   title       color elements                   &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;       &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt; &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;                      &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;1&lt;/span&gt; Barbie      pink  shoes - sparkles - feminism&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;2&lt;/span&gt; Oppenheimer red   history - fire&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;purrr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://purrr.tidyverse.org/reference/reduce.html&#39;&gt;reduce&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nv&#39;&gt;info_list&lt;/span&gt;, &lt;/span&gt;
&lt;span&gt;  \&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;add_element&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;, separator &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34; PLUS &#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;, &lt;/span&gt;
&lt;span&gt;  .init &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;movies&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;# A tibble: 2 × 3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   title       color elements                         &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;       &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt; &lt;span style=&#39;color: #555555; font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;                            &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;1&lt;/span&gt; Barbie      pink  shoes PLUS sparkles PLUS feminism&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;2&lt;/span&gt; Oppenheimer red   history PLUS fire&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And voilà!&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I presented my approximate understanding of &lt;a href=&#34;https://purrr.tidyverse.org/reference/reduce.html&#34;&gt;&lt;code&gt;purrr::reduce()&lt;/code&gt;&lt;/a&gt;, that helped me avoid writing some for loops and instead more elegant code&amp;hellip; or at least helped me understand a pattern that in the future I could use elegantly. I can only hope I &lt;a href=&#34;https://purrr.tidyverse.org/reference/accumulate.html&#34;&gt;&lt;code&gt;purrr::accumulate()&lt;/code&gt;&lt;/a&gt; more experience, as I very much still feel like a newbie.&lt;/p&gt;
&lt;p&gt;For more information I&amp;rsquo;d recommend reading the documentation of &lt;a href=&#34;https://purrr.tidyverse.org/reference/reduce.html&#34;&gt;&lt;code&gt;purrr::reduce()&lt;/code&gt;&lt;/a&gt; to be aware of other features, &lt;a href=&#34;https://adv-r.hadley.nz/functionals.html#reduce&#34;&gt;the content on the reduce family in Advanced R by Hadley Wickham&lt;/a&gt;&amp;hellip; and release-watching the purrr repo to keep up-to-date with latest recommendations. You can also use GitHub Advanced Search to find examples of usage of the function in, say, &lt;a href=&#34;https://github.com/search?q=purrr%3A%3Areduce+org%3Acran&amp;amp;type=code&#34;&gt;CRAN packages&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Edit: For another take of / use case of &lt;a href=&#34;https://purrr.tidyverse.org/reference/reduce.html&#34;&gt;&lt;code&gt;purrr::reduce()&lt;/code&gt;&lt;/a&gt;, June Choe wrote a nice detailed tutorial &lt;a href=&#34;https://yjunechoe.github.io/posts/2020-12-13-collapse-repetitive-piping-with-reduce/&#34;&gt;&amp;ldquo;Collapse repetitive piping with reduce()&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;The package is &lt;a href=&#34;https://github.com/lvaudor/glitter&#34;&gt;glitter&lt;/a&gt;, where we store query objects as a list. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Three useful (to me) R notions</title>
      <link>https://masalmon.eu/2023/07/24/basic-notions/</link>
      <pubDate>Mon, 24 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/07/24/basic-notions/</guid>
      <description>&lt;p&gt;Following my recent post on &lt;a href=&#34;https://masalmon.eu/2023/06/06/basic-patterns/&#34;&gt;three useful (to me) R patterns&lt;/a&gt;, I&amp;rsquo;ve written down three other things on a tiny sticky note. This post will allow me to throw away this beaten down sticky note, and maybe to show you one element you didn&amp;rsquo;t know?&lt;/p&gt;
&lt;h2 id=&#34;nzchar-a-fast-way-to-find-out-if-elements-of-a-character-vector-are-non-empty-strings&#34;&gt;&lt;code&gt;nzchar()&lt;/code&gt;: &amp;ldquo;a fast way to find out if elements of a character vector are non-empty strings&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;One of my favorite testing technique is the escape hatch strategy, about which I wrote a &lt;a href=&#34;https://blog.r-hub.io/2023/01/23/code-switch-escape-hatch-test/&#34;&gt;post on the R-hub blog&lt;/a&gt;: you make part of your code responsive to an environment variable, and you locally set that environment variable in your tests. In your code, to determine whether the environment variable has been set to any non-empty string, you can use the &lt;a href=&#34;https://rdrr.io/r/base/nchar.html&#34;&gt;&lt;code&gt;nzchar()&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/nchar.html&#39;&gt;nzchar&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;Hello World&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/nchar.html&#39;&gt;nzchar&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/nchar.html&#39;&gt;nzchar&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kc&#39;&gt;NA&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/nchar.html&#39;&gt;nzchar&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kc&#39;&gt;NA&lt;/span&gt;, keepNA &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] NA&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;# Now with an environment variable&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/nchar.html&#39;&gt;nzchar&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Sys.getenv.html&#39;&gt;Sys.getenv&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;blopblopblop&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] FALSE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_envvar.html&#39;&gt;with_envvar&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;  new &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;blopblopblop&#34;&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;bla&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;,&lt;/span&gt;
&lt;span&gt;  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/nchar.html&#39;&gt;nzchar&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Sys.getenv.html&#39;&gt;Sys.getenv&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;blopblopblop&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] TRUE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Allow me to mention the obvious: if you&amp;rsquo;re using &lt;a href=&#34;https://rdrr.io/r/base/nchar.html&#34;&gt;&lt;code&gt;nzchar()&lt;/code&gt;&lt;/a&gt; to examine an environment variable, do not forget &lt;a href=&#34;https://rdrr.io/r/base/Sys.getenv.html&#34;&gt;&lt;code&gt;Sys.getenv()&lt;/code&gt;&lt;/a&gt;. I spent too much time looking at the following piece of code last week: &lt;code&gt;nzchar(&amp;quot;BABELQUARTO_TESTS_URL&amp;quot;)&lt;/code&gt; wondering why it didn&amp;rsquo;t do what I expected it to do&amp;hellip; I had to replace it with &lt;code&gt;nzchar(Sys.getenv(&amp;quot;BABELQUARTO_TESTS_URL&amp;quot;))&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-backports-r-package-and-its-readme&#34;&gt;The backports R package, and its README&lt;/h2&gt;
&lt;p&gt;R is quite stable to say the least, but useful new functions have been added to it over time. For instance, R 3.3.0 saw the birth of &lt;a href=&#34;https://rdrr.io/r/base/trimws.html&#34;&gt;&lt;code&gt;trimws()&lt;/code&gt;&lt;/a&gt;, that trims white space.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/trimws.html&#39;&gt;trimws&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;useless whitespace &#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34; all around  &#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;useless whitespace&#34; &#34;all around&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To use such functions in your package, you might need to set a dependency on a recent version of R, making it harder for users with restrictive rights on their R install, to use your package. The &lt;a href=&#34;https://github.com/r-lib/backports&#34;&gt;backports R package&lt;/a&gt; can help you &lt;a href=&#34;https://blog.r-hub.io/2022/09/12/r-dependency/&#34;&gt;avoid to set that dependency&lt;/a&gt;: it provides backports for these useful new functions. The README explains how to set up its usage.&lt;/p&gt;
&lt;p&gt;I like both the existence of backports and its README because it is a list of these newer functions! I can&amp;rsquo;t pretend I&amp;rsquo;m a hipsteR but there are gems I forget or never heard about. Reading the list helps me see what&amp;rsquo;s there! For similar reasons I find the &lt;a href=&#34;https://lintr.r-lib.org/reference/index.html&#34;&gt;reference index of the lintr package&lt;/a&gt; to be a treasure trove.&lt;/p&gt;
&lt;h2 id=&#34;using-the-first-non-missing-thing-coalescing&#34;&gt;Using the first non-missing thing: coalescing&lt;/h2&gt;
&lt;p&gt;Sometimes you might have an ordered &amp;ldquo;wish list&amp;rdquo; in your code: use A, then if A is missing, use B, then if B is missing, use C, and so on and so forth until a default value or error. The pkgdown package for instance has a function called &lt;a href=&#34;https://github.com/r-lib/pkgdown/blob/c9206802f2888992de92aa41f517ba7812f05331/R/utils-fs.R#L75&#34;&gt;&lt;code&gt;path_first_existing()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I only recently realized this idea is usually called &lt;em&gt;coalescing&lt;/em&gt;. dplyr has a &lt;a href=&#34;https://dplyr.tidyverse.org/reference/coalesce.html&#34;&gt;&lt;code&gt;coalesce()&lt;/code&gt;&lt;/a&gt; function.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Given a set of vectors, coalesce() finds the first non-missing value at each position. It&amp;rsquo;s inspired by the SQL COALESCE function which does the same thing for SQL NULLs.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I know close to NULL about SQL, but I did notice the &lt;code&gt;COALESCE&lt;/code&gt; function in another query language, SPARQL, for which Lise Vaudor and I are working on a DSL, meaning a helper package, called &lt;a href=&#34;https://lvaudor.github.io/glitter/&#34;&gt;glitter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It makes me very happy to learn such an useful new word, or at least it usage in the programming realm.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;After writing a bit about &lt;a href=&#34;https://rdrr.io/r/base/nchar.html&#34;&gt;&lt;code&gt;nzchar()&lt;/code&gt;&lt;/a&gt;, the backports package and the idea of coalescence, I can now throw away my sticky note! Let&amp;rsquo;s see what makes its way onto a new sticky note&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Three useful (to me) R patterns</title>
      <link>https://masalmon.eu/2023/06/06/basic-patterns/</link>
      <pubDate>Tue, 06 Jun 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/06/06/basic-patterns/</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://podverse.fm/episode/g2Gtd-78N&#34;&gt;R Weekly highlights podcast&lt;/a&gt; hosted by Eric Nantz and Mike Thomas.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m happy to report that I thought &amp;ldquo;oh but I know a better way to write that code!&amp;rdquo; a few times lately when reading old scripts of mine, or scripts by others. It&amp;rsquo;s a good feeling because it shows progress! I&amp;rsquo;ve tooted about all three things I&amp;rsquo;ll present in this post: After reading Julia Evans&amp;rsquo; &lt;a href=&#34;https://jvns.ca/blog/2023/06/05/some-blogging-myths/&#34;&gt;post about blogging&lt;/a&gt;, I decided to train the blogging muscle a bit using these low-hanging fruits/toots&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&#34;combine-a-list-of-default-values-with-a-list-of-custom-values&#34;&gt;Combine a list of default values with a list of custom values&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://mastodon.social/@maelle/110134566950035337&#34;&gt;&lt;em&gt;Toot&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Imagine 💭&lt;/p&gt;
&lt;p&gt;🎚️ you have a &lt;code&gt;default_values&lt;/code&gt; list and 👇 want to let the user pass a &lt;code&gt;custom_values&lt;/code&gt; list to override some of them.&lt;/p&gt;
&lt;p&gt;✨ &lt;code&gt;utils::modifyList(default_values, custom_values)&lt;/code&gt;does that!&lt;/p&gt;
&lt;p&gt;So say you had code à la&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;default_values&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;a &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;, b &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;options&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;b &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;56&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;temporary_list&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;default_values&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;temporary_list&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/names.html&#39;&gt;names&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;options&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;options&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;options&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;temporary_list&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;options&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $a&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $b&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] 56&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;You can write it like so&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;default_values&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;a &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;, b &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;options&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/list.html&#39;&gt;list&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;b &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;56&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;options&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/utils/modifyList.html&#39;&gt;modifyList&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;default_values&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;options&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;options&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $a&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; $b&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] 56&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I learnt about that function in &lt;a href=&#34;https://github.com/r-lib/pkgdown/blob/c354aa7e5ea1f9936692494c28c89e5bdd31fc68/R/utils.R#L109&#34;&gt;pkgdown source&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;use-a-default-if-the-user-provided-null&#34;&gt;Use a default if the user provided NULL&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://mastodon.social/@maelle/110054745129675027&#34;&gt;&lt;em&gt;Toot&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Do you know the &lt;a href=&#34;https://rlang.r-lib.org/reference/op-null-default.html&#34;&gt;rlang &lt;code&gt;%||%&lt;/code&gt; operator&lt;/a&gt;?&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Code like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.null&lt;/span&gt;(blop)) {
  blop &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;can become&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;blop &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; blop &lt;span style=&#34;color:#666&#34;&gt;%||%&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Related to this, I&amp;rsquo;d recommend package developers read the &lt;a href=&#34;https://design.tidyverse.org/def-short.html&#34;&gt;chapter of the Tidyverse design guide on defaults&lt;/a&gt;, especially the section on the &lt;a href=&#34;https://design.tidyverse.org/def-short.html#arg-short-null&#34;&gt;&lt;code&gt;NULL&lt;/code&gt; default&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;extract-common-values-or-different--unique-values-from-two-vectors&#34;&gt;Extract common values or different / unique values from two vectors&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://mastodon.social/@maelle/110474929146978928&#34;&gt;&lt;em&gt;Toot&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Say I have a vector a and a vector b, and I need the unique a values that are not in b.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;a&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;thing&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;object&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;nv&#39;&gt;b&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;thing&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;gift&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I tended to write something like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/unique.html&#39;&gt;unique&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;a&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;!&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;a&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/match.html&#39;&gt;%in%&lt;/a&gt;&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;b&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;object&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;(or without the &lt;a href=&#34;https://rdrr.io/r/base/unique.html&#34;&gt;&lt;code&gt;unique()&lt;/code&gt;&lt;/a&gt; if a has only distinct values)&lt;/p&gt;
&lt;p&gt;that can be&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/sets.html&#39;&gt;setdiff&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;a&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;b&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;object&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Similarly, when looking for the unique values of the two vectors combined, instead of&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/unique.html&#39;&gt;unique&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/c.html&#39;&gt;c&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;a&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;b&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;thing&#34;  &#34;object&#34; &#34;gift&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I can write&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/sets.html&#39;&gt;union&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;a&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;b&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;thing&#34;  &#34;object&#34; &#34;gift&#34;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Because I&amp;rsquo;ve noticed I didn&amp;rsquo;t know these base R functions well enough, I open the Set Operations manual page more often, by typing &lt;a href=&#34;https://rdrr.io/r/base/sets.html&#34;&gt;&lt;code&gt;?setdiff&lt;/code&gt;&lt;/a&gt; for instance.&lt;/p&gt;
&lt;p&gt;Salix Dubois helpfully noted the functions can be &lt;a href=&#34;https://mastodon.social/@salixdubois@zeroes.ca/110477215577045367&#34;&gt;slower&lt;/a&gt;, and that one might not always want to drop duplicates.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I presented three basic (set of) functions (not all &lt;em&gt;base&lt;/em&gt; functions) that I&amp;rsquo;ve found serve me well: &lt;a href=&#34;https://rdrr.io/r/utils/modifyList.html&#34;&gt;&lt;code&gt;utils::modifyList()&lt;/code&gt;&lt;/a&gt;, &lt;code&gt;rlang::%||%&lt;/code&gt; and base Set Operations. I&amp;rsquo;m glad they&amp;rsquo;re now part of my R vocabulary.&lt;/p&gt;
&lt;p&gt;Note that you might still prefer the longer version of some of these patterns, depending on your needs, your code readers, etc. I won&amp;rsquo;t judge!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m curious to see what three new things I&amp;rsquo;ll have learnt in a few months (and will try not to beat myself up for not learning about them sooner 😇). If you&amp;rsquo;re interested about code quality in general, you might enjoy this &lt;a href=&#34;https://blog.r-hub.io/2022/03/21/code-style/&#34;&gt;post by Christophe Dervieux and myself on the R-hub blog&lt;/a&gt;.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I hope it&amp;rsquo;s a myth that your puns need to be good! &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Please don&amp;rsquo;t ask me to say this aloud, I have no idea how it&amp;rsquo;s pronounced. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>git and GitHub in R for the casual user</title>
      <link>https://masalmon.eu/2023/01/12/git-github-casual/</link>
      <pubDate>Thu, 12 Jan 2023 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2023/01/12/git-github-casual/</guid>
      <description>&lt;p&gt;If you&amp;rsquo;ve been taught git and GitHub but practice so rarely that you&amp;rsquo;re discouraged, what should you do to re-start more easily? Let&amp;rsquo;s imagine you have to, or really want to, use git and GitHub for your next analysis project. Here&amp;rsquo;s what I would recommend&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I assume you already own a GitHub account. If not, refer to &lt;a href=&#34;https://happygitwithr.com/github-acct.html&#34;&gt;happygitwithr guidance&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to the people who shared recommendations on Mastodon, whose names are acknowledged in the rest of the post!&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;prepare-your-tissues&#34;&gt;Prepare your tissues&amp;hellip;&lt;/h2&gt;
&lt;p&gt;Or rather your support system. Make sure a collaborator with more git and GitHub practice is on call! If not, remember &lt;a href=&#34;https://masalmon.eu/2018/07/22/wheretogethelp/&#34;&gt;where you post your R questions&lt;/a&gt;. This way if you get stuck somewhere along the line, things will get less desperate.&lt;/p&gt;
&lt;p&gt;You might also want to prepare your favorite hot beverage, but you probably won&amp;rsquo;t be able to read git guidance from tea leaves, hence the need for an actual support plan.&lt;/p&gt;
&lt;h2 id=&#34;clear-notifications&#34;&gt;Clear notifications&lt;/h2&gt;
&lt;p&gt;This step is not completely necessary but could help you for the next re-start. Look at your &lt;a href=&#34;https://github.com/notifications&#34;&gt;GitHub notifications&lt;/a&gt;! Hopefully you weren&amp;rsquo;t getting them by email the whole time&amp;hellip;&lt;/p&gt;
&lt;p&gt;If you see you&amp;rsquo;ve been getting far too many notifications, tweak the settings!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/settings/notifications&#34;&gt;Notification settings&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/notifications/subscriptions&#34;&gt;Threads (issues, PRs) you are subscribed to&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/watching&#34;&gt;Repositories you are watching&lt;/a&gt; (I find &lt;a href=&#34;https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository&#34;&gt;custom watching&lt;/a&gt; much more rewarding).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way next time you open GitHub, your notifications should have a better signal to noise ratio.&lt;/p&gt;
&lt;p&gt;Now if you notice you&amp;rsquo;ve been missing important notifications, try to either commit to log in more often or get those notifications out of GitHub and into your preferred system. For instance, tell collaborators it&amp;rsquo;s safer to email you. Another example: maybe don&amp;rsquo;t watch dplyr repository, but do subscribe to the Tidyverse blog.&lt;/p&gt;
&lt;h2 id=&#34;inject-a-bit-of-motivation&#34;&gt;Inject a bit of motivation&lt;/h2&gt;
&lt;p&gt;Why are you doing this anyway? 😅 Good reads are the &lt;a href=&#34;https://happygitwithr.com/big-picture.html&#34;&gt;&amp;ldquo;Big picture&amp;rdquo; section of happygitwithr&lt;/a&gt; (by Jenny Bryan and collaborators) and the &lt;a href=&#34;https://www.openscapes.org/blog/2022/05/27/github-illustrated-series/&#34;&gt;Openscapes GitHub illustrated series&lt;/a&gt; by Allison Horst and Julie Lowndes.&lt;/p&gt;
&lt;h2 id=&#34;decide-whether-to-use-github-desktop&#34;&gt;Decide whether to use GitHub Desktop&lt;/h2&gt;
&lt;p&gt;After I first shared my post on Mastodon, several people (&lt;a href=&#34;https://mastodon.social/@rmflight/109676738327559708&#34;&gt;Robert M Flight&lt;/a&gt;, &lt;a href=&#34;https://mastodon.social/@stevensanderson@mstdn.social/109677107513778953&#34;&gt;Steven P Sanderson&lt;/a&gt;, &lt;a href=&#34;https://mastodon.social/@jimgar@fosstodon.org/109678458557655706&#34;&gt;Jim Gardner&lt;/a&gt;, &lt;a href=&#34;https://mastodon.social/@frod_san@ecoevo.social/109677386173703866&#34;&gt;Francisco Rodriguez-Sanchez&lt;/a&gt;) recommended using &lt;a href=&#34;https://docs.github.com/en/desktop&#34;&gt;GitHub Desktop&lt;/a&gt;. Its nice interface would, as far as I understand, replace usethis. It&amp;rsquo;d mean you have R open somewhere, do your thing there, and regularly you do the git/GitHub stuff in the GitHub Desktop interface (setting up a GitHub repository, commits, pushes).&lt;/p&gt;
&lt;h2 id=&#34;check-your-rgithub-situation&#34;&gt;Check your R/GitHub situation&lt;/h2&gt;
&lt;p&gt;Skip if you use GitHub Desktop (and have installed git!). 😉&lt;/p&gt;
&lt;p&gt;In this I assume you have R and RStudio IDE installed. One problem at a time. 😸&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://mastodon.social/@hye@glammr.us/109676766952787983&#34;&gt;Tip by Hao Ye&lt;/a&gt;: first &lt;a href=&#34;https://usethis.r-lib.org/articles/usethis-setup.html&#34;&gt;setup R so that it loads usethis at each session start&lt;/a&gt;, so you might skip writing &lt;code&gt;usethis::&lt;/code&gt; in front of each usethis function.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see if you have git correctly installed and hooked with GitHub, and remediate if not. Run &lt;a href=&#34;https://usethis.r-lib.org/reference/git_sitrep.html&#34;&gt;&lt;code&gt;usethis::git_sitrep()&lt;/code&gt;&lt;/a&gt;. Also run &lt;a href=&#34;https://usethis.r-lib.org/reference/github-token.html&#34;&gt;&lt;code&gt;usethis::gh_token_help()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You might also want to run the whole &lt;a href=&#34;https://usethis.r-lib.org/articles/git-credentials.html&#34;&gt;usethis article about git and gitHub credentials&lt;/a&gt;. On Linux, you might need &lt;a href=&#34;https://blog.djnavarro.net/posts/2021-08-08_git-credential-helpers/&#34;&gt;Managing GitHub credentials from R, difficulty level linux&lt;/a&gt; by Danielle Navarro.&lt;/p&gt;
&lt;p&gt;For git installation, refer to &lt;a href=&#34;https://happygitwithr.com/install-git.html&#34;&gt;happygitwithr guidance&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Do not be surprised if your tokens expired since the last time you used GitHub from R. Also do not be surprised if it all takes a little while. Take notes on what you&amp;rsquo;re doing. Next time you might be able to re-start after just running the two sitrep functions!&lt;/p&gt;
&lt;p&gt;When re-creating tokens, make sure to give them an informative name (related to the computer you use them for, the project you use them for) as this is very useful for token management. I swear that no longer calling my tokens &amp;ldquo;mytoken1&amp;rdquo; has improved my life.&lt;/p&gt;
&lt;p&gt;Last but not least, run &lt;a href=&#34;https://usethis.r-lib.org/reference/git_vaccinate.html&#34;&gt;usethis::git_vaccinate()&lt;/a&gt;. It will prevent you leaking credentials, or useless files (&lt;code&gt;.DS_Store&lt;/code&gt;), on GitHub.&lt;/p&gt;
&lt;h2 id=&#34;run-a-full-cycle&#34;&gt;Run a full cycle&lt;/h2&gt;
&lt;p&gt;Even if your fantastic analysis project is still waiting for you to finish the &lt;em&gt;mise en place&lt;/em&gt;, it might be good to run a full cycle to see whether things work.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a project with &lt;a href=&#34;https://usethis.r-lib.org/reference/create_package.html&#34;&gt;&lt;code&gt;usethis::create_project(&amp;quot;../toy&amp;quot;)&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Initiate git usage with &lt;a href=&#34;https://usethis.r-lib.org/reference/use_git.html&#34;&gt;&lt;code&gt;usethis::use_git()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Add a text file containing, for instance &amp;ldquo;I will excel at git today!&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;git commit this file. Use RStudio git tab, or &lt;a href=&#34;https://docs.ropensci.org/gert/reference/git_commit.html&#34;&gt;&lt;code&gt;gert::git_add()&lt;/code&gt;&lt;/a&gt; then &lt;a href=&#34;https://docs.ropensci.org/gert/reference/git_commit.html&#34;&gt;&lt;code&gt;gert::git_commit()&lt;/code&gt;&lt;/a&gt;, or the command line&amp;hellip; whatever you were taught and remember vaguely liking.&lt;/li&gt;
&lt;li&gt;Create a GitHub repository with &lt;a href=&#34;https://usethis.r-lib.org/reference/use_github.html&#34;&gt;&lt;code&gt;usethis::use_github()&lt;/code&gt;&lt;/a&gt;, or GitHub Desktop.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Did it work? If not, turn to the docs, a search engine and your support network. If yes, continue!&lt;/p&gt;
&lt;h2 id=&#34;initiate-your-project-right&#34;&gt;Initiate your project right&lt;/h2&gt;
&lt;p&gt;Once you have your project folder set up with &lt;code&gt;create_project()&lt;/code&gt; for instance,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Initiate git usage with &lt;a href=&#34;https://usethis.r-lib.org/reference/use_git.html&#34;&gt;&lt;code&gt;usethis::use_git()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Make sure &lt;code&gt;.gitignore&lt;/code&gt; is correct: is there for instance a gigantic data file you work with locally but that you do not wish to commit to git, lest it is too heavy for git or GitHub? List it in &lt;code&gt;.gitignore&lt;/code&gt;. You can use &lt;a href=&#34;https://usethis.r-lib.org/reference/use_git_ignore.html&#34;&gt;&lt;code&gt;usethis::use_git_ignore()&lt;/code&gt;&lt;/a&gt; for that.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;upload-your-project-to-github&#34;&gt;Upload your project to GitHub&lt;/h2&gt;
&lt;h3 id=&#34;first-where-on-github-do-you-want-to-upload-your-project&#34;&gt;First, where on GitHub do you want to upload your project?&lt;/h3&gt;
&lt;p&gt;Your personal account or an organization?&lt;/p&gt;
&lt;p&gt;If you wish to upload it to an organization, be aware that it might fail if you don&amp;rsquo;t have the &lt;a href=&#34;https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/roles-in-an-organization&#34;&gt;correct access level&lt;/a&gt;. In some GitHub organizations any member can create a repository, in others only owners can. Contact an organization owner if needed.&lt;/p&gt;
&lt;p&gt;You might want to &lt;a href=&#34;https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch&#34;&gt;&lt;em&gt;create&lt;/em&gt; a GitHub organization&lt;/a&gt; for your project. Even with a single project in it, the big advantage is that you can better give access to your project to collaborators, with more granularity than for a repository hosted in a personal account.&lt;/p&gt;
&lt;h3 id=&#34;private-or-public&#34;&gt;Private or public?&lt;/h3&gt;
&lt;p&gt;Do you want your repository to be public or private? Sometimes the choice is obvious, for instance your project is top secret or you really don&amp;rsquo;t want to share it as is right now. Private repositories have a few less features than public repositories (for instance draft pull requests) depending on your GitHub subscription.&lt;/p&gt;
&lt;h3 id=&#34;use_github-or-github-desktop&#34;&gt;&lt;code&gt;use_github()&lt;/code&gt; (or GitHub Desktop)&lt;/h3&gt;
&lt;p&gt;Now run &lt;code&gt;usethis::use_github(organisation = &amp;quot;your-account-username-or-an-organization&amp;quot;, private = TRUE)&lt;/code&gt; with the correct arguments. After this you should see your project in a GitHub repository! 🎉&lt;/p&gt;
&lt;h2 id=&#34;make-commits-as-you-work&#34;&gt;Make commits as you work&lt;/h2&gt;
&lt;p&gt;Ideally, make a &lt;a href=&#34;https://happygitwithr.com/git-basics.html#commits-diffs-and-tags&#34;&gt;commit&lt;/a&gt; everytime you make a substantial, coherent set of changes. To encourage you, you could fill a jar of marbles, one marble per commit?&lt;/p&gt;
&lt;p&gt;Realistically, at least make a commit every time you take a break, especially when leaving at the end of your working session.&lt;/p&gt;
&lt;p&gt;Push often, each time you make a commit, with the RStudio git tab, the command line or &lt;a href=&#34;https://docs.ropensci.org/gert/reference/git_fetch.html&#34;&gt;&lt;code&gt;gert::git_push()&lt;/code&gt;&lt;/a&gt;, or GitHub Desktop.&lt;/p&gt;
&lt;p&gt;If you feel icky submitting ugly commits to your pristine repo, think about the idea of branches. With usethis you&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;create one with &lt;a href=&#34;https://docs.ropensci.org/gert/reference/git_branch.html&#34;&gt;&lt;code&gt;gert::git_branch_create()&lt;/code&gt;&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;experiment and make the ugly commits in there until the whole set of changes is good to go,&lt;/li&gt;
&lt;li&gt;then open a &amp;ldquo;pull request&amp;rdquo; on GitHub with &lt;a href=&#34;https://usethis.r-lib.org/articles/pr-functions.html&#34;&gt;usethis helpers&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;then you can &lt;a href=&#34;https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/merging-a-pull-request&#34;&gt;&amp;ldquo;squash and merge&amp;rdquo;&lt;/a&gt; it which means the whole thing becomes one single beautiful commit.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With GitHub Desktop you&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/making-changes-in-a-branch/managing-branches&#34;&gt;create a branch&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;experiment and make the ugly commits in there until the whole set of changes is good to go,&lt;/li&gt;
&lt;li&gt;then &lt;a href=&#34;https://docs.github.com/en/desktop/contributing-and-collaborating-using-github-desktop/working-with-your-remote-repository-on-github-or-github-enterprise/creating-an-issue-or-pull-request&#34;&gt;open a &amp;ldquo;pull request&amp;rdquo; on GitHub&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;then you can &lt;a href=&#34;https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/merging-a-pull-request&#34;&gt;&amp;ldquo;squash and merge&amp;rdquo;&lt;/a&gt; it which means the whole thing becomes one single beautiful commit.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;keep-track-of-your-todos&#34;&gt;Keep track of your TODOS&lt;/h2&gt;
&lt;p&gt;Since you are working on GitHub, you could use the &lt;a href=&#34;https://docs.github.com/en/issues&#34;&gt;issue tracker&lt;/a&gt; of your repository to write down ideas! You can create labels, milestones (so you could procrastinate a lot here 😅).&lt;/p&gt;
&lt;p&gt;On Mastodon, Francisco Rodriguez-Sanchez &lt;a href=&#34;https://mastodon.social/@frod_san@ecoevo.social/109677386173703866&#34;&gt;underlined how handy it can be to use GitHub for project management&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;put-the-closed-sign-before-you-leave&#34;&gt;Put the &amp;ldquo;Closed&amp;rdquo; sign before you leave&lt;/h2&gt;
&lt;p&gt;Have you done your last commit, last push and opened your last TODO issue? Have you looked over the history of what you did today and earlier in your GitHub repository?&lt;/p&gt;
&lt;p&gt;If you intend to leave GitHub for a while,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;make sure collaborators (or users of your package) have a good idea of how to contact you, and what maintenance is expected (for instance create a file &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; where you state the maintenance is stop and go).&lt;/li&gt;
&lt;li&gt;set a &lt;a href=&#34;https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/personalizing-your-profile#setting-a-status&#34;&gt;busy status on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;procrastinate-on-your-profile&#34;&gt;Procrastinate on your profile&lt;/h2&gt;
&lt;p&gt;A nice touch would be to make your &lt;a href=&#34;https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/about-your-profile&#34;&gt;GitHub profile&lt;/a&gt; informative, setting a picture, description, and potentially a &lt;a href=&#34;https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme&#34;&gt;GitHub README&lt;/a&gt;. If you have GitHub repositories you are proud of, &lt;a href=&#34;https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/pinning-items-to-your-profile&#34;&gt;pin them&lt;/a&gt; to your profile.&lt;/p&gt;
&lt;h2 id=&#34;schedule-training-sessions&#34;&gt;Schedule training sessions?&lt;/h2&gt;
&lt;p&gt;Your work on checking your git/GitHub situation in RStudio, credentials and such will make your next restart easier. However practice will also help a lot!&lt;/p&gt;
&lt;p&gt;Beside trying to get a bit more git into your daily work, you might want to schedule some sessions where you experiment with branches and pull requests in a toy or real repository you own, where you make you first pull request to an external repository. You could run these sessions with other (false) beginners!&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;First of all, it is awesome you want to use git and GitHub (or GitLab or something else for that matter)! It is not an easy toolset to learn, so no wonder you can get frustated. Hopefully the tips in this post, which I&amp;rsquo;d summarize as &amp;ldquo;Remember happygitwithr.com, usethis and/or GitHub Desktop, Openscapes illustrated series; Be patient with yourself&amp;rdquo;, can help a bit. Good luck!&lt;/p&gt;
&lt;h2 id=&#34;ps-improve-your-tooling&#34;&gt;PS: improve your tooling?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Tip by Robert M Flight: &lt;a href=&#34;https://mastodon.social/@rmflight/109676738327559708&#34;&gt;find a diff viewer you like&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Tip by Dave Braze: &lt;a href=&#34;https://mastodon.social/@davidbraze@mstdn.social/109676715427221572&#34;&gt;experiment with other IDEs, use magit&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>RSS, fantastic tool for keeping up-to-date</title>
      <link>https://masalmon.eu/2022/04/26/rss-feeds/</link>
      <pubDate>Tue, 26 Apr 2022 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2022/04/26/rss-feeds/</guid>
      <description>&lt;p&gt;I found an excuse to blog about XML &lt;a href=&#34;https://masalmon.eu/2022/04/08/xml-xpath/&#34;&gt;again&lt;/a&gt;! Yes, RSS feeds are in practice XML, but for most people, that&amp;rsquo;s not why they are cool. An RSS (&lt;em&gt;really simple syndication&lt;/em&gt;) feed is metadata about all, or the most recent posts published by a website: publication date, content or summary, etc. Much handier in my opinion to use that to get updates among Twitter &amp;ldquo;noise&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;rss-feed-example&#34;&gt;RSS feed example&lt;/h2&gt;
&lt;p&gt;Have a look at the RSS feed for this blog over at &lt;a href=&#34;https://masalmon.eu/post/index.xml&#34;&gt;https://masalmon.eu/post/index.xml&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;how-to-consume-rss&#34;&gt;How to consume RSS&lt;/h2&gt;
&lt;p&gt;Take a list of all your favorite websites whose updates you want to follow. Then you can syndicate all of them to some tool that will regularly look for new posts in the feed and present them to you, potentially with some bells and whistles like letting you mark them as &amp;ldquo;read&amp;rdquo; or &amp;ldquo;to read later&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;That tool could be &lt;a href=&#34;https://feedly.com/&#34;&gt;Feedly&lt;/a&gt;. Note that Feedly will find RSS feed addresses directly based on an URL. I&amp;rsquo;m quite happy with it.&lt;/p&gt;
&lt;p&gt;It could also be a local Hugo website you&amp;rsquo;d build as Hugo has support for XML hence RSS since version 0.90 (see &lt;a href=&#34;https://github.com/gohugoio/hugo/releases/tag/v0.90.0&#34;&gt;https://github.com/gohugoio/hugo/releases/tag/v0.90.0&lt;/a&gt;). I can imagine one would store addresses to RSS feeds in a JSON file, then have a template that fetch all of them and then transform them. Although, to be honest, it&amp;rsquo;d seem more natural to me to use some sort of R pipeline. Both ideas would be fun exercises. 😉&lt;/p&gt;
&lt;p&gt;Beyond the tool used, subscribing to RSS feeds is in my opinion very empowering. Instead of following an organization or person on say Twitter, I much prefer making sure I get notified of their important stuff via a feed (or a &lt;a href=&#34;https://ropensci.org/blog/2021/06/24/news-meta/&#34;&gt;newsletter&lt;/a&gt;!). Obviously it does not have the social aspect of social media but you can still share and discuss posts &lt;a href=&#34;https://r-way.netlify.app/#/38&#34;&gt;&amp;ldquo;somewhere&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last but not least, as mentioned in my &lt;a href=&#34;https://masalmon.eu/2022/04/05/github-tips/#7-add-your-github-timeline-to-your-rss-feed-reader&#34;&gt;previous post about GitHub&lt;/a&gt;, you can subscribe to your own GitHub timeline.&lt;/p&gt;
&lt;h2 id=&#34;how-to-produce-rss&#34;&gt;How to produce RSS&lt;/h2&gt;
&lt;p&gt;If you maintain some sort of blog, please make sure it produces an RSS feed! Type the name of your website generator and &amp;ldquo;RSS&amp;rdquo; into a search engine. E.g. here are the docs for &lt;a href=&#34;https://quarto.org/docs/websites/website-blog.html#rss-feed&#34;&gt;RSS feeds for Quarto blogs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Your website generator might let you create distinct RSS feeds for different categories or tags which might useful for your different audiences.&lt;/p&gt;
&lt;p&gt;If you created your RSS feed yourself, e.g. by tweaking a Hugo template quite a lot, validate it with this &lt;a href=&#34;https://validator.w3.org/feed/&#34;&gt;online validator&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;how-to-broadcast-rss&#34;&gt;How to broadcast RSS&lt;/h2&gt;
&lt;p&gt;If your website has an RSS feed, aggregators, not only individuals, can subscribe to it!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You could try and syndicate your blog on &lt;a href=&#34;https://www.r-bloggers.com/&#34;&gt;R bloggers&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;At the moment &lt;a href=&#34;https://rweekly.org/&#34;&gt;R Weekly&lt;/a&gt; no longer uses RSS feeds but it&amp;rsquo;ll probably soon use them again.&lt;/li&gt;
&lt;li&gt;There might be some sort of aggregators for some other communities you&amp;rsquo;re part of?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I briefly explained how to consume and produce RSS feeds. Note that there are also JSON feeds 😅, that there are newsletter tools for letting people subscribe to your updates by email, and that services such as Feedly have paid features that create feeds for websites that do not produce one, so that you can follow them. RSS feeds are not going away right now, and are regularly the topic of trending discussions on Hacker News (together with some trendy phrases like &amp;ldquo;slow web&amp;rdquo;). So it&amp;rsquo;s not that uncool to be &lt;a href=&#34;https://twitter.com/d_olivaw/status/1518584526188027904&#34;&gt;part of the group of old fashion RSSers&lt;/a&gt;, right? 😎&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Why I like XPath, XML and HTML</title>
      <link>https://masalmon.eu/2022/04/08/xml-xpath/</link>
      <pubDate>Fri, 08 Apr 2022 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2022/04/08/xml-xpath/</guid>
      <description>&lt;p&gt;One of my favorite tool is XPath, the query language for exploring XML and HTML trees. In this post, I will highlight a few use cases of this &lt;a href=&#34;https://github.com/hrbrmstr/htmltidy#htmltidy=&#34;&gt;&amp;ldquo;angle-bracket crunching tool&amp;rdquo;&lt;/a&gt; and hope to convince you that it&amp;rsquo;s an awesome thing to know about and play with.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to &lt;a href=&#34;https://cderv.rbind.io/&#34;&gt;Christophe Dervieux&lt;/a&gt; for useful feedback on this post! Mille mercis !&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;brief-intro-to-xpath-in-r&#34;&gt;Brief intro to XPath in R&lt;/h2&gt;
&lt;p&gt;Say I have some XML,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nv&#39;&gt;my_xml&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/read_xml.html&#39;&gt;read_xml&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;&amp;lt;wrapper&amp;gt;&amp;lt;thing&amp;gt;blop&amp;lt;/thing&amp;gt;&amp;lt;/wrapper&amp;gt;&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;rsquo;m using &lt;a href=&#34;https://xml2.r-lib.org/&#34;&gt;xml2&lt;/a&gt;, by Hadley Wickham, Jim Hester and Jeroen Ooms. This package is recommended over the XML package by e.g. the &lt;a href=&#34;https://devguide.ropensci.org/building.html#recommended-scaffolding&#34;&gt;rOpenSci dev guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With XPath I can query the &amp;ldquo;thing&amp;rdquo; element:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_find_all.html&#39;&gt;xml_find_all&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;my_xml&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;.//thing&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;#123;xml_nodeset (1)&amp;#125;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &amp;lt;thing&amp;gt;blop&amp;lt;/thing&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I can extract its content via &lt;a href=&#34;http://xml2.r-lib.org/reference/xml_text.html&#34;&gt;&lt;code&gt;xml2::xml_text()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_find_all.html&#39;&gt;xml_find_all&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;my_xml&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;.//thing&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; |&amp;gt;
  &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;blop&#34;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I could also &lt;a href=&#34;https://blog.r-hub.io/2020/01/22/mutable-api/#exposing-the-c-api-in-xml2&#34;&gt;replace the element&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, that was an especially simple XPath query. XPath&amp;rsquo;s strength is to allow you to really take advantage of the structure of the XML or HTML tree. You can extract nodes based on their attributes, on their parents, on their siblings, etc.&lt;/p&gt;
&lt;p&gt;Where to learn XPath? Two good websites to get started are&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/XPath&#34;&gt;Mozilla Developer Network&amp;rsquo;s intro to XPath&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.w3schools.com/xml/xpath_intro.asp&#34;&gt;w3schools&amp;rsquo; XPath tutorial&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A primary skill to learn is the name of elements, e.g. nodes, attributes, which will help write type better keywords into search engines when trying to figure out a query. 😉&lt;/p&gt;
&lt;p&gt;Note that if you are handling HTML, you might enjoy &lt;a href=&#34;https://sjp.co.nz/projects/selectr/&#34;&gt;selectr by Simon Potter&lt;/a&gt; that creates XPath filters based on CSS selectors.&lt;/p&gt;
&lt;p&gt;Knowing XPath, or even knowing it exists, is really empowering. In the rest of this post, I&amp;rsquo;ll highlight cases where this is useful.&lt;/p&gt;
&lt;h2 id=&#34;when-life-gives-you-xml-or-html&#34;&gt;When life gives you XML or HTML&lt;/h2&gt;
&lt;h3 id=&#34;web-scraping&#34;&gt;Web scraping&lt;/h3&gt;
&lt;p&gt;At the beginning of this blog I liked extracting data from websites. I did that with &lt;a href=&#34;https://masalmon.eu/2017/03/07/blinddates/&#34;&gt;regular expressions&lt;/a&gt;. Now I know better and would &lt;a href=&#34;https://masalmon.eu/2021/01/15/beanie-baby/&#34;&gt;wrangle HTML as HTML&lt;/a&gt;. Goodbye, &lt;a href=&#34;https://stringr.tidyverse.org/reference/str_detect.html&#34;&gt;&lt;code&gt;stringr::str_detect()&lt;/code&gt;&lt;/a&gt;, hello, &lt;a href=&#34;http://xml2.r-lib.org/reference/xml_find_all.html&#34;&gt;&lt;code&gt;xml2::xml_find_all()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A package that&amp;rsquo;s especially useful for web scraping is &lt;a href=&#34;https://rvest.tidyverse.org/&#34;&gt;rvest by Hadley Wickham&lt;/a&gt;. rvest builds upon selectr, and will write XPath for you.&lt;/p&gt;
&lt;h3 id=&#34;pkgdown&#34;&gt;pkgdown&lt;/h3&gt;
&lt;p&gt;If you use pkgdown to produce the documentation website of for your package, please know that part of its magic comes from various &amp;ldquo;HTML tweaks&amp;rdquo; that are powered by XPath, see for instance &lt;a href=&#34;https://github.com/r-lib/pkgdown/blob/98d5a5c735eb244cb98b2e6bab1d54bb27c0af95/R/tweak-reference.R#L1&#34;&gt;&amp;ldquo;tweak-reference.R&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;when-life-gives-you-something-else&#34;&gt;When life gives you something else&amp;hellip;&lt;/h2&gt;
&lt;p&gt;You can still make it XML to handle it as such, with XPath!&lt;/p&gt;
&lt;h3 id=&#34;markdown-manipulation-with-commonmark-tinkr&#34;&gt;Markdown manipulation with commonmark, tinkr&lt;/h3&gt;
&lt;p&gt;The commonmark package transforms Markdown to XML. This can be extremely handy to get data &lt;a href=&#34;https://ropensci.org/blog/2018/09/05/commonmark/&#34;&gt;on R Markdown or Markdown files&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, say you want to modify the Markdown file as XML then get a Markdown file back. It is also possible, with the &lt;a href=&#34;https://docs.ropensci.org/tinkr/&#34;&gt;tinkr package&lt;/a&gt;, started by yours truly, now maintained by Zhian Kamvar. The conversion back to Markdown relies on &lt;a href=&#34;https://docs.ropensci.org/xslt/&#34;&gt;xslt&lt;/a&gt; by Jeroen Ooms, a package that can use XSL stylesheets.&lt;/p&gt;
&lt;h3 id=&#34;code-tree-manipulation-with-xmlparsedata&#34;&gt;Code tree manipulation with xmlparsedata&lt;/h3&gt;
&lt;p&gt;Imagine you&amp;rsquo;re writing a domain-specific language where you let users write something like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;str_to_lower&lt;/span&gt;(itemTitle), &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;wikidata&amp;#39;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;that you want to somehow translate to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-sparql&#34; data-lang=&#34;sparql&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;REGEX&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;LCASE&lt;/span&gt;(&lt;span style=&#34;color:#bb60d5&#34;&gt;?itemTitle&lt;/span&gt;),&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;wikidata&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yes, that&amp;rsquo;s a real use case, from the &lt;a href=&#34;https://lvaudor.github.io/glitter/articles/internals.html&#34;&gt;glitter package (SPARQL DSL) maintained by Lise Vaudor&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The way we translate the code is to transform it to an XML tree via &lt;a href=&#34;https://r-lib.github.io/xmlparsedata/&#34;&gt;Gábor Csárdi&amp;rsquo;s xmlparsedata&lt;/a&gt;, then we can apply different tweaks based on XPath.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/parse.html&#39;&gt;parse&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;
  text &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;str_detect(str_to_lower(itemTitle), &#39;wikidata&#39;)&#34;&lt;/span&gt;,
  keep.source &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;
&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; |&amp;gt; 
  &lt;span class=&#39;nf&#39;&gt;xmlparsedata&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/xmlparsedata/man/xml_parse_data.html&#39;&gt;xml_parse_data&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;pretty &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; |&amp;gt; 
  &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/read_xml.html&#39;&gt;read_xml&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; |&amp;gt;
  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/character.html&#39;&gt;as.character&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; |&amp;gt;
  &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/cat.html&#39;&gt;cat&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; standalone=&#34;yes&#34;?&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;exprlist&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &amp;lt;expr line1=&#34;1&#34; col1=&#34;1&#34; line2=&#34;1&#34; col2=&#34;47&#34; start=&#34;49&#34; end=&#34;95&#34;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;expr line1=&#34;1&#34; col1=&#34;1&#34; line2=&#34;1&#34; col2=&#34;10&#34; start=&#34;49&#34; end=&#34;58&#34;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;SYMBOL_FUNCTION_CALL line1=&#34;1&#34; col1=&#34;1&#34; line2=&#34;1&#34; col2=&#34;10&#34; start=&#34;49&#34; end=&#34;58&#34;&amp;gt;str_detect&amp;lt;/SYMBOL_FUNCTION_CALL&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;/expr&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;OP-LEFT-PAREN line1=&#34;1&#34; col1=&#34;11&#34; line2=&#34;1&#34; col2=&#34;11&#34; start=&#34;59&#34; end=&#34;59&#34;&amp;gt;(&amp;lt;/OP-LEFT-PAREN&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;expr line1=&#34;1&#34; col1=&#34;12&#34; line2=&#34;1&#34; col2=&#34;34&#34; start=&#34;60&#34; end=&#34;82&#34;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;expr line1=&#34;1&#34; col1=&#34;12&#34; line2=&#34;1&#34; col2=&#34;23&#34; start=&#34;60&#34; end=&#34;71&#34;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;         &amp;lt;SYMBOL_FUNCTION_CALL line1=&#34;1&#34; col1=&#34;12&#34; line2=&#34;1&#34; col2=&#34;23&#34; start=&#34;60&#34; end=&#34;71&#34;&amp;gt;str_to_lower&amp;lt;/SYMBOL_FUNCTION_CALL&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;/expr&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;OP-LEFT-PAREN line1=&#34;1&#34; col1=&#34;24&#34; line2=&#34;1&#34; col2=&#34;24&#34; start=&#34;72&#34; end=&#34;72&#34;&amp;gt;(&amp;lt;/OP-LEFT-PAREN&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;expr line1=&#34;1&#34; col1=&#34;25&#34; line2=&#34;1&#34; col2=&#34;33&#34; start=&#34;73&#34; end=&#34;81&#34;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;         &amp;lt;SYMBOL line1=&#34;1&#34; col1=&#34;25&#34; line2=&#34;1&#34; col2=&#34;33&#34; start=&#34;73&#34; end=&#34;81&#34;&amp;gt;itemTitle&amp;lt;/SYMBOL&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;/expr&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;OP-RIGHT-PAREN line1=&#34;1&#34; col1=&#34;34&#34; line2=&#34;1&#34; col2=&#34;34&#34; start=&#34;82&#34; end=&#34;82&#34;&amp;gt;)&amp;lt;/OP-RIGHT-PAREN&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;/expr&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;OP-COMMA line1=&#34;1&#34; col1=&#34;35&#34; line2=&#34;1&#34; col2=&#34;35&#34; start=&#34;83&#34; end=&#34;83&#34;&amp;gt;,&amp;lt;/OP-COMMA&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;expr line1=&#34;1&#34; col1=&#34;37&#34; line2=&#34;1&#34; col2=&#34;46&#34; start=&#34;85&#34; end=&#34;94&#34;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;       &amp;lt;STR_CONST line1=&#34;1&#34; col1=&#34;37&#34; line2=&#34;1&#34; col2=&#34;46&#34; start=&#34;85&#34; end=&#34;94&#34;&amp;gt;&#39;wikidata&#39;&amp;lt;/STR_CONST&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;/expr&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;     &amp;lt;OP-RIGHT-PAREN line1=&#34;1&#34; col1=&#34;47&#34; line2=&#34;1&#34; col2=&#34;47&#34; start=&#34;95&#34; end=&#34;95&#34;&amp;gt;)&amp;lt;/OP-RIGHT-PAREN&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;   &amp;lt;/expr&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;/exprlist&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To me, having an XML tree at hand makes it easier to think of, and work with, an &amp;ldquo;abstract syntax tree&amp;rdquo;.&lt;/p&gt;
&lt;h3 id=&#34;xpath-for-all-the-things&#34;&gt;XPath for all the things&lt;/h3&gt;
&lt;p&gt;A tool that I haven&amp;rsquo;t used, but that sounds intriguing, is &lt;a href=&#34;https://twitter.com/groundwalkergmb/status/1502095683788042240&#34;&gt;rpath by Gabriel Becker&lt;/a&gt;, an &lt;em&gt;R package implementing xpath-like functionality for querying R objects&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id=&#34;data-documentation-with-eml&#34;&gt;Data documentation with EML&lt;/h3&gt;
&lt;p&gt;No matter what format your data is, you can create its metadata using the &lt;a href=&#34;https://docs.ropensci.org/EML/&#34;&gt;EML package&lt;/a&gt; maintained by Carl Boettiger that creates XML metadata following the Ecological Metadata Language. Sure, you might prefer using &lt;a href=&#34;https://docs.ropensci.org/dataspice/&#34;&gt;dataspice&lt;/a&gt; maintained by Bryce Mecum (and get JSON).&lt;/p&gt;
&lt;h2 id=&#34;when-you-are-creating-xml-or-html&#34;&gt;When you are creating XML or HTML&lt;/h2&gt;
&lt;p&gt;If the goal of your code or package is to produce XML or HTML, knowing XPath will help you write unit tests (that you might want to complement with &lt;a href=&#34;https://testthat.r-lib.org/articles/snapshotting.html&#34;&gt;snapshot unit tests&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I&amp;rsquo;ve explained why I find XPath, XML, HTML so useful. Applications are endless, not limited to the examples from this post: web scraping, HTML tweaks, Markdown manipulation, code tree manipulation&amp;hellip;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>8 (octo!) GitHub Tips</title>
      <link>https://masalmon.eu/2022/04/05/github-tips/</link>
      <pubDate>Tue, 05 Apr 2022 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2022/04/05/github-tips/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m spending quite a lot of my working time on GitHub, so have taken some habits. Maybe some of them can be useful to you!&lt;/p&gt;
&lt;h1 id=&#34;1-how-to-get-started&#34;&gt;1: How to get started&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve never actually taught git and GitHub, but I like sharing these useful links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://happygitwithr.com&#34;&gt;Happy Git and GitHub for the useR&lt;/a&gt; by Jenny Bryan, the STAT 545 TAs, Jim Hester. It includes a big picture section &lt;a href=&#34;https://happygitwithr.com/big-picture.html&#34;&gt;&amp;ldquo;Why Git? Why GitHub?&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://suzan.rbind.io/2018/03/reflections-4-months-of-github/&#34;&gt;Reflections on 4 months of GitHub: my advice to beginners&lt;/a&gt; by Suzan Baert. It&amp;rsquo;s pragmatic and encouraging.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://peerj.com/preprints/3159/&#34;&gt;Excuse me, do you have a moment to talk about version control?&lt;/a&gt; by Jenny Bryan.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;2-secure-your-account&#34;&gt;2: Secure your account&lt;/h1&gt;
&lt;p&gt;Please use a password manager with some sort of cloud backup.&lt;/p&gt;
&lt;p&gt;Enable &lt;a href=&#34;https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication&#34;&gt;two factor-authentication for your GitHub account&lt;/a&gt;. It should not take much time. Make sure you store the recovery keys into your password manager. Also make sure your two factor-authentication app, if that&amp;rsquo;s an app, has some sort of cloud backup.&lt;/p&gt;
&lt;p&gt;If you interact with GitHub programmatically, say with the usethis package, refer to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://usethis.r-lib.org/articles/git-credentials.html&#34;&gt;Managing Git(Hub) Credentials&lt;/a&gt; in usethis docs;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.djnavarro.net/posts/2021-08-08_git-credential-helpers/&#34;&gt;Managing GitHub credentials from R, difficulty level linux&lt;/a&gt; by Danielle Navarro (if you use Linux, that is!).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;3-refine-github-interface-with-refined-github&#34;&gt;3: Refine GitHub interface with&amp;hellip; Refined GitHub&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/refined-github/refined-github&#34;&gt;Refined GitHub&lt;/a&gt; is a browser extension that adds nice features such as the default ordering of issues from most recently udpated to least recently updated. It&amp;rsquo;s quite neat.&lt;/p&gt;
&lt;h1 id=&#34;4-make-your-profile-informative&#34;&gt;4: Make your profile informative&lt;/h1&gt;
&lt;p&gt;Try to fill your GitHub profile information (and to keep it up-to-date).&lt;/p&gt;
&lt;p&gt;Furthermore,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/pinning-items-to-your-profile&#34;&gt;Pin your most important repositories&lt;/a&gt;. They do not have to be &lt;em&gt;your&lt;/em&gt; repositories, actually, they only need to be repositories you contributed to.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Publicize the &lt;a href=&#34;https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-user-account/managing-your-membership-in-organizations/publicizing-or-hiding-organization-membership&#34;&gt;organization memberships&lt;/a&gt; you want to show.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a &lt;a href=&#34;https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme&#34;&gt;profile README&lt;/a&gt; (yes, I have still not done this myself).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;5-handle-pr-states-and-suggestions-with-available-features&#34;&gt;5: Handle PR states and suggestions with available features&lt;/h1&gt;
&lt;p&gt;You can make &lt;a href=&#34;https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests=&#34;&gt;&lt;em&gt;draft&lt;/em&gt; pull requests&lt;/a&gt; to indicate they are not ready yet. You can revert a pull request to the draft state. I find this most useful.&lt;/p&gt;
&lt;p&gt;In the first comment of a pull request, if you add a line &lt;a href=&#34;https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword=&#34;&gt;&lt;code&gt;Fix #42&lt;/code&gt;&lt;/a&gt; (or some other &lt;a href=&#34;https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword=&#34;&gt;recognized keyword&lt;/a&gt;), merging the PR will close issue 42. From the issue 42 itself, one will be able to see the PR is &amp;ldquo;linked&amp;rdquo; to it.&lt;/p&gt;
&lt;p&gt;When reviewing a pull request, in comments you can make actual change suggestions, &lt;a href=&#34;https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/incorporating-feedback-in-your-pull-request&#34;&gt;&amp;ldquo;commit suggestions&amp;rdquo;&lt;/a&gt; that the receiver can accept with a click. Using this instead of writing something à la &lt;code&gt;tipo -&amp;gt; typo&lt;/code&gt; is quite handy. When you are on the receiving end, to &lt;a href=&#34;https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/incorporating-feedback-in-your-pull-request&#34;&gt;incorporate the feedback&lt;/a&gt; you can either accept each suggestion individually or batch-accept them, but only from the files tab of the PR, not the main tab.&lt;/p&gt;
&lt;h1 id=&#34;6-custom-watch-repositories&#34;&gt;6: Custom watch repositories&lt;/h1&gt;
&lt;p&gt;Watching repositories can be very useful: your own repositories, a favorite package of yours, an important dependency of a project of yours, &lt;a href=&#34;https://github.com/headllines/hackernews-daily/&#34;&gt;Hacker News Daily Top 10&lt;/a&gt;, etc.&lt;/p&gt;
&lt;p&gt;When you watch a repository, you get notified of all issues, PRs, discussions, and also see all commits in your timeline. That last part might be a bit too much. Well, you can customize what to watch by &lt;a href=&#34;https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository=&#34;&gt;configuring your watch settings for an individual repository&lt;/a&gt;. I tend to subscribe to all issues, PRs and discussions, which I then tackle from my &lt;a href=&#34;https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/viewing-and-triaging-notifications/managing-notifications-from-your-inbox#about-your-inbox=&#34;&gt;notifications inbox&lt;/a&gt;, one repository at a time.&lt;/p&gt;
&lt;h1 id=&#34;7-add-your-github-timeline-to-your-rss-feed-reader&#34;&gt;7: Add your GitHub timeline to your RSS feed reader&lt;/h1&gt;
&lt;p&gt;At the very bottom of your GitHub timeline there is a link to your RSS feed, &amp;ldquo;Subscribe to your news feed&amp;rdquo; (it has a token in it so do not publicize it!). I have added mine to Feedly. Even if &lt;a href=&#34;https://github.blog/2022-03-22-improving-your-github-feed/&#34;&gt;GitHub has recently improved the timeline interface&lt;/a&gt;, I like it to be grouped with other tech RSS feeds I subscribe to. That might change, though.&lt;/p&gt;
&lt;h1 id=&#34;8-subscribe-to-the-github-blog&#34;&gt;8: Subscribe to the GitHub blog&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve also added the &lt;a href=&#34;https://github.blog/&#34;&gt;GitHub blog&lt;/a&gt; to Feedly to be aware of new features in a less random way than on Twitter (I&amp;rsquo;m actively reducing my dependency on Twitter for crucial information).&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In this post I have shared eight tips based on my GitHub usage. Thanks to those who taught me some of these! Do &lt;em&gt;you&lt;/em&gt; have some advice for GitHub users?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>How to become a better R code detective?</title>
      <link>https://masalmon.eu/2021/07/13/code-detective/</link>
      <pubDate>Tue, 13 Jul 2021 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2021/07/13/code-detective/</guid>
      <description>&lt;p&gt;&lt;em&gt;Huge thanks to &lt;a href=&#34;https://www.frick.ws/&#34;&gt;Hannah Frick&lt;/a&gt; for her useful feedback on this post! Vielen Dank!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://share.fireside.fm/episode/87RSVeFz+alD0Og1X&#34;&gt;R Weekly podcast&lt;/a&gt; by Eric Nantz.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When trying to fix a bug or add a feature to an R package, how do you go from viewing the code as a big messy ball of wool, to a logical diagram that you can bend to your will? In this post, I will share some resources and tips on getting better at debugging and reading code, written by someone else (or yourself but long enough ago to feel foreign!).&lt;/p&gt;
&lt;p&gt;After step 1, there&amp;rsquo;s not really an order for applying the techniques, but you definitely want to acquire enough knowledge through research before you tinker, otherwise you will be tinkering quite randomly.&lt;/p&gt;
&lt;p&gt;Apart from the idea of adding tests, most tips could apply to non-package code. If your motivation is to contribute to R itself please refer to &lt;a href=&#34;https://forwards.github.io/rdevguide/introduction.html&#34;&gt;A Guide to Contributing to R Core&lt;/a&gt; by Saranjeet Kaur and colleagues.&lt;/p&gt;
&lt;h2 id=&#34;step-0-only-deal-with-well-designed-code&#34;&gt;Step 0: Only deal with well-designed code&lt;/h2&gt;
&lt;p&gt;This is obviously not an actual tip, but more of a encouragement to try and write better and better code ourselves.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://style.tidyverse.org/&#34;&gt;Tidyverse style guide&lt;/a&gt; is a good read, both for learning tips, and for seeing what aspects such a style guide applies to. Of particular interest are e.g. the mention of &lt;a href=&#34;https://style.tidyverse.org/functions.html#comments-1&#34;&gt;function comments&lt;/a&gt;, and &lt;a href=&#34;https://style.tidyverse.org/package-files.html#organisation-1&#34;&gt;file organization&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Regarding code comments, I was intrigued and impressed by the notion of &amp;ldquo;explaining variables&amp;rdquo; mentioned in the tweet below referring a &lt;a href=&#34;https://blog.thepete.net/blog/2021/06/24/explaining-variable/&#34;&gt;great short post&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-dnt=&#34;true&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Great post on why &amp;quot;explaining variables&amp;quot; and &amp;quot;explaining functions or methods&amp;quot; are better than code comments.&lt;br&gt;&lt;br&gt;I found that my enthusiasm for writing/maintaining comments peaked many years ago and I&amp;#39;m better off using other techniques to make the non-obvious (more) obvious. &lt;a href=&#34;https://t.co/yIIOnd8qHz&#34;&gt;https://t.co/yIIOnd8qHz&lt;/a&gt;&lt;/p&gt;&amp;mdash; Jenny Bryan (@JennyBryan) &lt;a href=&#34;https://x.com/JennyBryan/status/1412140590842597385?ref_src=twsrc%5Etfw&#34;&gt;July 5, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.x.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;Beyond its being well designed, it&amp;rsquo;ll also help if the code is well tested: tests can help you understand the goals behind functions, and will help you re-factor without breaking features.&lt;/p&gt;
&lt;p&gt;Now, we don&amp;rsquo;t always choose what code we get, and even if it was well-designed, we might still need detective skills anyway!&lt;/p&gt;
&lt;h2 id=&#34;step-1-clone-and-build&#34;&gt;Step 1: Clone and build&lt;/h2&gt;
&lt;p&gt;In sharing this life-changing tip I am merely repeating the talk &amp;ldquo;Reading other people&amp;rsquo;s code&amp;rdquo; by Patricia Aas that I actually listened to as &lt;a href=&#34;https://www.allthingsgit.com/episodes/learning_a_new_codebase_with_patricia_aas.html&#34;&gt;an episode of the All Things Git podcast&lt;/a&gt;. The techniques presented by Patricia Aas are not specific to R but many of them are relevant for R codebases.&lt;/p&gt;
&lt;p&gt;Now to this tip&amp;hellip; Instead of being overwhelmed by the idea of starting to tinker with a codebase, create a local version-controlled project with the codebase in it! E.g. fork a GitHub repo, and use &lt;a href=&#34;https://usethis.r-lib.org/reference/create_from_github.html&#34;&gt;&lt;code&gt;usethis::create_from_github()&lt;/code&gt;&lt;/a&gt;. Then open it, install the dependencies via &lt;code&gt;remotes::install_deps(dependencies = TRUE)&lt;/code&gt;, build or load it. Before amending things, create a new branch via e.g. &lt;code&gt;gert::git_branch_create(&amp;quot;tinkering&amp;quot;)&lt;/code&gt;. I suppose that if I were fancy I&amp;rsquo;d say this step, preparing a local codebase to play with, is your &lt;a href=&#34;https://fortelabs.co/blog/mise-en-place-for-knowledge-workers/&#34;&gt;&lt;em&gt;mise en place&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Obviously to reach that stage you&amp;rsquo;ll need to know &lt;em&gt;what&lt;/em&gt; codebase is the one to be working on. However, you&amp;rsquo;ll probably start from some code in any case, e.g. your currently buggy code.&lt;/p&gt;
&lt;h2 id=&#34;make-your-problem-smaller&#34;&gt;Make your problem smaller&lt;/h2&gt;
&lt;p&gt;In case of a bug, you&amp;rsquo;ll often be advised to make it a minimal reproducible example. While you&amp;rsquo;ll often hear this when you try to communicate your bug to someone else, it is also great practice to do this for yourself! An important thing to know here is &lt;em&gt;reprex&lt;/em&gt;. A reprex is both a concept (reprex for reproducible example) and a package for communicating such examples, respectively promoted and maintained by Jenny Bryan. Why use reprex?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The isolated bug is easier to solve or will be solved by creating it! In Jenny Bryan&amp;rsquo;s talk &lt;a href=&#34;https://github.com/jennybc/debugging#readme&#34;&gt;&amp;ldquo;Object of type &amp;lsquo;closure&amp;rsquo; is not subsettable&amp;rdquo;&lt;/a&gt; there&amp;rsquo;s an example of original code and its minified version.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;As it is run in an isolated session you can be more sure that it&amp;rsquo;s reproducible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can send your bug in a format ideal for experts! But you might be writing a reprex just for yourself, to accompany some notes in a GitHub issue for instance.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How does reprex work?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You write some code in an editor (including loading libraries, creating toy data etc.).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You copy the code to your clipboard.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You run &lt;a href=&#34;https://reprex.tidyverse.org/reference/reprex.html&#34;&gt;&lt;code&gt;reprex::reprex()&lt;/code&gt;&lt;/a&gt; and reprex runs your code in an isolated session!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You get the rendered code on the clipboard (and a preview in RStudio Viewer pane)! Error messages rendered, images uploaded to imgur.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You paste the rendered code somewhere, potentially to show to someone.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To learn more about reprex and adopt it, I&amp;rsquo;d recommend watching &lt;a href=&#34;https://resources.rstudio.com/webinars/help-me-help-you-creating-reproducible-examples-jenny-bryan&#34;&gt;the RStudio webinar about reprex&lt;/a&gt; and reading reprex vignettes, in particular &lt;a href=&#34;https://reprex.tidyverse.org/articles/reprex-dos-and-donts.html&#34;&gt;&amp;ldquo;Reprex do&amp;rsquo;s and don&amp;rsquo;ts&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also in the case of a bug, maybe you don&amp;rsquo;t need to read this post further if your problem is in the bingo below. Often, you&amp;rsquo;ll only notice &amp;ldquo;obvious&amp;rdquo; mistakes after making the problem smaller (or after taking a break!).&lt;/p&gt;
&lt;p&gt;In case of amending the features of a package, it&amp;rsquo;ll be important to clearly defined the scope of what you&amp;rsquo;re after. Easier for your work as a code detective, but also for many other reasons, see &lt;a href=&#34;https://www.netlify.com/blog/2020/03/31/how-to-scope-down-prs/&#34;&gt;Sarah Drasner&amp;rsquo;s post &lt;em&gt;How to Scope Down PRs&lt;/em&gt;&lt;/a&gt; and Yihui Xie&amp;rsquo;s post &lt;a href=&#34;https://yihui.org/en/2018/02/bite-sized-pull-requests/&#34;&gt;&lt;em&gt;&amp;ldquo;Bite-sized&amp;rdquo; Pull Requests&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;pull-an-end--follow-the-trails&#34;&gt;Pull an end / Follow the trails&lt;/h2&gt;
&lt;p&gt;As you are not going to read code from cover to cover, you&amp;rsquo;ll need to find a logical way to explore the code.&lt;/p&gt;
&lt;p&gt;I like the phrase &lt;em&gt;follow the trails&lt;/em&gt; by Kara Woo in her excellent RStudio conference talk &lt;a href=&#34;https://www.rstudio.com/resources/rstudioconf-2019/box-plots-a-case-study-in-debugging-and-perseverance/&#34;&gt;&amp;ldquo;Box plots - A case study in debugging and perseverance&amp;rdquo;&lt;/a&gt; as well as the phrase &lt;em&gt;pull an end&lt;/em&gt; by Patricia Aas in her also excellent talk &lt;a href=&#34;https://patricia.no/2018/09/19/reading_other_peoples_code.html&#34;&gt;&amp;ldquo;Reading Other People&amp;rsquo;s Code&amp;rdquo;&lt;/a&gt; already mentioned in this post.&lt;/p&gt;
&lt;h3 id=&#34;find-where-to-start&#34;&gt;Find where to start&lt;/h3&gt;
&lt;p&gt;Easy case: there&amp;rsquo;s a message on screen telling you where an error occurred, or you know what function you want to amend.&lt;/p&gt;
&lt;p&gt;Alternatively,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can put the error / warning in a search engine.&lt;/li&gt;
&lt;li&gt;If there&amp;rsquo;s an unclear error you can try to see the traceback i.e. what functions were called leading to that error. In her talk &lt;a href=&#34;https://github.com/jennybc/debugging#readme&#34;&gt;&amp;ldquo;Object of type &amp;lsquo;closure&amp;rsquo; is not subsettable&amp;rdquo;&lt;/a&gt;, Jenny Bryan explains very well what a traceback is. In my &lt;a href=&#34;https://rstats.wtf/r-startup.html#rprofile&#34;&gt;&lt;code&gt;.Rprofile&lt;/code&gt;&lt;/a&gt; I have&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;options&lt;/span&gt;(
error &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; rlang&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;entrace, 
rlang_backtrace_on_error &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;branch&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;thanks to a &lt;a href=&#34;https://twitter.com/noamross/status/1202269314029621251&#34;&gt;tweet by Noam Ross&lt;/a&gt; reporting a tip by Jenny Bryan. &amp;ldquo;It gives trimmed tracebacks when using pipes.&amp;rdquo;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If there&amp;rsquo;s no error but a warning you could try to &lt;a href=&#34;https://adv-r.hadley.nz/debugging.html#non-error-failures&#34;&gt;convert the warning to an error&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;explore-from-that-starting-point&#34;&gt;Explore from that starting point&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You can use &amp;ldquo;grepping&amp;rdquo; as said by Patricia Aas: look for the occurrences of a function or variable name in a local folder, or via &lt;a href=&#34;https://docs.github.com/en/github/searching-for-information-on-github/getting-started-with-searching-on-github/about-searching-on-github&#34;&gt;GitHub (advanced) search&lt;/a&gt;. You can limit the hits to some types of files e.g. R scripts in &lt;code&gt;R/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In your IDE e.g. RStudio there might be a way to go directly to the &lt;em&gt;definition&lt;/em&gt; of function. With the &lt;a href=&#34;https://github.com/jimhester/lookup&#34;&gt;lookup package&lt;/a&gt; you can also easily look up the source of functions &lt;a href=&#34;https://blog.r-hub.io/2019/05/14/read-the-source/&#34;&gt;locally and on GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;how-to-read-code-space-and-time&#34;&gt;How to read code: space&amp;hellip; and time&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Hopefully the code makes sense on its own. If not, fear not, the next item right here, and the other sections of this post, as well as patience, will help.&lt;/li&gt;
&lt;li&gt;Sometimes &lt;a href=&#34;https://docs.github.com/en/github/managing-files-in-a-repository/managing-files-on-github/tracking-changes-in-a-file&#34;&gt;using git blame or looking at the git history&lt;/a&gt; might help understand the context of some aspects of the code, if there&amp;rsquo;s no code comment referring an issue. Do not actually &lt;em&gt;blame&lt;/em&gt; people, though. To make your own git history more informative for such later code archaeology, use &lt;a href=&#34;https://happygitwithr.com/git-branches.html&#34;&gt;branches&lt;/a&gt; and &lt;a href=&#34;https://docs.github.com/en/github/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges&#34;&gt;squash and merge&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;build-your-mental-model-of-the-code&#34;&gt;Build your mental model of the code&lt;/h2&gt;
&lt;p&gt;That&amp;rsquo;s what &lt;a href=&#34;https://www.allthingsgit.com/episodes/learning_a_new_codebase_with_patricia_aas.html&#34;&gt;Patricia Aas calls &amp;ldquo;mental machine&amp;rdquo;&lt;/a&gt;. You might want to draw some sort of diagram by hand (or &lt;a href=&#34;https://blog.r-hub.io/2019/12/12/internal-functions/#explore-internal-functions-within-a-package&#34;&gt;programmatically&lt;/a&gt;). Patricia Aas remarks that such diagrams might even be contributed to the codebase as developer documentation.&lt;/p&gt;
&lt;h2 id=&#34;browse-code-by-others&#34;&gt;Browse code by others&lt;/h2&gt;
&lt;p&gt;The life-hack [now deleted] by Julia Silge for fixing Travis CI builds&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, looking at other people&amp;rsquo;s configuration files, applies to any code endeavour.&lt;/p&gt;
&lt;p&gt;How to find good examples?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The lookup package can help you &lt;a href=&#34;https://blog.r-hub.io/2019/05/14/read-the-source/#how-to-search-the-source&#34;&gt;look up usage of a function on GitHub&lt;/a&gt; and in general &lt;a href=&#34;https://github.com/search/advanced&#34;&gt;GitHub Advanced search&lt;/a&gt; is really useful;&lt;/li&gt;
&lt;li&gt;You might look at the reverse dependencies of a package you are using;&lt;/li&gt;
&lt;li&gt;You might try to think of packages doing something similar to yours (e.g. another package munging XML data from an API ; another package wrapping a C library).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;beyond-browsing-files-browser&#34;&gt;Beyond browsing files, &lt;code&gt;browser()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Reading code and imagining what it does only goes so long. You can edit the code and see whether, from the outside, it does what you want it to. Sometimes you might also make do with print-debugging i.e. for instance writing &lt;code&gt;print(&amp;quot;coucou !&amp;quot;)&lt;/code&gt; to check whether a part of the code was run, or &lt;code&gt;print(class(x))&lt;/code&gt; to check an assumption about a thing. Sometimes print-debugging is the only technique you might be able to use if &lt;a href=&#34;https://adv-r.hadley.nz/debugging.html#print-debugging&#34;&gt;non-interactive debugging&lt;/a&gt;. It can also be perfect to know where a loop breaks which motivated a tweet by Sharla Gelfand.&lt;/p&gt;
&lt;p&gt;But often you will have to go experiment under the hood. For doing that efficiently you will need to learn about &lt;a href=&#34;https://rdrr.io/r/base/browser.html&#34;&gt;&lt;code&gt;browser()&lt;/code&gt;&lt;/a&gt; and friends! Or only just &lt;a href=&#34;https://rdrr.io/r/base/browser.html&#34;&gt;&lt;code&gt;browser()&lt;/code&gt;&lt;/a&gt; to start with!&lt;/p&gt;
&lt;p&gt;The basic idea is that you just replace the &lt;a href=&#34;https://rdrr.io/r/base/print.html&#34;&gt;&lt;code&gt;print()&lt;/code&gt;&lt;/a&gt; command you were about to write with &lt;a href=&#34;https://rdrr.io/r/base/browser.html&#34;&gt;&lt;code&gt;browser()&lt;/code&gt;&lt;/a&gt;, run the code and voilà! You entered the debugger and can run code line by line, explore options and environment variables, etc. Over time it&amp;rsquo;ll become a habit of yours, at least that&amp;rsquo;s what happened to me once I saw the light. 😁&lt;/p&gt;
&lt;p&gt;Here are some good resources to learn about debugging tools. These resources also overlap with some of the objectives of this very blog post.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://adv-r.hadley.nz/debugging.html&#34;&gt;Debugging advice in the Advanced R book by Hadley Wickham&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.rstudio.com/resources/webinars/debugging-techniques-in-rstudio/&#34;&gt;Webinar debugging techniques in RStudio by Amanda Gadrow&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://rstudio-education.github.io/hopr/debug.html&#34;&gt;Debugging advice in the Hands-on programming with R book by Garrett Grolemund&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://rstats.wtf/debugging-r-code.html&#34;&gt;Debugging advice in the materials of the course &amp;ldquo;What they forgot to teach you about R&amp;rdquo; by Jenny Bryan and Jim Hester&lt;/a&gt; &amp;ndash; it even includes tips for R Markdown debugging;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/jennybc/debugging#readme&#34;&gt;Jenny Bryan&amp;rsquo;s talk &amp;ldquo;Object of type &amp;lsquo;closure&amp;rsquo; is not subsettable&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;beyond-r&#34;&gt;Beyond R&lt;/h3&gt;
&lt;p&gt;Sometimes the bug or element to tweak will live outside of R. Maybe in some C code you are wrapping, maybe in a CSS file. You will therefore have to learn debugging tools for these things too!&lt;/p&gt;
&lt;h2 id=&#34;read-tests-write-some-for-sure&#34;&gt;Read tests? Write some for sure&lt;/h2&gt;
&lt;p&gt;In Patricia Aas&amp;rsquo; &lt;a href=&#34;https://patricia.no/2018/09/19/reading_other_peoples_code.html&#34;&gt;techniques&lt;/a&gt; features the idea of writing and running tests to see what&amp;rsquo;s the code is supposed to do. They especially mention integration tests, whereas in R packages you&amp;rsquo;ll mostly find unit tests. Those can also be useful to read, especially when they start breaking after your experiments.&lt;/p&gt;
&lt;p&gt;In any case, once you have amended a codebase to fix a bug or add a feature, add tests! In Kara Woo&amp;rsquo;s talk &lt;a href=&#34;https://www.rstudio.com/resources/rstudioconf-2019/box-plots-a-case-study-in-debugging-and-perseverance/&#34;&gt;&amp;ldquo;Box plots - A case study in debugging and perseverance&amp;rdquo;&lt;/a&gt;, she explained she added tests. In &lt;a href=&#34;https://github.com/jennybc/debugging#readme&#34;&gt;Jenny Bryan&amp;rsquo;s talk &amp;ldquo;Object of type &amp;lsquo;closure&amp;rsquo; is not subsettable&amp;rdquo;&lt;/a&gt; she uses the word &amp;ldquo;deter&amp;rdquo; in the &lt;a href=&#34;https://speakerdeck.com/jennybc/object-of-type-closure-is-not-subsettable?slide=69&#34;&gt;part of the talk where she gives such advice&lt;/a&gt;: adding tests and assertions, but also other tips such as running those on continuous integration, &amp;ldquo;using mind bendy stuff in moderation&amp;rdquo;, leaving access panels (e.g. verbose modes), writing error messages for humans.&lt;/p&gt;
&lt;p&gt;You could even write a failing test at the beginning of your code exploration, &lt;a href=&#34;https://r-pkgs.org/tests.html&#34;&gt;even leaving it failing for an easier restart when you come back to the codebase&lt;/a&gt; (better than a sticky note for sure!).&lt;/p&gt;
&lt;h2 id=&#34;rubberducking-to-a-person&#34;&gt;Rubberducking to a person&lt;/h2&gt;
&lt;p&gt;Another technique you will often see mentioned is rubberducking i.e. explaining your problem to a rubber duck. The simple act of phrasing your issue might help you solve it.&lt;/p&gt;
&lt;p&gt;However, you might prefer to speak to an actual person, or pretend you are as written in the tweet by Julia Evans below:&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-dnt=&#34;true&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;yea i don&amp;#39;t really like to talk about rubber duck debugging because personally I find it hard to get into the right mindset if I don&amp;#39;t have a specific person in mind who I&amp;#39;m talking to, even if I&amp;#39;m just writing them an email / Slack message which I later delete without sending it&lt;/p&gt;&amp;mdash; 🔎Julia Evans🔍 (@b0rk) &lt;a href=&#34;https://x.com/b0rk/status/1409533060790558725?ref_src=twsrc%5Etfw&#34;&gt;June 28, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.x.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;I liked seeing that as I sometimes open a Slack conversation with someone as if I were about to ask for their help, and whilst preparing my notes for them, I&amp;rsquo;ll solve my issue.&lt;/p&gt;
&lt;h2 id=&#34;refactoring&#34;&gt;Refactoring&lt;/h2&gt;
&lt;p&gt;Another &lt;a href=&#34;https://patricia.no/2018/09/19/reading_other_peoples_code.html&#34;&gt;tip by Patricia Aas&lt;/a&gt; is refactoring the code as it might improve your understanding of it. They underline that you should not contribute the results of your refactoring, especially as a first PR, as people might hate you! It&amp;rsquo;s an exercise for you.&lt;/p&gt;
&lt;p&gt;That said, I remember receiving nice PRs from someone who had just read the &lt;a href=&#34;https://qntm.org/clean&#34;&gt;Clean Code book by Robert C. Martin&lt;/a&gt;. That contributor started with a small PR, and were very polite. Since then I&amp;rsquo;ve seen &lt;a href=&#34;https://blog.wesleyac.com/posts/robert-martin&#34;&gt;some bad critic of the book and its author and wouldn&amp;rsquo;t recommend reading it&lt;/a&gt; but these PRs made perfect sense. I can however easily imagine a big refactoring PR would not be happily received!&lt;/p&gt;
&lt;p&gt;So, in a nutshell, as said by Patricia Aas, refactor to learn, &lt;em&gt;in your own local copy or your own fork&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&#34;asking-for-help&#34;&gt;Asking for help&lt;/h2&gt;
&lt;p&gt;As nice as solving a problem on one&amp;rsquo;s own is, asking for help might be the solution! It is also a skill, or more, a bunch of skills: both how and where to ask for help but also deciding when to ask for help, when it&amp;rsquo;s no longer worth anyone&amp;rsquo;s money to have you continuing to work alone on a problem.&lt;/p&gt;
&lt;h3 id=&#34;how-to-ask-for-help&#34;&gt;How to ask for help?&lt;/h3&gt;
&lt;p&gt;In the section of this post about making your problem smaller, we mentioned creating a reprex and having a clear scope. These are elements that will be featured in your plea for help.&lt;/p&gt;
&lt;p&gt;It can also be good if you have &lt;a href=&#34;https://wizardzines.com/comics/track-your-progress/&#34;&gt;tracked your progress&lt;/a&gt;, the various things you have tried.&lt;/p&gt;
&lt;h3 id=&#34;where-to-ask-for-help&#34;&gt;Where to ask for help?&lt;/h3&gt;
&lt;p&gt;Where to ask for help depends on your question and the codebase you are working on. If you are working on a pull request in a package where you already have a good working relationship with other developers, or where you were encouraged to open a PR (directly or via the contributing guide), you might get help from other contributors.&lt;/p&gt;
&lt;p&gt;I wrote a blog post on &lt;a href=&#34;https://masalmon.eu/2018/07/22/wheretogethelp/&#34;&gt;where to get help with your R questions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See also my post on the R-hub blog, &lt;a href=&#34;https://blog.r-hub.io/2019/04/11/r-package-devel/&#34;&gt;&lt;em&gt;How to get help with R package development? R-package-devel and beyond&lt;/em&gt;&lt;/a&gt;, for general venues where to ask for help about package development. My favorite ones are the &lt;a href=&#34;https://discuss.ropensci.org/&#34;&gt;rOpenSci forum&lt;/a&gt; and the &lt;a href=&#34;https://community.rstudio.com/c/package-development/11&#34;&gt;package development category of the RStudio community forum&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;reading-other-peoples-debugging-journeys-document-yours&#34;&gt;Reading other people&amp;rsquo;s debugging journeys, document yours&lt;/h2&gt;
&lt;p&gt;Sadly but understandably people will often only take the time to document their debugging journey when the bug is especially tricky or weird. However, few people write actual &lt;a href=&#34;https://jvns.ca/blog/2021/04/16/notes-on-debugging-puzzles/&#34;&gt;debugging games&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the meantime, you might enjoy watching or hearing some debugging journeys. You will notice how these programmers make and invalidate hypotheses.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.rstudio.com/resources/rstudioconf-2019/box-plots-a-case-study-in-debugging-and-perseverance/&#34;&gt;Kara Woo&amp;rsquo;s talk &amp;ldquo;Box plots - A case study in debugging and perseverance&amp;rdquo;&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.jimhester.com/post/2018-03-30-debugging-journey/&#34;&gt;&amp;ldquo;A debugging journey&amp;rdquo; by Jim Hester&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://blog.r-hub.io/2020/02/20/processx-blocked-sigchld/&#34;&gt;&amp;ldquo;Debugging: Signals and Subprocesses&amp;rdquo; by Gábor Csárdi&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://reside-ic.github.io/blog/debugging-and-fixing-crans-additional-checks-errors/&#34;&gt;&amp;ldquo;Debugging and Fixing CRAN&amp;rsquo;s &amp;lsquo;Additional Checks&amp;rsquo; errors&amp;rdquo; by Rich FitzJohn&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://reside-ic.github.io/blog/debugging-memory-errors-with-valgrind-and-gdb/&#34;&gt;&amp;ldquo;Debugging memory errors with valgrind and gdb&amp;rdquo; by Rich FitzJohn&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you end up documenting your own code detective story, please tell me, I&amp;rsquo;d like to read it!&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I presented various techniques useful for code detectives. Getting better at them will help you debug and amend codebases. Now, I was able to summarize these tips, but I can&amp;rsquo;t say I never get stuck. 🙂&lt;/p&gt;
&lt;h3 id=&#34;where-next&#34;&gt;Where next?&lt;/h3&gt;
&lt;p&gt;If you have no personal opinion on what to &amp;ldquo;study&amp;rdquo; next from the numerous links of this post or elsewhere, my recommendation would be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start with Kara Woo&amp;rsquo;s talk &lt;a href=&#34;https://www.rstudio.com/resources/rstudioconf-2019/box-plots-a-case-study-in-debugging-and-perseverance/&#34;&gt;&amp;ldquo;Box plots - A case study in debugging and perseverance&amp;rdquo;&lt;/a&gt; as it&amp;rsquo;s both a real and engaging story (with closure i.e. the bug was fixed! happy end!) and covers many useful debugging tools.&lt;/li&gt;
&lt;li&gt;Continue with the &lt;a href=&#34;https://adv-r.hadley.nz/debugging.html&#34;&gt;Debugging advice in the Advanced R book by Hadley Wickham&lt;/a&gt; that is very clear and well organized. &amp;ldquo;Advanced R&amp;rdquo; might a frightening title but really don&amp;rsquo;t be afraid.&lt;/li&gt;
&lt;li&gt;If you are an RStudio IDE user, you&amp;rsquo;ll find great use of &lt;a href=&#34;https://www.rstudio.com/resources/webinars/debugging-techniques-in-rstudio/&#34;&gt;Amanda Gadrow&amp;rsquo;s webinar about debugging techniques in RStudio&lt;/a&gt; and the &lt;a href=&#34;https://support.rstudio.com/hc/en-us/articles/205612627-Debugging-with-the-RStudio-IDE&#34;&gt;corresponding official RStudio documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Then you could watch Jenny Bryan&amp;rsquo;s talk &lt;a href=&#34;https://github.com/jennybc/debugging#readme&#34;&gt;&amp;ldquo;Object of type &amp;lsquo;closure&amp;rsquo; is not subsettable&amp;rdquo;&lt;/a&gt; as it covers a lot of ground around problem solving in R, with ideas extremely well conveyed (and if you want to binge watch more talks of Jenny Bryan&amp;rsquo;s, continue with &lt;a href=&#34;https://github.com/jennybc/code-smells-and-feels&#34;&gt;&amp;ldquo;Code feels, code smells&amp;rdquo;&lt;/a&gt; that&amp;rsquo;ll help you write better code to start with 🙂).&lt;/li&gt;
&lt;li&gt;Lastly, you might be interested in drawing your own lessons from non R specific resources such as &lt;a href=&#34;https://www.allthingsgit.com/episodes/learning_a_new_codebase_with_patricia_aas.html&#34;&gt;the All Things Git podcast episode with Patricia Aas&lt;/a&gt;, &lt;a href=&#34;https://jvns.ca/#debugging&#34;&gt;Julia Evans&amp;rsquo; blog posts about debugging&lt;/a&gt; and &lt;a href=&#34;https://wizardzines.com/zines/bugs/&#34;&gt;Julia Evans&amp;rsquo; comics about debugging&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And then, just wait for the next problem to tackle in your coding practice&amp;hellip; One never has to wait very long. 😅&lt;/p&gt;
&lt;h3 id=&#34;last-words&#34;&gt;Last words&lt;/h3&gt;
&lt;p&gt;Last but not least I want to emphasize that there are also human aspects to this process.&lt;/p&gt;
&lt;p&gt;&lt;blockquote class=&#34;twitter-tweet&#34; data-dnt=&#34;true&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;we think about debugging as a technical skill (and it absolutely is!!) but a huge amount of it is managing your feelings so you don&amp;#39;t get discouraged and being self-aware so you can recognize your incorrect assumptions&lt;/p&gt;&amp;mdash; 🔎Julia Evans🔍 (@b0rk) &lt;a href=&#34;https://x.com/b0rk/status/1403405539971842052?ref_src=twsrc%5Etfw&#34;&gt;June 11, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.x.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;blockquote class=&#34;twitter-tweet&#34; data-dnt=&#34;true&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;I love waking up and jumping back into solving a bug and immediately solving it with a fresh mind. Sleep is my favorite coding tool.&lt;/p&gt;&amp;mdash; Kelly Vaughn (@kvlly) &lt;a href=&#34;https://x.com/kvlly/status/1385573317277532162?ref_src=twsrc%5Etfw&#34;&gt;April 23, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.x.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;

&lt;/p&gt;
&lt;p&gt;What are your favourite tips and resources? Are you too eagerly awaiting &lt;a href=&#34;https://wizardzines.com/zines/bugs/&#34;&gt;Julia Evans&amp;rsquo; zine about debugging&lt;/a&gt;? Please tell me in the comments below!&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Travis CI itself is no longer recommended &lt;a href=&#34;https://ropensci.org/blog/2020/11/19/moving-away-travis/&#34;&gt;by rOpenSci for instance&lt;/a&gt;. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Draw me a project</title>
      <link>https://masalmon.eu/2021/06/30/r-projects/</link>
      <pubDate>Wed, 30 Jun 2021 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2021/06/30/r-projects/</guid>
      <description>&lt;p&gt;&lt;em&gt;I&amp;rsquo;ll be giving a remote keynote talk at the &lt;a href=&#34;https://rr2021.sciencesconf.org/program&#34;&gt;&lt;em&gt;Rencontres R&lt;/em&gt;&lt;/a&gt; (French R conference) on July the 12th, all in French.&lt;/em&gt; &lt;em&gt;This blog post is a written version of my presentation, but in English.&lt;/em&gt; &lt;em&gt;I decided to not &lt;a href=&#34;https://masalmon.eu/talks/&#34;&gt;talk&lt;/a&gt; about package development for once, but rather about workflows and how to structure &amp;amp; run an analysis.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to &lt;a href=&#34;https://cderv.rbind.io/&#34;&gt;Christophe Dervieux&lt;/a&gt; for useful feedback on this post! Merci beaucoup !&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post was featured on the &lt;a href=&#34;https://share.fireside.fm/episode/87RSVeFz+W6_0jLXR&#34;&gt;R Weekly podcast&lt;/a&gt; by Eric Nantz.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;/div&gt;
&lt;p&gt;Why discuss the making of R projects? Because any improvement in your workflow might improve the experience of anyone trying to run or audit an analysis later, including yourself. It&amp;rsquo;s also nice that there are always elements to refine, although that also means one might be procrastinating instead of making actual progress, so beware!&lt;/p&gt;
&lt;p&gt;Now why should &lt;em&gt;I&lt;/em&gt; discuss the making of R projects? While I am not often in charge of analyses these days, I &lt;a href=&#34;https://masalmon.eu/2019/01/25/uptodate/&#34;&gt;follow R news&lt;/a&gt; quite well so thought I might be able to deliver some useful tips to the audience.&lt;/p&gt;
&lt;h2 id=&#34;some-basics&#34;&gt;Some &amp;ldquo;basics&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;To start with I&amp;rsquo;d like to mention some rules or principles that are quite crucial. My main source of information for them is &lt;a href=&#34;https://jennybryan.org/&#34;&gt;Jenny Bryan&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Like many I identified with Sharla Gelfand&amp;rsquo;s quote&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; as reported by Kara Woo on Twitter, &amp;ldquo;Everything I know is from Jenny Bryan&amp;rdquo;.&lt;/p&gt;
&lt;figure&gt;&lt;a href=&#34;https://github.com/MonkmanMH/EIKIFJB&#34;&gt;
    &lt;img src=&#34;https://raw.githubusercontent.com/MonkmanMH/EIKIFJB/main/EIKIFJB_sigmar_hex.png&#34;
         alt=&#34;hex logo de &amp;#39;Everything I know is from Jenny Bryan&amp;#39; avec un ordinateur portable en feu&#34; width=&#34;350&#34;/&gt; &lt;/a&gt;
&lt;/figure&gt;

&lt;p&gt;There&amp;rsquo;s even a &lt;a href=&#34;https://github.com/MonkmanMH/EIKIFJB&#34;&gt;logo&lt;/a&gt; created by &lt;a href=&#34;https://github.com/MonkmanMH&#34;&gt;Martin Monkman&lt;/a&gt; for all of us agreeing with that statement! It features the letters EIKIFJB for &amp;ldquo;Everything I know is from Jenny Bryan&amp;rdquo; as well as a laptop on fire.&lt;/p&gt;
&lt;p&gt;Why a laptop on fire?!&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-dnt=&#34;true&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;The only two things that make &lt;a href=&#34;https://x.com/JennyBryan?ref_src=twsrc%5Etfw&#34;&gt;@JennyBryan&lt;/a&gt; 😤😠🤯. Instead use projects + here::here() &lt;a href=&#34;https://x.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; &lt;a href=&#34;https://t.co/GwxnHePL4n&#34;&gt;pic.twitter.com/GwxnHePL4n&lt;/a&gt;&lt;/p&gt;&amp;mdash; Hadley Wickham (@hadleywickham) &lt;a href=&#34;https://x.com/hadleywickham/status/940021008764846080?ref_src=twsrc%5Etfw&#34;&gt;December 11, 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.x.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;That&amp;rsquo;s a reference to a talk Jenny Bryan gave years ago, to which she said she&amp;rsquo;d put your computer on fire if you used &lt;code&gt;setwd(&amp;quot;C:\Users\jenny\path\that\only\I\have&amp;quot;)&lt;/code&gt; or &lt;code&gt;rm(list = ls())&lt;/code&gt; at the beginning of your scripts. This goes against the notion of a &lt;a href=&#34;https://www.tidyverse.org/blog/2017/12/workflow-vs-script/&#34;&gt;&amp;ldquo;project-oriented workflow&amp;rdquo;&lt;/a&gt;. I do not need to repeat the wisdom of her blog post in mine, so will only use cliff notes &amp;amp; some remarks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It&amp;rsquo;s handy to create your project with &lt;a href=&#34;https://usethis.r-lib.org/reference/create_package.html&#34;&gt;&lt;code&gt;usethis::create_project()&lt;/code&gt;&lt;/a&gt;. RStudio IDE and projects work well together cf &lt;a href=&#34;https://rstats.wtf/project-oriented-workflow.html#ide-support-for-projects&#34;&gt;IDE support for projects&lt;/a&gt; and &lt;a href=&#34;https://rstats.wtf/project-oriented-workflow.html#rstudio-projects&#34;&gt;RStudio projects&lt;/a&gt; (although you could use the principles of a project-oriented workflow outside of RStudio!).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When reading in data etc. use paths relative to the root of your project, possibly using the &lt;a href=&#34;https://here.r-lib.org/articles/here.html&#34;&gt;here package by Kirill Müller&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Re-start R often, do not e.g. load packages in your &lt;a href=&#34;https://rstats.wtf/r-startup.html#rprofile&#34;&gt;.Rprofile&lt;/a&gt;, &lt;a href=&#34;https://usethis.r-lib.org/reference/use_blank_slate.html&#34;&gt;&lt;code&gt;usethis::use_blank_slate()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Really, go and read her post if you haven&amp;rsquo;t yet!&lt;/p&gt;
&lt;p&gt;In my talk I&amp;rsquo;ll show pictures of the Kei-tora Gardening Contest where participants create beautiful gardens in little trucks, which I find is a good image of a project that should be independent (you can move your truck, you should be able to move your project too).&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-dnt=&#34;true&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;The Kei-tora Gardening Contest is an annual event put on by the Japan Federation of Landscape Contractors to see who can build the best looking garden on the back of a Kei truck. Here are some of the winners from the past 12 years. &lt;a href=&#34;https://t.co/IpkRiALn7a&#34;&gt;https://t.co/IpkRiALn7a&lt;/a&gt; &lt;a href=&#34;https://t.co/vep4K0VZt6&#34;&gt;pic.twitter.com/vep4K0VZt6&lt;/a&gt;&lt;/p&gt;&amp;mdash; Doctor Popular (@DocPop) &lt;a href=&#34;https://x.com/DocPop/status/1403009688392781824?ref_src=twsrc%5Etfw&#34;&gt;June 10, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.x.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;As the first part of my talk really is a collection of awesome content by Jenny Bryan, I will also show her rules for &lt;a href=&#34;http://www2.stat.duke.edu/~rcs46/lectures_2015/01-markdown-git/slides/naming-slides/naming-slides.pdf&#34;&gt;naming files&lt;/a&gt;. What Shakespeare said about &lt;a href=&#34;https://en.wikipedia.org/wiki/A_rose_by_any_other_name_would_smell_as_sweet&#34;&gt;roses&lt;/a&gt; isn&amp;rsquo;t true when programming. 😅&lt;/p&gt;
&lt;p&gt;Then I&amp;rsquo;ll &amp;ldquo;introduce&amp;rdquo; version control. I&amp;rsquo;ll first underline that you want to have a back-up of your stuff somewhere no matter how you do it (so even if you do not use git, think of backing things up with a good system!). I&amp;rsquo;ll briefly mention some basic git commands, and most importantly, how to run them! Here are my preferences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Using usethis (&lt;a href=&#34;https://usethis.r-lib.org/reference/use_git.html&#34;&gt;&lt;code&gt;usethis::use_git()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://usethis.r-lib.org/reference/use_github.html&#34;&gt;&lt;code&gt;usethis::use_github()&lt;/code&gt;&lt;/a&gt;, etc.) and gert (&lt;a href=&#34;https://docs.ropensci.org/gert/reference/git_fetch.html&#34;&gt;&lt;code&gt;gert::git_push()&lt;/code&gt;&lt;/a&gt;) so that I don&amp;rsquo;t need to leave R.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using RStudio git pane to not be too far from the R console.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using the terminal for commands copy-pasted from somewhere on the web (and for the ones I now know by heart!).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using a git interface like GitKraken (or the editor VSCODE that has a good git integration) for more complicated stuff&amp;hellip; which I haven&amp;rsquo;t really ever fully explored, actually.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ll share links to my favorite git resources that I send to anyone who asks (or doesn&amp;rsquo;t ask):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.tandfonline.com/doi/full/10.1080/00031305.2017.1399928&#34;&gt;Excuse Me, Do You Have a Moment to Talk About Version Control?&lt;/a&gt;, Jenny Bryan.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://happygitwithr.com/&#34;&gt;Happy Git and GitHub for the useR&lt;/a&gt;, Jenny Bryan, the STAT 545 TAs, Jim Hester.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-dnt=&#34;true&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Great observation: if you can write &lt;a href=&#34;https://x.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt;, you can use Git.&lt;br&gt;Great advice: when or before things get funky, practice tricky bits and disaster recovery in a bogus repo. &lt;a href=&#34;https://t.co/XVwHP9K4av&#34;&gt;https://t.co/XVwHP9K4av&lt;/a&gt;&lt;/p&gt;&amp;mdash; Jenny Bryan (@JennyBryan) &lt;a href=&#34;https://x.com/JennyBryan/status/970383613119184896?ref_src=twsrc%5Etfw&#34;&gt;March 4, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.x.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://suzan.rbind.io/2018/03/reflections-4-months-of-github/&#34;&gt;Reflections on 4 months of GitHub: my advice to beginners&lt;/a&gt;, Suzan Baert.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And in French there&amp;rsquo;s a great blog post by ThinkR: &lt;a href=&#34;https://thinkr.fr/travailler-avec-git-via-rstudio-et-versionner-son-code/&#34;&gt;Travailler avec Git via RStudio et versionner son code&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;how-to-protect-your-project-from-external-changes&#34;&gt;How to protect your project from external changes&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s a &lt;a href=&#34;https://en.wikipedia.org/wiki/Design-basis_event&#34;&gt;maximum credible accident&lt;/a&gt;: you write some pretty and handy code munging your data using &lt;code&gt;package::my_favorite_function()&lt;/code&gt;. Now you go and update that package and realize &lt;code&gt;my_favorite_function&lt;/code&gt; is gone! It was apparently removed for good reasons but now your script is broken!&lt;/p&gt;
&lt;p&gt;To prevent that, you need to encapsulate your project. You can track and restore package dependencies of your package by using the &lt;a href=&#34;https://rstudio.github.io/renv/&#34;&gt;renv package&lt;/a&gt; by Kevin Ushey. The renv package is the successor of the packrat package by the same author.&lt;/p&gt;
&lt;p&gt;Using renv is actually quite easy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In a new project you run &lt;a href=&#34;https://rstudio.github.io/renv//reference/init.html&#34;&gt;&lt;code&gt;renv::init()&lt;/code&gt;&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;After that you install and remove packages as you normally would (renv is smart and will copy files from your local not-project library to be faster). Regularly run &lt;a href=&#34;https://rstudio.github.io/renv//reference/snapshot.html&#34;&gt;&lt;code&gt;renv::snapshot()&lt;/code&gt;&lt;/a&gt;.&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; Metadata about packages (where do they come from) are stored in the &lt;code&gt;renv.lock&lt;/code&gt; file that you&amp;rsquo;d put under version control;&lt;/li&gt;
&lt;li&gt;Anyone getting the project runs &lt;a href=&#34;https://rstudio.github.io/renv//reference/restore.html&#34;&gt;&lt;code&gt;renv::restore()&lt;/code&gt;&lt;/a&gt; to have the exact same project library as you.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also worth of a mention is &lt;a href=&#34;https://github.com/MilesMcBain/capsule&#34;&gt;capsule&lt;/a&gt; by Miles McBain that is &amp;ldquo;an inversion of renv for low effort reproducible R package libraries&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Now if you want to go further and also freeze the operating system used etc. you could check out &lt;a href=&#34;https://colinfay.me/docker-r-reproducibility/&#34;&gt;Docker&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;what-structure-for-your-project&#34;&gt;What structure for your project?&lt;/h2&gt;
&lt;p&gt;What&amp;rsquo;s in your project? Probably something like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Data or the code to get them from a database or a remote resource;&lt;/li&gt;
&lt;li&gt;Some code munging and analysing them;&lt;/li&gt;
&lt;li&gt;Some output that could be a graph, a report etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now how should you structure your project? It&amp;rsquo;s important to use a structure that&amp;rsquo;s consistent between your (team&amp;rsquo;s) project, and that can be created automatically.&lt;/p&gt;
&lt;p&gt;While I have never used the &lt;a href=&#34;https://github.com/KentonWhite/ProjectTemplate&#34;&gt;ProjectTemplate package&lt;/a&gt; by Kenton White, I really like the blog post &lt;a href=&#34;https://hilaryparker.com/2012/08/25/love-for-projecttemplate/&#34;&gt;Love for ProjectTemplate&lt;/a&gt; by Hilary Parker as it underlines advantages that should be requirement for any tool that helps create an analysis.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Routine is your friend&amp;rdquo;.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;It&amp;rsquo;s easier to start somewhere and then customize, rather than start from the ground up.&amp;quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Reproducibility should be as easy as possible.&amp;quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Finding things should also be as easy as possible.&amp;quot;&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now some people find all these advantages by structuring their analyses as R packages. Creating an R package to share code and data you use throughout projects is not subject to debate: it&amp;rsquo;s great! You can even build &lt;a href=&#34;https://golemverse.org/&#34;&gt;Shiny apps as package with golem&lt;/a&gt;. Creating your analysis as a package, with dependencies in &lt;code&gt;DESCRIPTION&lt;/code&gt;, functions in &lt;code&gt;R/&lt;/code&gt;, analysis in e.g. a vignette, &lt;em&gt;is&lt;/em&gt; subject to debate.&lt;/p&gt;
&lt;p&gt;The advantages are that when doing that you can re-use or refresh your package development skills, and foremost that you can re-use tools made for package development (like devtools and usethis). There&amp;rsquo;s a paper presenting and promoting the approach, where such packages are called research compendia: &lt;a href=&#34;https://www.tandfonline.com/doi/abs/10.1080/00031305.2017.1375986?journalCode=utas20&#34;&gt;Packaging Data Analytical Work Reproducibly Using R (and Friends)&lt;/a&gt;, Ben Marwick, Carl Boettiger &amp;amp; Lincoln Mullen (2018), The American Statistician, 72:1, 80-88, DOI: &amp;lt;10.1080/00031305.2017.1375986&amp;gt;&lt;/p&gt;
&lt;p&gt;There are specific tools for building and using research compendia:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/benmarwick/rrtools&#34;&gt;rrtools&lt;/a&gt; by Ben Marwick. &lt;em&gt;&amp;ldquo;The goal of rrtools is to provide instructions, templates, and functions for making a basic compendium suitable for writing a reproducible journal article or report with R.&amp;quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://karthik.github.io/holepunch/&#34;&gt;holepunch&lt;/a&gt; by Karthik Ram. &lt;em&gt;&amp;ldquo;holepunch will read the contents of your R project on GitHub, create a DESCRIPTION file with all dependencies, write a Dockerfile, add a badge to your README, and build a Docker image. Once these 4 steps are complete, any reader can click the badge and within minutes, be dropped into a free, live, RStudio server. Here they can run your scripts and notebooks and see how everything works.&amp;quot;&lt;/em&gt; (🤫 holepunch works &lt;a href=&#34;https://github.com/karthik/holepunch#alternate-setup-method&#34;&gt;without the compendium structure&lt;/a&gt; as well.)&lt;/li&gt;
&lt;li&gt;The &lt;a href=&#34;https://ropensci.org/r-universe/&#34;&gt;R-universe project&lt;/a&gt; at rOpenSci, built by Jeroen Ooms. As it automatically builds vignettes, it could be used to publish your packaged analysis online.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now it&amp;rsquo;s good to know not everyone loves the idea of projects as R packages. Miles McBain wrote a blog post &lt;a href=&#34;https://www.milesmcbain.com/posts/an-okay-idea/&#34;&gt;&amp;ldquo;Project as an R package: An okay idea&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I found this quote quite interesting:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;ldquo;My response to advocates of project as a package is: ==You&amp;rsquo;re wasting precious time making the wrong packages.==&amp;rdquo;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&amp;ldquo;Instead of shoehorning your work into the package development domain, with all the loss of fidelity that entails, why aren&amp;rsquo;t you packaging tools that create the smooth {devtools}/{usethis} style experience for your own domain?&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In my talk my own advice is to use whatever structure you, and your team if you have one, prefers, and to choose a structure that can be created automatically. You could be the one creating the package to create projects, as Miles said &amp;ndash; although he also mentioned the &lt;a href=&#34;https://www.milesmcbain.com/posts/an-okay-idea/#where-to-next&#34;&gt;risk of &amp;ldquo;bitrot&amp;rdquo;&lt;/a&gt; for tools maintained and used by few people.&lt;/p&gt;
&lt;h2 id=&#34;how-to-run-your-project&#34;&gt;How to run your project?&lt;/h2&gt;
&lt;p&gt;How do you go from resources and scripts to the analysis output? If your project &amp;ldquo;only&amp;rdquo; contains one or a few R Markdown document(s), maybe you can simply use the knit button. Now you might be dealing with some challenges warranting the use of dedicated tools. I&amp;rsquo;ll briefly present two.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note that not all tools separate ways to structure and run projects i.e. you could be using a workflow package that&amp;rsquo;s opinionated about both.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;optimize-pipeline-with-targets&#34;&gt;Optimize pipeline with targets&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&#34;https://books.ropensci.org/targets/walkthrough.html#inspect-the-pipeline&#34;&gt;targets package&lt;/a&gt; by Will Landau, reviewed at rOpenSci software peer-review, helps optimizing pipelines by recognizing dependencies between steps (e.g. if you change the raw data you need to re-run everything, but if you change only the model fit you only need to re-run the final plot) and only running those that are needed at the moment. To make a project a targets project you need a script called &lt;code&gt;_targets.R&lt;/code&gt; where you load packages, source e.g. functions from &lt;code&gt;R/&lt;/code&gt; and define &lt;em&gt;targets&lt;/em&gt;. Now what are targets? Looking at part of a &lt;code&gt;_targets.R&lt;/code&gt; from targets manual,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Raw data file. Notice the format argument is used.&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;tar_target&lt;/span&gt;(
    raw_data_file,
    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/raw_data.csv&amp;#34;&lt;/span&gt;,
    format &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt;
  ),
  &lt;span style=&#34;color:#06287e&#34;&gt;tar_target&lt;/span&gt;(
    raw_data,
    &lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(raw_data_file, col_types &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;cols&lt;/span&gt;())
  ),
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# The dplyr package has been previously loaded&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;tar_target&lt;/span&gt;(
    data,
    raw_data &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
      &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(Ozone))
  ),
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# The create_plot() function comes from a script that has been previously sourced&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;tar_target&lt;/span&gt;(hist, &lt;span style=&#34;color:#06287e&#34;&gt;create_plot&lt;/span&gt;(data)),
  &lt;span style=&#34;color:#06287e&#34;&gt;tar_target&lt;/span&gt;(fit, &lt;span style=&#34;color:#06287e&#34;&gt;biglm&lt;/span&gt;(Ozone &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; Wind &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; Temp, data))
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;the targets are defined in a list. Each of them uses the &lt;code&gt;tar_target()&lt;/code&gt; function, has a name, and code that creates it, or, in the case of the raw data file, the path to the file. To build the project you run &lt;a href=&#34;https://docs.ropensci.org/targets/reference/tar_make.html&#34;&gt;&lt;code&gt;targets::tar_make()&lt;/code&gt;&lt;/a&gt; (and to destroy everything if you need to, &lt;a href=&#34;https://docs.ropensci.org/targets/reference/tar_destroy.html&#34;&gt;&lt;code&gt;targets::tar_destroy()&lt;/code&gt;&lt;/a&gt;). To see the network of dependencies between targets you can run &lt;a href=&#34;https://docs.ropensci.org/targets/reference/tar_glimpse.html&#34;&gt;&lt;code&gt;targets::tar_glimpse()&lt;/code&gt;&lt;/a&gt; and other functions that &lt;a href=&#34;https://books.ropensci.org/targets/walkthrough.html#inspect-the-pipeline&#34;&gt;inspect the pipeline&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a &lt;a href=&#34;https://wlandau.github.io/targetopia/&#34;&gt;whole ecosystem of packages around targets, the Targetopia&lt;/a&gt; e.g. the tarchetypes package defines targets making functions that lets you define targets that need to be re-run after a certain time.&lt;/p&gt;
&lt;p&gt;To get started with targets, I&amp;rsquo;d recommend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Reading the &lt;a href=&#34;https://books.ropensci.org/targets/&#34;&gt;manual&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Watching the talk &lt;a href=&#34;https://www.youtube.com/watch?v=FODSavXGjYg&#34;&gt;Reproducible Computation at Scale in R with {targets}&lt;/a&gt; (Will Landau at the RUG of Lille).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Starting with a small project (my current non-expertise level 😅).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To follow evolutions of targets as it keeps getting better, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.blog/changelog/2018-11-27-watch-releases/&#34;&gt;Release-watch&lt;/a&gt; the &lt;a href=&#34;https://github.com/ropensci/targets&#34;&gt;targets&lt;/a&gt; GitHub repo;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Follow &lt;a href=&#34;https://twitter.com/wmlandau&#34;&gt;Will Landau&lt;/a&gt; on Twitter;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Subscribe to &lt;a href=&#34;https://ropensci.org/news/&#34;&gt;rOpenSci newsletter&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;track-versions-of-an-analysis-with-orderly&#34;&gt;Track versions of an analysis with orderly&lt;/h2&gt;
&lt;p&gt;Imagine you want to keep track of the different versions of an analysis and everything that went into it, and to run analysis comparing versions. The &lt;a href=&#34;https://www.vaccineimpact.org/orderly/&#34;&gt;orderly package&lt;/a&gt;, maintained by Rich FitzJohn&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;, offers an infrastructure for that kind of workflows.&lt;/p&gt;
&lt;p&gt;With orderly you have repos and in repos you have reports/tasks, or only one report/task. Here&amp;rsquo;s an example with an orderly repo with one report. From an RStudio project I ran &lt;code&gt;orderly::orderly_init(&amp;quot;blop&amp;quot;)&lt;/code&gt; which created the repo in a new folder &amp;ldquo;blop&amp;rdquo;, and then &lt;code&gt;orderly::orderly_new(&amp;quot;example&amp;quot;, &amp;quot;blop&amp;quot;)&lt;/code&gt; after which I modified files using &lt;a href=&#34;https://www.vaccineimpact.org/orderly/articles/orderly.html&#34;&gt;the orderly introduction vignette&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;blop/&lt;/code&gt; folder there&amp;rsquo;s a general orderly configuration that I haven&amp;rsquo;t needed to touch, &lt;code&gt;orderly_config.yml&lt;/code&gt;. There&amp;rsquo;s also a &lt;code&gt;src/&lt;/code&gt; folder corresponding to the source of my example report.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;blop
├── orderly_config.yml
└── src
    └── example
        ├── orderly.yml
        └── script.R
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That example report consists of two files so it&amp;rsquo;s a very small one. You could put anything in there as orderly is not opinionated about that! It &lt;em&gt;is&lt;/em&gt; opinionated about being told about packages, resources, scripts, artefacts in the &lt;code&gt;blop/src/example/orderly.yml&lt;/code&gt; configuration.&lt;/p&gt;
&lt;p&gt;In the example the configuration lists one script and two artefacts:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;script&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;script.R&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;artefacts&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;  &lt;/span&gt;- &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;staticgraph&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;description&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;A&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;graph&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;of&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;things&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;filenames&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;mygraph.png&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;  &lt;/span&gt;- &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;data&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;description&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Data&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;that&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;went&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;into&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;the&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;plot&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;      &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;filenames&lt;/span&gt;:&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;mydata.csv&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The script creates those two artefacts:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dat &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;data.frame&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;runif&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;))
&lt;span style=&#34;color:#06287e&#34;&gt;write.csv&lt;/span&gt;(dat, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;mydata.csv&amp;#34;&lt;/span&gt;, row.names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;png&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;mygraph.png&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;plot&lt;/span&gt;(dat)
&lt;span style=&#34;color:#06287e&#34;&gt;dev.off&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now how do you run the project?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You can use the &lt;a href=&#34;https://www.vaccineimpact.org/orderly/articles/orderly.html#developing-a-report-1&#34;&gt;development mode&lt;/a&gt; when developing a report, to have things at your current working directory.&lt;/li&gt;
&lt;li&gt;You can build a draft version of the report with &lt;code&gt;id &amp;lt;- orderly::orderly_run(&amp;quot;example&amp;quot;, root = &amp;quot;blop&amp;quot;)&lt;/code&gt; after which your whole analysis, input and output, appears in &lt;code&gt;blop/draft/example/some-id-that-contains-the-date-and-a-hash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If you like it you can commit it with &lt;code&gt;orderly::orderly_commit(id, root = &amp;quot;blop&amp;quot;)&lt;/code&gt; which moves the whole analysis folder from &lt;code&gt;blop/draft/example/some-id-that-contains-the-date-and-a-hash&lt;/code&gt; to &lt;code&gt;blop/archive/example/some-id-that-contains-the-date-and-a-hash&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note that as the draft and archive folders can be gigantic you are expected to back up with some system. You are expected &lt;em&gt;not&lt;/em&gt; to use git to track these folders as git does not behave well with very large files. You can still use git to track other files in the orderly repo.&lt;/p&gt;
&lt;p&gt;To get started with orderly you can read the &lt;a href=&#34;https://www.vaccineimpact.org/orderly/&#34;&gt;orderly website&lt;/a&gt; that I found very clear, and you should start with a small project&amp;hellip; which again is my current non-expertise level.&lt;/p&gt;
&lt;p&gt;To follow orderly news, as it&amp;rsquo;s actively used and developed, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.blog/changelog/2018-11-27-watch-releases/&#34;&gt;Release-watch&lt;/a&gt; the &lt;a href=&#34;https://github.com/vimc/orderly&#34;&gt;orderly GitHub repo&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;read &lt;a href=&#34;https://reside-ic.github.io/&#34;&gt;the blog of the team behind orderly&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;follow &lt;a href=&#34;https://twitter.com/rgfitzjohn&#34;&gt;Rich FitzJohn&lt;/a&gt; on Twitter.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;other-tools-for-building-analyses&#34;&gt;Other tools for building analyses&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&#34;https://docs.ropensci.org/targets&#34;&gt;targets&lt;/a&gt; and &lt;a href=&#34;https://www.vaccineimpact.org/orderly&#34;&gt;orderly&lt;/a&gt; packages are not the only ones helping run analyses: &lt;a href=&#34;https://jdblischak.github.io/workflowr/&#34;&gt;workflowr&lt;/a&gt;, &lt;a href=&#34;https://github.com/nt-williams/cabinets&#34;&gt;cabinets&lt;/a&gt;, &lt;a href=&#34;https://cran.r-project.org/web/views/ReproducibleResearch.html&#34;&gt;etc.&lt;/a&gt;. You might even want to build your own!&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post/talk I have discussed several aspects of drawing a project&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some &amp;ldquo;basics&amp;rdquo; that are not all easy (all are habits to take, and some are trickier to learn than others);&lt;/li&gt;
&lt;li&gt;Encapsulating your project by tracking its dependencies with e.g. renv;&lt;/li&gt;
&lt;li&gt;Structuring your project in a way that suits your team&amp;rsquo;s wishes, is consistent over time, and can be automated;&lt;/li&gt;
&lt;li&gt;Using tools for building outputs that answers your needs (optimizing a pipeline? tracking versions of an analysis projects?).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All in all my tips would be to read everything Jenny Bryan writes 😁, and to not be afraid to change tools over time as new cool tools will appear and as your needs and experience will change. I&amp;rsquo;d be interested to hear any thoughts in the comments below!&lt;/p&gt;
&lt;h3 id=&#34;further-resources&#34;&gt;Further resources&lt;/h3&gt;
&lt;p&gt;These items might be relevant for you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://annakrystalli.me/rrresearchACCE20/&#34;&gt;Course &amp;ldquo;Reproducible Research Data and Project Management in R&amp;rdquo;&lt;/a&gt; by Anna Krystalli.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://rdes_dreal.gitlab.io/publication_guide/production/index.html#quest-ce-quun-projet-collaboratif-propre&#34;&gt;Guide &amp;ldquo;Organisation d&amp;rsquo;un projet collaboratif de publication PROPRE&amp;rdquo;&lt;/a&gt; de Sébastien Rochette.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1005510&#34;&gt;Good enough practices in scientific computing&lt;/a&gt; Wilson G, Bryan J, Cranston K, Kitzes J, Nederbragt L, et al. (2017) Good enough practices in scientific computing. PLOS Computational Biology 13(6): e1005510. &lt;a href=&#34;https://doi.org/10.1371/journal.pcbi.1005510&#34;&gt;https://doi.org/10.1371/journal.pcbi.1005510&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://the-turing-way.netlify.app/welcome&#34;&gt;The Turing Way&lt;/a&gt;, an open source community-driven guide to reproducible, ethical, inclusive and collaborative data science.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;The Little Prince might have asked &amp;ldquo;Please draw me a &lt;em&gt;sheep&lt;/em&gt;&amp;rdquo;, not a &lt;em&gt;project&lt;/em&gt;, but I liked tweaking that quote for a title as one will often end up putting R projects in boxes (folders, &lt;em&gt;maybe&lt;/em&gt; packages). &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Note that Sharla Gelfand themselves is a great source of good ideas! See e.g. their talk &lt;a href=&#34;https://sharla.party/talk/2020-01-01-rstudio-conf/&#34;&gt;Don&amp;rsquo;t repeat yourself, talk to yourself! Repeated reporting in the R universe&lt;/a&gt; from the RStudio::conf 2020. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Unless you go for &lt;a href=&#34;https://rstudio.github.io/renv/reference/config.html#configuration&#34;&gt;automatic snapshots&lt;/a&gt;. &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Many thanks to Rich for answering some questions of mine! &lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Server-side MathJax rendering with R?</title>
      <link>https://masalmon.eu/2021/06/15/serverside-mathjax/</link>
      <pubDate>Tue, 15 Jun 2021 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2021/06/15/serverside-mathjax/</guid>
      <description>&lt;p&gt;&lt;em&gt;Edit: now there is an R package for server-side MathJax rendering, &lt;a href=&#34;https://ropensci.org/blog/2021/07/13/katex-release/&#34;&gt;katex by Jeroen Ooms&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Whilst I most certainly do not write LaTeX formulas on the regular anymore, I got curious about their &lt;a href=&#34;https://www.mathjax.org/&#34;&gt;MathJax&lt;/a&gt; rendering on websites.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; In brief : your website source contains LaTeX code, and the MathJax JS library (self-hosted or hosted on a CDN) transforms it into something humans can understand: some HTML with inline CSS but also some MathML for screen-reader users.&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; As I quite like the idea of moving things from the client-side to the server-side, I started wondering whether the processing of LaTeX code could happen before an user opens a website. Searching for &amp;ldquo;server-side MathJax rendering&amp;rdquo; on the web gave a few hits. A few hits only, sure, which shows how niche the topic is, and meant reading resources was not too verwhelming. 😁 In this post I am reporting on my findings.&lt;/p&gt;
&lt;h2 id=&#34;why-render-mathjax-on-the-server-side&#34;&gt;Why render MathJax on the server-side&lt;/h2&gt;
&lt;p&gt;Let me be honest, there is no extremely strong reason for &lt;em&gt;me&lt;/em&gt;. Sure loading MathJax from a CDN might be a privacy problem (as the CDN measures traffic) or make your website potentially fragile if the CDN goes down (remember the &lt;a href=&#34;https://en.wikipedia.org/wiki/Fastly#Operation&#34;&gt;Fastly outage&lt;/a&gt; last week). Now you could still self-host MathJax to mitigate that (and to know exactly who to blame in case of an outage i.e. yourself 😉). Not having MathJax might mean the page takes less time to load&amp;hellip; if having the MathJax-rendered HTML weren&amp;rsquo;t making the page bigger than the same page with LaTeX code instead. But hey I still think it&amp;rsquo;s an interesting problem.&lt;/p&gt;
&lt;p&gt;Something I realized whilst working on this post is that one probably does not want to remove all MathJax JS from the browser, as it includes &lt;a href=&#34;https://docs.mathjax.org/en/v2.7-latest/options/extensions/a11y-extensions.html#a11y-extensions&#34;&gt;accessibility options&lt;/a&gt;! You need some JS in order to have a menu etc. That&amp;rsquo;s not something I&amp;rsquo;ve tackled here, I think that to extract the right MathJax JS to have only the components for the menu but not those for processign input, one would need to understand MathJax much better than I do.&lt;/p&gt;
&lt;h2 id=&#34;how-to-render-mathjax-on-the-server-side&#34;&gt;How to render MathJax on the server-side&lt;/h2&gt;
&lt;p&gt;The recipe would be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;extract LaTeX code. E.g. use XPath with xml2 for HTML; or regular expressions if that&amp;rsquo;s your jam.&lt;/li&gt;
&lt;li&gt;transform the LaTeX string into HTML somehow.&lt;/li&gt;
&lt;li&gt;replace the LaTeX code with the HTML.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first and second steps are things close to e.g. the &lt;a href=&#34;https://github.com/r-lib/pkgdown/blob/master/R/html-tweak.R&#34;&gt;HTML tweaking pkgdown does&lt;/a&gt;. They might well shall entail (un)escaping problems.&lt;/p&gt;
&lt;p&gt;Now the second step, how to transform LaTeX code into HTML? The best summary of the state-of-the-art I found is the blog post &lt;a href=&#34;https://danilafe.com/blog/math_rendering_is_wrong/&#34;&gt;Math Rendering is Wrong&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Solutions I saw are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a Node module called &lt;a href=&#34;https://github.com/mathjax/mathjax-node-cli&#34;&gt;mathjax-node-cli&lt;/a&gt;. I know there are &lt;a href=&#34;https://blog.r-hub.io/2020/08/25/js-r/#bundling-javascript-code&#34;&gt;ways to use JS from R&lt;/a&gt; but I got lazy once I saw I had to update my Node installation or whatever the error message was.&lt;/li&gt;
&lt;li&gt;a way to run a &lt;a href=&#34;https://github.com/chialab/math-api&#34;&gt;MathJax API&lt;/a&gt;, which I have not tried.&lt;/li&gt;
&lt;li&gt;rendering math &lt;a href=&#34;https://advancedweb.hu/mathjax-processing-on-the-server-side/&#34;&gt;on a browser and extracting the result&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will now focus on the last solution as it works well from R these days.&lt;/p&gt;
&lt;h2 id=&#34;mathjax-but-not-in-the-viewers-browser&#34;&gt;MathJax, but not in the viewer&amp;rsquo;s browser!&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s take a minimal HTML with MathJax loaded from a CDN and an empty paragraph with class &amp;ldquo;mathp&amp;rdquo;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nv&#39;&gt;html&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/read_xml.html&#39;&gt;read_html&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#39;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;MathJax&amp;lt;/title&amp;gt;
&amp;lt;meta http-equiv=&#34;Content-Type&#34; content=&#34;text/html; charset=UTF-8&#34; /&amp;gt;
&amp;lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1&#34;&amp;gt;
&amp;lt;script type=&#34;text/javascript&#34; src=&#34;https://mathjax.rstudio.com/2.7.2/MathJax.js?config=TeX-AMS-MML_HTMLorMML&#34;&amp;gt;&amp;lt;/script&amp;gt;

&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;p class=&#34;mathp&#34;&amp;gt;

&amp;lt;/p&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&#39;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now let&amp;rsquo;s add math to it. Note that a real solution would have to differentiate in-line and block maths whose resulting HTML has a different XPath.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nv&#39;&gt;mathp&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_find_all.html&#39;&gt;xml_find_first&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;html&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;//p[@class=&#39;mathp&#39;]&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;mathp&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;r&#34;($$x = &amp;#123;-b \pm \sqrt&amp;#123;b^2-4ac&amp;#125; \over 2a&amp;#125;.$$)&#34;&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/character.html&#39;&gt;as.character&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;html&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;&amp;lt;!DOCTYPE html&amp;gt;\n&amp;lt;html&amp;gt;\n&amp;lt;head&amp;gt;\n&amp;lt;title&amp;gt;MathJax&amp;lt;/title&amp;gt;\n&amp;lt;meta http-equiv=\&#34;Content-Type\&#34; content=\&#34;text/html; charset=UTF-8\&#34;&amp;gt;\n&amp;lt;meta name=\&#34;viewport\&#34; content=\&#34;width=device-width, initial-scale=1\&#34;&amp;gt;\n&amp;lt;script type=\&#34;text/javascript\&#34; src=\&#34;https://mathjax.rstudio.com/2.7.2/MathJax.js?config=TeX-AMS-MML_HTMLorMML\&#34;&amp;gt;&amp;lt;/script&amp;gt;\n&amp;lt;/head&amp;gt;\n&amp;lt;body&amp;gt;\n\n&amp;lt;p class=\&#34;mathp\&#34;&amp;gt;$$x = &amp;#123;-b \\pm \\sqrt&amp;#123;b^2-4ac&amp;#125; \\over 2a&amp;#125;.$$&amp;lt;/p&amp;gt;\n\n&amp;lt;/body&amp;gt;\n&amp;lt;/html&amp;gt;\n&#34;&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;file&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;withr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://withr.r-lib.org/reference/with_tempfile.html&#39;&gt;local_tempfile&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;fileext &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;.html&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; Setting deferred event(s) on global environment.&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;   * Execute (and clear) with `withr::deferred_run()`.&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;   * Clear (without executing) with `withr::deferred_clear()`.&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/write_xml.html&#39;&gt;write_html&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;html&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;file&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now we shall load the file in a browser via &lt;a href=&#34;https://github.com/rstudio/chromote/&#34;&gt;chromote&lt;/a&gt;&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; and extract the HTML Pandoc produced. To find the XPath, I examined the HTML with the DevTools of my browser.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;kr&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/library.html&#39;&gt;library&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;chromote&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;b&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/chromote/man/ChromoteSession.html&#39;&gt;ChromoteSession&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;new&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;b&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;Page&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;navigate&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/sprintf.html&#39;&gt;sprintf&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;file://%s&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;file&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; 
&lt;span class=&#39;c&#39;&gt;#&amp;gt; $frameId&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;7FC1F01C63F746D0D66CC7E2DC40EF87&#34;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; $loaderId&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;A3031F97EEF09D8BF745DF8C089F448F&#34;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;# Make sure we wait long enough&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/Sys.sleep.html&#39;&gt;Sys.sleep&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;2&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;doc&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;b&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;DOM&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;getDocument&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;b&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;DOM&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;querySelector&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;doc&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;root&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;nodeId&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;.MathJax_Display&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;math_html&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;b&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;DOM&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;getOuterHTML&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;nodeId&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; $outerHTML&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;&amp;lt;div class=\&#34;MathJax_Display\&#34; style=\&#34;text-align: center;\&#34;&amp;gt;&amp;lt;span class=\&#34;MathJax\&#34; id=\&#34;MathJax-Element-1-Frame\&#34; tabindex=\&#34;0\&#34; data-mathml=\&#34;&amp;lt;math xmlns=&amp;amp;quot;http://www.w3.org/1998/Math/MathML&amp;amp;quot; display=&amp;amp;quot;block&amp;amp;quot;&amp;gt;&amp;lt;mi&amp;gt;x&amp;lt;/mi&amp;gt;&amp;lt;mo&amp;gt;=&amp;lt;/mo&amp;gt;&amp;lt;mrow class=&amp;amp;quot;MJX-TeXAtom-ORD&amp;amp;quot;&amp;gt;&amp;lt;mfrac&amp;gt;&amp;lt;mrow&amp;gt;&amp;lt;mo&amp;gt;&amp;amp;amp;#x2212;&amp;lt;/mo&amp;gt;&amp;lt;mi&amp;gt;b&amp;lt;/mi&amp;gt;&amp;lt;mo&amp;gt;&amp;amp;amp;#x00B1;&amp;lt;/mo&amp;gt;&amp;lt;msqrt&amp;gt;&amp;lt;msup&amp;gt;&amp;lt;mi&amp;gt;b&amp;lt;/mi&amp;gt;&amp;lt;mn&amp;gt;2&amp;lt;/mn&amp;gt;&amp;lt;/msup&amp;gt;&amp;lt;mo&amp;gt;&amp;amp;amp;#x2212;&amp;lt;/mo&amp;gt;&amp;lt;mn&amp;gt;4&amp;lt;/mn&amp;gt;&amp;lt;mi&amp;gt;a&amp;lt;/mi&amp;gt;&amp;lt;mi&amp;gt;c&amp;lt;/mi&amp;gt;&amp;lt;/msqrt&amp;gt;&amp;lt;/mrow&amp;gt;&amp;lt;mrow&amp;gt;&amp;lt;mn&amp;gt;2&amp;lt;/mn&amp;gt;&amp;lt;mi&amp;gt;a&amp;lt;/mi&amp;gt;&amp;lt;/mrow&amp;gt;&amp;lt;/mfrac&amp;gt;&amp;lt;/mrow&amp;gt;&amp;lt;mo&amp;gt;.&amp;lt;/mo&amp;gt;&amp;lt;/math&amp;gt;\&#34; role=\&#34;presentation\&#34; style=\&#34;text-align: center; position: relative;\&#34;&amp;gt;&amp;lt;nobr aria-hidden=\&#34;true\&#34;&amp;gt;&amp;lt;span class=\&#34;math\&#34; id=\&#34;MathJax-Span-1\&#34; style=\&#34;width: 10.144em; display: inline-block;\&#34;&amp;gt;&amp;lt;span style=\&#34;display: inline-block; position: relative; width: 9.552em; height: 0px; font-size: 106%;\&#34;&amp;gt;&amp;lt;span style=\&#34;position: absolute; clip: rect(0.307em, 1009.47em, 3.054em, -1000em); top: -2.182em; left: 0em;\&#34;&amp;gt;&amp;lt;span class=\&#34;mrow\&#34; id=\&#34;MathJax-Span-2\&#34;&amp;gt;&amp;lt;span class=\&#34;mi\&#34; id=\&#34;MathJax-Span-3\&#34; style=\&#34;font-family: MathJax_Math-italic;\&#34;&amp;gt;x&amp;lt;/span&amp;gt;&amp;lt;span class=\&#34;mo\&#34; id=\&#34;MathJax-Span-4\&#34; style=\&#34;font-family: MathJax_Main; padding-left: 0.278em;\&#34;&amp;gt;=&amp;lt;/span&amp;gt;&amp;lt;span class=\&#34;texatom\&#34; id=\&#34;MathJax-Span-5\&#34; style=\&#34;padding-left: 0.278em;\&#34;&amp;gt;&amp;lt;span class=\&#34;mrow\&#34; id=\&#34;MathJax-Span-6\&#34;&amp;gt;&amp;lt;span class=\&#34;mfrac\&#34; id=\&#34;MathJax-Span-7\&#34;&amp;gt;&amp;lt;span style=\&#34;display: inline-block; position: relative; width: 7.116em; height: 0px; margin-right: 0.12em; margin-left: 0.12em;\&#34;&amp;gt;&amp;lt;span style=\&#34;position: absolute; clip: rect(2.879em, 1007em, 4.443em, -1000em); top: -4.753em; left: 50%; margin-left: -3.498em;\&#34;&amp;gt;&amp;lt;span class=\&#34;mrow\&#34; id=\&#34;MathJax-Span-8\&#34;&amp;gt;&amp;lt;span class=\&#34;mo\&#34; id=\&#34;MathJax-Span-9\&#34; style=\&#34;font-family: MathJax_Main;\&#34;&amp;gt;−&amp;lt;/span&amp;gt;&amp;lt;span class=\&#34;mi\&#34; id=\&#34;MathJax-Span-10\&#34; style=\&#34;font-family: MathJax_Math-italic;\&#34;&amp;gt;b&amp;lt;/span&amp;gt;&amp;lt;span class=\&#34;mo\&#34; id=\&#34;MathJax-Span-11\&#34; style=\&#34;font-family: MathJax_Main; padding-left: 0.222em;\&#34;&amp;gt;±&amp;lt;/span&amp;gt;&amp;lt;span class=\&#34;msqrt\&#34; id=\&#34;MathJax-Span-12\&#34; style=\&#34;padding-left: 0.222em;\&#34;&amp;gt;&amp;lt;span style=\&#34;display: inline-block; position: relative; width: 4.567em; height: 0px;\&#34;&amp;gt;&amp;lt;span style=\&#34;position: absolute; clip: rect(3.073em, 1003.54em, 4.268em, -1000em); top: -4.009em; left: 1em;\&#34;&amp;gt;&amp;lt;span class=\&#34;mrow\&#34; id=\&#34;MathJax-Span-13\&#34;&amp;gt;&amp;lt;span class=\&#34;msubsup\&#34; id=\&#34;MathJax-Span-14\&#34;&amp;gt;&amp;lt;span style=\&#34;display: inline-block; position: relative; width: 0.858em; height: 0px;\&#34;&amp;gt;&amp;lt;span style=\&#34;position: absolute; clip: rect(3.139em, 1000.42em, 4.197em, -1000em); top: -4.009em; left: 0em;\&#34;&amp;gt;&amp;lt;span class=\&#34;mi\&#34; id=\&#34;MathJax-Span-15\&#34; style=\&#34;font-family: MathJax_Math-italic;\&#34;&amp;gt;b&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;position: absolute; top: -4.298em; left: 0.429em;\&#34;&amp;gt;&amp;lt;span class=\&#34;mn\&#34; id=\&#34;MathJax-Span-16\&#34; style=\&#34;font-size: 70.7%; font-family: MathJax_Main;\&#34;&amp;gt;2&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=\&#34;mo\&#34; id=\&#34;MathJax-Span-17\&#34; style=\&#34;font-family: MathJax_Main; padding-left: 0.222em;\&#34;&amp;gt;−&amp;lt;/span&amp;gt;&amp;lt;span class=\&#34;mn\&#34; id=\&#34;MathJax-Span-18\&#34; style=\&#34;font-family: MathJax_Main; padding-left: 0.222em;\&#34;&amp;gt;4&amp;lt;/span&amp;gt;&amp;lt;span class=\&#34;mi\&#34; id=\&#34;MathJax-Span-19\&#34; style=\&#34;font-family: MathJax_Math-italic;\&#34;&amp;gt;a&amp;lt;/span&amp;gt;&amp;lt;span class=\&#34;mi\&#34; id=\&#34;MathJax-Span-20\&#34; style=\&#34;font-family: MathJax_Math-italic;\&#34;&amp;gt;c&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;position: absolute; clip: rect(3.56em, 1003.57em, 3.958em, -1000em); top: -4.69em; left: 1em;\&#34;&amp;gt;&amp;lt;span style=\&#34;display: inline-block; position: relative; width: 3.567em; height: 0px;\&#34;&amp;gt;&amp;lt;span style=\&#34;position: absolute; font-family: MathJax_Main; top: -4.009em; left: -0.084em;\&#34;&amp;gt;−&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;position: absolute; font-family: MathJax_Main; top: -4.009em; left: 2.873em;\&#34;&amp;gt;−&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;font-family: MathJax_Main; position: absolute; top: -4.009em; left: 0.388em;\&#34;&amp;gt;−&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;font-family: MathJax_Main; position: absolute; top: -4.009em; left: 0.885em;\&#34;&amp;gt;−&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;font-family: MathJax_Main; position: absolute; top: -4.009em; left: 1.382em;\&#34;&amp;gt;−&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;font-family: MathJax_Main; position: absolute; top: -4.009em; left: 1.879em;\&#34;&amp;gt;−&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;font-family: MathJax_Main; position: absolute; top: -4.009em; left: 2.376em;\&#34;&amp;gt;−&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;position: absolute; clip: rect(2.983em, 1001.02em, 4.536em, -1000em); top: -4.103em; left: 0em;\&#34;&amp;gt;&amp;lt;span style=\&#34;font-family: MathJax_Size1;\&#34;&amp;gt;√&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;position: absolute; clip: rect(3.167em, 1001.01em, 4.196em, -1000em); top: -3.323em; left: 50%; margin-left: -0.514em;\&#34;&amp;gt;&amp;lt;span class=\&#34;mrow\&#34; id=\&#34;MathJax-Span-21\&#34;&amp;gt;&amp;lt;span class=\&#34;mn\&#34; id=\&#34;MathJax-Span-22\&#34; style=\&#34;font-family: MathJax_Main;\&#34;&amp;gt;2&amp;lt;/span&amp;gt;&amp;lt;span class=\&#34;mi\&#34; id=\&#34;MathJax-Span-23\&#34; style=\&#34;font-family: MathJax_Math-italic;\&#34;&amp;gt;a&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 4.009em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;position: absolute; clip: rect(0.811em, 1007.12em, 1.238em, -1000em); top: -1.281em; left: 0em;\&#34;&amp;gt;&amp;lt;span style=\&#34;display: inline-block; overflow: hidden; vertical-align: 0em; border-top: 1.3px solid; width: 7.116em; height: 0px;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 1.061em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span class=\&#34;mo\&#34; id=\&#34;MathJax-Span-24\&#34; style=\&#34;font-family: MathJax_Main;\&#34;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;display: inline-block; width: 0px; height: 2.182em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span style=\&#34;display: inline-block; overflow: hidden; vertical-align: -0.8em; border-left: 0px solid; width: 0px; height: 2.662em;\&#34;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/nobr&amp;gt;&amp;lt;span class=\&#34;MJX_Assistive_MathML MJX_Assistive_MathML_Block\&#34; role=\&#34;presentation\&#34;&amp;gt;&amp;lt;math xmlns=\&#34;http://www.w3.org/1998/Math/MathML\&#34; display=\&#34;block\&#34;&amp;gt;&amp;lt;mi&amp;gt;x&amp;lt;/mi&amp;gt;&amp;lt;mo&amp;gt;=&amp;lt;/mo&amp;gt;&amp;lt;mrow class=\&#34;MJX-TeXAtom-ORD\&#34;&amp;gt;&amp;lt;mfrac&amp;gt;&amp;lt;mrow&amp;gt;&amp;lt;mo&amp;gt;−&amp;lt;/mo&amp;gt;&amp;lt;mi&amp;gt;b&amp;lt;/mi&amp;gt;&amp;lt;mo&amp;gt;±&amp;lt;/mo&amp;gt;&amp;lt;msqrt&amp;gt;&amp;lt;msup&amp;gt;&amp;lt;mi&amp;gt;b&amp;lt;/mi&amp;gt;&amp;lt;mn&amp;gt;2&amp;lt;/mn&amp;gt;&amp;lt;/msup&amp;gt;&amp;lt;mo&amp;gt;−&amp;lt;/mo&amp;gt;&amp;lt;mn&amp;gt;4&amp;lt;/mn&amp;gt;&amp;lt;mi&amp;gt;a&amp;lt;/mi&amp;gt;&amp;lt;mi&amp;gt;c&amp;lt;/mi&amp;gt;&amp;lt;/msqrt&amp;gt;&amp;lt;/mrow&amp;gt;&amp;lt;mrow&amp;gt;&amp;lt;mn&amp;gt;2&amp;lt;/mn&amp;gt;&amp;lt;mi&amp;gt;a&amp;lt;/mi&amp;gt;&amp;lt;/mrow&amp;gt;&amp;lt;/mfrac&amp;gt;&amp;lt;/mrow&amp;gt;&amp;lt;mo&amp;gt;.&amp;lt;/mo&amp;gt;&amp;lt;/math&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&#34;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;math_html&lt;/code&gt; above is the MathJax-rendered math HTML we were after!&lt;/p&gt;
&lt;p&gt;Now we create a minimal HTML without MathJax and add the math HTML to it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nv&#39;&gt;html&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/read_xml.html&#39;&gt;read_html&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#39;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;MathJax&amp;lt;/title&amp;gt;
&amp;lt;meta http-equiv=&#34;Content-Type&#34; content=&#34;text/html; charset=UTF-8&#34; /&amp;gt;
&amp;lt;meta name=&#34;viewport&#34; content=&#34;width=device-width, initial-scale=1&#34;&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;p id=&#34;mathp&#34; class=&#34;mathp&#34;&amp;gt;

&amp;lt;/p&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&#39;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;mathp&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_find_all.html&#39;&gt;xml_find_first&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;html&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;//p[@id=&#39;mathp&#39;]&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;mathp&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;math_html&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;$&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;outerHTML&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Sadly the step above means the math HTML will have been escaped. One could find an actual fix, but my fix will be to unescape the HTML à la pkgdown i.e. literally using an internal function of pkgdown&amp;rsquo;s.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;c&#39;&gt;# from https://github.com/r-lib/pkgdown/blob/23eb05ceceda1c44573b254dd8b96e92cd91f825/R/html-build.R#L49&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;unescape_html&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;
  &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/grep.html&#39;&gt;gsub&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;&amp;amp;lt;&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;&amp;lt;&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
  &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/grep.html&#39;&gt;gsub&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;&amp;amp;gt;&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;&amp;gt;&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
  &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/grep.html&#39;&gt;gsub&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;&amp;amp;amp;&#34;&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;&amp;amp;&#34;&lt;/span&gt;, &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
  &lt;span class=&#39;nv&#39;&gt;x&lt;/span&gt;
&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;html&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/read_xml.html&#39;&gt;read_html&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;unescape_html&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/character.html&#39;&gt;as.character&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;html&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/write_xml.html&#39;&gt;write_html&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;html&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;example.html&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now we can look at the &lt;a href=&#34;example.html&#34;&gt;example&lt;/a&gt; and see that it has indeed some math! It&amp;rsquo;s probably lacking fonts, the absence of any MathJax JS means that we see the math twice, one of them being a div for assistive technology.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I explored server-side MathJax rendering. I have not created a workable solution : An actually acceptable solution would necessitate more knowledge of MathJax, be far more detail-oriented and would check the accessibility of the produced document! Nevertheless, it was interesting to me to use chromote to extract HTML produced by MathJax and to learn more about MathJax. I don&amp;rsquo;t think I&amp;rsquo;ll feel like writing more LaTeX than now but I am sure curious to also check out MathJax &amp;ldquo;competitors&amp;rdquo; like KaTeX.&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;MathJax is not the only way to render math for the web but it is the most popular one. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I found the video &lt;a href=&#34;https://www.writethedocs.org/videos/na/2016/accessible-math-on-the-web-a-server-client-solution-tim-arnold/&#34;&gt;Accessible Math on the Web: A Server/Client Solution&lt;/a&gt; interesting, albeit a few years old already. Yes, I watched a video about SAS documentation. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;One could also choose to use &lt;a href=&#34;https://github.com/RLesur/crrri&#34;&gt;crrri&lt;/a&gt; but this is left as an exercise to the reader. &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;If you use Katex you might be interested in a &lt;a href=&#34;https://github.com/rstudio/rmarkdown/pull/1940&#34;&gt;related PR to rmarkdown&lt;/a&gt;. &lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Stingy Beanie baby webscraping</title>
      <link>https://masalmon.eu/2021/01/15/beanie-baby/</link>
      <pubDate>Fri, 15 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2021/01/15/beanie-baby/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve just finished teaching &lt;a href=&#34;https://masalmon.eu/talks/2021-01-15-blogging-r-markdown/&#34;&gt;blogging with R Markdown at R-Ladies Bangalore&lt;/a&gt;. This has two consequences: I need to calm down a bit after the stress of live demoing &amp;amp; co, and I am inspired to, well, blog with R Markdown! As I&amp;rsquo;ve just read a &lt;a href=&#34;https://www.goodreads.com/book/show/20821185-the-great-beanie-baby-bubble&#34;&gt;fascinating book about the beanie baby bubble&lt;/a&gt; and as I&amp;rsquo;ve seen rvest is getting an update, I&amp;rsquo;ve decided to harvest &lt;a href=&#34;https://beaniepedia.com&#34;&gt;Beaniepedia&lt;/a&gt;. Both of these things show I spend too much time on Twitter, as the book has been tweeted about &lt;a href=&#34;https://twitter.com/vboykis/status/1347575684802240512&#34;&gt;by Vicki Boykis&lt;/a&gt;, and the package changes have been tweeted about &lt;a href=&#34;https://twitter.com/hadleywickham/status/1347260116932976643&#34;&gt;by Hadley Wickham&lt;/a&gt;. I call that &lt;a href=&#34;https://masalmon.eu/2019/01/25/uptodate/&#34;&gt;staying up-to-date&lt;/a&gt;, of course.&lt;/p&gt;
&lt;p&gt;So, as a little challenge for today, what are the most common animals among Beanie babies? Do I even need much webscraping to find this out?&lt;/p&gt;
&lt;h2 id=&#34;how-does-one-webscrape-these-days&#34;&gt;How does one webscrape these days&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve always liked webscraping, as I think I enjoy getting and transforming data more than I enjoy analyzing it. Compared to my former self,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I know a bit more about XPath (starting with knowing it exists!) so I don&amp;rsquo;t use regular expression to parse HTML.&lt;/li&gt;
&lt;li&gt;I use &lt;a href=&#34;https://dmi3kno.github.io/polite/&#34;&gt;polite&lt;/a&gt; for polite webscraping!&lt;/li&gt;
&lt;li&gt;I know it&amp;rsquo;s best to spend more time pondering about strategies before hammering requests at a website.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As to rvest recent changes, I had a quick look at the &lt;a href=&#34;https://rvest.tidyverse.org/news/index.html&#34;&gt;changelog&lt;/a&gt; but since I hadn&amp;rsquo;t used it in so long, it&amp;rsquo;s not as if I had any habit to change!&lt;/p&gt;
&lt;h2 id=&#34;how-to-harvest-beaniepedia&#34;&gt;How to harvest Beaniepedia&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve noticed Beaniepedia has a &lt;a href=&#34;view-source:https://beaniepedia.com/beanies/sitemap.xml&#34;&gt;sitemap for all beanies&lt;/a&gt; so from that I can extract the URLs to all Beanie pages. That&amp;rsquo;s a necessary step.&lt;/p&gt;
&lt;p&gt;Now from there I could either&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Scrape each of these pages, respectfully slowly, and extract the table that includes the beanie&amp;rsquo;s information;&lt;/li&gt;
&lt;li&gt;Use a more frugal strategy by parsing URLs. E.g. from the path of &lt;code&gt;https://beaniepedia.com/beanies/beanie-babies/january-the-birthday-bear-series-2/&lt;/code&gt; I can extract the category of the Beanie (a beanie baby as opposed to, say, an attic treasure) and the animal by splitting &lt;code&gt;january-the-birthday-bear-series-2&lt;/code&gt; into pieces and see whether one is an animal. How would I recognize animals? By extracting the word coming after &amp;ldquo;the&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;rsquo;ll choose the second strategy and leave the first one as an exercise to the reader. 😉&lt;/p&gt;
&lt;h2 id=&#34;from-xml-to-animal-frequencies&#34;&gt;From XML to animal frequencies&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s get to work! A &lt;em&gt;sine qua non&lt;/em&gt; condition is obviously the website being ok with our scraping stuff. The polite package would tell us whether the robots.txt file were against our doing this, and I also took time looking whether the website had any warning. I didn&amp;rsquo;t find any so I think we&amp;rsquo;re good to go.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nv&#39;&gt;session&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;polite&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/polite/man/bow.html&#39;&gt;bow&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;
  url &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;https://beaniepedia.com/beanies/sitemap.xml&#34;&lt;/span&gt;,
  user_agent &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;Maëlle Salmon https://masalmon.eu&#34;&lt;/span&gt;
  &lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;sitemap&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;polite&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/polite/man/scrape.html&#39;&gt;scrape&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;session&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;sitemap&lt;/span&gt;

&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;#123;xml_document&amp;#125;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &amp;lt;urlset schemaLocation=&#34;http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd&#34; xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34; xmlns=&#34;http://www.sitemaps.org/schemas/sitemap/0.9&#34;&amp;gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [1] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/&amp;lt;/loc&amp;gt;\n  &amp;lt;lastmod&amp;gt;2021-01 ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [2] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/jerry-the-mi ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [3] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/snowball-the ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [4] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/jemima-puddl ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [5] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/jeff-gordon- ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [6] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/jeff-burton- ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [7] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/jeepers-the- ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [8] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/jeanette-the ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [9] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/jaz-the-cat/ ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [10] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/japan-the-be ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [11] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/laughter-the ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [12] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/righty-2000- ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [13] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/lefty-2004-t ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [14] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/lefty-the-do ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [15] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/lefty-the-do ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [16] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/january-the- ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [17] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/january-the- ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [18] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/beanie-babies/janglemouse- ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [19] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/attic-treasures/burrows-th ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [20] &amp;lt;url&amp;gt;\n  &amp;lt;loc&amp;gt;https://beaniepedia.com/beanies/attic-treasures/klause-the ...&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;sitemap&lt;/code&gt; object is an XML document. I will extract URLs with the xml2 package.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nv&#39;&gt;sitemap&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_ns_strip.html&#39;&gt;xml_ns_strip&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;sitemap&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;urls&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_text.html&#39;&gt;xml_text&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;xml2&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;http://xml2.r-lib.org/reference/xml_find_all.html&#39;&gt;xml_find_all&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;sitemap&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;.//loc&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/utils/head.html&#39;&gt;head&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;urls&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;

&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] &#34;https://beaniepedia.com/beanies/&#34;                                          &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [2] &#34;https://beaniepedia.com/beanies/beanie-babies/jerry-the-minion-2/&#34;         &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [3] &#34;https://beaniepedia.com/beanies/beanie-babies/snowball-the-snowman/&#34;       &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [4] &#34;https://beaniepedia.com/beanies/beanie-babies/jemima-puddle-duck-the-duck/&#34;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [5] &#34;https://beaniepedia.com/beanies/beanie-babies/jeff-gordon-24-the-bear/&#34;    &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [6] &#34;https://beaniepedia.com/beanies/beanie-babies/jeff-burton-no-31-the-bear/&#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now I need to parse the URLs. In an URL path like &lt;code&gt;beanies/beanie-babies/jerry-the-minion-2/&lt;/code&gt; the second part is the category, the third part is the Beanie Baby name. I, as if I were a good collector 🙃, am not interested in Attic treasures, only in Beanie Babies.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nv&#39;&gt;urls_df&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;urltools&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/pkg/urltools/man/url_parse.html&#39;&gt;url_parse&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;urls&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;urls_df&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;dplyr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://dplyr.tidyverse.org/reference/filter.html&#39;&gt;filter&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;urls_df&lt;/span&gt;, &lt;span class=&#39;nf&#39;&gt;stringr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://stringr.tidyverse.org/reference/str_detect.html&#39;&gt;str_detect&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;beanie-babies&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This gives me 632 Beanie babies. Let&amp;rsquo;s parse the last part of their path. An earlier attempt ignored that some Beanie babies don&amp;rsquo;t have any &amp;ldquo;the&amp;rdquo; in their names, e.g. the Hello Kitty ones. This is a limitation of my stingy approach. The error messages by dplyr were most helpful! &amp;ldquo;The error occurred in row 185.&amp;rdquo; is so handy!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;
&lt;span class=&#39;nv&#39;&gt;get_animal&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;kr&#39;&gt;function&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parsed_path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;
  
  &lt;span class=&#39;kr&#39;&gt;if&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/all.html&#39;&gt;all&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/unlist.html&#39;&gt;unlist&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parsed_path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;!=&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;the&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;#123;&lt;/span&gt;
    &lt;span class=&#39;kr&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/function.html&#39;&gt;return&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;kc&#39;&gt;NA&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
  &lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;
  
  &lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/unlist.html&#39;&gt;unlist&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parsed_path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/which.html&#39;&gt;which&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/unlist.html&#39;&gt;unlist&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parsed_path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;==&lt;/span&gt; &lt;span class=&#39;s&#39;&gt;&#34;the&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;+&lt;/span&gt; &lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;
  &lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/length.html&#39;&gt;length&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;animals&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt; &lt;span class=&#39;c&#39;&gt;# thanks, &#34;The End the bear&#34;&lt;/span&gt;
&lt;span class=&#39;o&#39;&gt;&amp;#125;&lt;/span&gt;

&lt;span class=&#39;kr&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/library.html&#39;&gt;library&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&lt;a href=&#39;https://magrittr.tidyverse.org&#39;&gt;&#34;magrittr&#34;&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;span class=&#39;nv&#39;&gt;animals_df&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#39;nv&#39;&gt;urls_df&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#39;nf&#39;&gt;dplyr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://dplyr.tidyverse.org/reference/rowwise.html&#39;&gt;rowwise&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#39;nf&#39;&gt;dplyr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://dplyr.tidyverse.org/reference/mutate.html&#39;&gt;mutate&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;parsed_path &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;stringr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://stringr.tidyverse.org/reference/str_split.html&#39;&gt;str_split&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;/&#34;&lt;/span&gt;, simplify &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;[&lt;/span&gt;&lt;span class=&#39;m&#39;&gt;1&lt;/span&gt;,&lt;span class=&#39;m&#39;&gt;3&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;]&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#39;nf&#39;&gt;dplyr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://dplyr.tidyverse.org/reference/mutate.html&#39;&gt;mutate&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;parsed_path &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;stringr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://stringr.tidyverse.org/reference/str_split.html&#39;&gt;str_split&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parsed_path&lt;/span&gt;, &lt;span class=&#39;s&#39;&gt;&#34;-&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#39;nf&#39;&gt;dplyr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://dplyr.tidyverse.org/reference/mutate.html&#39;&gt;mutate&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;animal &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;nf&#39;&gt;get_animal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;parsed_path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now we&amp;rsquo;re getting somewhere!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nf&#39;&gt;dplyr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://dplyr.tidyverse.org/reference/count.html&#39;&gt;count&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;
  &lt;span class=&#39;nv&#39;&gt;animals_df&lt;/span&gt;,
  &lt;span class=&#39;nv&#39;&gt;animal&lt;/span&gt;,
  sort &lt;span class=&#39;o&#39;&gt;=&lt;/span&gt; &lt;span class=&#39;kc&#39;&gt;TRUE&lt;/span&gt;
&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;

&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;# A tibble: 150 x 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;# Rowwise: &lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;    animal      n&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;    &lt;span style=&#39;color: #555555;font-style: italic;&#39;&gt;&amp;lt;chr&amp;gt;&lt;/span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span style=&#39;color: #555555;font-style: italic;&#39;&gt;&amp;lt;int&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt; 1&lt;/span&gt;&lt;span&gt; bear      222&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt; 2&lt;/span&gt;&lt;span&gt; cat        38&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt; 3&lt;/span&gt;&lt;span&gt; dog        32&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt; 4&lt;/span&gt;&lt;span&gt; rabbit     23&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt; 5&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span style=&#39;color: #BB0000;&#39;&gt;NA&lt;/span&gt;&lt;span&gt;         15&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt; 6&lt;/span&gt;&lt;span&gt; pig        12&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt; 7&lt;/span&gt;&lt;span&gt; unicorn     9&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt; 8&lt;/span&gt;&lt;span&gt; polar       7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt; 9&lt;/span&gt;&lt;span&gt; giraffe     6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;10&lt;/span&gt;&lt;span&gt; penguin     6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;span style=&#39;color: #555555;&#39;&gt;# … with 140 more rows&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Is this result surprising? Probably not! Now, let&amp;rsquo;s have a look at the ones we did not identify.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nv&#39;&gt;animals_df&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#39;nf&#39;&gt;dplyr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://dplyr.tidyverse.org/reference/filter.html&#39;&gt;filter&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://rdrr.io/r/base/NA.html&#39;&gt;is.na&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;animal&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt; &lt;span class=&#39;o&#39;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#39;nf&#39;&gt;dplyr&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://dplyr.tidyverse.org/reference/pull.html&#39;&gt;pull&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;nv&#39;&gt;path&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;

&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [1] &#34;beanies/beanie-babies/hello-kitty-rainbow-with-cupcake/&#34;    &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [2] &#34;beanies/beanie-babies/boston-red-sox-key-clip/&#34;             &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [3] &#34;beanies/beanie-babies/i-love-you-bears/&#34;                    &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [4] &#34;beanies/beanie-babies/zodiac-horse/&#34;                        &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [5] &#34;beanies/beanie-babies/hong-kong-toy-fair-2017-brown/&#34;       &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [6] &#34;beanies/beanie-babies/hello-kitty-bunny-costume/&#34;           &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [7] &#34;beanies/beanie-babies/hello-kitty-pink-tartan/&#34;             &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [8] &#34;beanies/beanie-babies/hello-kitty-gold-angel/&#34;              &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;  [9] &#34;beanies/beanie-babies/rock-hello-kitty/&#34;                    &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [10] &#34;beanies/beanie-babies/hello-kitty-i-love-japan-usa-version/&#34;&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [11] &#34;beanies/beanie-babies/hello-kitty-i-love-japan-uk-version/&#34; &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [12] &#34;beanies/beanie-babies/zodiac-ox/&#34;                           &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [13] &#34;beanies/beanie-babies/zodiac-tiger/&#34;                        &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [14] &#34;beanies/beanie-babies/happy-birthday-sock-monkey/&#34;          &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [15] &#34;beanies/beanie-babies/zodiac-goat/&#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Fair enough, and nothing endangering our conclusion that bears win.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I set out to find out what animals are the most common among Beanie babies. I thought I&amp;rsquo;d freshen my rvest-ing skill but thanks to the sitemap, that&amp;rsquo;s my rusty dplyr knowledge I was able to update a bit. In the end, I learnt that 35% of Beanie babies, at least the ones registered on Beaniepedia, are bears. Thanks to Beaniepedia maintainer for allowing this fun!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Storytime preparedness with av</title>
      <link>https://masalmon.eu/2020/12/10/av-storytime/</link>
      <pubDate>Thu, 10 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2020/12/10/av-storytime/</guid>
      <description>&lt;p&gt;My kids got a cool electronic storyteller as a gift. It is basically a pretty cube that you shake to make it play tracks. &lt;a href=&#34;https://www.joyeuse.io/&#34;&gt;&lt;em&gt;La conteuse merveilleuse&lt;/em&gt;&lt;/a&gt; comes with pre-loaded songs and stories, but you can also add your own. Very handy, as we had e.g. CDs that came with magazines. According to the anti-manual&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, to add a mp3 or wav file you own, you first need to convert it to the storyteller&amp;rsquo;s expected format by using the company&amp;rsquo;s online converter, &lt;em&gt;la moulinette&lt;/em&gt; (the mill). In this post I shall explain how I, a cool anti-mom, used R, in particular the av package, instead.&lt;/p&gt;
&lt;h2 id=&#34;official-guidance-on-how-to-convert-audio-files-on-the-conteuse-merveilleuse&#34;&gt;Official guidance on how to convert audio files on the Conteuse merveilleuse&lt;/h2&gt;
&lt;p&gt;The storyteller can be plugged into a computer like an USB stick, using its specific red cable. The interface of the storyteller is the file system, which is rather intuitive to me. There is a folder for each face of the cube. When you shake the cube three times with e.g. the lion face facing upwards, it plays a random track from the LION folder.&lt;/p&gt;
&lt;p&gt;As a side note, something that&amp;rsquo;s fascinating to me is that the settings of the cube, like the maximal volume, are to be tweaked via a text file called settings.txt! Not even reglages.txt! Furthermore, your storyteller&amp;rsquo;s ID (needed to register the device on the company&amp;rsquo;s website) is stored as a text filename.&lt;/p&gt;
&lt;p&gt;You can buy new tracks from the company&amp;rsquo;s website, record your own tracks in their studio, and upload your local stories to the website for then getting them as compatible mp3. You are limited to 5 conversions a day, of files up to 100Mb. I had some connection issues and couldn&amp;rsquo;t even get a few conversions, and besides, some of the tracks (from our &lt;a href=&#34;http://www.lacachette.fr/lacachette_nancy.php&#34;&gt;local kid theater&lt;/a&gt;, unsurprisingly currently closed) I wanted to use were a bit bigger than 100Mb.&lt;/p&gt;
&lt;h2 id=&#34;using-r-instead&#34;&gt;Using R instead&lt;/h2&gt;
&lt;p&gt;When reading the FAQ on the website, sadly not linkable as it&amp;rsquo;s in the website section where you&amp;rsquo;re logged in, I saw a sentence describing the mp3 formats for &amp;ldquo;geeks&amp;rdquo;: &lt;em&gt;mono, 64 kbps, 16 khz, constant bitrate&lt;/em&gt;. Maybe I felt targeted by the word geek, in any case seeing this made me realize I could probably use other tools to convert tracks. I remembered about Jeroen Ooms&amp;rsquo; av package, and decided to read its docs, in particular of &lt;a href=&#34;https://docs.ropensci.org/av/reference/encoding.html&#34;&gt;&lt;code&gt;av::av_audio_convert()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, I still had no clear idea what all the numbers in the format description meant, but I realized av has a function very similar to &lt;a href=&#34;https://docs.ropensci.org/magick/reference/attributes.html&#34;&gt;&lt;code&gt;magick::image_info()&lt;/code&gt;&lt;/a&gt;: &lt;a href=&#34;https://docs.ropensci.org/av/reference/info.html&#34;&gt;&lt;code&gt;av::av_media_info()&lt;/code&gt;&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;I used it on a track pre-loaded on the cube.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;c&#39;&gt;# I did not add the space character&lt;/span&gt;
&lt;span class=&#39;nf&#39;&gt;av&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/av/reference/info.html&#39;&gt;av_media_info&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;/media/maelle/JOYEUSE-AD/FR/NUAGE/Je respire.mp3&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;

&lt;span class=&#39;c&#39;&gt;#&amp;gt; $duration&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] 426.564&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; $video&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; NULL&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; $audio&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;   channels sample_rate    codec frames bitrate layout&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1        1       16000 mp3float     NA   64000   mono&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This helped me see the parameter values of &lt;a href=&#34;https://docs.ropensci.org/av/reference/encoding.html&#34;&gt;&lt;code&gt;av::av_audio_convert()&lt;/code&gt;&lt;/a&gt; I needed to use: &lt;code&gt;channels = 1&lt;/code&gt; and &lt;code&gt;sample_rate = 16000&lt;/code&gt;. I did not tweak the &lt;code&gt;bitrate&lt;/code&gt;, I didn&amp;rsquo;t see how, and anyway my tracks had a lower bit rate (so lower quality) than the company&amp;rsquo;s ones.&lt;/p&gt;
&lt;p&gt;After the conversion I&amp;rsquo;ll describe later, here&amp;rsquo;s the info I got about new tracks.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;
&lt;pre class=&#39;chroma&#39;&gt;&lt;code class=&#39;language-r&#39; data-lang=&#39;r&#39;&gt;&lt;span class=&#39;nf&#39;&gt;av&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/av/reference/info.html&#39;&gt;av_media_info&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;/media/maelle/JOYEUSE-AD/FR/LION/choum.mp3&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;

&lt;span class=&#39;c&#39;&gt;#&amp;gt; $duration&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] 265.356&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; $video&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; NULL&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; $audio&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;   channels sample_rate    codec frames bitrate layout&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1        1       16000 mp3float     NA   24000   mono&lt;/span&gt;

&lt;span class=&#39;nf&#39;&gt;av&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;::&lt;/span&gt;&lt;span class=&#39;nf&#39;&gt;&lt;a href=&#39;https://docs.ropensci.org/av/reference/info.html&#39;&gt;av_media_info&lt;/a&gt;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;(&lt;/span&gt;&lt;span class=&#39;s&#39;&gt;&#34;/media/maelle/JOYEUSE-AD/FR/ROUGE/leila.mp3&#34;&lt;/span&gt;&lt;span class=&#39;o&#39;&gt;)&lt;/span&gt;

&lt;span class=&#39;c&#39;&gt;#&amp;gt; $duration&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; [1] 762.984&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; $video&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; NULL&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; &lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; $audio&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt;   channels sample_rate    codec frames bitrate layout&lt;/span&gt;
&lt;span class=&#39;c&#39;&gt;#&amp;gt; 1        1       16000 mp3float     NA   24000   mono&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;No need to tell av what format to use as the &lt;code&gt;output&lt;/code&gt; filename extension gives it away.&lt;/p&gt;
&lt;p&gt;I wrote two conversions functions&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One for tracks coming with a magazine, to crop out the intro song. This was crucial for user-friendliness of the cube as the title of the story comes after the 41 seconds (admittedly very cute) intro song which is a long time without knowing whether you want to listen or shake again to get another random track.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;convert_belles &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(audio_path) {
  av&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;av_audio_convert&lt;/span&gt;(
    audio &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; audio_path,
    output &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;file.path&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;basename&lt;/span&gt;(audio_path)),
    channels &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;,
    start_time &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;41&lt;/span&gt;,
    sample_rate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16000&lt;/span&gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;One for other tracks needing no cropping, but including some &amp;ldquo;wav&amp;rdquo; files.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;convert_autres &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(audio_path) {
  av&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;av_audio_convert&lt;/span&gt;(
    audio &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; audio_path,
    output &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;file.path&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;wav&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;mp3&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;basename&lt;/span&gt;(audio_path))),
    channels &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;,
    sample_rate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16000&lt;/span&gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I could have written a single function instead with one more parameter. 🤷&lt;/p&gt;
&lt;p&gt;To apply the functions&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I put the tracks in two folders (by hand).&lt;/li&gt;
&lt;li&gt;For each folder I used &lt;a href=&#34;https://fs.r-lib.org/&#34;&gt;fs&lt;/a&gt; and &lt;a href=&#34;https://purrr.tidyverse.org/&#34;&gt;purrr&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;to_convert &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; fs&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;dir_ls&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;input/belles-h&amp;#34;&lt;/span&gt;)

convert_belles &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(audio_path) {
  av&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;av_audio_convert&lt;/span&gt;(
    audio &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; audio_path,
    output &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;file.path&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;basename&lt;/span&gt;(audio_path)),
    channels &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;,
    start_time &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;41&lt;/span&gt;,
    sample_rate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16000&lt;/span&gt;
  )
}

purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;walk&lt;/span&gt;(
  to_convert,
  convert_belles
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After that I manually copy-pasted output tracks to the face folders of the cube. Now the tracks corresponding to theater stories are all in the ROUGE face for instance.&lt;/p&gt;
&lt;p&gt;In reality I started by converting &lt;em&gt;one&lt;/em&gt; track, then put it in a face folder of the cube and tried playing it.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this post I presented my small script converting mp3 and wav tracks to mp3 compatible with my offspring&amp;rsquo;s storyteller. To me these were a few empowering lines of utility code. I think it exemplifies the usefulness of &lt;a href=&#34;https://docs.ropensci.org/av&#34;&gt;av&lt;/a&gt; for audio manipulation. Now, maybe I&amp;rsquo;ll go record some tale about R to put on my kids&amp;rsquo; cube&amp;hellip;&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Apparently when you&amp;rsquo;re a cool new startup you don&amp;rsquo;t call your docs a manual! &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Single-source publishing for R users</title>
      <link>https://masalmon.eu/2020/11/06/single-source-publishing-r/</link>
      <pubDate>Fri, 06 Nov 2020 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2020/11/06/single-source-publishing-r/</guid>
      <description>&lt;p&gt;A big part of my work includes putting content about R online, in blog posts and online books.
I&amp;rsquo;m therefore very interested in the technical infrastructure that allows us R users to produce beautiful products out of R Markdown or Markdown source files.
In this post I shall summarize my recent experiments around making HTML and PDF versions of books.
Thanks to &lt;a href=&#34;https://julie-blanc.fr/blog/2020-11-05_chiragan/&#34;&gt;Julie Blanc&amp;rsquo;s inspiring post in French&lt;/a&gt;, I have learnt this is called &lt;a href=&#34;https://en.wikipedia.org/wiki/Single-source_publishing&#34;&gt;&lt;em&gt;single-source publishing&lt;/em&gt;&lt;/a&gt;.
So let&amp;rsquo;s dive into the &lt;a href=&#34;https://en.wikipedia.org/wiki/The_Incredible_Machine_%28series%29&#34;&gt;incredible machines&lt;/a&gt; allowing single-source publishing for R users. 😉&lt;/p&gt;
&lt;h2 id=&#34;what-i-want-for-writing-books&#34;&gt;What I want for writing books&lt;/h2&gt;
&lt;p&gt;&lt;del&gt;I want technical tools that allow me to procrastinate whilst learning a ton.&lt;/del&gt;
Just kidding, or not. 😇
My official criteria are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For a book(let), I want a beautiful, usable website as well as a beautiful, usable PDF since some folks might prefer that for printing or offline usage.&lt;/li&gt;
&lt;li&gt;I want to be able to write content in R Markdown or Markdown files, with some helpers for elements that Markdown doesn&amp;rsquo;t allow, for instance I might use a custom block to show an alert.&lt;/li&gt;
&lt;li&gt;I want continuous deployment for my books, using git and a continuous integration service, so that every change in the source is reflected in the online versions of my book without my needing to think about it.&lt;/li&gt;
&lt;li&gt;I would prefer to knit R Markdown files only once.&lt;/li&gt;
&lt;li&gt;I don&amp;rsquo;t want to have to learn two ways to style things. &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, let&amp;rsquo;s dive into three workflows I&amp;rsquo;ve used or experimented with.&lt;/p&gt;
&lt;h2 id=&#34;the-standard-way-bookdown-gitbook-and-pdf_book&#34;&gt;The standard way: bookdown gitbook and pdf_book&lt;/h2&gt;
&lt;p&gt;We R users are very lucky to be able to use bookdown for making books.
You write content in Rmd files in a single folder, you order their filenames in a config file and choose an output format when knitting.
There are many books out there built using bookdown, and often they&amp;rsquo;re knit twice so that there&amp;rsquo;s an HTML and PDF version.
See for instance &lt;a href=&#34;https://devguide.ropensci.org&#34;&gt;rOpenSci dev guide&lt;/a&gt;, that is deployed with GitHub Actions.&lt;/p&gt;
&lt;p&gt;Advantages of bookdown include its widespread usage and stability, as well as its docs, both by its authors and users. For instance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There is a &lt;a href=&#34;https://bookdown.org/yihui/bookdown/&#34;&gt;bookdown book&lt;/a&gt; by bookdown maintainer Yihui Xie.&lt;/li&gt;
&lt;li&gt;Emil Hvitfeldt wrote a post about &lt;a href=&#34;https://www.hvitfeldt.me/blog/bookdown-netlify-github-actions/&#34;&gt;deploying your bookdown project to Netlify with Github Actions&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A downside of bookdown &lt;del&gt;for the procrastinators out there&lt;/del&gt; is, in my opinion, that if you want a PDF and HTML versions of a book, you have to knit it twice.
Furthermore, if you introduce some fancy things such as a custom block, you will have to define it both with CSS and with LaTeX environments.
Now, I have written a &lt;a href=&#34;https://www.editions-ellipses.fr/accueil/5374-l-oral-de-biologie-aux-concours-bcpst-9782729853693.html&#34;&gt;whole book with LaTeX&lt;/a&gt; so I used to partially know how to use it, but these days I&amp;rsquo;d prefer learning about CSS only as there&amp;rsquo;s already a lot to digest in there. 😅&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s dive into two DIY ways of publishing a book in HTML and PDF.&lt;/p&gt;
&lt;h2 id=&#34;hugo-and-pagedjs-cli&#34;&gt;Hugo and pagedjs-cli&lt;/h2&gt;
&lt;p&gt;In this proof-of-concept, content is stored in Markdown files, that could have been generated with &lt;a href=&#34;https://hugodown.r-lib.org/&#34;&gt;hugodown&lt;/a&gt;.
Actors are &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt;, a powerful static website generator that you get in the form of a binary, and &lt;a href=&#34;https://gitlab.pagedmedia.org/tools/pagedjs-cli&#34;&gt;pagedjs-cli&lt;/a&gt;, a Node package that prints HTML to PDF.&lt;/p&gt;
&lt;p&gt;You can find a &lt;a href=&#34;https://github.com/maelle/testbook&#34;&gt;repo corresponding to this experiment&lt;/a&gt; on GitHub, and the &lt;a href=&#34;https://hugo-pagedjs-book.netlify.app/&#34;&gt;resulting book&lt;/a&gt; on Netlify.&lt;/p&gt;
&lt;p&gt;This proof-of-concept is based on the great &lt;a href=&#34;https://github.com/alex-shpak/hugo-book&#34;&gt;hugo-book theme&lt;/a&gt;.
My &amp;ldquo;work&amp;rdquo; was just to add a bit of setup magic (Netlify config, config/ dir).&lt;/p&gt;
&lt;p&gt;The idea is to run two Hugo builds with &lt;a href=&#34;https://gohugo.io/getting-started/configuration/&#34;&gt;different configurations&lt;/a&gt;.
In the &lt;a href=&#34;https://github.com/r-lib/hugodown/issues/14#issuecomment-632850506&#34;&gt;words of Hadley Wickham&lt;/a&gt;, &lt;em&gt;&amp;ldquo;hugo provides a bewildering array of possible config locations&amp;rdquo;&lt;/em&gt;.
In this proof-of-concept/incredible machine, this array of possibilities is key to success.
The two configurations use different layout directories, layout directories being the templates telling Hugo where to put your words, e.g. every blog post on its own page, and a page showing summaries of all of them.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One Hugo build, &lt;code&gt;hugo -d public --environment &#39;website&#39;&lt;/code&gt;, creates the HTML website with a link to &amp;ldquo;book.pdf&amp;rdquo; somewhere, in the &lt;code&gt;public/&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;The second one, &lt;code&gt;hugo -d public2 --environment &#39;pdf&#39;&lt;/code&gt;, creates a website with a single HTML page containing &lt;em&gt;all&lt;/em&gt; the book content.&lt;/li&gt;
&lt;li&gt;Then that single page is printed to PDF using pagedjs-cli and copied as &amp;ldquo;book.pdf&amp;rdquo; to public/. &lt;code&gt;pagedjs-cli public2/all/index.html -o public/book.pdf&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The live website uses the content of the &lt;code&gt;public/&lt;/code&gt; folder so it has the website and the PDF.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Netlify can run all these commands&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;[build]
publish = &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;/public&amp;#34;&lt;/span&gt;
command = &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hugo -d public --environment &amp;#39;website&amp;#39; &amp;amp;&amp;amp; hugo -d public2 --environment &amp;#39;pdf&amp;#39; &amp;amp;&amp;amp; pagedjs-cli public2/all/index.html -o public/book.pdf&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The dependency on pagedjs-cli is indicated with package.json (the DESCRIPTION of Node projects).&lt;/p&gt;
&lt;p&gt;Now if the content lived in R Markdown files, we would need to use a service like GitHub Actions to knit things.&lt;/p&gt;
&lt;h3 id=&#34;advantages&#34;&gt;Advantages&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The Markdown files that are the source of both versions of the book would be generated only once if you started from R Markdown.&lt;/li&gt;
&lt;li&gt;Styling both versions rely on CSS. I haven&amp;rsquo;t added any print styles but if you used this workflow for real, then it&amp;rsquo;d be better to, of course.&lt;/li&gt;
&lt;li&gt;Compared to creating a gitbook with &lt;code&gt;bookdown&lt;/code&gt;, one could customize the HTML website more easily, and use any Hugo feature.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;further-work&#34;&gt;Further work&lt;/h3&gt;
&lt;p&gt;If I decided to take this further, that is!
All the work would be aimed at making the PDF version better&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Improve the Hugo layout to add various tables of contents (for the whole book, for chapters).&lt;/li&gt;
&lt;li&gt;Actually work on the CSS print sheet for the PDF version.&lt;/li&gt;
&lt;li&gt;Make Katex, Mermaid etc. work for the PDF version.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;related-work&#34;&gt;Related work&lt;/h3&gt;
&lt;p&gt;The work presented by &lt;a href=&#34;https://julie-blanc.fr/blog/2020-11-05_chiragan/&#34;&gt;Julie Blanc&lt;/a&gt; is a similar pipeline, where content lives in Markdown files rendered to two HTML versions by Jekyll, another static website generator.
One HTML version is a website, the other one is a printable version thanks to Paged.js (the PDF is not pre-generated but you can get it from any modern browser).
The big differences with my experiment are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Julie Blanc&amp;rsquo;s work is not an experiment, it&amp;rsquo;s deployed to production!&lt;/li&gt;
&lt;li&gt;Both versions of the book are absolutely stunning, there was actual CSS work involved.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;bookdownbs4_book-xml2-and-pagedjs-cli&#34;&gt;bookdown::bs4_book(), xml2 and pagedjs-cli&lt;/h2&gt;
&lt;p&gt;In another experiment, I used bookdown&amp;rsquo;s brand-new HTML book format, &lt;a href=&#34;https://twitter.com/hadleywickham/status/1323038454914187264&#34;&gt;&lt;code&gt;bs4_book()&lt;/code&gt; by Hadley Wickham&lt;/a&gt; (only available in bookdown&amp;rsquo;s dev version).
I used this one because I find it looks better than gitbook, and because it uses Bootswatch themes, you get to use &lt;a href=&#34;https://bootswatch.com/cerulean/&#34;&gt;divs such as a alerts&lt;/a&gt;.
See bookdown&amp;rsquo;s docs about &lt;a href=&#34;https://bookdown.org/yihui/rmarkdown-cookbook/custom-blocks.html&#34;&gt;custom blocks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/maelle/bspagedjs&#34;&gt;source&lt;/a&gt; is open. See the
&lt;a href=&#34;https://maelle.github.io/bspagedjs/intro.html&#34;&gt;HTML version&lt;/a&gt; and &lt;a href=&#34;https://maelle.github.io/bspagedjs/result.pdf&#34;&gt;PDF version&lt;/a&gt;.
This time I took time to learn a bit about print CSS. 😸&lt;/p&gt;
&lt;p&gt;Here the steps are knit using the &lt;code&gt;bs4_book()&lt;/code&gt; template for HTML and then for getting a PDF&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;tweaks of the HTML e.g. moving the chapter table of contents from the sidebar to the main content, and merging of all chapters using xml2 and XPath (so yeah you&amp;rsquo;re ditching LaTeX in favor of a workflow involving XPath, so modern 🙃) in &lt;a href=&#34;https://github.com/maelle/bspagedjs/blob/master/build.R&#34;&gt;build.R&lt;/a&gt;. I could have made my life easier by using &lt;a href=&#34;https://sjp.co.nz/projects/selectr/&#34;&gt;selectr&lt;/a&gt; for translating &lt;em&gt;&amp;rdquo; CSS3 Selectors and translates them to XPath 1.0 expressions. &amp;ldquo;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;some print CSS, see &lt;a href=&#34;style.css&#34;&gt;stylesheet&lt;/a&gt;. It turns out that &lt;a href=&#34;https://www.pagedjs.org/documentation/05-designing-for-print/&#34;&gt;following Paged.js docs about print CSS&lt;/a&gt; is not that hard. See my &lt;a href=&#34;https://github.com/maelle/bspagedjs/blob/master/style.css&#34;&gt;stylesheet&lt;/a&gt;, I changed the display of some things in print, and I used &lt;a href=&#34;https://www.pagedjs.org/documentation/07-generated-content-in-margin-boxes/%60&#34;&gt;properties&lt;/a&gt; to add the page number and chapter title to the footer.&lt;/li&gt;
&lt;li&gt;pagedjs-cli.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Locally I sourced build.R to see whether it works, but then I also wrote a &lt;a href=&#34;https://github.com/maelle/bspagedjs/blob/master/.github/workflows/main.yml&#34;&gt;GitHub Actions workflow&lt;/a&gt; that installs dependencies, runs the script, and deploys the docs/ folder to a gh-pages branch.&lt;/p&gt;
&lt;p&gt;Note that Bootstrap provides &lt;a href=&#34;https://getbootstrap.com/docs/4.0/utilities/display/#display-in-print&#34;&gt;classes you can add to elements for changing their display in print&lt;/a&gt;.
So to not show the burger menu in print, you can either do as I did with a CSS property&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;@&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;media&lt;/span&gt; &lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;print&lt;/span&gt; {
  .&lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;btn&lt;/span&gt;.&lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;btn-outline-primary&lt;/span&gt;.&lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;d-lg-none&lt;/span&gt;.&lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;ml-2&lt;/span&gt;.&lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;mt-1&lt;/span&gt; {
    &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;display&lt;/span&gt;: &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;none&lt;/span&gt;;
}

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or you&amp;rsquo;d add the &lt;code&gt;.d-print-none&lt;/code&gt; to that element in your HTML template.
If you can control said HTML template, that is.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/maelle/bspagedjs/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc&#34;&gt;Further work needed in this experiment&lt;/a&gt; is listed in GitHub issues.
For instance footnotes aren&amp;rsquo;t tackled yet.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So, as an R user writing content in R Markdown, you have different possibilities for respecting the principles of single-source publishing.
I would still recommend using bookdown or other official rmarkdown formats, knitting twice&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; if you need two versions, as it is the only stable and widely used solution, but I found it fun to explore other workflows.
Both the DIY ways I presented use pagedjs-cli to generate a PDF out of HTML. I strongly recommend following the work done by the &lt;a href=&#34;https://www.pagedjs.org/&#34;&gt;lovely Paged.js folks&lt;/a&gt; in the world of paged media, and to learn more about CSS for print.
If you want to produce only paged content out of your R Markdown file, check out the &lt;a href=&#34;https://pagedown.rbind.io/&#34;&gt;pagedown package&lt;/a&gt; and its fantastic output formats.&lt;/p&gt;
&lt;p&gt;If you too want to experiment with homemade pipelines, have fun customizing things. 😉
Now, of course, the possibility of customization might actually be a curse when you are trying to write something.
But this was not a blog post about productivity. 😁&lt;/p&gt;
&lt;p&gt;At this point, let me thank &lt;a href=&#34;https://twitter.com/RLesur&#34;&gt;Romain Lesur&lt;/a&gt; (one of pagedown authors) for his work promoting Paged.js in the R community. 🙏&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Yes, I should probably re-style this very website. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Potentially, knitr &lt;a href=&#34;https://bookdown.org/yihui/rmarkdown-cookbook/cache-path.html&#34;&gt;cache&lt;/a&gt; might make knitting a thing a second time very fast? 🤔 &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>How I Taught Scientific Blogging with R Markdown, Online</title>
      <link>https://masalmon.eu/2020/07/08/rmd-blogging-course/</link>
      <pubDate>Wed, 08 Jul 2020 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2020/07/08/rmd-blogging-course/</guid>
      <description>&lt;p&gt;Last week I had the pleasure to lead an online course about &amp;ldquo;Scientific Blogging with R Markdown&amp;rdquo;, invited by &lt;a href=&#34;https://twitter.com/najkoja&#34;&gt;Najko Jahn&lt;/a&gt; and &lt;a href=&#34;https://twitter.com/ahobert&#34;&gt;Anne Hobert&lt;/a&gt; from &lt;a href=&#34;https://www.sub.uni-goettingen.de/en/news/&#34;&gt;SUB Göttingen&lt;/a&gt;.
To follow the &lt;a href=&#34;https://alison.rbind.io/post/2020-06-02-tidymodels-virtually/&#34;&gt;example set&lt;/a&gt; by the &lt;a href=&#34;https://alison.rbind.io/&#34;&gt;incredible Alison Hill&lt;/a&gt;, I&amp;rsquo;ll write a summary of what I&amp;rsquo;ve learnt and would like to do better next time.&lt;/p&gt;
&lt;h2 id=&#34;the-topic&#34;&gt;The topic&lt;/h2&gt;
&lt;p&gt;The topic of the course was &amp;ldquo;Scientific Blogging with R Markdown&amp;rdquo;.
For months I would sometimes write down some ideas, from &amp;ldquo;present distill&amp;rdquo; to &amp;ldquo;show web developer console&amp;rdquo;, that I had whilst reading things online.
I was already interested in topics related to R Markdown blogging and website development, but having the course on my agenda made me pay even more attention.
I did my note taking in a physical notebook and then I set up a GitHub repo to use its issue tracker.&lt;/p&gt;
&lt;p&gt;A bit later I had to start drafting an actual schedule, and decided I would try and not recommend a single tool, but instead show three ways of blogging with R Markdown: using the distill package whose goal is scientific and technical writing; using Hugo since that&amp;rsquo;s what I use at work; using WordPress since this comes up on Twitter every so often and seems like a good alternative workflow for when one does not use Git yet.
I thought it might help each attendee see a tool that suit them better, and that it might mean everyone would learn something.
I suppose it also helped reduce my responsability if folks ended up not liking their tool, since I did not recommend a single one.  😜&lt;/p&gt;
&lt;p&gt;The course summary I wrote was&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Are you an R user who works in science? Would you like sharing more online? How about starting a new blog, with R Markdown (Rmd)?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In this 2-hour course with live coding, we’ll go on three short adventures:&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;setting up a scientific Rmd blog with the Distill framework and the distill package&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;setting up a scientific Rmd blog with the Hugo website generator and the hugodown package&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;adding Rmd posts to a Wordpress blog.&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;We’ll prepare for the adventures by defining what we expect of an Rmd blog. We’ll end the course by reflecting on each adventure as well as mentioning important future paths such as how to promote your blog. You should leave the course ready to start a scientific R Markdown blog with your tool of choice, and knowing where to find more resources and help.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-practical-plan&#34;&gt;The practical plan&lt;/h2&gt;
&lt;p&gt;When I first said yes to giving the course a while ago, it was supposed to happen in person in Göttingen in Germany, but unsurprisingly that plan changed a few months ago.
Online it would be! With Zoom.
Anne Hobert and Najko Jahn, who organized the workshop and taught basic R Markdown on the first day, were technical helpers on the second day.&lt;/p&gt;
&lt;p&gt;My course was to take place on the second day, in two hours.
In the afternoon attendees would have time to work together in breakout rooms or on their own, and I stayed online for questions, as did Anne and Najko.&lt;/p&gt;
&lt;p&gt;Anne had the idea to open my course to more attendees than the workshop first day i.e. open it to 10 attendees outside of the funding stream, bringing the maximum to 20 attendees.
We decided to advertise it via R-Ladies communication channels (telling R-Ladies could share the info with their friends and colleagues from under-represented groups), and Anne gave spots on a first come first serve basis.&lt;/p&gt;
&lt;p&gt;There was an online pad associated with the course, where attendees could write who they were (so cool to see that) and their questions.
We had a short call at the beginning of the week to ensure we could hear each other.
The three of us read &lt;a href=&#34;https://carpentries.org/blog/2020/03/tips-for-teaching-online/&#34;&gt;The Carpentries guidance for teaching online&lt;/a&gt; and e.g. used the idea to ask attendees to write &amp;ldquo;hand&amp;rdquo; and &amp;ldquo;hand helper&amp;rdquo; in the Zoom chat if they wanted to ask a question to the instructor (me) or a helper.&lt;/p&gt;
&lt;h2 id=&#34;a-course-website&#34;&gt;A course website&lt;/h2&gt;
&lt;p&gt;Since it was a course about blogging, setting up a website seemed natural.
It was also an excellent way to productively procrastinate if I&amp;rsquo;m being honest, but in the end I really liked filling and working with &lt;a href=&#34;https://scientific-rmd-blogging.netlify.app/&#34;&gt;the course website&lt;/a&gt; so I&amp;rsquo;d say it was time well spent?&lt;/p&gt;
&lt;p&gt;I used two Hugo themes,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/matcornic/hugo-theme-learn&#34;&gt;Hugo theme learn&lt;/a&gt; (that has a nice table of contents on the left, search, copy-paste button for code&amp;hellip;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/dzello/reveal-hugo&#34;&gt;Hugo theme reveal-hugo&lt;/a&gt; (for slides)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Slides for each section are listed in the menu and opened in a new tab (thanks to a &lt;a href=&#34;https://github.com/maelle/rmd-blogging-course/blob/main/layouts/partials/menu.html&#34;&gt;custom menu layout&lt;/a&gt;, compared to the original Hugo learn theme).&lt;/p&gt;
&lt;p&gt;Some Markdown content was generated with &lt;a href=&#34;https://rmarkdown.rstudio.com/&#34;&gt;R Markdown&lt;/a&gt;, using &lt;a href=&#34;https://github.com/r-lib/hugodown/&#34;&gt;hugodown&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The website is deployed by &lt;a href=&#34;https://www.netlify.com/&#34;&gt;Netlify&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Slides could be printed to PDF using Decktape which I &lt;a href=&#34;https://github.com/maelle/test-course-site&#34;&gt;had done in a concept&lt;/a&gt; but I did not pursue it further.&lt;/p&gt;
&lt;p&gt;Why use Hugo for both the website and slidedecks, and not, say Hugo+hugodown for pages and xaringan for slides?
This way the source of slides is html produced by Hugo from Markdown content.
It allowed me to use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;downlit syntax highlighting for slides created from R Markdown with hugodown output format;&lt;/li&gt;
&lt;li&gt;Chroma syntax highlighting for other languages;&lt;/li&gt;
&lt;li&gt;emojis!&lt;/li&gt;
&lt;li&gt;Shortcodes in slides, which I ended up doing for diagrams.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, because slides are in the content, they are indexed by the Hugo learn theme so searchable!&lt;/p&gt;
&lt;p&gt;I learnt a few Hugo tricks whilst setting up the website which was fun per se, and I really liked the end product, as mentioned above. Two highlights for me were&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;to have a table of contents on the left that I could use on the day of the course&lt;/li&gt;
&lt;li&gt;the page with snippets for demos that solved my problem &amp;ldquo;How am I going to organize the small pieces of code I need for demos?&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The website also had questions for topics not mentioned during the course, where I e.g. stuffed the content from the notes I had taken.&lt;/p&gt;
&lt;h2 id=&#34;the-newest-tools-&#34;&gt;The newest tools 😬&lt;/h2&gt;
&lt;p&gt;In two parts of the course I actually demo-ed packages in development which is not optimal, but I had excuses each time.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;For using R Markdown and Hugo, I never fully used blogdown myself. When one day in my GitHub timeline I saw Hadley Wickham create &lt;a href=&#34;https://hugodown.r-lib.org/&#34;&gt;hugodown&lt;/a&gt;, I got very excited because it fit more with the way I had used Hugo and R Markdown. I started using it so that was the tool I wanted to share about. I think one can trust hugodown&amp;rsquo;s maintainer. 😁&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For using R Markdown and WordPress, the existing function relies on unmaintained packages (XML and RCurl), whereas there is a REST API associated with WordPress websites nowadays. I wrote a minimal package called &lt;a href=&#34;https://maelle.github.io/goodpress/&#34;&gt;goodpress&lt;/a&gt; with which it is possible to write directly from R Markdown to WordPress. It does not work for all WordPress packages yet, but I think that with Bob Rudis&amp;rsquo; efforts in &lt;a href=&#34;https://github.com/hrbrmstr/pressur&#34;&gt;pressur&lt;/a&gt;, with some work (and contributors 😉) things could work for all WordPress websites. I would only recommend goodpress on &lt;em&gt;existing&lt;/em&gt; websites at the moment, where it can only be a better idea than trying to use RCurl IMHO.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope my different warning signs will have helped the learners see what&amp;rsquo;s stable vs what&amp;rsquo;s not.&lt;/p&gt;
&lt;h2 id=&#34;what-we-did&#34;&gt;What we did&lt;/h2&gt;
&lt;p&gt;During the course two hours, I shared my whole desktop with the attendees&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.
I had several slidedecks integrated in my website.&lt;/p&gt;
&lt;p&gt;The slidedecks related to the three tools had a slide telling it was time for a demo, and then a few slides ending with a break countdown (I had to remove the last break).
For the demos, I had printed my notes after knitting them to PDF.
The demos were my doing website things in RStudio and Firefox.
Compared to the demos on the website, for hugodown I only showed &lt;code&gt;create_site_academic()&lt;/code&gt;, not how to make another theme hugodown-compatible.&lt;/p&gt;
&lt;p&gt;In the end I took time to present my decks about reproducibility and about interactions with readers (including blog promotion and analytics).&lt;/p&gt;
&lt;p&gt;It was a bit intense, which I need to think about if I teach this again.&lt;/p&gt;
&lt;p&gt;In the few hours after my course, some attendees remained in breakout rooms (I got one question I think, about a Pandoc installation issue) and two of them showed their experiments in the final sharing session (where there were more than the two still online, although some people understandably had to leave).&lt;/p&gt;
&lt;h2 id=&#34;questions-i-got&#34;&gt;Questions I got&lt;/h2&gt;
&lt;p&gt;And my tentative answers.&lt;/p&gt;
&lt;h3 id=&#34;about-distill-is-there-a-difference-between-knitting-and-using-the-build-tab&#34;&gt;(about distill) Is there a difference between knitting and using the build tab?&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;I think at that point I realized I&amp;rsquo;d need to use distill more regularly to differentiate the different parts and the magic happening from RStudio.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Apparently from RStudio the website gets built when one edits the site configuration, and when one knits a post. You need to knit posts; and if you edit about.Rmd you need to either knit it or re-build the website. My impression is that you need to knit with intent, but most often the build part happens magically.&lt;/p&gt;
&lt;h3 id=&#34;what-is-the-difference-proscons-between-hugo-and-distill&#34;&gt;What is the difference (pros/cons) between hugo and distill?&lt;/h3&gt;
&lt;p&gt;I mentioned it a bit, distill is perfect for scientific/technical blogging but not very flexible. Hugo is very flexible which might be a curse. 😉 With Hugo you can really build any website: for this course website I mixed two Hugo themes, with a few custom layouts for instance (so even the slides used hugodown). But it requires time for learning. You could try both before committing, and you could still switch tools one day even if that&amp;rsquo;d take time.&lt;/p&gt;
&lt;h3 id=&#34;is-it-possible-to-have-one-citation-style-file-for-all-postsfolders-with-hugo-or-does-it-need-to-be-in-the-same-folder-as-the-post&#34;&gt;Is it possible to have one citation style file for all posts/folders with Hugo or does it need to be in the same folder as the post?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;For distill not yet &lt;a href=&#34;https://github.com/rstudio/distill/issues/82&#34;&gt;https://github.com/rstudio/distill/issues/82&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For hugodown not yet either &lt;a href=&#34;https://github.com/r-lib/hugodown/issues/28&#34;&gt;https://github.com/r-lib/hugodown/issues/28&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So for both distill and hugodown, it&amp;rsquo;s not possible &lt;em&gt;yet&lt;/em&gt; but at least you can store .bib at the root and refer to it as ../../../refs.bib or so in your post YAML.&lt;/p&gt;
&lt;h3 id=&#34;how-to-limit-the-readership-of-your-blog---if-i-want-my-website-to-only-be-viewable-to-the-people-in-my-company&#34;&gt;How to limit the readership of your blog - if i want my website to only be viewable to the people in my company?&lt;/h3&gt;
&lt;p&gt;For WordPress websites having private posts seem to be built-in.&lt;/p&gt;
&lt;p&gt;For Hugo and distill it depends on how you deploy. I.e. from &lt;a href=&#34;https://hugodown.r-lib.org/articles/deploy.html&#34;&gt;https://hugodown.r-lib.org/articles/deploy.html&lt;/a&gt; if you choose say Amazon S3 you could look for &amp;ldquo;Amazon S3 private website&amp;rdquo;.
Such a feature might not be in the free tier of the service.&lt;/p&gt;
&lt;p&gt;Or you could deploy to a server that your team has?&lt;/p&gt;
&lt;h3 id=&#34;regarding-reproducibility-do-you-have-any-thoughts-on-how-to-share-your-data-belonging-to-the-code-in-such-a-blogpost&#34;&gt;Regarding reproducibility: Do you have any thoughts on how to share your data belonging to the code in such a blogpost?&lt;/h3&gt;
&lt;p&gt;You could distribute it with your Hugo website (in the post folder or from static &amp;ndash; I haven&amp;rsquo;t tried), otherwise sharing it in a GitHub repo works; but better for bigger datasets would be to use Figshare/Zenodo/etc.&lt;/p&gt;
&lt;h3 id=&#34;using-utterancees-you-have-some-sort-of-notification-if-someone-comments-on-your-post&#34;&gt;Using utterance.es, you have some sort of notification if someone comments on your post?&lt;/h3&gt;
&lt;p&gt;Yes, same as other GitHub notifications (so email or web depending on your settings).&lt;/p&gt;
&lt;h3 id=&#34;is-there-a-way-to-collaborate-on-the-same-blog&#34;&gt;Is there a way to collaborate on the same blog?&lt;/h3&gt;
&lt;p&gt;Yes definitely. At rOpenSci we use GitHub for that (we even have a guide, &lt;a href=&#34;https://blogguide.ropensci.org/&#34;&gt;blogguide.ropensci.org&lt;/a&gt;), you could use GitLab too. Adding posts by pull requests is nice because of the pull requests review infrastructure. Without a git platform I think it might be less natural to edit collaboratively but you could still find an alternative workflow.&lt;/p&gt;
&lt;h3 id=&#34;is-it-a-good-idea-to-use-the-distill-format-for-the-lab-where-you-work-instead-of-being-a-personal-blog&#34;&gt;Is it a good idea to use the distill format for the lab where you work instead of being a personal blog?&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve seen &lt;a href=&#34;https://scientific-rmd-blogging.netlify.app/distill/further-resources/#websites-for-inspiration-&#34;&gt;distill for groups&lt;/a&gt;, I think it works well for that too, if your colleagues are ok editing from R / letting you edit things.&lt;/p&gt;
&lt;h3 id=&#34;do-you-know-cheap-hosting-services&#34;&gt;Do you know cheap hosting services?&lt;/h3&gt;
&lt;p&gt;That question was a good reminder of my privilege: for me a custom domain costing a few dollars a month is not expensive.
For others, especially in some countries, it can be a luxury.
In that case, using GitHub pages, free Netlify domains, etc. is a good workaround and better than having no website.&lt;/p&gt;
&lt;h3 id=&#34;comment-by-anne-gdpr-privacy-page-in-germany-imprint&#34;&gt;Comment by Anne: GDPR, privacy page, in Germany imprint.&lt;/h3&gt;
&lt;p&gt;I shortly mentioned one should add a privacy page mentioning what data is collected, and Anne Hobert reminded attendees that in Germany all websites need to have a page called Impressum/imprint.&lt;/p&gt;
&lt;h2 id=&#34;possible-improvements&#34;&gt;Possible improvements&lt;/h2&gt;
&lt;p&gt;I might get even more ideas from participants&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; but here are a few ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I think next time it&amp;rsquo;d make sense to set up a second device to see the Zoom screen at all times. Or a second screen if Zoom lets me share one screen only.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I would not be that ambitious regarding what one can show with hugodown.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I&amp;rsquo;d like to know more about distill and WordPress to feel more at ease showing them, or to let someone else teach these parts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I am not sure &lt;em&gt;how&lt;/em&gt;, but I&amp;rsquo;d like to interact more with attendees.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A big limitation of the format, and the way I taught (giving a few recipes but not ensuring attendees live with a website), is that I can&amp;rsquo;t know attendees will actually go and build a website.
Or maybe I&amp;rsquo;ll know, in a few weeks, if/when I receive URLs.
I think that with websites, there&amp;rsquo;s a need for technical knowledge for sure, but maybe also some sort of accountability/support group.&lt;/p&gt;
&lt;h2 id=&#34;thank-you&#34;&gt;Thank you&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;d like to thank Najko Jahn and Anne Hobert for trusting me to give this course and for being such helpful and nice collaborators.
Thanks to the participants, I&amp;rsquo;m looking forward to seeing new blogs but no pressure. 😉
My course website has a &lt;a href=&#34;https://scientific-rmd-blogging.netlify.app/credits&#34;&gt;credits page&lt;/a&gt; where I&amp;rsquo;m sure I forgot names. 😬&lt;/p&gt;
&lt;h2 id=&#34;next-time&#34;&gt;Next time?&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;d love to teach the topic again, re-using and building upon my materials.
If you&amp;rsquo;re the organizer of a meetup for under-represented R users, get in touch to see if my skills and availabilities can be a fit for your group.
If you&amp;rsquo;re organizing something else, let&amp;rsquo;s talk business i.e. in that case I wouldn&amp;rsquo;t teach for free. 😉
In all cases, I&amp;rsquo;m looking forward to keep learning new things myself.&lt;/p&gt;
&lt;p&gt;If you taught or attended a workshop about blogging and R Markdown, feel free to share your own insights and good ideas. 🙏&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Sharing my whole screen makes me quite nervous. I had written a list of things to do before hand such as making sure Slack and Mattermost were closed and wouldn&amp;rsquo;t send any notification. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Participants were sent a pin.up link to add feedback on sticky notes &lt;a href=&#34;https://twitter.com/ma_salmon/status/974606612773163008&#34;&gt;à la Carpentries&lt;/a&gt;. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>How to showcase CSS&#43;JS&#43;HTML snippets with Hugo?</title>
      <link>https://masalmon.eu/2020/04/21/css-snippet/</link>
      <pubDate>Tue, 21 Apr 2020 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2020/04/21/css-snippet/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve recently found myself having to write a bit of CSS or JS for websites made with Hugo.
&lt;em&gt;Note for usual readers: it is a topic not directly related to R, but you might have played with either or both CSS and JS for your R blog or Shiny app.&lt;/em&gt;
On a scale from &lt;a href=&#34;https://www.youtube.com/watch?v=-pzckbNyqfc&#34;&gt;Peter Griffin programming CSS window blinds&lt;/a&gt; to &lt;a href=&#34;https://twitter.com/liatrisbian/status/1251239842861678592&#34;&gt;making art with CSS&lt;/a&gt;, I&amp;rsquo;m sadly much closer to the former; my JS knowledge is not better.
I often scour forums for answers to my numerous and poorly formulated questions, and often end up at code playgrounds like &lt;a href=&#34;https://codepen.io/&#34;&gt;Codepen&lt;/a&gt; where folks showcase snippets of HTML on its own or with either or both CSS and JS, together with the resulting HTML document.
You can even edit the code and run it again.
Quite neat!&lt;/p&gt;
&lt;p&gt;Now, as I was listening to &lt;a href=&#34;https://ladybug.dev/blogging-101&#34;&gt;an episode from the Ladybug podcast about blogging&lt;/a&gt;, one of the hosts, &lt;a href=&#34;https://twitter.com/ASpittel&#34;&gt;Ali Spittel&lt;/a&gt;, mentioned integrating Codepens into blog posts&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, which sounds useful indeed, and I started wondering: &lt;strong&gt;how could one showcase CSS+JS+HTML snippets on a Hugo website?&lt;/strong&gt;
In this post I shall go over three solutions, with and without Codepen, in all cases based on &lt;a href=&#34;https://gohugo.io/templates/shortcode-templates/#create-custom-shortcodes&#34;&gt;custom shortcodes&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;the-easiest-way-embed-a-codepen&#34;&gt;The easiest way: Embed a Codepen&lt;/h1&gt;
&lt;p&gt;As reported in a &lt;a href=&#34;https://ryancampbell.blog/blog/codepen-shortcode/&#34;&gt;2018 blog post by Ryan Campbell&lt;/a&gt; and a &lt;a href=&#34;https://kinson.io/post/embed-codepen/&#34;&gt;2019 blog post by Jeremy Kinson&lt;/a&gt;, Jorin Vogel &lt;a href=&#34;https://github.com/jorinvo/hugo-shortcodes/blob/master/shortcodes/pen.html&#34;&gt;created and shared a Hugo shortcode for Codepen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Save it under layouts/pen.html and voilà, you can call it! Below I&amp;rsquo;ll embed a cool CSS art snippet by &lt;a href=&#34;https://fossheim.io/&#34;&gt;Sarah L. Fossheim&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;{{&amp;lt; pen user=&amp;quot;fossheim&amp;rdquo; id=&amp;quot;oNjxrZa&amp;rdquo; &amp;gt;}}&lt;/p&gt;
&lt;p&gt;Gives&lt;/p&gt;










&lt;script
    data-slug-hash=&#34;oNjxrZa&#34;
    data-user=&#34;fossheim&#34;
    data-height=&#34;500&#34;
    data-default-tab=&#34;result&#34;
    data-theme-id=&#34;8862&#34;
    class=&#39;codepen&#39;
    async
    src=&#34;//codepen.io/assets/embed/ei.js&#34;
&gt;&lt;/script&gt;

&lt;p&gt;For a blog post showcasing code of yours, it might get a bit tiring to create and keep track of Codepens.
Moreover, you might want more ownership of your code.&lt;/p&gt;
&lt;h1 id=&#34;the-diy-way-load-html-css-and-js-code-into-an-iframe&#34;&gt;The DIY way: load HTML, CSS, and JS code into an iFrame&lt;/h1&gt;
&lt;p&gt;I was completely stuck trying to find out how to create and embed my own iframe and then luckily found &lt;a href=&#34;https://dev.to/pulljosh/how-to-load-html-css-and-js-code-into-an-iframe-2blc#solution-blob-urls&#34;&gt;a perfect post by Josh Pullen&lt;/a&gt; &lt;em&gt;&amp;ldquo;How to Load HTML, CSS, and JS Code into an iFrame&amp;rdquo;&lt;/em&gt;, with a perfect definition of the problem &lt;em&gt;&amp;ldquo;If you&amp;rsquo;ve ever used JSFiddle, Codepen, or others, this problem will be familiar to you: The goal is to take some HTML, CSS, and JS (stored as strings) and create an iframe with the code loaded inside.&amp;quot;&lt;/em&gt;.  🙌
Good stuff!&lt;/p&gt;
&lt;p&gt;Based on the code in the post, I created a shortcode called &amp;ldquo;snippet.html&amp;rdquo;.
It is a &lt;a href=&#34;https://gohugo.io/templates/shortcode-templates/#paired-example-highlight&#34;&gt;paired shortcode&lt;/a&gt;: there is input between two markers, and one option passed via the first marker.
It expects input like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;{{&amp;lt; snippet an&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;id&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;unique&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;the&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;post &amp;gt;}}
&lt;span style=&#34;color:#4070a0&#34;&gt;```css
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;// css code
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;```&lt;/span&gt;

&lt;span style=&#34;color:#4070a0&#34;&gt;```html
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;// HTML code
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;```&lt;/span&gt;

&lt;span style=&#34;color:#4070a0&#34;&gt;```js
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;// js code
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;```&lt;/span&gt;
{{&amp;lt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;snippet &amp;gt;}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The shortcode itself is shown below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;34
&lt;/span&gt;&lt;span style=&#34;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;35
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;h4&lt;/span&gt;&amp;gt;My snippet {{ .Get 0 }}&amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;h4&lt;/span&gt;&amp;gt;
{{ $content := .Inner }}
{{ $content := replaceRE &amp;#34;```html&amp;#34; &amp;#34;\n **HTML code:** \n```html&amp;#34; $content }}
{{ $content := replaceRE &amp;#34;```css&amp;#34; &amp;#34;\n **CSS code:** \n```css&amp;#34; $content }}
{{ $content := replaceRE &amp;#34;```js&amp;#34; &amp;#34;\n **JS code:** \n```js&amp;#34; $content }}

{{ $content | markdownify }}

{{ $css := replaceRE &amp;#34;```html(.|\n)*?```&amp;#34; &amp;#34;$1&amp;#34; .Inner }}
{{ $css := replaceRE &amp;#34;```js(.|\n)*?```&amp;#34; &amp;#34;$1&amp;#34; $css }}
{{ $css := replaceRE &amp;#34;```css&amp;#34; &amp;#34;$1&amp;#34; $css }}
{{ $css := replaceRE &amp;#34;```&amp;#34; &amp;#34;$1&amp;#34; $css }}

{{ $js := replaceRE &amp;#34;```html(.|\n)*?```&amp;#34; &amp;#34;$1&amp;#34; .Inner }}
{{ $js := replaceRE &amp;#34;```css(.|\n)*?```&amp;#34; &amp;#34;$1&amp;#34; $js }}
{{ $js := replaceRE &amp;#34;```js&amp;#34; &amp;#34;$1&amp;#34; $js }}
{{ $js := replaceRE &amp;#34;```&amp;#34; &amp;#34;$1&amp;#34; $js }}

{{ $html := replaceRE &amp;#34;```css(.|\n)*?```&amp;#34; &amp;#34;$1&amp;#34; .Inner }}
{{ $html := replaceRE &amp;#34;```js(.|\n)*?```&amp;#34; &amp;#34;$1&amp;#34; $html }}
{{ $html := replaceRE &amp;#34;```html&amp;#34; &amp;#34;$1&amp;#34; $html }}
{{ $html := replaceRE &amp;#34;```&amp;#34; &amp;#34;$1&amp;#34; $html }}

&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;b&lt;/span&gt;&amp;gt;Result:&amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;b&lt;/span&gt;&amp;gt;&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;br&lt;/span&gt;&amp;gt;

&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;iframe&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;{{ .Get 0 }}&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;allowfullscreen&lt;/span&gt;
      &lt;span style=&#34;color:#4070a0&#34;&gt;style&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;width:100%;height:100%;&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;iframe&lt;/span&gt;&amp;gt;

&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;/js/blob.js&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt; 
&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;
&lt;span style=&#34;color:#007020&#34;&gt;document&lt;/span&gt;.addEventListener(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;DOMContentLoaded&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;function&lt;/span&gt;() {
   mySnippet(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;{{ $html }}&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;{{ $js }}&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;{{ $css }}&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;{{ .Get 0 }}&amp;#39;&lt;/span&gt;);
}, &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;false&lt;/span&gt;);
&amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt; 

&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Lines 2 to 7 create and &lt;a href=&#34;https://gohugo.io/functions/markdownify/&#34;&gt;markdownify&lt;/a&gt; the three highlighted blocks, with a note on the language before each.
Using markdownify means the code will be &lt;a href=&#34;https://gohugo.io/content-management/syntax-highlighting/&#34;&gt;highlighted using Chroma&lt;/a&gt; without my having to make any further efforts.&lt;/p&gt;
&lt;p&gt;Then there is some non elegant string manipulation going on to extract the CSS, JS and HTML, until line 58.&lt;/p&gt;
&lt;p&gt;After that I use the code &lt;a href=&#34;https://dev.to/pulljosh/how-to-load-html-css-and-js-code-into-an-iframe-2blc#solution-blob-urls&#34;&gt;from Josh Pullen&amp;rsquo;s post&lt;/a&gt; to create blob URLs and an iframe.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I create an iframe with the ID given as argument of the shortcode.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Once the page is loaded, I call a function defined below and saved under &lt;code&gt;/js/blob.js&lt;/code&gt;, again recycling code from &lt;a href=&#34;https://dev.to/pulljosh/how-to-load-html-css-and-js-code-into-an-iframe-2blc#solution-blob-urls&#34;&gt;Josh Pullen&amp;rsquo;s post&lt;/a&gt;, with the HTML, CSS and JS code, as well as the frame ID, as argument. The code creates blob URLs with the JS and CSS, then a blob URL with the HTML calling the JS and CSS, and finally assign that last blob URL to the iframe. ✨&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;function&lt;/span&gt; mySnippet(html, js, css, id) {
  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;const&lt;/span&gt; getGeneratedPageURL &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; ({ html, css, js }) =&amp;gt; {
  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;const&lt;/span&gt; getBlobURL &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; (code, type) =&amp;gt; {
    &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;const&lt;/span&gt; blob &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;new&lt;/span&gt; Blob([code], { type });
    &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;const&lt;/span&gt; url &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; URL.createObjectURL(blob);
    &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;return&lt;/span&gt; url;
  };

  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;const&lt;/span&gt; cssURL &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; getBlobURL(css, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;text/css&amp;#39;&lt;/span&gt;)
  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;const&lt;/span&gt; jsURL &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; getBlobURL(js, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;text/javascript&amp;#39;&lt;/span&gt;)

  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;const&lt;/span&gt; source &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;`
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;    &amp;lt;html&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;      &amp;lt;head&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;      &amp;lt;meta charset=&amp;#34;utf-8&amp;#34;/&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#70a0d0;font-style:italic&#34;&gt;${&lt;/span&gt;css &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;`&amp;lt;link rel=&amp;#34;stylesheet&amp;#34; type=&amp;#34;text/css&amp;#34; href=&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#70a0d0;font-style:italic&#34;&gt;${&lt;/span&gt;cssURL&lt;span style=&#34;color:#70a0d0;font-style:italic&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; /&amp;gt;`&lt;/span&gt;&lt;span style=&#34;color:#70a0d0;font-style:italic&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#70a0d0;font-style:italic&#34;&gt;${&lt;/span&gt;js &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;`&amp;lt;script src=&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#70a0d0;font-style:italic&#34;&gt;${&lt;/span&gt;jsURL&lt;span style=&#34;color:#70a0d0;font-style:italic&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; type=&amp;#34;text/javascript&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;`&lt;/span&gt;&lt;span style=&#34;color:#70a0d0;font-style:italic&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;      &amp;lt;/head&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;      &amp;lt;body&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#70a0d0;font-style:italic&#34;&gt;${&lt;/span&gt;html &lt;span style=&#34;color:#666&#34;&gt;||&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#70a0d0;font-style:italic&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;      &amp;lt;/body&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;    &amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;  `&lt;/span&gt;;
  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;return&lt;/span&gt; getBlobURL(source, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;text/html&amp;#39;&lt;/span&gt;);
};

&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;const&lt;/span&gt; url &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; getGeneratedPageURL({
  html&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt; html,
  css&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt; css,
  js&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt; js
});

&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;const&lt;/span&gt; getid &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; id;

&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;const&lt;/span&gt; iframe &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020&#34;&gt;document&lt;/span&gt;.querySelector(getid);
iframe.src &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; url;
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;demos&#34;&gt;Demos&lt;/h2&gt;
&lt;p&gt;In this demo below I use &lt;a href=&#34;https://www.w3schools.com/jsref/event_onclick.asp&#34;&gt;w3schools.com tutorial about buttons&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;{{&amp;lt; snippet number42 &amp;gt;}}
&lt;span style=&#34;color:#4070a0&#34;&gt;```css
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;p {
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;  color: red;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;}
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;button {
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;  background-color: pink;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;}
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;```&lt;/span&gt;

&lt;span style=&#34;color:#4070a0&#34;&gt;```html
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;lt;p&amp;gt; Some text &amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;lt;button onclick=&amp;#34;getTime()&amp;#34;&amp;gt;What time is it??&amp;lt;/button&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;lt;p id=&amp;#34;demo&amp;#34;&amp;gt;&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;```&lt;/span&gt;

&lt;span style=&#34;color:#4070a0&#34;&gt;```js
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;function getTime() {
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;  document.getElementById(&amp;#39;demo&amp;#39;).innerHTML = Date();
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;}
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;```&lt;/span&gt;
{{&amp;lt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;snippet &amp;gt;}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Gives&lt;/p&gt;
&lt;h4&gt;My snippet number42&lt;/h4&gt;





&lt;p&gt;&lt;strong&gt;CSS code:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;p&lt;/span&gt; {
  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;color&lt;/span&gt;: &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;red&lt;/span&gt;;
}
&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;button&lt;/span&gt; {
  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;background-color&lt;/span&gt;: &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pink&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;HTML code:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt; Some text &amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;button&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;onclick&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;getTime()&amp;#34;&lt;/span&gt;&amp;gt;What time is it??&amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;button&lt;/span&gt;&amp;gt;
&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;p&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;id&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;demo&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;JS code:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;function&lt;/span&gt; getTime() {
  &lt;span style=&#34;color:#007020&#34;&gt;document&lt;/span&gt;.getElementById(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;demo&amp;#39;&lt;/span&gt;).innerHTML &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020&#34;&gt;Date&lt;/span&gt;();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
















&lt;b&gt;Result:&lt;/b&gt;&lt;br&gt;

&lt;iframe id=&#34;number42&#34; allowfullscreen
      style=&#34;width:100%;height:100%;&#34;&gt;&lt;/iframe&gt;

&lt;script src=&#34;https://masalmon.eu/js/blob.js&#34; type=&#34;text/javascript&#34;&gt;&lt;/script&gt; 
&lt;script type=&#34;text/javascript&#34;&gt;
document.addEventListener(&#39;DOMContentLoaded&#39;, function() {
   mySnippet(&#39;\n\n\n\n\n\u003cp\u003e Some text \u003c\/p\u003e\n\u003cbutton onclick=\u0022getTime()\u0022\u003eWhat time is it??\u003c\/button\u003e\n\u003cp id=\u0022demo\u0022\u003e\u003c\/p\u003e\n\n\n\n\n&#39;, &#39;\n\n\n\n\n\n\n\nfunction getTime() {\n  document.getElementById(\u0027demo\u0027).innerHTML = Date();\n}\n\n&#39;, &#39;\n\np {\n  color: red;\n}\nbutton {\n  background-color: pink;\n}\n\n\n\n\n\n\n\n&#39;, &#39;number42&#39;);
}, false);
&lt;/script&gt; 

&lt;p&gt;Below is another, simpler, one.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;{{&amp;lt; snippet number66 &amp;gt;}}
&lt;span style=&#34;color:#4070a0&#34;&gt;```css
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;p {
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;  color: blue;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;}
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;```&lt;/span&gt;

&lt;span style=&#34;color:#4070a0&#34;&gt;```html
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;lt;p&amp;gt; There is no JS in this snippet. &amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;```&lt;/span&gt;

{{&amp;lt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;snippet &amp;gt;}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Gives&lt;/p&gt;
&lt;h4&gt;My snippet number66&lt;/h4&gt;





&lt;p&gt;&lt;strong&gt;CSS code:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;p&lt;/span&gt; {
  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;color&lt;/span&gt;: &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;blue&lt;/span&gt;;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;HTML code:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt; There is no JS in this snippet. &amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;p&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
















&lt;b&gt;Result:&lt;/b&gt;&lt;br&gt;

&lt;iframe id=&#34;number66&#34; allowfullscreen
      style=&#34;width:100%;height:100%;&#34;&gt;&lt;/iframe&gt;

&lt;script src=&#34;https://masalmon.eu/js/blob.js&#34; type=&#34;text/javascript&#34;&gt;&lt;/script&gt; 
&lt;script type=&#34;text/javascript&#34;&gt;
document.addEventListener(&#39;DOMContentLoaded&#39;, function() {
   mySnippet(&#39;\n\n\n\n\n\u003cp\u003e There is no JS in this snippet. \u003c\/p\u003e\n\n\n&#39;, &#39;\n\n\n\n\n\n\n&#39;, &#39;\n\np {\n  color: blue;\n}\n\n\n\n\n\n&#39;, &#39;number66&#39;);
}, false);
&lt;/script&gt; 

&lt;h2 id=&#34;to-dos&#34;&gt;To-dos&lt;/h2&gt;
&lt;p&gt;Clearly, my custom shortcode could do with&amp;hellip; styling, which is sort of ironic, but this is left as an exercise to the reader. 😉&lt;/p&gt;
&lt;h1 id=&#34;the-mix-own-your-code-present-it-through-codepen&#34;&gt;The mix: own your code, present it through Codepen&lt;/h1&gt;
&lt;p&gt;A page of Codepen docs caught my attention: &lt;a href=&#34;https://blog.codepen.io/documentation/prefill-embeds/&#34;&gt;&amp;ldquo;Prefill Embeds &amp;ldquo;&lt;/a&gt; &lt;em&gt;CodePen Prefill Embeds allow you to enhance code that you are already displaying on your own website and transform it into an interactive environment.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Using them make you rely on Codepen, of course, but you can therefore use all of Codepen fixings (even preprocessing!).&lt;/p&gt;
&lt;p&gt;I created another shortcode as a proof-of-concept, not encompassing all features.
In this case I was able to use &lt;a href=&#34;https://gohugo.io/templates/shortcode-templates/#nested-shortcode-image-gallery&#34;&gt;nested shortcodes&lt;/a&gt;.
In the previous solution I didn&amp;rsquo;t find how I could do that given I needed to use the content of each block on its own and together in the iframe.&lt;/p&gt;
&lt;p&gt;The shortcode expects input like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;{{&amp;lt; prefillembed &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;A title for the pen&amp;#34;&lt;/span&gt; &amp;gt;}}
  {{&amp;lt; pcode css &amp;gt;}}
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// CSS code
&lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;&lt;/span&gt;  {{&amp;lt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;pcode &amp;gt;}}
  
  {{&amp;lt; pcode html &amp;gt;}}
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// HTML code
&lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;&lt;/span&gt;  {{&amp;lt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;pcode &amp;gt;}}
  
  {{&amp;lt; pcode js &amp;gt;}}
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// JS code
&lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;&lt;/span&gt;  {{&amp;lt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;pcode &amp;gt;}}
  
{{&amp;lt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;prefillembed &amp;gt;}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The main shortcode code is quite simple:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;div&lt;/span&gt; 
  &lt;span style=&#34;color:#4070a0&#34;&gt;class&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;codepen&amp;#34;&lt;/span&gt; 
  &lt;span style=&#34;color:#4070a0&#34;&gt;data-prefill&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;{
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;    &amp;#34;title&amp;#34;: &amp;#34;{{ .Get 0 }}&amp;#34;}&amp;#39;&lt;/span&gt;
  &lt;span style=&#34;color:#4070a0&#34;&gt;data-height&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;400&amp;#34;&lt;/span&gt; 
  &lt;span style=&#34;color:#4070a0&#34;&gt;data-theme-id&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#4070a0&#34;&gt;data-default-tab&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;html,result&amp;#34;&lt;/span&gt; 
&amp;gt;
  {{ .Inner }}
&amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;div&lt;/span&gt;&amp;gt;
&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;async&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://static.codepen.io/assets/embed/ei.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The sub-shortcodes are not much more complicated.
An important aspect is the escaping of HTML, that Codepen docs warn about.
I felt quite proud knowing about &lt;code&gt;htmlEscape&lt;/code&gt; but it was not enough, I had to pipe the output into &lt;code&gt;safeHTML&lt;/code&gt; so I was no longer so full of myself after that. 😸&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;pre&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;data-lang&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;{{ .Get 0 }}&amp;#34;&lt;/span&gt;&amp;gt;
  {{ if eq (.Get 0) &amp;#34;html&amp;#34; }}
    {{ .Inner| htmlEscape | safeHTML }}
  {{ else }}
    {{ .Inner }}
  {{ end }}
&amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;pre&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;demo&#34;&gt;Demo&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;{{&amp;lt; prefillembed &amp;quot;My Pen&amp;quot; &amp;gt;}}

  {{&amp;lt; pcode css &amp;gt;}}
  p {
    color: red;
  }
  button {
    background-color: pink;
  }
  {{&amp;lt; /pcode &amp;gt;}}
  
  {{&amp;lt; pcode html &amp;gt;}}
  &amp;lt;p&amp;gt; Some text &amp;lt;/p&amp;gt;
  &amp;lt;button onclick=&amp;quot;getTime()&amp;quot;&amp;gt;What time is it??&amp;lt;/button&amp;gt;
  &amp;lt;p id=&amp;quot;demo&amp;quot;&amp;gt;&amp;lt;/p&amp;gt;
  {{&amp;lt; /pcode &amp;gt;}}
  
  {{&amp;lt; pcode js &amp;gt;}}
  function getTime() {
    document.getElementById(&#39;demo&#39;).innerHTML = Date();
  }
  {{&amp;lt; /pcode &amp;gt;}}
  
{{&amp;lt; /prefillembed &amp;gt;}}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;gives&lt;/p&gt;
&lt;div 
  class=&#34;codepen&#34; 
  data-prefill=&#39;{
    &#34;title&#34;: &#34;My Pen&#34;}&#39;
  data-height=&#34;400&#34; 
  data-theme-id=&#34;1&#34;
  data-default-tab=&#34;html,result&#34; 
&gt;
  

  &lt;pre data-lang=&#34;css&#34;&gt;
  
    
  p {
    color: red;
  }
  button {
    background-color: pink;
  }
  
  
&lt;/pre&gt;
  
  &lt;pre data-lang=&#34;html&#34;&gt;
  
    
  &amp;lt;p&amp;gt; Some text &amp;lt;/p&amp;gt;
  &amp;lt;button onclick=&amp;#34;getTime()&amp;#34;&amp;gt;What time is it??&amp;lt;/button&amp;gt;
  &amp;lt;p id=&amp;#34;demo&amp;#34;&amp;gt;&amp;lt;/p&amp;gt;
  
  
&lt;/pre&gt;
  
  &lt;pre data-lang=&#34;js&#34;&gt;
  
    
  function getTime() {
    document.getElementById(&#39;demo&#39;).innerHTML = Date();
  }
  
  
&lt;/pre&gt;
  

&lt;/div&gt;
&lt;script async src=&#34;https://static.codepen.io/assets/embed/ei.js&#34;&gt;&lt;/script&gt;
&lt;h2 id=&#34;to-dos-1&#34;&gt;To-dos&lt;/h2&gt;
&lt;p&gt;This shortcode could do with more parameterization to allow using &lt;a href=&#34;https://blog.codepen.io/documentation/prefill-embeds/&#34;&gt;all features of Codepen&amp;rsquo;s prefill embeds&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In this post I went over three ways to showcase CSS+JS+HTML snippets with Hugo: adding a custom shortcode for embedding Codepen; creating a custom shortcode thanks to which the code is displayed in highlighted code blocks but also loaded into an iframe; creating a custom shortcode that uses Codepen prefill embeds.
Each approach has its pros and cons depending on whether or not you want to rely on Codepen.
Please don&amp;rsquo;t hesitate to share your alternative approaches or your extensions of my shortcodes!&lt;/p&gt;
&lt;p&gt;Taking a step back, such shortcodes, if much improved, could maybe be shared in &lt;a href=&#34;https://discourse.gohugo.io/t/how-to-use-multi-theme/19413/4&#34;&gt;a Hugo theme&lt;/a&gt; as a developer toolbelt&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;?
Even if copy-pasting shortcodes from someone else&amp;rsquo;s repo, with attribution, works well too. 🙂
It could contain shortcodes for developer websites that use OEmbed (so &lt;a href=&#34;https://meta.stackexchange.com/questions/136277/can-we-support-oembed&#34;&gt;not Stack Overflow&lt;/a&gt;, &lt;a href=&#34;https://stackoverflow.com/a/44893092/5489251&#34;&gt;not GitHub&lt;/a&gt;), and &lt;a href=&#34;https://medium.com/slack-developer-blog/everything-you-ever-wanted-to-know-about-unfurling-but-were-afraid-to-ask-or-how-to-make-your-e64b4bb9254&#34;&gt;unfurling&lt;/a&gt; workarounds for others.
Quite a lot to explore!&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I looked up the &lt;a href=&#34;https://github.com/ladybug-podcast/ladybug-website/blob/master/transcripts/03-blogging-101.md&#34;&gt;episode transcript&lt;/a&gt; to find out which of the hosts said that because I can&amp;rsquo;t recognize their voices (yet?). 😁 &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I am using this term because of &lt;a href=&#34;https://github.com/lockedatapublished/hugo-utilitybelt&#34;&gt;Steph Locke&amp;rsquo;s Hugo utility belt&lt;/a&gt;. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>What to know before you adopt Hugo/blogdown</title>
      <link>https://masalmon.eu/2020/02/29/hugo-maintenance/</link>
      <pubDate>Sat, 29 Feb 2020 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2020/02/29/hugo-maintenance/</guid>
      <description>&lt;p&gt;Fancy (re-)creating your website using Hugo, with or without blogdown?
Feeling &lt;a href=&#34;https://twitter.com/OscarBaruffa/status/1233133764282322945&#34;&gt;a bit anxious&lt;/a&gt;?
This post is aimed at being the Hugo equivalent of &lt;em&gt;&amp;ldquo;What to know before you adopt a pet&amp;rdquo;&lt;/em&gt;.
We shall go through things that can/will break in the future, and what you can do to prevent future pain.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I&amp;rsquo;m writing this post with R users in mind, which means I shall use R analogies and mentioning &lt;code&gt;blogdown&lt;/code&gt;,
but I hope some aspects are generalizable to other potential Hugo adopters.&lt;/em&gt;
&lt;em&gt;Some aspects are specific to deploying your website using git and an online git platform such as GitHub.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;why-hugoblogdown&#34;&gt;Why Hugo/blogdown?&lt;/h1&gt;
&lt;p&gt;If you&amp;rsquo;re reading this you&amp;rsquo;ve probably heard of Hugo somewhere.
It&amp;rsquo;s getting quite popular in the R community thanks to the &lt;code&gt;blogdown&lt;/code&gt; package, whose associated book features an &lt;a href=&#34;https://bookdown.org/yihui/blogdown/static-sites.html&#34;&gt;excellent intro to why Hugo (and &lt;code&gt;blogdown&lt;/code&gt;)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I myself have used Hugo for this website (with a bit of &lt;code&gt;blogdown&lt;/code&gt;) and dived into more details whilst &lt;a href=&#34;https://ropensci.org/technotes/2019/01/09/hugo/&#34;&gt;working on tweaks to the rOpenSci website&lt;/a&gt;.
I really enjoy working with this website generator, partly because it&amp;rsquo;s fast and open-source&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h1 id=&#34;what-can-break-or-evolve&#34;&gt;What can break or evolve?&lt;/h1&gt;
&lt;p&gt;When you have a website created with Hugo, there are two to four main actors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Hugo itself which you could think of as R;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A Hugo &lt;em&gt;theme&lt;/em&gt; which defines the layout and style of your website. You could think of the theme as an R package. Your theme is a folder inside your website folder. You need one, no matter how minimal.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;the other things your website theme might depend on, such as Font Awesome.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;potential fourth actor: your tweaks to the theme which might be your editing an R package source; or maintaining a script/a second package on to of that R package to add some syntactic sugar or so to the existing functions of the package.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So what&amp;rsquo;s going to break and evolve?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Just like R packages need to keep up with changes to R sometimes, Hugo themes need to keep up with Hugo changes. Hugo is a trustworthy framework, that keeps improving, which however means sometimes removing support for some things or ways of doing them. Example: &lt;a href=&#34;https://github.com/yoshiharuyamashita/blackburn/commit/123ebe8bb4fd3708fc51dab42613e6a3a7d37d4c&#34;&gt;this commit to the theme I&amp;rsquo;m using made a small change for making the theme compatible with Hugo&amp;gt;0.57&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Just like R packages need to keep up with changes to their external dependencies (web APIs, data format standard), Hugo themes need to keep with changes to external dependencies (font providers, JS scripts, etc). Example: &lt;a href=&#34;https://github.com/yoshiharuyamashita/blackburn/commit/fef095af788816dbc27f040ca98eee3df6b60c1c&#34;&gt;a commit to the theme I&amp;rsquo;m using that updates the templates to use the new syntax for Font Awesome icons&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Just like R packages often improve with time, Hugo themes evolve. And just as you might like updating packages to get the best new tools, you might like getting the fancy features offered by a new version of your theme. For instance look at &lt;a href=&#34;https://sourcethemes.com/academic/updates/v4.6.0/&#34;&gt;this release notes for some version of Hugo academic theme&lt;/a&gt;: there are bug fixes but also cool improvements!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Just like your taste or needs of R packages in your script might evolve, e.g. you might want to update old scripts to use &lt;code&gt;data.table&lt;/code&gt; instead of &lt;code&gt;dplyr&lt;/code&gt;, you might even want to switch themes!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;how-to-reduce-the-likelihood-of-breakages&#34;&gt;How to reduce the likelihood of breakages?&lt;/h1&gt;
&lt;h2 id=&#34;choose-your-theme-wisely-and-keep-in-touch&#34;&gt;Choose your theme wisely and keep in touch!&lt;/h2&gt;
&lt;p&gt;When choosing a theme i.e. a collection of layouts for your website,
you&amp;rsquo;ll have aesthetics and practicalities in mind.
E.g. if you&amp;rsquo;re a prolific blogger you&amp;rsquo;ll want the posts to be quite prominent.
As the blogdown book mentions, &lt;a href=&#34;https://bookdown.org/yihui/blogdown/themes.html&#34;&gt;also look at the theme&amp;rsquo;s popularity and activity&lt;/a&gt; before adopting it.
This way you can have more trust in the theme&amp;rsquo;s responding to Hugo changes and to bug reports.&lt;/p&gt;
&lt;p&gt;Now, you&amp;rsquo;ll have to know when the theme gets updated. How?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You could go hardcore git and make the theme &lt;a href=&#34;https://git-scm.com/book/en/v2/Git-Tools-Submodules&#34;&gt;a git submodule&lt;/a&gt; of your website repo.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You could &lt;a href=&#34;https://help.github.com/en/github/receiving-notifications-about-activity-on-github/watching-and-unwatching-releases-for-a-repository&#34;&gt;watch i.e. subscribe to the GitHub releases of that theme&lt;/a&gt;, or, if the maintainer(s) use a less formal workflow, watch all activity from that repo.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Any other idea? Maybe involving GitHub Actions, Dependabot, something else?
Maybe just a reminder to have a coffee date with your theme repo once in a while?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;what-if-your-theme-gets-orphaned&#34;&gt;What if your theme gets orphaned?&lt;/h2&gt;
&lt;p&gt;What if you chose your theme wisely but it lost its maintainer(s)?
In that case you&amp;rsquo;ll need to look into adopting it or rolling out your own version, or changing themes.&lt;/p&gt;
&lt;h2 id=&#34;make-well-defined-tweaks-to-the-theme&#34;&gt;Make well-defined tweaks to the theme&lt;/h2&gt;
&lt;p&gt;Although you&amp;rsquo;ve adopted a theme, you&amp;rsquo;ll probably want to personalize it a bit.
If you do so, do it with a good file structure and documentation hygiene!
As &lt;a href=&#34;https://bookdown.org/yihui/blogdown/custom-layouts.html&#34;&gt;very well explained in the &lt;code&gt;blogdown&lt;/code&gt; book&lt;/a&gt;,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;some tweaks are directly supported by the theme via the website config file (think of it as an R function parameters) e.g. adding your name to the homepage rather than Jane Doe&amp;rsquo;s;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;some tweaks require your writing layout files (think of it as writing a wrapper for an R package/re-writing your own version of some functions) e.g. adding some fun sentence to the footer which the original theme doesn&amp;rsquo;t support. In this case you should store your custom layouts, like the fancy footer partial template, in a folder called &lt;code&gt;layouts/&lt;/code&gt; at the root of your website folder; &lt;em&gt;not&lt;/em&gt; in the theme folder. &lt;a href=&#34;https://gohugo.io/templates/lookup-order/&#34;&gt;Hugo will give priority to &lt;code&gt;layouts/&lt;/code&gt; stuff when defined&lt;/a&gt;, to use them on top of theme stuff; and you&amp;rsquo;ll easily see what you changed. Your future self will probably find much joy in your present self&amp;rsquo;s documenting the why and how of your custom layouts in some sort of developer notes. The more custom layouts you write, the greater your future responsability.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;If you define CSS and JS files, they&amp;rsquo;d live in &lt;code&gt;static/&lt;/code&gt; and be referred to in the website config file.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;imho-have-your-content-as-markdown-not-html-files&#34;&gt;IMHO Have your content as Markdown, not html files&lt;/h2&gt;
&lt;p&gt;With &lt;code&gt;blogdown&lt;/code&gt; you can use .Rmd, .RMarkdown or .md as your website source, refer to &lt;a href=&#34;https://bookdown.org/yihui/blogdown/output-format.html&#34;&gt;this exhaustive and clear comparison&lt;/a&gt;.
I am strongly in favour of never using .Rmd in a blogdown site because its output is an html file, not a .markdown/.md file. html files seem less portable to me. I like the idea of being able to take my Markdown content and rather easily move them to a new theme (or even a new framework, like when I migrated this website &lt;a href=&#34;https://bookdown.org/yihui/blogdown/from-jekyll.html&#34;&gt;from Jekyll&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Now, as explained in the table mentioned above, using .RMarkdown/.md has its limitations.
For html widgets I can recommend looking at &lt;a href=&#34;https://www.reconlearn.org/post/tutorial-post-creation.html#html-widgets-plotly-leaflet&#34;&gt;the setup Steph Locke created for the RECON learn website&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;update-your-theme&#34;&gt;Update your theme&lt;/h2&gt;
&lt;p&gt;So if you&amp;rsquo;ve tweaked cleanly, you can update your theme when needed!
If you work with version control, and &lt;a href=&#34;https://happygitwithr.com/&#34;&gt;you probably should&lt;/a&gt;, make a branch and work on the update in that branch.
If you don&amp;rsquo;t, backup your website&amp;rsquo;s current state first.&lt;/p&gt;
&lt;p&gt;To &amp;ldquo;update your theme&amp;rdquo;, you need to replace the theme folder of your website folder with the new theme files.&lt;/p&gt;
&lt;p&gt;You could do update the theme manually, or use &lt;code&gt;blogdown::install_theme()&lt;/code&gt; with &lt;code&gt;force = TRUE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Build your website, look at what needs to be changed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;maybe the config parameter names changed (like an R function which would have renamed one of the parameters);&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;your custom layout might need some work too.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To figure out what needs to be changed, you&amp;rsquo;ll probably want to read the changelog (or commit history) of your theme, and maybe even Hugo changelog.&lt;/p&gt;
&lt;p&gt;Often, changes in your theme, and work needed on your website, won&amp;rsquo;t be dramatic: the theme folder update, maybe one config parameter, a few lines diff in your custom layouts.&lt;/p&gt;
&lt;h2 id=&#34;follow-hugo-news&#34;&gt;Follow Hugo news?&lt;/h2&gt;
&lt;p&gt;If you wrote no custom layouts and use a very well maintained theme, you might never need to keep up with Hugo changes yourself.
However, if you&amp;rsquo;ve written Hugo custom layouts, or strive to become a contributor to your theme, you might want to read &lt;a href=&#34;https://gohugo.io/news/&#34;&gt;Hugo changelogs&lt;/a&gt;, follow &lt;a href=&#34;https://github.com/gohugoio/hugo&#34;&gt;Hugo&amp;rsquo;s source repository&lt;/a&gt;, or &lt;a href=&#34;https://twitter.com/GoHugoIO&#34;&gt;Hugo&amp;rsquo;s Twitter account&lt;/a&gt;, etc.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit in May 2020. After asking on the Hugo forum how to follow Hugo more automatically for websites I (co-)maintain on GitHub, I ended up &lt;a href=&#34;https://discourse.gohugo.io/t/how-to-follow-install-hugo-updates-more-automatically/24950/4&#34;&gt;creating a GitHub Actions workflow&lt;/a&gt; that will look for Hugo updates once a month, and if needed open a PR amending Hugo version in the Netlify config file.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;dont-live-on-the-edge&#34;&gt;Don&amp;rsquo;t live on the edge&lt;/h2&gt;
&lt;p&gt;If you have a workflow on a continuous integration system updating your website every day from an external data source, &lt;a href=&#34;https://www.noamross.net/2019/08/09/a-new-website/&#34;&gt;like Noam Ross&lt;/a&gt; and &lt;a href=&#34;https://www.jimhester.com/&#34;&gt;Jim Hester&lt;/a&gt; do (yes that&amp;rsquo;s a very cool and very fancy setup!), use a specific Hugo version there, don&amp;rsquo;t let the workflow install Hugo&amp;rsquo;s latest version because it could break your website without your noticing.
Update Hugo with intent, after reading a bit and/or testing it doesn&amp;rsquo;t break your website.&lt;/p&gt;
&lt;h2 id=&#34;what-if-i-just-never-update-hugo-or-my-theme&#34;&gt;What if I just never update Hugo or my theme?&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Edit in August 2024: I think pinning Hugo and the theme at a version that works for you is a fantastic idea! You can use &lt;a href=&#34;https://hugodown.r-lib.org/articles/config.html&#34;&gt;hugodown&lt;/a&gt; to pin the Hugo version (and probably blogdown too).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;No, it&amp;rsquo;s not a good solution in my opinion.
Never updating Hugo (neither locally nor on say Netlify) nor your theme probably means your website will still build as it used to.
However, updates to Hugo/themes contain both improvements and &lt;strong&gt;bug fixes&lt;/strong&gt; so it&amp;rsquo;s better to know you&amp;rsquo;ll probably update the tools at least once in a while.&lt;/p&gt;
&lt;h1 id=&#34;quick-fixes-to-bad-news&#34;&gt;Quick fixes to bad news&lt;/h1&gt;
&lt;p&gt;Imagine you made yourself a pretty website to showcase your cool posts and informative slidedecks.
In the meantime, you changed laptops and today Saturday you want to post the link to your talk from last week,
before you head out for a barbecue with friends.
Your laptop doesn&amp;rsquo;t have Hugo installed so you install its latest version using &lt;code&gt;blogdown::install_hugo()&lt;/code&gt;, add your talk page, build the website, look at the preview and&amp;hellip; notice it all looks wonky! Your website is broken!
If you remember the beginning of this post, what happened is probably an update in Hugo breaking your theme version. You&amp;rsquo;ll eventually need to update your theme.&lt;/p&gt;
&lt;p&gt;But you don&amp;rsquo;t have time right now before your barbecue to do that, let alone to learn how to do that if it&amp;rsquo;s the first time, so what can you do apart from not posting your talk content?&lt;/p&gt;
&lt;h2 id=&#34;if-your-site-is-deployed-by-gh-pages&#34;&gt;If your site is deployed by gh-pages&lt;/h2&gt;
&lt;p&gt;I.e. your build your website locally and then push the rendered content to a gh-pages branch of a GitHub repo, you need to retrograde Hugo before doing that. Note that &lt;code&gt;blogdown::install_hugo()&lt;/code&gt; has a &lt;code&gt;version&lt;/code&gt; argument, refer to Hugo changelogs to see what version you had last used.&lt;/p&gt;
&lt;h2 id=&#34;if-your-site-is-deployed-by-netlify&#34;&gt;If your site is deployed by Netlify&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re lucky, you can just push your content, and since the Hugo version of your Netlify&amp;rsquo;s config file hasn&amp;rsquo;t changed, your website will build smoothly. You could make a PR to your own website to get a preview there before merging.&lt;/p&gt;
&lt;h2 id=&#34;later&#34;&gt;Later&lt;/h2&gt;
&lt;p&gt;Eventually, one day soon, get to updating Hugo again, looking at your theme&amp;rsquo;s changes, if needed extracting your tweaks from the theme folder if you made them there (I&amp;rsquo;ve done that, and now I sure stick to using the &lt;code&gt;layouts/&lt;/code&gt; folder as mentioned earlier).
Use some of the tips of the beginning of the post to reduce the likelihood of the scenario happening again.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In this blog post I presented what the maintenance of a Hugo website entails in my experience.
I haven&amp;rsquo;t mentioned other possible sources of breakage that are not specific to Hugo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://ropensci.org/technotes/2019/12/19/urls-tidying/&#34;&gt;URLs in the content getting obsolete&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Your changing deploy workflows (so use your own domain instead of a Netlify&amp;rsquo;s one?);&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Your website source disappearing (so use backups);&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;etc.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Coming back to Hugo, if you encounter problems I&amp;rsquo;d unsurprisingly recommend &lt;a href=&#34;https://gohugo.io/documentation/&#34;&gt;Hugo docs&lt;/a&gt; and &lt;a href=&#34;https://discourse.gohugo.io/&#34;&gt;Hugo forum&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now, if this all sounds overwhelming, I don&amp;rsquo;t think these tech skills are harder than R skills but time is a limited resource so maybe you could outsource some of your website&amp;rsquo;s creating and maintenance.
Maybe you can hire someone, or do a skill swap?&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t hesitate to share your own experience and advice on maintaining Hugo websites!&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Also because I love the font of &lt;a href=&#34;https://gohugo.io/documentation/&#34;&gt;its docs website&lt;/a&gt; and looking at pages full of curly braces. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</description>
    </item>
    
    <item>
      <title>Goodbye, Disqus! Hello, Utterances!</title>
      <link>https://masalmon.eu/2019/10/02/disqus/</link>
      <pubDate>Wed, 02 Oct 2019 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2019/10/02/disqus/</guid>
      <description>&lt;p&gt;Removing Disqus from my blogdown blog had been on my mind for a while,
ever since I saw &lt;a href=&#34;https://twitter.com/hrbrmstr/status/1135915244532822018&#34;&gt;Bob Rudis’ tweet enjoining Noam Ross to &lt;em&gt;not&lt;/em&gt; use
it&lt;/a&gt; for &lt;a href=&#34;https://www.noamross.net/2019/08/09/a-new-website/&#34;&gt;his
brand-new website&lt;/a&gt;.
The same Twitter thread introduced me to
&lt;a href=&#34;https://github.com/utterance/utterances&#34;&gt;Utterances&lt;/a&gt;, a “lightweight
comments widget built on GitHub issues”, which I have at last installed
to my blog in lieu of Disqus. How did I manage to not lose anything of
value? How easy was it to switch tools? Read on to learn more!&lt;/p&gt;
&lt;h1 id=&#34;was-saying-goodbye-to-disqus-hard&#34;&gt;Was saying goodbye to Disqus hard?&lt;/h1&gt;
&lt;p&gt;Removing Disqus was neither emotionally nor technically hard.&lt;/p&gt;
&lt;h2 id=&#34;comments-i-kinda-let-go-of&#34;&gt;Comments I (kinda) let go of&lt;/h2&gt;
&lt;p&gt;To deal with my fear of loss, I &lt;a href=&#34;https://help.disqus.com/en/articles/1717199-importing-exporting#exporting-from-disqus&#34;&gt;exported all the comments to an
XML&lt;/a&gt;.
It means I have a backup, that in theory I could explore within R! I’ll
show some XML wrangling a bit later. The export does contain Disqus
usernames and names which means I’m now responsible for person
identifying information that Disqus collected.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks a lot to commenters in the past system for taking the time to
leave me a note: it helped me keep blogging!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The Disqus XML contains information about&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;posts&lt;/em&gt; that are in fact comments, not &lt;em&gt;blog&lt;/em&gt; posts, along with
their threading information i.e. both whose blog post the comment
was on, and if relevant, which comment the comment is an answer to;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;threads&lt;/em&gt;, one thread per comment but not necessarily one comment
per thread, and potentially more than one thread per blog post. Each
top-level comment is a thread, but a website page with no comment
also gets a thread, obviously empty.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the code below, I shall
&lt;a href=&#34;https://speakerdeck.com/jennybc/data-rectangling-1&#34;&gt;&lt;em&gt;rectangle&lt;/em&gt;&lt;/a&gt; the
information about threads (id, title) and about comments (message,
author name, date, thread id, was it spam, was it deleted) using the
&lt;a href=&#34;https://devguide.ropensci.org/building.html#recommended-scaffolding&#34;&gt;&lt;code&gt;xml2&lt;/code&gt;
package&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;export &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_xml&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/disqus-export.xml&amp;#34;&lt;/span&gt;)
export
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## {xml_document}
## &amp;lt;disqus schemaLocation=&amp;quot;http://disqus.com/api/schemas/1.0/disqus.xsd http://disqus.com/api/schemas/1.0/disqus-internals.xsd&amp;quot; xmlns=&amp;quot;http://disqus.com&amp;quot; xmlns:dsq=&amp;quot;http://disqus.com/disqus-internals&amp;quot; xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&amp;gt;
##  [1] &amp;lt;category dsq:id=&amp;quot;5516420&amp;quot;&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  &amp;lt;title&amp;gt;Ge ...
##  [2] &amp;lt;thread dsq:id=&amp;quot;5169974011&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [3] &amp;lt;thread dsq:id=&amp;quot;5177145143&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [4] &amp;lt;thread dsq:id=&amp;quot;5192091523&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [5] &amp;lt;thread dsq:id=&amp;quot;5490361085&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [6] &amp;lt;thread dsq:id=&amp;quot;5490455492&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [7] &amp;lt;thread dsq:id=&amp;quot;5496622766&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [8] &amp;lt;thread dsq:id=&amp;quot;5496655533&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [9] &amp;lt;thread dsq:id=&amp;quot;5499530252&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [10] &amp;lt;thread dsq:id=&amp;quot;5499566886&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [11] &amp;lt;thread dsq:id=&amp;quot;5503605733&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [12] &amp;lt;thread dsq:id=&amp;quot;5503629818&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [13] &amp;lt;thread dsq:id=&amp;quot;5519522381&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [14] &amp;lt;thread dsq:id=&amp;quot;5521172753&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [15] &amp;lt;thread dsq:id=&amp;quot;5523856167&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [16] &amp;lt;thread dsq:id=&amp;quot;5523862926&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [17] &amp;lt;thread dsq:id=&amp;quot;5544585525&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [18] &amp;lt;thread dsq:id=&amp;quot;5544919490&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [19] &amp;lt;thread dsq:id=&amp;quot;5544919711&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [20] &amp;lt;thread dsq:id=&amp;quot;5544920033&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Explaining how to parse XML is beyond the scope of this blog post, but
let me just mention I used a search engine to answer questions such as
“XPath extract nodes by name”, “xml2 namespace”. I reckon my code could
be more elegant if I knew more XPath.&lt;/p&gt;
&lt;p&gt;Let me start with threads.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# extract nodes corresponding to comments&lt;/span&gt;
threads_nodes &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(export, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;d1:thread&amp;#34;&lt;/span&gt;)
threads_nodes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## {xml_nodeset (283)}
##  [1] &amp;lt;thread dsq:id=&amp;quot;5169974011&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [2] &amp;lt;thread dsq:id=&amp;quot;5177145143&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [3] &amp;lt;thread dsq:id=&amp;quot;5192091523&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [4] &amp;lt;thread dsq:id=&amp;quot;5490361085&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [5] &amp;lt;thread dsq:id=&amp;quot;5490455492&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [6] &amp;lt;thread dsq:id=&amp;quot;5496622766&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [7] &amp;lt;thread dsq:id=&amp;quot;5496655533&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [8] &amp;lt;thread dsq:id=&amp;quot;5499530252&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
##  [9] &amp;lt;thread dsq:id=&amp;quot;5499566886&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [10] &amp;lt;thread dsq:id=&amp;quot;5503605733&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [11] &amp;lt;thread dsq:id=&amp;quot;5503629818&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [12] &amp;lt;thread dsq:id=&amp;quot;5519522381&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [13] &amp;lt;thread dsq:id=&amp;quot;5521172753&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [14] &amp;lt;thread dsq:id=&amp;quot;5523856167&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [15] &amp;lt;thread dsq:id=&amp;quot;5523862926&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [16] &amp;lt;thread dsq:id=&amp;quot;5544585525&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [17] &amp;lt;thread dsq:id=&amp;quot;5544919490&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [18] &amp;lt;thread dsq:id=&amp;quot;5544919711&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [19] &amp;lt;thread dsq:id=&amp;quot;5544920033&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## [20] &amp;lt;thread dsq:id=&amp;quot;5544931944&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;forum&amp;gt;masalmon&amp;lt;/forum&amp;gt;\n  ...
## ...
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# extract interesting information from each node,&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# information that is potentially nested&lt;/span&gt;
threads &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(
  thread_id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_attr&lt;/span&gt;( threads_nodes, 
                              &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;),
  title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_text&lt;/span&gt;(
    xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(threads_nodes, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;d1:title&amp;#34;&lt;/span&gt;)
    ))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now on to comments…&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# extract nodes corresponding to comments&lt;/span&gt;
comments_nodes &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(export, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;d1:post&amp;#34;&lt;/span&gt;) 
comments_nodes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## {xml_nodeset (206)}
##  [1] &amp;lt;post dsq:id=&amp;quot;2916181700&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;La poss ...
##  [2] &amp;lt;post dsq:id=&amp;quot;3118121105&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Great b ...
##  [3] &amp;lt;post dsq:id=&amp;quot;3118236082&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Nice Ma ...
##  [4] &amp;lt;post dsq:id=&amp;quot;3118757895&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Thanks  ...
##  [5] &amp;lt;post dsq:id=&amp;quot;3118758593&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Thanks  ...
##  [6] &amp;lt;post dsq:id=&amp;quot;3118783826&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;I love  ...
##  [7] &amp;lt;post dsq:id=&amp;quot;3118785805&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Thanks! ...
##  [8] &amp;lt;post dsq:id=&amp;quot;3121124991&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Chouett ...
##  [9] &amp;lt;post dsq:id=&amp;quot;3121137475&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Oops qu ...
## [10] &amp;lt;post dsq:id=&amp;quot;3121945521&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;I poste ...
## [11] &amp;lt;post dsq:id=&amp;quot;3122653372&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Another ...
## [12] &amp;lt;post dsq:id=&amp;quot;3122759373&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Thank y ...
## [13] &amp;lt;post dsq:id=&amp;quot;3123851616&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Great s ...
## [14] &amp;lt;post dsq:id=&amp;quot;3126340152&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Once ag ...
## [15] &amp;lt;post dsq:id=&amp;quot;3126343942&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Thank y ...
## [16] &amp;lt;post dsq:id=&amp;quot;3140125477&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;The ide ...
## [17] &amp;lt;post dsq:id=&amp;quot;3140136118&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Thank y ...
## [18] &amp;lt;post dsq:id=&amp;quot;3140161542&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Not rel ...
## [19] &amp;lt;post dsq:id=&amp;quot;3140329480&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;Yes def ...
## [20] &amp;lt;post dsq:id=&amp;quot;3150961786&amp;quot;&amp;gt;\n  &amp;lt;id/&amp;gt;\n  &amp;lt;message&amp;gt;&amp;lt;![CDATA[&amp;lt;p&amp;gt;That&#39;s  ...
## ...
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# extract interesting information from each node,&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# information that is potentially nested&lt;/span&gt;
comments &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(
  thread_id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_attr&lt;/span&gt;(
    xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(comments_nodes, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;d1:thread&amp;#34;&lt;/span&gt;), 
    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;),
  message &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_text&lt;/span&gt;(
    xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(comments_nodes, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;d1:message&amp;#34;&lt;/span&gt;)
    ),
  date &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;  xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_text&lt;/span&gt;(
    xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(comments_nodes, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;d1:createdAt&amp;#34;&lt;/span&gt;)
    ),
  deleted &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_text&lt;/span&gt;(
    xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(comments_nodes, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;d1:isDeleted&amp;#34;&lt;/span&gt;)
    ),
  spam &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_text&lt;/span&gt;(
    xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(comments_nodes, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;d1:isSpam&amp;#34;&lt;/span&gt;)
    ),
  author &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_text&lt;/span&gt;(
    xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(
    xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(comments_nodes, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;d1:author&amp;#34;&lt;/span&gt;), 
    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;d1:name&amp;#34;&lt;/span&gt;)))
  
comments &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(comments,
                          date &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; anytime&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;anydate&lt;/span&gt;(date),
                          deleted &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; deleted &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;,
                          spam &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; spam &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I was then able to join the two tables.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;comments &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(comments, threads,
                             by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;thread_id&amp;#34;&lt;/span&gt;)
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(comments, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;comments.csv&amp;#34;&lt;/span&gt;)

comments[2&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;)]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 11 x 2
##    message                                        title                    
##    &amp;lt;chr&amp;gt;                                          &amp;lt;chr&amp;gt;                    
##  1 &amp;quot;&amp;lt;p&amp;gt;Great blog post, thank you! I really appr… French villages and a so…
##  2 &amp;lt;p&amp;gt;Nice Maëlle!&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;Good, interesting quest… French villages and a so…
##  3 &amp;lt;p&amp;gt;Thanks Nick!&amp;lt;/p&amp;gt;                            French villages and a so…
##  4 &amp;lt;p&amp;gt;Thanks Lisa! Toponomy is quite fascinating… French villages and a so…
##  5 &amp;quot;&amp;lt;p&amp;gt;I love this! I wonder, would it be possib… French villages and a so…
##  6 &amp;lt;p&amp;gt;Thanks! I got a similar question on Twitte… French villages and a so…
##  7 &amp;quot;&amp;lt;p&amp;gt;Chouette! Mais la mer c&#39;est \&amp;quot;sea\&amp;quot;, \&amp;quot;se… French villages and a so…
##  8 &amp;lt;p&amp;gt;Oops quelle faute de frappe idiote, je la … French villages and a so…
##  9 &amp;quot;&amp;lt;p&amp;gt;I posted an update! &amp;lt;a href=\&amp;quot;http://www.… French villages and a so…
## 10 &amp;lt;p&amp;gt;Another good one, Maëlle! It&#39;s a great exa… More water, a bit more a…
## 11 &amp;lt;p&amp;gt;Thank you! Lol on ninja grep skills, I wis… More water, a bit more a…
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I got a pretty nice rectangle in the end, that could be used for some
text analysis, but in my case, I mostly view it as memorabilia. I hope
any comment warranting action had been tackled. I wrote 93
(&lt;code&gt;sum(comments$author == &amp;quot;Maëlle Salmon&amp;quot;)&lt;/code&gt;) out of the 206 comments
(Disqus classified a few comments as spam, 15 to be exact, of which a
few were informative comments. ), because I tend to answer comments, if
only with a simple thank you! Now that I have GitHub issues as comments,
I could also answer with emojis.&lt;/p&gt;
&lt;p&gt;It was fun because I didn’t even remember about some notes I had gotten.
I hope you don’t feel slighted, dear reader, now that I keep these old
comments to myself! Be happy you’re no longer tracked.&lt;/p&gt;
&lt;h2 id=&#34;getting-rid-of-disqus&#34;&gt;Getting rid of Disqus&lt;/h2&gt;
&lt;p&gt;I removed Disqus from my website, and my website from Disqus!&lt;/p&gt;
&lt;p&gt;To remove Disqus from a Hugo website, one can, depending on the
website’s theme:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;use &lt;a href=&#34;https://gohugo.io/about/hugo-and-gdpr/&#34;&gt;Hugo’s Disqus GDPR
setting&lt;/a&gt; if the website
theme uses Hugo’s built-in Disqus template (i.e. if there’s a
mention of a &lt;a href=&#34;https://gohugo.io/templates/internal/#use-the-disqus-template&#34;&gt;internal Disqus
partial&lt;/a&gt;,
not of a Disqus partial stored somewhere in the theme files);&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;or remove one’s Disqus username from the config file, or remove the
Disqus partial mention in the post template. To do that, the best
process is not to edit the e.g. post/single.html file in the theme
folder, but instead to save it and edit it under
layouts/post/single.html. &lt;a href=&#34;https://bookdown.org/yihui/blogdown/custom-layouts.html&#34;&gt;Refer to the blogdown book for more
information&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After that, there should be no mention of Disqus scripts in your website
source.&lt;/p&gt;
&lt;p&gt;Then, to delete my website from my Disqus account, following &lt;a href=&#34;https://help.disqus.com/en/articles/1717289-how-do-i-remove-my-site&#34;&gt;Disqus
guidance&lt;/a&gt;,
I logged into my account and, &lt;em&gt;after exporting my website’s comments&lt;/em&gt;,
confirmed I wanted to do that and voilà!&lt;/p&gt;
&lt;h1 id=&#34;adding-utterances&#34;&gt;Adding Utterances&lt;/h1&gt;
&lt;p&gt;To add Utterances, a “lightweight comments widget built on GitHub
issues”, I also followed &lt;a href=&#34;https://utteranc.es/#configuration&#34;&gt;official
guidance&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I installed the app to my website GitHub repo.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In my custom single.html layout for posts (again, &lt;a href=&#34;https://bookdown.org/yihui/blogdown/custom-layouts.html&#34;&gt;refer to the
blogdown book for clear information on the
topic&lt;/a&gt;), I
added the script tag corresponding to Utterances. The docs linked
above help you configure the appearance of the widget.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s the Utterances script tag for my blog. The label needs to &lt;a href=&#34;https://help.github.com/en/articles/creating-a-label&#34;&gt;have been created for your website repo&lt;/a&gt;, since Utterances can only use existing issue labels.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&amp;lt;&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;script&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;src&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://utteranc.es/client.js&amp;#34;&lt;/span&gt;
        &lt;span style=&#34;color:#4070a0&#34;&gt;repo&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;maelle/simplymaelle&amp;#34;&lt;/span&gt;
        &lt;span style=&#34;color:#4070a0&#34;&gt;issue-term&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;
        &lt;span style=&#34;color:#4070a0&#34;&gt;label&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;comments 💬&amp;#34;&lt;/span&gt;
        &lt;span style=&#34;color:#4070a0&#34;&gt;theme&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;github-light&amp;#34;&lt;/span&gt;
        &lt;span style=&#34;color:#4070a0&#34;&gt;crossorigin&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;anonymous&amp;#34;&lt;/span&gt;
        &lt;span style=&#34;color:#4070a0&#34;&gt;async&lt;/span&gt;&amp;gt;
&amp;lt;/&lt;span style=&#34;color:#062873;font-weight:bold&#34;&gt;script&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then wrote a comment under &lt;a href=&#34;https://masalmon.eu/2019/01/25/uptodate/&#34;&gt;one of my
posts&lt;/a&gt; to make sure things
worked. I also took a few seconds to &lt;a href=&#34;https://utteranc.es/#sites-using-utterances&#34;&gt;add my site to the list of sites
using Utterances&lt;/a&gt;. Overall,
I found the process easy, as I had the first time I installed Utterances
&lt;a href=&#34;https://blog.r-hub.io/&#34;&gt;on a blogdown website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I am aware that a downside of Utterances is that it is tied to GitHub.
However, I am not afraid of switching to yet another tool in the future,
and hope not too many potential commenters will be turned off by the
necessity to use a GitHub account to comment.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In this post I explained how I removed Disqus from my blog and vice
versa, and how I installed Utterances instead. What I did not do was
analyzing the Disqus data. I moreover did not try to &lt;em&gt;transfer&lt;/em&gt; old
comments to the new system, partly because that’d mean removing
commenters’ ownership on what they had written.&lt;/p&gt;
&lt;p&gt;In &lt;a href=&#34;https://twitter.com/hrbrmstr/status/1135915244532822018&#34;&gt;his tweet that motivated me to say goodbye to
Disqus&lt;/a&gt;, Bob
wrote &lt;em&gt;“Yet another service where you and your site visitors are the
product. Plus it acts like malicious javascript.”&lt;/em&gt;. I therefore feel a
bit better about this website! Now, I didn’t have a ton of comments, and
I don’t have a real need for moderating comments, so maybe you’ll make a
different decision for your website. I’d be glad to hear about it… in
the comments section below! Also feel free to tell me if you explore
your own Disqus data in a more thorough way than I!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>How did Axios rectangle Trump&#39;s PDF schedule? A try with R</title>
      <link>https://masalmon.eu/2019/02/11/trump-schedule/</link>
      <pubDate>Mon, 11 Feb 2019 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2019/02/11/trump-schedule/</guid>
      <description>&lt;p&gt;Last week, &lt;a href=&#34;https://www.axios.com/donald-trump-private-schedules-leak-executive-time-34e67fbb-3af6-48df-aefb-52e02c334255.html&#34;&gt;Axios published a very interesting piece reporting on
Trump’s private schedule thanks to an insider’s
leak&lt;/a&gt;.
The headlines all were about Trump’s spending more than 60% of his time
in “executive time” which admittedly was indeed the most important
aspect of the story. I, however, also got curious about Axios’ work to
go from the PDF schedules to the spreadsheet they made public. In this
post, I’ll have a got at using rOpenSci’s Jeroen Ooms’ &lt;code&gt;pdftools&lt;/code&gt;
package and some data-wrangling stubborness of mine to try and rectangle
Trump’s PDF schedules.&lt;/p&gt;
&lt;h1 id=&#34;available-data-available-software&#34;&gt;Available data, available software&lt;/h1&gt;
&lt;p&gt;Axios published both &lt;a href=&#34;https://docs.google.com/spreadsheets/d/1oITCuVsYdhNXtY7GElLelsrbjRRIPJ1ce-_v-8J1X_A/edit#gid=0&#34;&gt;the spreadsheet they made from the data
leaked&lt;/a&gt;,
and PDF corresponding to the schedules retyped in the format White House
staff received them. I tried finding out how they went from the latter
to the former, but this was apparently not reported. Quite a niche
topic, I agree. Here’s the untidy PDF below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;pdf_file &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/Axios-President-Donald-Trump-Private-Schedules.pdf&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
pdftools&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pdf_render_page&lt;/span&gt;(pdf_file, page &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2019-02-11-trump-schedule/ex1-1.png&#34; width=&#34;612&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Seeing the PDF format above reminded me of &lt;a href=&#34;https://ropensci.org/technotes/2018/12/14/pdftools-20/&#34;&gt;the cool new &lt;code&gt;pdftools&lt;/code&gt;
feature Jeroen Ooms announced back in
December&lt;/a&gt;: low
level text extraction.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# High level text extraction&lt;/span&gt;
pdftools&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pdf_text&lt;/span&gt;(pdf_file)[1]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;                       SCHEDULE OF THE PRESIDENT\n                          Wednesday, November 7, 2018\n8:00 AM        EXECUTIVE TIME\n(3 hr)         Location:           Oval Office\n11:00 AM       MEETING WITH THE CHIEF OF STAFF\n(30 min)       Location:           Oval Office\n11:30 AM       EXECUTIVE TIME\n(1 hr)         Location:           Oval Office\n12:30 PM       LUNCH\n(1 hr)         Location:           Private Dining Room\n1:30 PM        EXECUTIVE TIME\n(3 hr, 30 min) Location:           Oval Office\nRON:           The White House\n&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Low level text extraction&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(pdftools&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pdf_data&lt;/span&gt;(pdf_file)[[1]])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;##   width height   x  y space       text
## 1    60     12 220 72  TRUE   SCHEDULE
## 2    15     12 283 72  TRUE         OF
## 3    23     12 301 72  TRUE        THE
## 4    62     12 327 72 FALSE  PRESIDENT
## 5    54     12 236 99  TRUE Wednesday,
## 6    46     12 293 99  TRUE   November
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While the &lt;code&gt;pdftools::pdf_text()&lt;/code&gt; function returns “a character vector of
length equal to the number of pages in the file”, &lt;code&gt;pdftools::pdf_data&lt;/code&gt;
returns a list of as many &lt;code&gt;data.frame&lt;/code&gt;’s as there are pages, each one
indicating the coordinates and width of each text piece. So powerful!
Trump’s schedule appeared to be a perfect use case for this
functionality!&lt;/p&gt;
&lt;h2 id=&#34;special-tale-for-ubuntu-users&#34;&gt;Special tale for Ubuntu users&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Edit: &lt;a href=&#34;https://www.benjaminlouis-stat.fr/&#34;&gt;Benjamin Louis&lt;/a&gt; posted a link to &lt;a href=&#34;https://askubuntu.com/questions/1112856/how-to-install-poppler-0-73-on-ubuntu-18-04/1112947#1112947&#34;&gt;a helpful thread about installing Poppler&amp;rsquo;s latest version and &lt;code&gt;pdftools&lt;/code&gt; on Ubuntu 18.04&lt;/a&gt; in the comments. Thank you!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Sadly, as noted in Jeroen’s tech note, the new Poppler version that is
necessary for &lt;code&gt;pdftools&lt;/code&gt; to support low level text extraction… is not
available on Linux yet, and I’ve just switched to Ubuntu from Windows
(an accidental New Year’s resolution after Windows disappeared from my
laptop). Jeroen wrote “Linux users probably have to wait for the latest
version of poppler to become available in their system package manager
(or compile from source).”. I thought, OK, let me &lt;em&gt;just&lt;/em&gt; compile Poppler
from source then. I’m not sure I’d recommend trying this at home so take
my experience report with a bit of caution. I downloaded &lt;a href=&#34;https://poppler.freedesktop.org/#Download&#34;&gt;Poppler’s
latest version&lt;/a&gt;, unzipped it,
created a &lt;code&gt;build&lt;/code&gt; folder inside the poppler folder and ran something
like this (inspired by &lt;a href=&#34;https://gist.github.com/Dayjo/618794d4ff37bb82ddfb02c63b450a81&#34;&gt;this
gist&lt;/a&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cmake ..
make
sudo make install
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It seemed to work but then re-installing &lt;code&gt;pdftools&lt;/code&gt; failed. Jeroen
thankfully advised me to remove my old Poppler installation with a
drastic command that affected all softwares depending on Poppler (that’s
why you might not want to reproduce this at home) like GIMP or Libre
Office Writer: &lt;code&gt;sudo apt-get remove libpoppler*&lt;/code&gt;. But, after I did that,
I was able to install &lt;code&gt;pdftools&lt;/code&gt; using the newest Poppler version.&lt;/p&gt;
&lt;h1 id=&#34;general-strategy&#34;&gt;General strategy&lt;/h1&gt;
&lt;p&gt;I started work by carefully looking at the PDF. There were one-page
daily schedules like on page 1,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;pdftools&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pdf_render_page&lt;/span&gt;(pdf_file, page &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2019-02-11-trump-schedule/ex1bis-1.png&#34; width=&#34;612&#34; /&gt;&lt;/p&gt;
&lt;p&gt;but also schedules continued on several pages,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;pdftools&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pdf_render_page&lt;/span&gt;(pdf_file, page &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2019-02-11-trump-schedule/ex2-1.png&#34; width=&#34;612&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Because of that, I decided to extract the dates of pages that had one,
then assign to each undated page the latest available date, before
splitting the PDF low level text data into dates and working on a
pipeline by date.&lt;/p&gt;
&lt;h2 id=&#34;splitting-the-low-level-text-data-by-date&#34;&gt;Splitting the low level text data by date&lt;/h2&gt;
&lt;p&gt;In a first step, I wrote a pipeline adding the page number to each
&lt;code&gt;data.frame&lt;/code&gt; from &lt;code&gt;pdftools::pdf_data()&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;pdf_data &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pdftools&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pdf_data&lt;/span&gt;(pdf_file)

read_page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(page, pdf_data){
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pdf_data[[page]]
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(df) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;) {
    df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; page
    df
  } else {
    &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
  }
}

pdf_text &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;pdftools&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pdf_info&lt;/span&gt;(pdf_file)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;pages,
                       read_page,
                       pdf_data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; pdf_data)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# remove empty pages&lt;/span&gt;
pdf_text &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;discard&lt;/span&gt;(pdf_text, is.null)

&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(pdf_text[[1]])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;##   width height   x  y space       text page
## 1    60     12 220 72  TRUE   SCHEDULE    1
## 2    15     12 283 72  TRUE         OF    1
## 3    23     12 301 72  TRUE        THE    1
## 4    62     12 327 72 FALSE  PRESIDENT    1
## 5    54     12 236 99  TRUE Wednesday,    1
## 6    46     12 293 99  TRUE   November    1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then for each of them I tried extracting the date.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;get_date &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(page_data){
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(page_data&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text[[1]] &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;SCHEDULE&amp;#34;&lt;/span&gt;){
    date &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(
      glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue_collapse&lt;/span&gt;(page_data&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text[6&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;8&lt;/span&gt;],
                          sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;))
    date &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;parse_date_time&lt;/span&gt;(date, 
                                       orders &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;BdY&amp;#34;&lt;/span&gt;, 
                                       locale &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;en_US.utf8&amp;#34;&lt;/span&gt;, tz &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;EST&amp;#34;&lt;/span&gt;)
    date &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.Date&lt;/span&gt;(date)
  }else{
    date &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;
  }
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(date &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; date,
                 page &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; page_data&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;page[1])
}

dates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(pdf_text, get_date)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, I created a gigantic &lt;code&gt;data.frame&lt;/code&gt; of all the &lt;code&gt;data.frame&lt;/code&gt;’s
from &lt;code&gt;pdftools::pdf_text()&lt;/code&gt;, sorted it by page just to be sure it was
sorted by page, assigned to each row the latest non missing page, and
then split the data by date which was a better unit to work from. In
order to not mess up coordinates, within each date I added 700, 1400,
etc. to y-coordinates from the second, third, etc. page.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;split_days &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(pdf_text, dates){
  pdf_text &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(dates, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;page&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(page) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(date &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; zoo&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;na.locf&lt;/span&gt;(date)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(date) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; y &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; (page &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(page)) &lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;700&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;split&lt;/span&gt;(.$date)
}
  
pdf_text &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;split_days&lt;/span&gt;(pdf_text, dates)

&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(pdf_text)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] 50
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;pdf_text[[2]]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 243 x 8
##    width height     x     y space text       page date      
##    &amp;lt;int&amp;gt;  &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;lgl&amp;gt; &amp;lt;chr&amp;gt;     &amp;lt;int&amp;gt; &amp;lt;date&amp;gt;    
##  1    60     12   220    72 TRUE  SCHEDULE      2 2018-11-08
##  2    15     12   283    72 TRUE  OF            2 2018-11-08
##  3    23     12   301    72 TRUE  THE           2 2018-11-08
##  4    62     12   327    72 FALSE PRESIDENT     2 2018-11-08
##  5    44     12   240    99 TRUE  Thursday,     2 2018-11-08
##  6    46     12   287    99 TRUE  November      2 2018-11-08
##  7     8     12   336    99 TRUE  8,            2 2018-11-08
##  8    21     12   347    99 FALSE 2018          2 2018-11-08
##  9    19     12    72   140 TRUE  8:00          2 2018-11-08
## 10    17     12    94   140 FALSE AM            2 2018-11-08
## # … with 233 more rows
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tail&lt;/span&gt;(pdf_text[[2]])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 6 x 8
##   width height     x     y space text         page date      
##   &amp;lt;int&amp;gt;  &amp;lt;int&amp;gt; &amp;lt;int&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;lgl&amp;gt; &amp;lt;chr&amp;gt;       &amp;lt;int&amp;gt; &amp;lt;date&amp;gt;    
## 1    28     12   229  1069 FALSE House           3 2018-11-08
## 2    51     12   288   799 TRUE  Christopher     3 2018-11-08
## 3    31     12   342   799 FALSE Liddell         3 2018-11-08
## 4    30     12   288   813 FALSE Closed          3 2018-11-08
## 5    21     12   288   826 TRUE  Oval            3 2018-11-08
## 6    28     12   312   826 FALSE Office          3 2018-11-08
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At that point I took a minute to compare the dates I had with the ones
in Axios’ clean data.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;clean_data &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/axios_data.csv&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(clean_data&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;date[&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;clean_data&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;date &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; dates&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;date])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;##  [1] &amp;quot;2018-11-12&amp;quot; &amp;quot;2018-11-16&amp;quot; &amp;quot;2018-11-20&amp;quot; &amp;quot;2018-11-21&amp;quot; &amp;quot;2018-11-22&amp;quot;
##  [6] &amp;quot;2018-12-06&amp;quot; &amp;quot;2018-12-24&amp;quot; &amp;quot;2018-12-25&amp;quot; &amp;quot;2018-12-26&amp;quot; &amp;quot;2018-12-27&amp;quot;
## [11] &amp;quot;2018-12-28&amp;quot; &amp;quot;2018-12-31&amp;quot; &amp;quot;2019-01-01&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wat?! I had a look at the PDF, and actually, these dates are not even in
the PDF I’m fighting, so no need for me to try and revise my R script.&lt;/p&gt;
&lt;h2 id=&#34;digesting-each-dates-data&#34;&gt;Digesting each date’s data&lt;/h2&gt;
&lt;p&gt;This part was the most crucial, and difficult one. I wanted to obtain a
table with one line by event. My strategy was to first extract times by
filtering text data whose x-coordinate was in an interval I had decided
on by looking at some pages, clean these times to obtain time, duration
and y-coordinate of the top of the time info, and then assign words from
the right of the page to each event thanks to fuzzy joins: words
correspond to an event if their y-coordinate is between the y-coordinate
of the time of that event and the y-coordinate of next event.&lt;/p&gt;
&lt;p&gt;On top of that I had to decide what to do with pages with times in
several timezones, like below&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;pdftools&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pdf_render_page&lt;/span&gt;(pdf_file, page &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;13&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2019-02-11-trump-schedule/tz-1.png&#34; width=&#34;612&#34; /&gt;&lt;/p&gt;
&lt;p&gt;I simply removed all times that where in parentheses, assumed a time
with no timezone information had the same timezone as the last event
with a timezone, and that the first event of the day, if lacking a
timezone, was in EST. In real life if I were really working on such data
I’d probably still make such a general assumption but then review the
result page by page, preferably with several pairs of eyes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;get_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(page_data){
  times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(page_data,
                         dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;between&lt;/span&gt;(x, &lt;span style=&#34;color:#40a070&#34;&gt;72&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;117&lt;/span&gt;))
  rest &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(page_data,
                        &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;between&lt;/span&gt;(x, &lt;span style=&#34;color:#40a070&#34;&gt;72&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;117&lt;/span&gt;))
  
  times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; times &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(y) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue_collapse&lt;/span&gt;(text, sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;))
  
  times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(times,
                         &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\(&amp;#34;&lt;/span&gt;, text)&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;M&amp;#34;&lt;/span&gt;, text)))
  clean_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(times,
                               time &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;if_else&lt;/span&gt;(
                                 &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;M&amp;#34;&lt;/span&gt;, text)&lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;RON&amp;#34;&lt;/span&gt;, text),
                                 text,
                                 &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;),
                               duration &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;if_else&lt;/span&gt;(
                                 &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\(&amp;#34;&lt;/span&gt;, dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;lead&lt;/span&gt;(text)),
                                       dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;lead&lt;/span&gt;(text),
                                       &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
                               )
  clean_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(clean_times, time &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  clean_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(clean_times, y, time, duration)
  clean_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(clean_times,
                               timezone &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.*\\:.*M &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, time), 
                               timezone &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(timezone &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; time,
                                                 &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;, timezone))
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(clean_times&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;timezone[1])){
    clean_times&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;timezone[1] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;EST&amp;#34;&lt;/span&gt;
  }
  clean_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(clean_times,
                               timezone &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; zoo&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;na.locf&lt;/span&gt;(timezone))
  
  clean_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(clean_times,
                               timezone &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(timezone),
                               timezone &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,timezone),
                               time &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;M.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;M&amp;#34;&lt;/span&gt;, time))
  
  clean_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(clean_times,
                               start &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; y, 
                               end &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;lead&lt;/span&gt;(y) &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; start,
                                            dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;lead&lt;/span&gt;(y) &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, start), 
                               end &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(end),
                                            &lt;span style=&#34;color:#40a070&#34;&gt;99999&lt;/span&gt;, end))
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(clean_times) &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;){
    &lt;span style=&#34;color:#06287e&#34;&gt;print&lt;/span&gt;(page_data&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;date[1])
    &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;)
  }
  
  rest &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rest,
                        start &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; y, end &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; y)
  
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; fuzzyjoin&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;interval_left_join&lt;/span&gt;(clean_times,
                                      rest,
                                      by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;start&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;end&amp;#34;&lt;/span&gt;))
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(df, time, duration, timezone, x, y.y, text)
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rename&lt;/span&gt;(df, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; y.y)
  
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; df &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(time, duration, timezone) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(event &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(
      glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue_collapse&lt;/span&gt;(text[y &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(y)], sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;))) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(time, duration, timezone, y, event) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(
      glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue_collapse&lt;/span&gt;(text, sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;)
    )) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(time, duration, timezone, event) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;toupper&lt;/span&gt;(event) &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; event,
                                &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(
                                  glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue_collapse&lt;/span&gt;(text, sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;)
                                ), text)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;()
  
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(df) &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;){
    df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(event &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(
      glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue_collapse&lt;/span&gt;(page_data&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text, sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;)
    ))
  }
  
  df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;date &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; page_data&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;date[1]
  df
}

all_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(pdf_text,
                            get_times)

&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(all_events)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 6 x 7
##   time    duration    timezone     y event         text          date      
##   &amp;lt;chr&amp;gt;   &amp;lt;chr&amp;gt;       &amp;lt;chr&amp;gt;    &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;         &amp;lt;chr&amp;gt;         &amp;lt;date&amp;gt;    
## 1 1:30 PM (3 hr, 30 … EST        302 EXECUTIVE TI… EXECUTIVE TI… 2018-11-07
## 2 1:30 PM (3 hr, 30 … EST        315 EXECUTIVE TI… Location: Ov… 2018-11-07
## 3 11:00 … (30 min)    EST        180 MEETING WITH… MEETING WITH… 2018-11-07
## 4 11:00 … (30 min)    EST        194 MEETING WITH… Location: Ov… 2018-11-07
## 5 11:30 … (1 hr)      EST        221 EXECUTIVE TI… EXECUTIVE TI… 2018-11-07
## 6 11:30 … (1 hr)      EST        234 EXECUTIVE TI… Location: Ov… 2018-11-07
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;cleaning-each-event&#34;&gt;Cleaning each event&lt;/h2&gt;
&lt;p&gt;At that point I was fairly happy but I knew that a code review would
have been great in real life, and that in any case I needed more work. I
wanted to have a duration in minutes for each event as well as a start
and end as times, and I wanted each event’s info to be in a single row.&lt;/p&gt;
&lt;p&gt;I first made each event a row.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;gather_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(all_events){
    all_events &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(event, text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(clean_text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(event[1], &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, text))) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rename&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; clean_text)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# events with no text&lt;/span&gt;
  no_text_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; all_events &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(time, duration, 
                    timezone, date) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;all&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nzchar&lt;/span&gt;(text))) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(event &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(event),
                     text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;,
                     y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(y))
  
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# events with text&lt;/span&gt;
  text_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; all_events  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(time, duration, 
                    timezone, date) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;any&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;nzchar&lt;/span&gt;(text))) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;nzchar&lt;/span&gt;(text)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(y),&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#y gives us the *certain* order of events in a day&lt;/span&gt;
                     event &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(text[&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\:&amp;#34;&lt;/span&gt;, text)]) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,
                                    &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(
                                 glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue_collapse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(event, text[&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\:&amp;#34;&lt;/span&gt;, text)&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;text&lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt;event]))), sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;),
                       event),
                     text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(text&lt;span style=&#34;color:#06287e&#34;&gt;[grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\:&amp;#34;&lt;/span&gt;, text)]) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,
                                   &lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(text&lt;span style=&#34;color:#06287e&#34;&gt;[grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\:&amp;#34;&lt;/span&gt;, text)]),
                                   &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
  all_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(no_text_events, text_events)
  all_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;(all_events)
  all_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(all_events, date, y)
  all_events
}
all_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gather_events&lt;/span&gt;(all_events)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Before binding the events with text and no text I had checked by had
that no events got lost (using &lt;code&gt;dplyr::n_groups()&lt;/code&gt;).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(all_events)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 6 x 7
##   time    duration   timezone date       event          text              y
##   &amp;lt;chr&amp;gt;   &amp;lt;chr&amp;gt;      &amp;lt;chr&amp;gt;    &amp;lt;date&amp;gt;     &amp;lt;chr&amp;gt;          &amp;lt;chr&amp;gt;         &amp;lt;dbl&amp;gt;
## 1 8:00 AM (3 hr)     EST      2018-11-07 EXECUTIVE TIME Location: Ov…   140
## 2 11:00 … (30 min)   EST      2018-11-07 MEETING WITH … Location: Ov…   180
## 3 11:30 … (1 hr)     EST      2018-11-07 EXECUTIVE TIME Location: Ov…   221
## 4 12:30 … (1 hr)     EST      2018-11-07 LUNCH          Location: Pr…   261
## 5 1:30 PM (3 hr, 30… EST      2018-11-07 EXECUTIVE TIME Location: Ov…   302
## 6 RON:    &amp;quot;&amp;quot;         EST      2018-11-07 The White Hou… &amp;quot;&amp;quot;              342
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(all_events&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Location: Oval Office&amp;quot;         &amp;quot;Location: Oval Office&amp;quot;        
## [3] &amp;quot;Location: Oval Office&amp;quot;         &amp;quot;Location: Private Dining Room&amp;quot;
## [5] &amp;quot;Location: Oval Office&amp;quot;         &amp;quot;&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Further work aimed at extracting “Location”, “Note”, etc. into specific
columns. This code is especially ugly.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;extract_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(all_events){
  all_events &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(time, duration, timezone, date, event, y) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(location &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;any&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Location&amp;#34;&lt;/span&gt;, 
                                                        &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;)))),
                                  &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Location\\: &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, 
                                       &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;))&lt;span style=&#34;color:#06287e&#34;&gt;[grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Location&amp;#34;&lt;/span&gt;, 
                                                        &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;)))]),
                                  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;),
                project_officer &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;any&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Project Officer&amp;#34;&lt;/span&gt;, 
                                                        &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;)))),
                                  &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Project Officer\\: &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, 
                                       &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;))&lt;span style=&#34;color:#06287e&#34;&gt;[grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Project Officer&amp;#34;&lt;/span&gt;, 
                                                        &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;)))]),
                                  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;),
                press &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;any&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Press&amp;#34;&lt;/span&gt;, 
                                                        &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;)))),
                                  &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Press\\: &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, 
                                       &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;))&lt;span style=&#34;color:#06287e&#34;&gt;[grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Press&amp;#34;&lt;/span&gt;, 
                                                        &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;)))]),
                                  &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(location &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(location),
                project_officer &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(project_officer),
                press &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(press))
}
  
all_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;extract_info&lt;/span&gt;(all_events)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At this point, again, in a real work environment I’d spend time checking
data carefuly, but instead, I’ll just have a rough look at the clean
data vs my own cleaned data.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(clean_data, listed_project_officer, sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 39 x 2
##    listed_project_officer     n
##    &amp;lt;chr&amp;gt;                  &amp;lt;int&amp;gt;
##  1 &amp;lt;NA&amp;gt;                     369
##  2 Ambassador John Bolton    33
##  3 Sarah Sanders             25
##  4 Lindsay Reynolds          18
##  5 Shahira Knight            18
##  6 William McGinley          18
##  7 Christopher Liddell       13
##  8 John DeStefano            10
##  9 Mercedes Schlapp           9
## 10 Tim Pataki                 7
## # … with 29 more rows
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(all_events, &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(project_officer), sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 32 x 2
##    `trimws(project_officer)`     n
##    &amp;lt;chr&amp;gt;                     &amp;lt;int&amp;gt;
##  1 &amp;lt;NA&amp;gt;                        467
##  2 Ambassador John Bolton       32
##  3 Sarah Sanders                23
##  4 Shahira Knight               18
##  5 William McGinley             16
##  6 Lindsay Reynolds             15
##  7 Christopher Liddell          13
##  8 John DeStefano               10
##  9 Mercedes Schlapp              9
## 10 Tim Pataki                    7
## # … with 22 more rows
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(clean_data, listed_location, sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 36 x 2
##    listed_location             n
##    &amp;lt;chr&amp;gt;                   &amp;lt;int&amp;gt;
##  1 Oval office               310
##  2 &amp;lt;NA&amp;gt;                       75
##  3 Oval Office                48
##  4 Private dining room        34
##  5 Buenos Aires, Argentina    21
##  6 oval office                 9
##  7 Grand foyer                 7
##  8 Roosevelt room              6
##  9 Cabinet Room                5
## 10 East Room                   5
## # … with 26 more rows
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(all_events, &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(location), sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 34 x 2
##    `trimws(location)`            n
##    &amp;lt;chr&amp;gt;                     &amp;lt;int&amp;gt;
##  1 Oval Office                 377
##  2 &amp;lt;NA&amp;gt;                        151
##  3 Private Dining Room          35
##  4 Buenos Aires                 18
##  5 Grand Foyer                   8
##  6 Cabinet Room                  7
##  7 Roosevelt Room                7
##  8 Biloxi                        4
##  9 Diplomatic Reception Room     4
## 10 McAllen                       4
## # … with 24 more rows
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I surprisingly have &lt;em&gt;more&lt;/em&gt; events in my data than in Axios’ clean data,
which would require further exploration. Part of that might be due to my
data listing “RON” as events, where RON means “Remainder of the Night”
which is not an event, but a way to indicate where the President spent
the rest of his time on that day. On one day, the whole schedule is
actually “RON”.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(all_events, date &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2018-11-23&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 1 x 10
##   time  duration timezone date       event text      y location
##   &amp;lt;chr&amp;gt; &amp;lt;chr&amp;gt;    &amp;lt;chr&amp;gt;    &amp;lt;date&amp;gt;     &amp;lt;chr&amp;gt; &amp;lt;chr&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;   
## 1 RON:  &amp;quot;&amp;quot;       EST      2018-11-23 Mar-… &amp;quot;&amp;quot;      180 &amp;lt;NA&amp;gt;    
## # … with 2 more variables: project_officer &amp;lt;chr&amp;gt;, press &amp;lt;chr&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For some reasons, in its clean data Axios classified that day as
executive time, although the PDF does not indicate anything about it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(clean_data, date &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2018-11-23&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 1 x 11
##    week date       time_start time_end duration listed_title top_category
##   &amp;lt;dbl&amp;gt; &amp;lt;date&amp;gt;     &amp;lt;time&amp;gt;     &amp;lt;time&amp;gt;      &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;        &amp;lt;chr&amp;gt;       
## 1     3 2018-11-23 08:00      17:00           9 Executive t… executive_t…
## # … with 4 more variables: listed_location &amp;lt;chr&amp;gt;,
## #   listed_project_officer &amp;lt;chr&amp;gt;, detail_category &amp;lt;chr&amp;gt;, notes &amp;lt;chr&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I then had a go at cleaning times and durations.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;clean_time_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(all_events){
  all_events &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(start &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;parse_date_time&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(date, time),
                                                   orders &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Ymd HM p&amp;#34;&lt;/span&gt;, 
                                                   locale &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;en_US.utf8&amp;#34;&lt;/span&gt;, tz &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;EST&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(duration &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\(&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, duration),
                            duration &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\)&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, duration)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(hours &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hr&amp;#34;&lt;/span&gt;, duration),
                               &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hr.*$&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, duration))),
                               &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;),
                minutes &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;min&amp;#34;&lt;/span&gt;, duration),
                               &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_remove&lt;/span&gt;(
                                 &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;^.*\\,&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, duration),
                                 &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;min&amp;#34;&lt;/span&gt;))),
                               &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(duration &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;hours &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; minutes) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; hours, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; minutes) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(date) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(end &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(duration),
                             &lt;span style=&#34;color:#06287e&#34;&gt;as.POSIXct&lt;/span&gt;(dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;lead&lt;/span&gt;(start),
                                        origin &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;1970-01-01&amp;#34;&lt;/span&gt;),
                             &lt;span style=&#34;color:#06287e&#34;&gt;as.POSIXct&lt;/span&gt;(start &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;minutes&lt;/span&gt;(duration),
                                        origin &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;1970-01-01&amp;#34;&lt;/span&gt;)))
}
  
all_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;clean_time_info&lt;/span&gt;(all_events)
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(all_events)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 6 x 12
## # Groups:   date [1]
##   time  duration timezone date       event text      y location
##   &amp;lt;chr&amp;gt;    &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;    &amp;lt;date&amp;gt;     &amp;lt;chr&amp;gt; &amp;lt;chr&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;   
## 1 8:00…      180 EST      2018-11-07 EXEC… Loca…   140 Oval Of…
## 2 11:0…       30 EST      2018-11-07 MEET… Loca…   180 Oval Of…
## 3 11:3…       60 EST      2018-11-07 EXEC… Loca…   221 Oval Of…
## 4 12:3…       60 EST      2018-11-07 LUNCH Loca…   261 Private…
## 5 1:30…      210 EST      2018-11-07 EXEC… Loca…   302 Oval Of…
## 6 RON:         0 EST      2018-11-07 The … &amp;quot;&amp;quot;      342 &amp;lt;NA&amp;gt;    
## # … with 4 more variables: project_officer &amp;lt;chr&amp;gt;, press &amp;lt;chr&amp;gt;,
## #   start &amp;lt;dttm&amp;gt;, end &amp;lt;dbl&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I stopped there, not willing to further work on the data. More work on
timezones, and on filling missing durations based on context, would be
useful. I’d be delighted to see someone cleaning the dataset more
thoroughly than I did here!&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In this post I took advantage of the nifty &lt;code&gt;pdftools::pdf_data()&lt;/code&gt;
function to extract text from Trump’s PDF schedule along with
coordinates, in the hope to be able to rectangle the data. Part of that
went well in particular thanks to &lt;code&gt;fuzzyjoin&lt;/code&gt; and Tidyverse tooling,
part of that went less well, in particular due to the inexact data
formatting and less than optimal indication of timezones… and my not
desiring to spend my week cleaning the data. I have no idea how Axios
prepared the dataset, but if I were to clean such data for actual work,
after scripting as much as possible I’d request at least one colleague
to review the code, and this person and I would also sample a few if not
all events and compare their information in the PDF and the resulting
data.&lt;/p&gt;
&lt;p&gt;The advantage of scripting at least part of the cleaning is
reproducibility, for being able to explain what happened to the data,
but also to apply the code to new data. This morning I read that &lt;a href=&#34;https://www.axios.com/trump-schedule-leaks-4840f751-e663-49c0-b288-2dd39bde9c79.html&#34;&gt;more
schedules had been
leaked&lt;/a&gt;
so I tried my code on it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;pdf_file2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/newschedules.pdf&amp;#34;&lt;/span&gt;
pdf_data2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pdftools&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pdf_data&lt;/span&gt;(pdf_file2)

pdf_text2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;pdftools&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pdf_info&lt;/span&gt;(pdf_file2)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;pages,
                       read_page,
                       pdf_data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; pdf_data2) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;discard&lt;/span&gt;(is.null)

dates2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(pdf_text2, get_date)

all_events2  &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pdf_text2 &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;split_days&lt;/span&gt;(dates2) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(get_times) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;gather_events&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;extract_info&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;clean_time_info&lt;/span&gt;()

&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(all_events2)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 6 x 12
## # Groups:   date [1]
##   time  duration timezone date       event text      y location
##   &amp;lt;chr&amp;gt;    &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;    &amp;lt;date&amp;gt;     &amp;lt;chr&amp;gt; &amp;lt;chr&amp;gt; &amp;lt;dbl&amp;gt; &amp;lt;chr&amp;gt;   
## 1 8:00…      180 EST      2019-02-04 EXEC… Loca…   141 Oval Of…
## 2 11:0…       30 EST      2019-02-04 MEET… Loca…   180 Oval Of…
## 3 11:3…       15 EST      2019-02-04 EXEC… Loca…   219 Oval Of…
## 4 11:4…       30 EST      2019-02-04 INTE… Proj…   258 Oval Of…
## 5 12:1…       30 EST      2019-02-04 EXEC… Loca…   310 Oval Of…
## 6 12:4…       60 EST      2019-02-04 LUNC… Proj…   349 Private…
## # … with 4 more variables: project_officer &amp;lt;chr&amp;gt;, press &amp;lt;chr&amp;gt;,
## #   start &amp;lt;dttm&amp;gt;, end &amp;lt;dbl&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think that the fact that my (imperfect!) pipeline seems to work on the
new schedules shows the power of scripting one’s data cleaning… as well
as the hard work Axios’ journalists did! If you work on the PDF data,
I’d be glad to hear how you handled it, so share links to gists and
posts in the comments below! If you prefer playing with the data, check
out &lt;a href=&#34;https://apps.garrickadenbuie.com/trump-tweet-time/&#34;&gt;this cool Shiny app by Garrick
Aden-Buie&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Keeping up to date with R news</title>
      <link>https://masalmon.eu/2019/01/25/uptodate/</link>
      <pubDate>Fri, 25 Jan 2019 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2019/01/25/uptodate/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve now given &lt;a href=&#34;https://maelle.github.io/fluctuat_nec_mergitur/#1&#34;&gt;my talk about &amp;ldquo;How to be a resilient R user&amp;rdquo;&lt;/a&gt; three times, at &lt;a href=&#34;https://www.meetup.com/es/R-Ladies-Strasbourg/events/255348307/&#34;&gt;R-Ladies Strasbourg&lt;/a&gt; and &lt;a href=&#34;https://www.meetup.com/es/rladies-paris/events/257585346/&#34;&gt;R-Ladies Paris&lt;/a&gt; in person, and at &lt;a href=&#34;https://www.meetup.com/rladies-san-jose/events/dbnnkpydcfbcb/&#34;&gt;R-Ladies San José&lt;/a&gt; via Google Hangouts. It was fun! I covered part of the content of that talk in a &lt;a href=&#34;https://masalmon.eu/2018/07/22/wheretogethelp/&#34;&gt;blog post about where to get R help&lt;/a&gt;. Today, it&amp;rsquo;s time for a post full of my personal opinions! I&amp;rsquo;ll cover the rest of the talk: why and how stay up to date with R news?&lt;/p&gt;
&lt;h1 id=&#34;why-its-important-to-stay-informed&#34;&gt;Why it&amp;rsquo;s important to stay informed&lt;/h1&gt;
&lt;p&gt;Following the news is a big part of being a resilient R user, because it helps you solve the problems you didn&amp;rsquo;t know you had (maybe you&amp;rsquo;ll see a package that can replace a cumbersome script of yours!) and the problems you will have (one day, you&amp;rsquo;ll need to make a map, and be thankful you already vaguely know &lt;code&gt;sf&lt;/code&gt; exists). Obviously, staying aware helps because you learn about tools and their applications. But it also helps because it makes you learn about people and organizations! It is highly valuable to get a sense of who&amp;rsquo;s working on what and of where the developments on a topic happen, because when you consciously look for something later, it&amp;rsquo;ll help you find your way more easily.&lt;/p&gt;
&lt;h1 id=&#34;where-to-get-your-r-news-fix&#34;&gt;Where to get your R news fix&lt;/h1&gt;
&lt;p&gt;Here is a probably non exhaustive list of where to get R news. Pick the ones that fit your interests and workflow better, and do not hesitate to tell me of other information sources in the comments!&lt;/p&gt;
&lt;h2 id=&#34;infinite-information-flows-twitter-github-and-devto&#34;&gt;Infinite information flows: Twitter, GitHub and dev.to&lt;/h2&gt;
&lt;p&gt;Both Twitter and GitHub offer some sort of timeline, as does dev.to.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;On Twitter, there&amp;rsquo;s the timeline made of content (re-)tweeted (or liked, thanks to that new random aspect of Twitter&amp;hellip;) by accounts you follow. You choose your own adventure by selecting which accounts to follow! There&amp;rsquo;s also the #rstats feed, either &lt;a href=&#34;https://twitter.com/search?vertical=default&amp;amp;q=%23rstats&amp;amp;src=typd&#34;&gt;recent tweets by popularity&lt;/a&gt; or &lt;a href=&#34;https://twitter.com/search?f=tweets&amp;amp;vertical=default&amp;amp;q=%23rstats&amp;amp;src=typd&#34;&gt;all tweets by publication time&lt;/a&gt;. I like browsing the latter to see interesting questions, news or applications of packages, R-Ladies boasting, etc. Keys to a good experience are, in my opinion&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Muting the spam and accounts you do not like. In particular, keep the habit to mute the big data blabla companies that start polluting the feed, you&amp;rsquo;ll see gems more easily.&lt;/li&gt;
&lt;li&gt;Not being a completist. I&amp;rsquo;ve been told it&amp;rsquo;s stressful to see the flow never stops. Well, make peace with that, you won&amp;rsquo;t read everything and you&amp;rsquo;ll be fine.&lt;/li&gt;
&lt;li&gt;Practice! I know I&amp;rsquo;ve gotten more deliberate, and much faster at browsing the content. Interestingly it probably means that content producers need to be wise in their choice of emojis, illustrations etc. to catch people&amp;rsquo;s attention, but that&amp;rsquo;s not today&amp;rsquo;s topic.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;On GitHub, I only use the timeline fed by accounts I &lt;em&gt;follow&lt;/em&gt; and repos I &lt;em&gt;watch&lt;/em&gt;: repos created or forked, new releases, people following each other (kind of cute when you see long time R friends following each other!), repos starred. It can help discovering new code, and new people. By the way, adding an avatar and minimal information to your GitHub account is crucial in general, and useful for the few seconds of screen time you get on someone&amp;rsquo;s timeline after being followed by someone they follow: if your account is empty, nothing is read, otherwise, people will see &amp;ldquo;Jane Doe started following Ada Lovelace, computer scientist&amp;rdquo; which is more informative than &amp;ldquo;Jane Doe started following alvlc&amp;rdquo;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that there&amp;rsquo;s no ad on GitHub timelines&amp;hellip; yet.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;ca&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;When reading my GitHub timeline and seeing what I think are people experimenting with &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; usethis/devtools, I wonder whether the default description could be sold as ad space 😉 &lt;a href=&#34;https://t.co/eUVkUqdZyX&#34;&gt;pic.twitter.com/eUVkUqdZyX&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/971993590439145473?ref_src=twsrc%5Etfw&#34;&gt;9 de març de 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;ul&gt;
&lt;li&gt;Thanks to &lt;a href=&#34;https://news.ropensci.org/2019-01-23/&#34;&gt;rOpenSci&amp;rsquo;s excellent newsletter maintained by Scott Chamberlain&lt;/a&gt;, I&amp;rsquo;ve learnt about dev.to. Scott wrote &lt;em&gt;&amp;ldquo;A shout out to a probably lesser know place to share and gain R knowledge: If you haven’t heard of dev.to, it’s a sort of developer forum for sharing articles and discussing. They have an R tag &lt;a href=&#34;https://dev.to/t/r&#34;&gt;https://dev.to/t/r&lt;/a&gt; and an rstats tag &lt;a href=&#34;https://dev.to/t/rstats&#34;&gt;https://dev.to/t/rstats&lt;/a&gt; - the former has more traffic.&amp;quot;&lt;/em&gt; I have not started reading it myself, but it&amp;rsquo;s good to know!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;news-aggregators&#34;&gt;News aggregators&lt;/h2&gt;
&lt;p&gt;This is a category I made up, where I&amp;rsquo;m putting these information sources that are less overwhelming than Twitter because already more organized and curated.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.r-project.org/mail.html&#34;&gt;R mailing lists&lt;/a&gt; could be your thing, be it one of the field specific ones, or the more general R-announce.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://rweekly.org/&#34;&gt;R Weekly&lt;/a&gt; is a great newsletter organized in categories making it easier to browse it and select what picks your interest. The very first section, highlights, is made of a few links on which R Weekly team voted. You can subscribe by RSS feed, email, or follow &lt;a href=&#34;https://twitter.com/rweekly_org&#34;&gt;the Twitter account&lt;/a&gt;. R Weekly content stems from RSS feeds R Weekly subscribes to, and pull requests. Note that if you want to know how to get &lt;em&gt;your&lt;/em&gt; content on folks&amp;rsquo; radar, you should check out &lt;a href=&#34;https://masalmon.eu/2018/07/16/soapbox/&#34;&gt;this post of mine about blog promotion&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://news.ropensci.org/&#34;&gt;rOpenSci biweekly newsletter&lt;/a&gt; is as written earlier excellent. It includes news about rOpenSci packages, their application in scientific articles and in blog posts, reminders of recent content on rOpenSci blog, and since this week related news (that&amp;rsquo;s how I read about dev.to), as well as call for maintainers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.r-bloggers.com/&#34;&gt;R-Bloggers&lt;/a&gt; aggregates content from R blogs, re-rendering the whole content on their website. It can be a way to discover interesting blogs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You could create your own news aggregators made up of RSS (or JSON?) feeds of blogs and newsletters you enjoy. I don&amp;rsquo;t have a routine for that, but have heard of Feedly and co.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;r-conferences-and-meetups&#34;&gt;R conferences and meetups&lt;/h2&gt;
&lt;p&gt;R conferences (satRdays, useR!, RStudio::conf, LatinR, ConectaR, etc.) and meetups (R-Ladies meetups, R User groups) will allow you to stay aware of new developments as well as to make R friends. How to know which ones are taking place?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;R Weekly has a section about upcoming events.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There&amp;rsquo;s a weekly post about events &lt;a href=&#34;https://community.rstudio.com/c/irl&#34;&gt;on RStudio community forum&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Jumping Rivers maintains &lt;a href=&#34;https://jumpingrivers.github.io/meetingsR/&#34;&gt;a list of R conferences and local user groups&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, &lt;em&gt;attending&lt;/em&gt; events is obviously fantastic, but you can also make the most of what&amp;rsquo;s online!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Conference &lt;em&gt;programs&lt;/em&gt; can give you a good insight into what&amp;rsquo;s new, trendy, and interesting to catch up on. Especially topics you see in several programs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Slidedecks are often made available and links aggregated on the conference website or by volunteers (here&amp;rsquo;s a &lt;a href=&#34;https://github.com/kbroman/RStudioConf2019Slides&#34;&gt;links collection for RStudio::conf 2019 maintained by Karl Broman&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you&amp;rsquo;re lucky you&amp;rsquo;ll even find a recording for the talk you&amp;rsquo;re interested in! See &lt;a href=&#34;https://resources.rstudio.com/rstudio-conf-2019&#34;&gt;Rstudio::conf 2019 videos&lt;/a&gt;, &lt;a href=&#34;https://capetown2018.satrdays.org/#programme&#34;&gt;SatRday Cape Town 2018 recordings&lt;/a&gt;, &lt;a href=&#34;https://www.youtube.com/channel/UC_R5smHVXRYGhZYDJsnXTwg/videos&#34;&gt;useR! 2018 videos&lt;/a&gt;. A cheap way to get information!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point, I&amp;rsquo;d like to add a short side note about R-Ladies abstract peer-review system organized by &lt;a href=&#34;https://jenthompson.me/&#34;&gt;Jennifer Thompson&lt;/a&gt;! The idea is to encourage R-Ladies to speak at R conferences by giving them feedback on their abstracts. R-Ladies, &lt;a href=&#34;https://docs.google.com/forms/d/e/1FAIpQLSck8FBjNWjziI8pPIoCBlf5J4oQ_6pzeUdbQ1HjYfJ2bNDwDw/viewform&#34;&gt;submit your abstract&lt;/a&gt;. R-Ladies and allies, &lt;a href=&#34;https://docs.google.com/forms/d/e/1FAIpQLSdj44iOqfg6cyhRH57YjQuI-OjbksDmY5LHfsqGSXZrhOONTw/viewform&#34;&gt;volunteer as abstract reviewer&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;other-sources-of-information&#34;&gt;Other sources of information&lt;/h2&gt;
&lt;p&gt;Maybe you&amp;rsquo;re into podcasts? If so, check out e.g. &lt;a href=&#34;http://nssdeviations.com/&#34;&gt;Not So Standard Deviations&lt;/a&gt;, &lt;a href=&#34;https://soundcloud.com/crediblycurious&#34;&gt;Credibly Curious&lt;/a&gt; and &lt;a href=&#34;https://r-podcast.org/&#34;&gt;The R Podcast&lt;/a&gt;. The &lt;a href=&#34;https://r-podcast.org/episode/026-rstudioconf-trifecta/&#34;&gt;latest R Podcast episode&lt;/a&gt; is a crossover between the three since R Podcast&amp;rsquo;s host Eric Nantz is joined by Credibly Curious co-host Nick Tierny and Not So Standard Deviations co-host Hilary Parker! Jumping Rivers maintains &lt;a href=&#34;https://jumpingrivers.github.io/podcasts/technical-podcasts.html&#34;&gt;a list of data science podcasts&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I like this monthly post by RStudio Joseph Rickert, &lt;a href=&#34;https://rviews.rstudio.com/2018/08/27/july-2018-top-40-new-packages/&#34;&gt;selecting 40 packages among all new CRAN releases&lt;/a&gt;, organized in sections which makes it easy to digest.&lt;/p&gt;
&lt;h1 id=&#34;what-to-do-with-the-information&#34;&gt;What to do with the information&lt;/h1&gt;
&lt;p&gt;Now that you know how to get a ton of info, what should you do with it?&lt;/p&gt;
&lt;h2 id=&#34;assess-it&#34;&gt;Assess it!&lt;/h2&gt;
&lt;p&gt;Assess the information you get much like you would assess any piece of news, and maybe ask your R friends what they think. If hesitating to try out a new package, always perform a mini assessment to estimate whether it&amp;rsquo;s worth your time and trust. Assessing a package is not the topic of this post, but have a look at e.g. &lt;a href=&#34;https://github.com/ropenscilabs/packagemetrics&#34;&gt;criteria used in this rOpenSci unconf project&lt;/a&gt;, &lt;a href=&#34;https://simplystatistics.org/2015/11/06/how-i-decide-when-to-trust-an-r-package/&#34;&gt;Jeff Leek&amp;rsquo;s post about how he decides to trust an R package&lt;/a&gt;, &lt;a href=&#34;https://ropensci.github.io/dev_guide/building.html&#34;&gt;rOpenSci packaging guidelines&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;store-it-somehow&#34;&gt;Store it somehow&lt;/h2&gt;
&lt;p&gt;Maybe you don&amp;rsquo;t need any system because you have a good memory, maybe you do need one. I&amp;rsquo;m not an organization coach so will only throw a few links/ideas. Figuring out what works best for you is very important, it&amp;rsquo;ll make this time investment reading news worth it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://jsta.rbind.io/blog/making-a-twitter-dashboard-with-r/&#34;&gt;Joseph Stachelek wrote about how to make a dashboard out of his Twitter favorites&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can search &lt;a href=&#34;https://github.com/maelle?tab=stars&#34;&gt;your GitHub starred repos&lt;/a&gt; so starring a repo is a bit like bookmarking it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/suzanbaert/Resources_and_Bookmarks&#34;&gt;Suzan Baert maintains a public treasure trove of interesting links, for herself and anyone interested&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;http://perso.ens-lyon.fr/lise.vaudor/se-souvenir-de-tout/&#34;&gt;Lise Vaudor wrote a blog post in French about &lt;em&gt;se souvenir de tout&lt;/em&gt;&lt;/a&gt;, including a pic of the cheatsheets near her desk.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;share-it&#34;&gt;Share it!&lt;/h2&gt;
&lt;p&gt;Maybe needless to say, if you like something you read or use, go forth and post it in your networks, to help feed the information flows. :-)&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In this post inspired by my recent R-Ladies talks, I summarized my views on why, where and how to stay aware of news about R. I had included the topic in my talks because I&amp;rsquo;ve been asked &amp;ldquo;But how do you know about this?!&amp;rdquo; and answered &amp;ldquo;Oh, I simply read about it&amp;rdquo;. After a few similar conversations, I realized that maybe it&amp;rsquo;d be useful to share my personal experience. I hope you find your own optimal routine, discover awesome stuff&amp;hellip; and remember about it when needed!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Your and my 2019 R goals</title>
      <link>https://masalmon.eu/2019/01/01/r-goals/</link>
      <pubDate>Tue, 01 Jan 2019 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2019/01/01/r-goals/</guid>
      <description>&lt;p&gt;Here we go again, using a Twitter trend as blog fodder! Colin Fay
launched an inspiring movement by sharing his R goals of 2019.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-dnt=&#34;true&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;My &lt;a href=&#34;https://x.com/hashtag/RStats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#RStats&lt;/a&gt; goals for 2019: &lt;br&gt;&lt;br&gt;1️⃣ Becoming entirely fluent with {data.table}&lt;br&gt;&lt;br&gt;2️⃣ Getting at ease with {Rcpp} &lt;br&gt;&lt;br&gt;What are yours?&lt;a href=&#34;https://x.com/hashtag/rdatatable?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rdatatable&lt;/a&gt; &lt;a href=&#34;https://x.com/hashtag/rcpp?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rcpp&lt;/a&gt;&lt;/p&gt;&amp;mdash; Colin 🤘🌱🏃‍♀️ (@_ColinFay) &lt;a href=&#34;https://x.com/_ColinFay/status/1078953442385772544?ref_src=twsrc%5Etfw&#34;&gt;December 29, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.x.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;It’s been quite interesting reading the objectives of other tweeps: what
they want to learn, make, how they want to get involved in the
community, etc. As Mike Kearney, &lt;code&gt;rtweet&lt;/code&gt;’s maintainer, underlined, it
is excellent reading material!&lt;/p&gt;
&lt;p&gt;… but also blogging material! Let me fetch and tokenize these tweets to
summarize them!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer: I later saw that &lt;a href=&#34;https://twitter.com/jsonbaik/status/1079967070207516672&#34;&gt;Jason Baik got the same
idea&lt;/a&gt; and was
faster than I, find the analysis
&lt;a href=&#34;https://github.com/jasonbaik94/rstats-2019-goals&#34;&gt;here&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id=&#34;collect-twitter-data&#34;&gt;Collect Twitter data&lt;/h1&gt;
&lt;p&gt;If you’re using &lt;code&gt;rtweet&lt;/code&gt; for the first time, check out &lt;a href=&#34;https://rtweet.info/&#34;&gt;its
website&lt;/a&gt; for information about use and setup and
also refer to &lt;a href=&#34;https://developer.twitter.com/&#34;&gt;Twitter API docs&lt;/a&gt;
themselves for knowing more about rate limitation and e.g. learning that
the search endpoint won’t let you get tweets older than 6-9 days old.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rtweet&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;search_tweets&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Rstats goals 2019&amp;#34;&lt;/span&gt;,
                                include_rts &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I obtained 87 tweets from 85 unique users. Definitely not big data, but
not bad!&lt;/p&gt;
&lt;h1 id=&#34;tokenize-tweets&#34;&gt;Tokenize tweets&lt;/h1&gt;
&lt;p&gt;I then set out to tokenize the tweets into words using the specific
&lt;code&gt;tokenizers::tokenize_tweets()&lt;/code&gt; tokenizer via the &lt;code&gt;tidytext&lt;/code&gt; package. If
you’re new to &lt;code&gt;tidytext&lt;/code&gt; I’d recommend reading the book written by &lt;a href=&#34;https://www.tidytextmining.com/&#34;&gt;its
authors&lt;/a&gt;. &lt;em&gt;A token in natural language
processing can be a word, line, etc. which is a totally different
concept from a token for &lt;code&gt;rtweet&lt;/code&gt; functions (your API credentials).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The tweet tokenization is a “tokenization by word that preserves
usernames, hashtags, and URLS”. So awesome, and today is the first time
I find an occasion to use it! I also removed stopwords.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)

stopwords &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rcorpora&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;corpora&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;words/stopwords/en&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;stopWords

tokens &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tweets &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  tidytext&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(token, text,
                        token &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tweets&amp;#34;&lt;/span&gt;,
                        drop &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;token &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; stopwords) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;analyze-tweets&#34;&gt;Analyze tweets&lt;/h1&gt;
&lt;h2 id=&#34;most-mentioned-topics&#34;&gt;Most mentioned topics&lt;/h2&gt;
&lt;p&gt;I first was able to draw a figure similar to Jason Baik’s one, with the
most common tokens. I too removed digits.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggalt&amp;#34;&lt;/span&gt;)
tokens &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(token &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_remove_all&lt;/span&gt;(token, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[^\x01-\x7F]&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(token &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_remove_all&lt;/span&gt;(token, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[:digit:]]&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt; token &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#rstats&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;goals&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(token, sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(token &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;reorder&lt;/span&gt;(token, n)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;18&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;()  &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_lollipop&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(token, n),
                size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1.5&lt;/span&gt;, col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;salmon&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  hrbrthemes&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;,
                          axis_title_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;coord_flip&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2019-01-01-r-goals/lollipop.png&#34; alt=&#34;Most common tokens in 2019 R goals tweets&#34; width=&#34;700&#34;&gt;
&lt;h1 id=&#34;what-actions&#34;&gt;What actions?&lt;/h1&gt;
&lt;p&gt;In this figure I identify verbs like &lt;em&gt;learn&lt;/em&gt;, &lt;em&gt;finish&lt;/em&gt;, &lt;em&gt;write&lt;/em&gt;, &lt;em&gt;build&lt;/em&gt;
and &lt;em&gt;contribute&lt;/em&gt;. Let me look at a sample of lines for each of them.
This is a sample of lines for a small sample of verbs.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;lines &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tweets &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  tidytext&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(line, text,
                        token &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lines&amp;#34;&lt;/span&gt;)

sample_verb &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(verb, lines){
  &lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;)
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(lines, stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(line, &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(verb, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;))) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;sample_n&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;)
}

samples &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;learn&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;finish&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;write&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;contribute&amp;#34;&lt;/span&gt;), sample_verb, lines)

knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(samples)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&#34;width: 100%&#34; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th style=&#34;text-align: left;&#34;&gt;line&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;3️⃣ learn how to make r packages and write my code so it could be made into an r package more easily&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;1. learn how to do spatial analysis in r&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;2️⃣ learn better way to automate feature engineering (neural nets) for text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;1️⃣ finally finish all the courses and certifications i started last year on #coursera and #datacamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;2️⃣ finish my track and field r package&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;3). finish that text mining project i started in october&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;4️⃣ write an advanced shiny book with bookdown 🎈&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;3️⃣ learn how to make r packages and write my code so it could be made into an r package more easily&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;1️⃣ write the htmlwidgets book&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;- build my first #rstats package (aiming for 2 but 1 would be great :d)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;2⃣ build a shiny web app to explore tx staar data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;- use f(x) regularly &amp;amp; build own package. cease patching.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;5⃣ contribute to foss &lt;a href=&#34;https://t.co/oh7mwcq50r&#34; class=&#34;uri&#34;&gt;https://t.co/oh7mwcq50r&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;2 contribute more to #rstats community through #scicomm, #stackoverflow, etc&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td style=&#34;text-align: left;&#34;&gt;3) contribute to #swdchallenge (with r, duh)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;These actions are quite varied, e.g. writing is applied to software as
well as reading material. My goal was to summarize tweets, but I keep
thinking reading all of them is interesting!&lt;/p&gt;
&lt;h2 id=&#34;packages&#34;&gt;Packages?&lt;/h2&gt;
&lt;p&gt;I wondered how many of the tokens correspond to a package name. I
limited myself to CRAN packages, by using the &lt;code&gt;available.packages()&lt;/code&gt;
function, but one could have a look at the &lt;a href=&#34;https://github.com/ropenscilabs/available&#34;&gt;source code of the
&lt;code&gt;available&lt;/code&gt; package&lt;/a&gt; to get
an idea of how to find names of packages from Bioconductor and GitHub.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;cran_pkgs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(
  &lt;span style=&#34;color:#06287e&#34;&gt;available.packages&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;contrib.url&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;https://cran.r-project.org&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;source&amp;#39;&lt;/span&gt;))[,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Package&amp;#34;&lt;/span&gt;])
pkg_tokens &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(tokens,
                            token &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, token)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(token &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; cran_pkgs)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using the data I’ll look at tweets with the most packages, and most
frequent packages.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;pkg_tokens &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(pkg_text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(token), text)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(pkg_text, sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pull&lt;/span&gt;(pkg_text)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;portfolio, blogdown, rmarkdown, knitr, shiny, maps I really like seeing all these #rstats 2019 goals. My own, in order of urgency:\n1) Finish my personal website and online portfolio using blogdown\n2) Get rolling with project workflows, rmarkdown, and knitr \n3) Create shiny apps for custom interactive maps&amp;quot;                                           
## [2] &amp;quot;inference, projects, import, rvest, httr, xml2 My #rstats 2019 goals:\n1. Improve my statistical modeling and inference skills\n2. Develop business literacy and apply it in data analysis projects\n3. Continue to post on my blog (1 post every 2 months)\n4. Learn to import data using DBI, rvest, httr, and xml2&amp;quot;                                           
## [3] &amp;quot;shiny, templates, shiny, shiny, bookdown, shiny My #RStats goals for 2019: \n\n1&amp;lt;U+FE0F&amp;gt;&amp;lt;U+20E3&amp;gt; Improve shinydashboardPlus, bs4Dash and argonDash ..&amp;lt;U+0001F973&amp;gt; \n\n2&amp;lt;U+FE0F&amp;gt;&amp;lt;U+20E3&amp;gt; Release new shiny templates              \n3&amp;lt;U+FE0F&amp;gt;&amp;lt;U+20E3&amp;gt; Open a consulting service for https://t.co/k3PAbxyVMa about shiny \n4&amp;lt;U+FE0F&amp;gt;&amp;lt;U+20E3&amp;gt; Write an advanced shiny book with bookdown &amp;lt;U+0001F388&amp;gt;\n#rstats #shiny #consulting https://t.co/Fyc7MhaeW8&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are false positives, e.g. &lt;code&gt;projects&lt;/code&gt; was here meant as a word, not
a package name. What about the most popular packages among the tweets?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(pkg_tokens, token, sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 66 x 2
##    token         n
##    &amp;lt;chr&amp;gt;     &amp;lt;int&amp;gt;
##  1 shiny        16
##  2 blogdown      9
##  3 projects      9
##  4 rmarkdown     9
##  5 tidyverse     6
##  6 bookdown      5
##  7 purrr         4
##  8 track         4
##  9 caret         3
## 10 markdown      3
## # ... with 56 more rows
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this table, we get a glimpse at current popular packages, apart from
“projects”, “track” and “markdown”. If I’m reading the list correctly
they’re all developed at RStudio!&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In this post I followed an approach similar to &lt;a href=&#34;https://github.com/jasonbaik94/rstats-2019-goals/blob/master/analysis.Rmd&#34;&gt;Jason
Baik’s&lt;/a&gt;
to summarize tweets about 2019 R goals announced on Twitter: I collected
tweets with &lt;code&gt;rtweet&lt;/code&gt; and then used &lt;code&gt;tidytext&lt;/code&gt; and the tidyverse to
summarize them. Goals often included learning about stuff, building
packages (find &lt;a href=&#34;https://masalmon.eu/2017/12/11/goodrpackages/&#34;&gt;my list of
resources&lt;/a&gt; and don’t miss
&lt;a href=&#34;https://twitter.com/StephdeSilva/status/1079871083535167488&#34;&gt;this offer by Steph de
Silva&lt;/a&gt;),
and mentions of RStudio packages.&lt;/p&gt;
&lt;p&gt;What about my own R goals, that I haven’t tweeted? I have not made any
list, but have exciting projects at work, and hope to keep
semi-consistently posting on this blog. In January I’ll also get to
start 2019 by giving two R talks, &lt;a href=&#34;https://www.meetup.com/rladies-paris/events/257585346/&#34;&gt;one at R-Ladies
Paris&lt;/a&gt; and a
remote one at &lt;a href=&#34;https://www.conectar2019.org/#schedule&#34;&gt;ConectaR 2019&lt;/a&gt;!
Happy 2019, I hope you can meet your own R goals!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>My #Best9of2018 tweets</title>
      <link>https://masalmon.eu/2018/12/28/best9of2018/</link>
      <pubDate>Fri, 28 Dec 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/12/28/best9of2018/</guid>
      <description>&lt;p&gt;As 2018 nears its end, it’s time for me to look back on my R/Twitter
year with the same simple method as &lt;a href=&#34;https://masalmon.eu/2017/12/30/best9of2017/&#34;&gt;last
year&lt;/a&gt;: let me identify and webshoot my 9 best
tweets of 2018!&lt;/p&gt;
&lt;h1 id=&#34;downloading-and-opening-my-twitter-data&#34;&gt;Downloading and opening my Twitter data&lt;/h1&gt;
&lt;p&gt;Like in 2017 I tweeted too much and therefore was unable to rely on
&lt;code&gt;rtweet::get_timeline()&lt;/code&gt; (or &lt;code&gt;rtweet::get_my_timeline()&lt;/code&gt;) to download my
tweets so I exported data via the Tweets tab of
&lt;a href=&#34;https://analytics.twitter.com/&#34;&gt;https://analytics.twitter.com/&lt;/a&gt;. Last year, I downloaded one file per
quarter but somehow had to download one per month this time. It was
monotonous but not horrible.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;dir&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;, full.names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;read_csv) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;-&amp;gt;&lt;/span&gt; my_tweets
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;4196 tweets!&lt;/p&gt;
&lt;h1 id=&#34;getting-the-top-9-tweets&#34;&gt;Getting the top 9 tweets&lt;/h1&gt;
&lt;p&gt;Similarly to my 2017 post, I chose the number of likes as criterion to
define my best tweets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;my_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(my_tweets, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; likes)
my_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; janitor&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;clean_names&lt;/span&gt;(my_tweets)

knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(my_tweets[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;9&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;likes&amp;#34;&lt;/span&gt;])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;likes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;162&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;151&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;128&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;112&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;95&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;94&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;91&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;86&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;75&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;best9 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; my_tweets&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;tweet_permalink[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;9&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The table above shows that my best tweets were not &lt;em&gt;extremely&lt;/em&gt; popular.&lt;/p&gt;
&lt;h1 id=&#34;webshooting-and-combining-the-tweets&#34;&gt;Webshooting and combining the tweets&lt;/h1&gt;
&lt;p&gt;My 2017 blog post inspired Bob Rudis to contribute a &lt;code&gt;tweet_shot()&lt;/code&gt;
function to &lt;code&gt;rtweet&lt;/code&gt;, relying on the &lt;code&gt;webshot&lt;/code&gt; package, so that’s what I
used.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;shot &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(permalink){
  rtweet&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tweet_shot&lt;/span&gt;(permalink) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_crop&lt;/span&gt;(magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;geometry_area&lt;/span&gt;(width &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;517&lt;/span&gt;,
                                             height &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;517&lt;/span&gt;,
                       y_off &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;88&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_border&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;salmon&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;20x20&amp;#34;&lt;/span&gt;)
}

images &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(best9),
                     shot)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I improved the collage code with two tweaks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I created rows then columns instead of the other way round, because
that’s what Instagram does. I did not pay attention to this last
year but Andrew Caines told me this in a comment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I did not save the intermediary images to disk. I’ve upped my
&lt;code&gt;magick&lt;/code&gt; game!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;make_row &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(i, images){
  images&lt;span style=&#34;color:#06287e&#34;&gt;[&lt;/span&gt;((i&lt;span style=&#34;color:#40a070&#34;&gt;-1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;3+1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;((i&lt;span style=&#34;color:#40a070&#34;&gt;-1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;3+3&lt;/span&gt;)] &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_join&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_append&lt;/span&gt;()
}

purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;, make_row,
           images &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; images) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_join&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_append&lt;/span&gt;(stack &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_border&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;salmon&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;20x20&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2018-12-28-best9of2018/best9.png&#34; alt=&#34;best 9 of 2018&#34; width=&#34;700&#34;&gt;
&lt;p&gt;Worth noting from my R year are, according to these tweets,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;my re-designing &lt;a href=&#34;https://masalmon.eu/&#34;&gt;my website&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;the slides of my R-Ladies Strasbourg talk &lt;a href=&#34;https://maelle.github.io/fluctuat_nec_mergitur/&#34;&gt;about how to be a
resilient R user&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;my &lt;a href=&#34;https://masalmon.eu/bio/&#34;&gt;starting work&lt;/a&gt; at rOpenSci and Locke
Data (yay!);&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;my blog post about &lt;a href=&#34;https://masalmon.eu/2018/01/07/rainbowing/&#34;&gt;rainbowing a set of
pictures&lt;/a&gt;;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;another blog post featuring &lt;code&gt;magick&lt;/code&gt;, about &lt;a href=&#34;https://masalmon.eu/2018/02/22/hexcombine/&#34;&gt;combining
hexes&lt;/a&gt; but I’d recommend
reading &lt;a href=&#34;https://blog.mitchelloharawild.com/blog/user-2018-feature-wall/&#34;&gt;this post by Mitchell O’Hara
Wild&lt;/a&gt;
instead;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;my blog post about &lt;a href=&#34;https://masalmon.eu/2018/07/22/wheretogethelp/&#34;&gt;where to get R
help&lt;/a&gt; that might be
the personal blog post I’m the proudest of.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What about your R year, on Twitter and elsewhere? Have a good last days
of 2018, and a happy 2019!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Advent of Code: Most Popular Languages</title>
      <link>https://masalmon.eu/2018/12/15/adventofcode/</link>
      <pubDate>Sat, 15 Dec 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/12/15/adventofcode/</guid>
      <description>&lt;p&gt;You might have heard of the &lt;a href=&#34;https://adventofcode.com/&#34;&gt;Advent of Code&lt;/a&gt;,
a 25-day challenge involving a programming puzzle a day, to be solved
with the language of your choice. I’ve noted the popularity of this
activity in my Twitter timeline but also in my GitHub timeline where
I’ve seen the creation of a few &lt;code&gt;advent-of-code&lt;/code&gt; or so repositories.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-dnt=&#34;true&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;AoC is largely an exercise in figuring how to write your favourite language as if were C or C++ 😁, which can be fun ... in moderation&lt;/p&gt;&amp;mdash; Jenny Bryan (@JennyBryan) &lt;a href=&#34;https://x.com/JennyBryan/status/1072724282705203201?ref_src=twsrc%5Etfw&#34;&gt;December 12, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.x.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;


&lt;p&gt;If I were to participate one year, I’d probably use R. Jenny Bryan’s
tweet above inspired me to try and gauge the popularity of languages
used in the Advent of Code. To do that, in this post, I shall use the
search endpoint of GitHub V3 API to identify Advent of Code 2018 repos.&lt;/p&gt;
&lt;h1 id=&#34;searching-repositories-on-github&#34;&gt;Searching repositories on GitHub&lt;/h1&gt;
&lt;h2 id=&#34;study-design--&#34;&gt;Study design ;-)&lt;/h2&gt;
&lt;p&gt;GitHub’s V3 API offers a &lt;a href=&#34;https://developer.github.com/v3/search/#search-repositories&#34;&gt;search
endpoint&lt;/a&gt;,
that however gives you less results than doing the &lt;a href=&#34;https://github.com/search?q=adventofcode+2018&#34;&gt;same search via the
web interface&lt;/a&gt;, even when
using pagination right (or at least, when believing I use pagination
right!). I’m however willing to use that sub-sample as basis for my
study of language popularity. It’s actually a sub-sub-sample, since I’m
only looking at Advent of code projects published on GitHub.&lt;/p&gt;
&lt;p&gt;In order to circumvent the sub-sub-sampling a bit, I’ll do the search in
two steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Searching for Advent of code 2018 in general among repos, and
extracting the language of the repos.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Searching for Advent of code 2018 &lt;em&gt;for each of these languages
separately&lt;/em&gt; and extracting the total count of hits.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that I am not filtering the repos by activity, so some of them
could very well have been created for a few days only. If they are empty
though, they do not get assigned a language.&lt;/p&gt;
&lt;p&gt;Regarding the language of repos, GitHub assigns a language to each
repository. This information can be wrong, which is e.g. mentioned in
&lt;a href=&#34;https://ropensci.github.io/dev_guide/grooming.html#github-linguist&#34;&gt;rOpenSci’s development
guide&lt;/a&gt;.
Furthermore, my using this piece of information means I’m disregarding
the fact that &lt;a href=&#34;https://www.benkraft.org/2017/12/26/advent-of-code/&#34;&gt;some people actually use a mix of technologies to solve
the puzzles&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;actual-queries&#34;&gt;Actual queries&lt;/h2&gt;
&lt;p&gt;I first defined a function to search the API whilst respecting the rate
limiting. I even erred on the side of caution and queried very slowly.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;.search &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(page){
  gh&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;gh&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;GET /search/repositories&amp;#34;&lt;/span&gt;,
         q &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;adventofcode 2018&amp;#34;&lt;/span&gt;,
         page &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; page,
         fork &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)
}

search &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ratelimitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;limit_rate&lt;/span&gt;(.search,
                                ratelimitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rate&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;60&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then wrote two other functions to help me rectangle the API output for
each repository.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;empty_null &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x){
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.null&lt;/span&gt;(x)){
    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
  }else{
    x
  }
}

rectangle &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(item){
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(full_name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; item&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;full_name,
                 language &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;empty_null&lt;/span&gt;(item&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;language))
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I created a function putting these two pieces together.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;get_page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(page){
  results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;search&lt;/span&gt;(page), silent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)

  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# an early return&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;inherits&lt;/span&gt;(results, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;try-error&amp;#34;&lt;/span&gt;)){
    &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;)
  }

  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(results&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;items,
                rectangle)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And I then ran the following pipeline.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;total_count &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;search&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;total_count
pages &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;ceiling&lt;/span&gt;(total_count&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;100&lt;/span&gt;))

results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(pages, get_page)
results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(results)

languages &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(results&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;language)
languages &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; languages[languages &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This got me 814 repos, with 46 non empty languages. Repo names are quite
varied: rdmueller/aoc-2018, petertseng/adventofcode-rb-2018,
NiXXeD/adventofcode, Arxcis/adventofcode2018,
Stupremee/adventofcode-2018, phaazon/advent-of-code-2k18.&lt;/p&gt;
&lt;p&gt;With that information obtained, I was able to run a query by language.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;.get_one_language_count &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(language){
  gh&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;gh&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;GET /search/repositories&amp;#34;&lt;/span&gt;,
         q &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;adventofcode 2018&amp;amp;language:{language}&amp;#34;&lt;/span&gt;),
         fork &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;total_count &lt;span style=&#34;color:#666&#34;&gt;-&amp;gt;&lt;/span&gt; count
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(language &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; language,
                 count &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; count)
}

get_one_language_count &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ratelimitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;limit_rate&lt;/span&gt;(.get_one_language_count,
                                 ratelimitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rate&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;60&lt;/span&gt;))

counts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(languages,
                        get_one_language_count)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In total, the &lt;code&gt;counts&lt;/code&gt; table contains information about 2080
repositories, a bit less than half the number of Advent of code 2018
repositories I’d find via the web interface.&lt;/p&gt;
&lt;h1 id=&#34;advent-of-codes-languages-popularity&#34;&gt;Advent of Code’s languages popularity&lt;/h1&gt;
&lt;p&gt;I’ll concentrate on the 15 most popular languages in the sample, which
automatically excludes R with… 8 repositories only.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggalt&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)

counts &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; count) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;15&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(language &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;reorder&lt;/span&gt;(language, count))   &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_lollipop&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(language, count),
                size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;, col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;salmon&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  hrbrthemes&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;,
                          axis_title_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;coord_flip&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Advent of Code Languages&amp;#34;&lt;/span&gt;,
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Among a sample of GitHub repositories, with language information from GitHub linguist&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2018-12-15-adventofcode/adventofcode.png&#34; alt=&#34;popularity of languages&#34;&gt;&lt;/p&gt;
&lt;p&gt;The results are not surprising after reading e.g. the &lt;a href=&#34;https://insights.stackoverflow.com/survey/2018/#technology&#34;&gt;insights from
Stack Overflow’s 2018
survey&lt;/a&gt;, although the Python domination is crazy! I find interesting to reflect on the
fact that Jenny Bryan says that the challenge is best for C or C++, that
are not the most popular languages in these samples… but still more
popular than R, ok.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In this post I used GitHub V3 API to get a glimpse at the popularity of languages used to solve the Advent of Code. Further work could include looking at the &lt;em&gt;completion&lt;/em&gt; of the challenge by language, potentially using the GitHub activity of each repo as an (imperfect) proxy.&lt;/p&gt;
&lt;p&gt;I do not take part in the challenge myself, my principal Advent’s
specific activity being instead the lazy and delightful watching of the
&lt;a href=&#34;https://sv.wikipedia.org/wiki/Julkalendern_i_Sveriges_Television&#34;&gt;Swedish TV channel SVT Adventskalender for
kids&lt;/a&gt;.
Incidentally, &lt;a href=&#34;https://sv.wikipedia.org/wiki/Storm_p%C3%A5_Lugna_gatan&#34;&gt;this year’s
storyline&lt;/a&gt;
includes a Christmas competition, which however features competitive
eating of saffron buns and gingerhouse building rather than programming
puzzles… Do &lt;em&gt;you&lt;/em&gt; participate to Advent of Code this year? If so, with
which language and why?&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Make a trailer for your slidedeck with av</title>
      <link>https://masalmon.eu/2018/10/07/trailer/</link>
      <pubDate>Sun, 07 Oct 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/10/07/trailer/</guid>
      <description>&lt;p&gt;rOpenSci post-doc hacker &lt;a href=&#34;https://github.com/jeroen/&#34;&gt;Jeroen Ooms&lt;/a&gt; has just released a cool new package, &lt;a href=&#34;https://github.com/ropensci/av&#34;&gt;&lt;code&gt;av&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://ropensci.org/technotes/2018/10/06/av-release/&#34;&gt;that he wrote &amp;ldquo;will become the video counterpart of the magick package which [rOpenSci uses] for working with images.&amp;quot;&lt;/a&gt;. &lt;code&gt;av&lt;/code&gt; provides bindings to the FFmepg libraries for editing videos. It&amp;rsquo;s already become a renderer for &lt;a href=&#34;https://github.com/thomasp85/gganimate&#34;&gt;&lt;code&gt;gganimate&lt;/code&gt; by Thomas Lin Pedersen&lt;/a&gt;, but &lt;code&gt;av&lt;/code&gt; allows more than making videos of graphics. In this post, I&amp;rsquo;ll show how to use &lt;code&gt;av&lt;/code&gt; and &lt;code&gt;webshot&lt;/code&gt; to make a trailer/sneak preview of a slidedeck, i.e. a short video featuring the first few slides on music!&lt;/p&gt;
&lt;h1 id=&#34;why-make-a-trailer-of-your-slidedeck&#34;&gt;Why make a trailer of your slidedeck?&lt;/h1&gt;
&lt;p&gt;No, making a trailer of a slidedeck isn&amp;rsquo;t only a pretext for trying out &lt;code&gt;av&lt;/code&gt;! In case you hadn&amp;rsquo;t noticed, I&amp;rsquo;m all about promoting your work once you&amp;rsquo;ve put in the work. I&amp;rsquo;ve even written &lt;a href=&#34;https://masalmon.eu/2018/07/16/soapbox/&#34;&gt;a whole post about blog promotion&lt;/a&gt;. Promoting a slidedeck after a talk, or a talk before the event, is quite similar to promoting a blog post both in terms of benefits and technically. In particular, a tweet about it will be more powerful if featuring an illustration, and why not making it animated?&lt;/p&gt;
&lt;p&gt;For more tips about advertising for a thing via a talk, check out the excellent &lt;a href=&#34;https://www.tidyverse.org/articles/2018/07/carpe-talk/&#34;&gt;&amp;ldquo;Carpe Talk&amp;rdquo; article on tidyverse.org&lt;/a&gt; by &lt;a href=&#34;https://jennybryan.org/&#34;&gt;Jenny Bryan&lt;/a&gt; and &lt;a href=&#34;https://maraaverick.rbind.io/&#34;&gt;Mara Averick&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;capture-the-first-few-slides&#34;&gt;Capture the first few slides&lt;/h1&gt;
&lt;p&gt;In this post, I&amp;rsquo;ll use &lt;a href=&#34;https://jeroen.github.io/uros2018&#34;&gt;the slidedeck that Jeroen shared after giving a talk about R infrastructure after the uRos conference&lt;/a&gt;. I&amp;rsquo;ll capture the first few slides minus the ones where he introduced himself, because I wanted the focus of the trailer to be on the talk topic. I didnd&amp;rsquo;t know &lt;code&gt;webshot::webshot()&lt;/code&gt; was vectorized, thanks to Jeroen for telling me that which shortened the code below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;fs&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;dir_create&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;slides&amp;#34;&lt;/span&gt;)

urls &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sprintf&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://jeroen.github.io/uros2018/#%d&amp;#34;&lt;/span&gt;,
                &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;))
webshot&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;webshot&lt;/span&gt;(urls, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;slides/webshot.png&amp;#39;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At that point, I had a folder with 8 PNGs. If your talk isn&amp;rsquo;t html, but say Power Point, you could export to PDF, and use &lt;a href=&#34;https://github.com/ropensci/pdftools&#34;&gt;the rOpenSci &lt;code&gt;pdftools&lt;/code&gt; package&lt;/a&gt; &lt;a href=&#34;https://github.com/ropensci/pdftools#bonus-feature-rendering-pdf&#34;&gt;to render slides to images&lt;/a&gt;. Note that the PNGs I got didn&amp;rsquo;t have the right font, which is something I could solve by using decktape instead of &lt;code&gt;webshot&lt;/code&gt;, to render the html slides to PDF and then to PNG with &lt;code&gt;pdftools&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;create-the-video&#34;&gt;Create the video&lt;/h1&gt;
&lt;p&gt;The video creation was extremely simple and fast once I had selected a soundtrack. Note that having a soundtrack is optional!&lt;/p&gt;
&lt;p&gt;Jeroen&amp;rsquo;s talk was about building stuff so I looked for construction sounds and selected &lt;a href=&#34;https://www.zapsplat.com/music/road-construction-environment-with-jackhammer/&#34;&gt;this sample published by Audio Hero on Zapsplat&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;slides &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; fs&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;dir_ls&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;slides&amp;#34;&lt;/span&gt;)
slides &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(slides[1], slides, slides&lt;span style=&#34;color:#06287e&#34;&gt;[length&lt;/span&gt;(slides)])

av&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;av_encode_video&lt;/span&gt;(slides,
                    &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# it could be a fraction!&lt;/span&gt;
                    framerate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;,
                    &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# if too short there&amp;#39;ll be silence &lt;/span&gt;
                    &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# at the end&lt;/span&gt;
                    &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# if too long it&amp;#39;ll be truncated&lt;/span&gt;
                    audio &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; audio,
                    output &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;trailer.mp4&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;video width=&#34;100%&#34; controls&gt;
&lt;source src=&#34;https://masalmon.eu/figure/source/2018-10-07-trailer/trailer.mp4&#34;&gt;
Trailer of Jeroen&#39;s slidedeck. Your browser does not support the video tag.
&lt;/video&gt;
&lt;p&gt;Tada! Thanks &lt;a href=&#34;https://www.zapsplat.com/music/road-construction-environment-with-jackhammer/&#34;&gt;to Audio Hero for the sound sample&lt;/a&gt;. Now, if you want to read more of that cool slidedeck, you&amp;rsquo;ll find it &lt;a href=&#34;https://jeroen.github.io/uros2018/#1&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In this post, I was able to write R code to take screenshots of the first few slides of a slidedeck, and to combine them in a video with sounds related to the slidedeck topic. That new &lt;code&gt;av&lt;/code&gt; package is quite promising!&lt;/p&gt;
&lt;p&gt;Regarding &lt;a href=&#34;https://r-resources.massey.ac.nz/rmarkdown/&#34;&gt;accessibility&lt;/a&gt; of the produced trailer, on Twitter you can&amp;rsquo;t add an alternative description to a video, so it might be nice to either replace the music with a voice over, or to tweet once with music/sound and once with voice over? I guess the tweet itself can also help counterbalance the information lost by being informative and featuring a link to the actual slidedeck. If you&amp;rsquo;re as much into listening to your own voice as I am into listening to mine (i.e. &lt;strong&gt;not at all&lt;/strong&gt;!), you might want to try &lt;a href=&#34;https://github.com/ropensci/googleLanguageR&#34;&gt;rOpenSci&amp;rsquo;s &lt;code&gt;googleLanguageR&lt;/code&gt; package &lt;/a&gt; that helps use &lt;a href=&#34;https://cloud.google.com/text-to-speech/&#34;&gt;Google text to speech API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, if you use a cool Xaringan theme like &lt;a href=&#34;https://github.com/emitanaka/ninja-theme&#34;&gt;Emi Tanaka&amp;rsquo;s ninja theme&lt;/a&gt;, you&amp;rsquo;d a bit disappointed to create a preview that loses the nice animated transitions. Luckily, &lt;a href=&#34;https://ropensci.org/technotes/2018/10/06/av-release/&#34;&gt;in his tech note&lt;/a&gt; Jeroen promised &amp;ldquo;In future versions we also want to add things like screen capturing and reading raw video frames and audio samples for analysis in R.&amp;rdquo; so one could depend on screen capturing rather than screen shooting. I&amp;rsquo;m looking forward to future versions of &lt;code&gt;av&lt;/code&gt;, and encourage you to give it a try!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Spookify: Halloween Name Generation in R</title>
      <link>https://masalmon.eu/2018/10/05/spookify/</link>
      <pubDate>Fri, 05 Oct 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/10/05/spookify/</guid>
      <description>&lt;p&gt;It’s October, time for spooky Twitter names! If you’re on this social
media platform, you might have noticed some of your friends switching
their names to something spooky and punny. Last year I was “Maelstrom
Salmon”, which I find scary but is arguably not that funny. Anyhow, what
if you want to switch your name but have no inspiration? In this post,
we shall explore R’s abilities to help us with that with the help of
webscraping, phonetic spelling and string distance algorithms, and the
magic of randomness!&lt;/p&gt;
&lt;p&gt;My strategy for spooky name generation will be to replace each part of a
name (e.g. first and last names) with the phonetically closest
Halloween-related words. Therefore, the technical challenges here were
to find a list of Halloween-related words, and to measure &lt;em&gt;phonetical&lt;/em&gt;
string distance.&lt;/p&gt;
&lt;h1 id=&#34;getting-spooky-words&#34;&gt;Getting spooky words&lt;/h1&gt;
&lt;p&gt;The &lt;a href=&#34;https://masalmon.eu/tags/rcorpora/&#34;&gt;otherwise very useful&lt;/a&gt; package
&lt;a href=&#34;https://github.com/gaborcsardi/rcorpora&#34;&gt;&lt;code&gt;rcorpora&lt;/code&gt;&lt;/a&gt; doesn’t have a
“spooky” category, so I decided to scrape &lt;a href=&#34;https://holidappy.com/holidays/halloween-words-and-halloween-vocabulary-lists&#34;&gt;this webpage of Halloween
words for
kids&lt;/a&gt;.
It was one of the first search results, and being for kids it couldn’t
be offensive. Like the last two times I webscraped, I used the &lt;a href=&#34;https://masalmon.eu/2018/07/31/alldatascience/&#34;&gt;very
cool&lt;/a&gt;
&lt;a href=&#34;https://github.com/dmi3kno/polite&#34;&gt;&lt;code&gt;polite&lt;/code&gt;&lt;/a&gt; package!&lt;/p&gt;
&lt;p&gt;There were two less useful sections on the page, with French and Spanish
words, that I very inelegantly removed after looking up their div ID in
the page source.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# introduce myself&lt;/span&gt;
session &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; polite&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bow&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://holidappy.com/holidays/halloween-words-and-halloween-vocabulary-lists&amp;#34;&lt;/span&gt;,
                       user_agent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Maëlle Salmon https://masalmon.eu/&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# scrape&lt;/span&gt;
page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; polite&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;scrape&lt;/span&gt;(session)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## No encoding supplied: defaulting to UTF-8.
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# remove the two sections I don&amp;#39;t want&lt;/span&gt;
French &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(page,
                            xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;//div[@id=&amp;#39;mod_37589248&amp;#39;]&amp;#34;&lt;/span&gt;)

xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_remove&lt;/span&gt;(French)

Spanish &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(page,
                              xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;//div[@id=&amp;#39;mod_37589143&amp;#39;]&amp;#34;&lt;/span&gt;)

xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_remove&lt;/span&gt;(Spanish)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# extract the words&lt;/span&gt;
words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(page,
                            xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;//td[contains(@class, &amp;#39;tableCell&amp;#39;)]&amp;#34;&lt;/span&gt;)

words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_text&lt;/span&gt;(words)
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(words)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;All Hallows&#39; Eve\n\t&amp;quot; &amp;quot;lantern\n\t&amp;quot;          &amp;quot;prank\n\t&amp;quot;           
## [4] &amp;quot;costume\n\t&amp;quot;          &amp;quot;make-believe\n\t&amp;quot;     &amp;quot;sweets\n\t&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I cleaned the words a bit. Some of them were not &lt;em&gt;words&lt;/em&gt; so I split
them. I hesitated between this solution and keeping only one-word
phrases… I’m still not sure it was the best decision!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_remove_all&lt;/span&gt;(words, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\\n\\\t&amp;#34;&lt;/span&gt;)
words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(words)
words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tokenizers&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tokenize_words&lt;/span&gt;(words)
words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(words&lt;span style=&#34;color:#06287e&#34;&gt;[lengths&lt;/span&gt;(words) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;])
words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; words[&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(words, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[0-9]&amp;#34;&lt;/span&gt;)]
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(words)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;all&amp;quot;     &amp;quot;hallows&amp;quot; &amp;quot;eve&amp;quot;     &amp;quot;lantern&amp;quot; &amp;quot;prank&amp;quot;   &amp;quot;costume&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I obtained 258 words.&lt;/p&gt;
&lt;h1 id=&#34;matching-names-and-spooky-words&#34;&gt;Matching names and spooky words&lt;/h1&gt;
&lt;p&gt;Once I had this vector of Halloween-related words, all I needed was a
way to compute a phonetical distance between each of them and a name. It
turned out more complicated than I thought! The &lt;code&gt;soundex&lt;/code&gt; method of the
&lt;a href=&#34;https://github.com/markvanderloo/stringdist&#34;&gt;&lt;code&gt;stringdist&lt;/code&gt;&lt;/a&gt; package
returned 1 or 0 only, so I set out to search another package supporting
phonetical comparison. I found the
&lt;a href=&#34;https://github.com/howardjp/phonics&#34;&gt;&lt;code&gt;phonics&lt;/code&gt;&lt;/a&gt; package that has a
paper in JOSS, that implements more algorithms translating strings to
phonetic “codes”. I ended up using the &lt;code&gt;phonics::nysiis()&lt;/code&gt; function,
corresponding to the New York State Identification and Intelligence
System phonetic algorithm. That package also has an algorithm suitable
for German, via &lt;code&gt;phonics::cologne()&lt;/code&gt;, and one for French, via
&lt;code&gt;phonics::statcan()&lt;/code&gt;, but I haven’t explored that further.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;phonics&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nysiis&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pain&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;PAN&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;phonics&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nysiis&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pane&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;PAN&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;phonics&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nysiis&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;train&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;TRAN&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I was at a loss as to how best compare output from &lt;code&gt;phonics::nysiis()&lt;/code&gt;
and very hackily used… &lt;code&gt;stringdist::stringdist()&lt;/code&gt; with a default method!
Below is the function finding the closest match for any name part.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;spookify_word &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(word, seed &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;, words){

  phon &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; phonics&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nysiis&lt;/span&gt;(words)
  dist &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringdist&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;stringdist&lt;/span&gt;(phonics&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nysiis&lt;/span&gt;(word),
                                 phon)
  &lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(seed)
  &lt;span style=&#34;color:#06287e&#34;&gt;sample&lt;/span&gt;(words[dist &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(dist)], &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
}
&lt;span style=&#34;color:#06287e&#34;&gt;spookify_word&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Jane&amp;#34;&lt;/span&gt;, words &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; words)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;bones&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So &lt;code&gt;spookify_word()&lt;/code&gt; samples a word among the closest matches… that
aren’t necessarily very close to the original name. But that’s fine!&lt;/p&gt;
&lt;h1 id=&#34;mixing-it-all-in-a-chauldron-function&#34;&gt;Mixing it all in a &lt;del&gt;chauldron&lt;/del&gt; function&lt;/h1&gt;
&lt;p&gt;I finally created a function taking a whole name, say “Maëlle Salmon” or
“Ada Colau Ballano”, tokenizes it into words thanks to the
&lt;a href=&#34;https://github.com/ropensci/tokenizers&#34;&gt;&lt;code&gt;tokenizers&lt;/code&gt;&lt;/a&gt; package, gets the
closest match for each part and then collapses everything together,
capitalizing first letters thanks to
&lt;a href=&#34;https://github.com/Tazinho/snakecase&#34;&gt;&lt;code&gt;snakecase&lt;/code&gt;&lt;/a&gt;… before announcing
the result with the cool &lt;a href=&#34;https://github.com/sckott/cowsay&#34;&gt;&lt;code&gt;cowsay&lt;/code&gt;&lt;/a&gt;
package! I made sure to only use animals that are associated with
Halloween.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;spookify &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(name, seed,
                     words){
  name_parts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(tokenizers&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tokenize_words&lt;/span&gt;(name))
  spook_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(name_parts,
                                spookify_word,
                                seed, words)
  spook_name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(spook_names, collapse &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;)
  spook_name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; snakecase&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;to_upper_camel_case&lt;/span&gt;(spook_name,
                                               sep_out &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;)
  
  &lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(seed)
  animal &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sample&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;owl&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;spider&amp;#34;&lt;/span&gt;,
                     &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pumpkin&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ghost&amp;#34;&lt;/span&gt;,
                     &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bat&amp;#34;&lt;/span&gt;), &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)

  cowsay&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;say&lt;/span&gt;(what &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Byebye &amp;#34;&lt;/span&gt;, name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;,
                           &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;You are now &amp;#34;&lt;/span&gt;, spook_name),
              by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; animal)

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And because I didn’t want to make fun of anyone else than me, I created
7 fake names using the &lt;code&gt;charlatan&lt;/code&gt; package and ran &lt;code&gt;spookify&lt;/code&gt; on them!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;)
names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; charlatan&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ch_name&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;7&lt;/span&gt;)
purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;walk2&lt;/span&gt;(names, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(names),
             spookify, words &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; words)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Colors cannot be applied in this environment :( Try using a terminal or RStudio.

## 
## 
##  ----- 
## Byebye Tyrik Graham PhD
## You are now Trick Grinning Giant 
##  ------ 
##     \   
##      \
##               |
##               |
##               |
##              __
##           | /  \ |
##          \_\\  //_/
##           .&#39;/()\&#39;.
##            \\  //  [nosig]
## 

## Colors cannot be applied in this environment :( Try using a terminal or RStudio.

## 
##  ----- 
## Byebye Jeremy Rippin
## You are now Horrify Rotten 
##  ------ 
##     \   
##      \  
##       \
##        /\___/\
##        {o}{o}|
##        \ v  /|
##        |    \ \
##         \___/_/       [ab] 
##           | |

## Colors cannot be applied in this environment :( Try using a terminal or RStudio.

## 
##  ----- 
## Byebye Margarett Purdy
## You are now Boogers Party 
##  ------ 
##     \   
##      \  
##       \
##        /\___/\
##        {o}{o}|
##        \ v  /|
##        |    \ \
##         \___/_/       [ab] 
##           | |

## Colors cannot be applied in this environment :( Try using a terminal or RStudio.

## 
## 
##  ----- 
## Byebye Miss Tilla Funk DDS
## You are now Ooze Vil Fangs Dead 
##  ------ 
##     \   
##      \
##                   ___
##                ___)__|_
##           .-*&#39;          &#39;*-,
##          /      /|   |\     \
##         ;      /_|   |_\     ;
##         ;   |\           /|  ;
##         ;   | &#39;&#39;--...--&#39;&#39; |  ;
##          \  &#39;&#39;---.....--&#39;&#39;  /
##           &#39;&#39;*-.,_______,.-*&#39;  [nosig]
## 

## Colors cannot be applied in this environment :( Try using a terminal or RStudio.

## 
## 
##  ----- 
## Byebye Wilton Carroll IV
## You are now Cartoon Cruella Eve 
##  ------ 
##     \   
##      \
##               |
##               |
##               |
##              __
##           | /  \ |
##          \_\\  //_/
##           .&#39;/()\&#39;.
##            \\  //  [nosig]
## 

## Colors cannot be applied in this environment :( Try using a terminal or RStudio.

## 
## 
##  ----- 
## Byebye Tevin Conn
## You are now Coffin Bones 
##  ------ 
##     \   
##      \
##      .-.
##     (o o)
##     | O \
##      \   \
##       `~~~&#39; [nosig]
## 

## Colors cannot be applied in this environment :( Try using a terminal or RStudio.

## 
## 
##  ------------- 
## Byebye Dr. Ballard Langworth III
## You are now Dish Blood Cemetery Dish 
##  -------------- 
##               \   
##                \  
##                 \
##         __.--&#39;\     \.__./     /&#39;--.__
##     _.-&#39;       &#39;.__.&#39;    &#39;.__.&#39;       &#39;-._
##   .&#39;                                      &#39;.
##  /                                          \
## |                                            |
## |                                            |
##  \         .---.              .---.         /
##   &#39;._    .&#39;     &#39;.&#39;&#39;.    .&#39;&#39;.&#39;     &#39;.    _.&#39;
##      &#39;-./            \  /           \.-&#39;
##                       &#39;&#39;mrf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that &lt;a href=&#34;https://github.com/sckott/cowsay/issues/65&#34;&gt;I reported the message I got from
&lt;code&gt;cowsay&lt;/code&gt;&lt;/a&gt;. It’s not too bad,
&lt;code&gt;cowsay&lt;/code&gt; is not designed for use in R Markdown I think.&lt;/p&gt;
&lt;p&gt;I found the results not fantastic, but not too bad either! I especially
liked “Boogers Party”!&lt;/p&gt;
&lt;h1 id=&#34;mucus-anyone&#34;&gt;Mucus, anyone?&lt;/h1&gt;
&lt;p&gt;In conclusion, in this post I showed how to build a corpus of
Halloween-related words by responsibly webscraping, and how to more or
less hackily compare strings based on their pronunciation. I obviously
tried the function on my own name (without the accent, useless in this
case) and wasn’t too happy…&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;spookify&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Maelle Salmon&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;, words)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Colors cannot be applied in this environment :( Try using a terminal or RStudio.

## 
## 
##  ------------- 
## Byebye Maelle Salmon
## You are now Mucus Bulging 
##  -------------- 
##               \   
##                \  
##                 \
##         __.--&#39;\     \.__./     /&#39;--.__
##     _.-&#39;       &#39;.__.&#39;    &#39;.__.&#39;       &#39;-._
##   .&#39;                                      &#39;.
##  /                                          \
## |                                            |
## |                                            |
##  \         .---.              .---.         /
##   &#39;._    .&#39;     &#39;.&#39;&#39;.    .&#39;&#39;.&#39;     &#39;.    _.&#39;
##      &#39;-./            \  /           \.-&#39;
##                       &#39;&#39;mrf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But then, at least, it &lt;em&gt;is&lt;/em&gt; scary.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>O&#39;Reilly animals in trouble? Conservation status of book covers</title>
      <link>https://masalmon.eu/2018/08/25/oreilly/</link>
      <pubDate>Sat, 25 Aug 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/08/25/oreilly/</guid>
      <description>&lt;p&gt;What can a kaka, a kakapo, an European rabbit and a grey heron have in
common? Well, they might co-habit in the bookshelf of an R user, since
they’re all animals on the covers of popular R books: &lt;a href=&#34;http://r-pkgs.had.co.nz/&#34;&gt;“R
Packages”&lt;/a&gt;, &lt;a href=&#34;http://r4ds.had.co.nz/&#34;&gt;“R for Data
Science”&lt;/a&gt;, &lt;a href=&#34;https://www.tidytextmining.com/&#34;&gt;“Text mining with
R”&lt;/a&gt; and &lt;a href=&#34;https://csgillespie.github.io/efficientR/&#34;&gt;“Efficient R
programming”&lt;/a&gt;, respectively.
Their publisher, O’Reilly, has now based its brand on covers featuring
beautiful gravures of animals.&lt;/p&gt;
&lt;p&gt;Recently, while wondering what the name of R for Data Science bird was
again (I thought it was a kea!), I was thrilled to find &lt;a href=&#34;https://www.oreilly.com/animals.csp&#34;&gt;the whole
O’Reilly menagerie&lt;/a&gt;, i.e. a list of
books and corresponding animals! The website also features a link to &lt;a href=&#34;https://www.oreilly.com/ideas/a-short-history-of-the-oreilly-animals&#34;&gt;“A
short history of the O’Reilly
animals”&lt;/a&gt;
that was an amazing read. In it was noted that “The animals are in
trouble.”, with a few examples of endangered species. It inspired me to
actually try and assess the conservation status of O’Reilly animals
using responsible webscraping, taxonomic name resolving and IUCN Redlist
API querying…&lt;/p&gt;
&lt;h1 id=&#34;scraping-the-menagerie-an-utter-delight&#34;&gt;Scraping the menagerie: an utter delight!&lt;/h1&gt;
&lt;p&gt;I had a great time webscraping the menagerie, not only thanks to my now
reasonable experience doing such things, but also thanks to&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;my using the &lt;a href=&#34;https://github.com/dmi3kno/polite&#34;&gt;wonderful &lt;code&gt;polite&lt;/code&gt; package for
webscraping&lt;/a&gt;, that makes me feel
so good about myself. Read more about this package &lt;a href=&#34;https://masalmon.eu/2018/07/31/alldatascience/&#34;&gt;in my previous
post&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;the webpage having really good structured html with specific
classes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The menagerie is divided into pages of 20 books, so I mapped over all
possible offsets up to the number of animals indicated on the website,
1227.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
home_url &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.oreilly.com/animals.csp&amp;#34;&lt;/span&gt;

session &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; polite&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bow&lt;/span&gt;(home_url,
                       user_agent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Maëlle Salmon https://masalmon.eu/&amp;#34;&lt;/span&gt;)

get_twenty &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(offset, session){
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# offset parameter to get all books 20 by 20&lt;/span&gt;
  params &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;?x-o={offset}&amp;#34;&lt;/span&gt;)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# scraping with content parameter&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# cf https://github.com/dmi3kno/polite/issues/6&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# https://www.oreilly.com/animals.csp?x-o=720 was problematic&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# (German characters)&lt;/span&gt;
  page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; polite&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;scrape&lt;/span&gt;(session, params &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; params, 
                         content &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;text/html;charset=iso-8859-1&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get all animal rows&lt;/span&gt;
  rows &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_nodes&lt;/span&gt;(page,
                           xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;//div[@class=&amp;#39;animal-row&amp;#39;]&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# extract book titles&lt;/span&gt;
  rows &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_nodes&lt;/span&gt;(xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;a[@class=&amp;#39;book&amp;#39;]&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_nodes&lt;/span&gt;(xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;h1[@class=&amp;#39;book-title&amp;#39;]&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;html_text&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;-&amp;gt;&lt;/span&gt; book_titles
  
  rows &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_nodes&lt;/span&gt;(xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;h2[@class=&amp;#39;animal-name&amp;#39;]&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;html_text&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;-&amp;gt;&lt;/span&gt; animal_names
  
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(book &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; book_titles,
                 animal &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; animal_names)
  
}

no_animals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1227&lt;/span&gt; &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# by hand!&lt;/span&gt;

offsets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; (&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;floor&lt;/span&gt;(no_animals&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;))&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;

purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(offsets, get_twenty, session &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; session) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;oreilly_animals.csv&amp;#34;&lt;/span&gt;)
  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I got 1134 rows, each corresponding to a book, with animals potentially
repeated.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;animals
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 1,134 x 2
##    book                            animal                                 
##    &amp;lt;chr&amp;gt;                           &amp;lt;chr&amp;gt;                                  
##  1 Mobile Design and Development   12-Wired Bird of Paradise              
##  2 Windows PowerShell for Develop~ 3-Banded Armadillo                     
##  3 Jakarta Commons Cookbook        Aardvark                               
##  4 Clojure Cookbook                Aardwolf                               
##  5 Ubuntu: Up and Running          Addax, aka Screwhorn Antelope          
##  6 Social eCommerce                Adjutant (Storks)                      
##  7 BioBuilder                      Aegina Citrea, narcomedusae, jellyfish 
##  8 JRuby Cookbook                  African Civet                          
##  9 C# 5.0 Pocket Reference         African Crowned Crane aka Grey Crowned~
## 10 Programming C# 5.0              African Crowned Crane aka Grey Crowned~
## # ... with 1,124 more rows
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the short history of animals, Edie Freedman mentions having
discovered “that there were intriguing correspondences between specific
technologies and specific animals”. This made me curious about my last
name, Salmon!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;animals &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(animal, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[Ss]almon&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;book&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;animal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Values, Units, and Colors&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Salmon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;CSS Text&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Salmon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;CSS Fonts&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Salmon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Selectors, Specificity, and the Cascade&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Salmon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Transitions and Animations in CSS&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Salmon2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I have no idea what trait of salmons make them good at design, other
than my not sharing that trait with them. When my friend Adrien and I
wrote &lt;a href=&#34;https://www.editions-ellipses.fr/product_info.php?products_id=7159&#34;&gt;a (non O’Reilly)
book&lt;/a&gt;
years ago, we selected a frog for the cover based on its being pretty,
which is much less cool than O’Reilly branding!&lt;/p&gt;
&lt;h1 id=&#34;from-animals-common-names-to-scientific-names&#34;&gt;From animals common names to scientific names?&lt;/h1&gt;
&lt;p&gt;Now, you’ll have noticed the names of animals are written in English. My
ultimate goal being the querying of IUCN Red List API, and this API only
accepting scientific names (contrary to the website of the same
organization), I needed to resolve the common names to scientific names.
This is a hard problem! My strategy here was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cleaning the names a bit to remove the parts after “aka” for
instance.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;clean &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(animal){
  semiclean &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; animal &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_remove_all&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;aka.*&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_remove_all&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\,.*&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_remove_all&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\(.*&amp;#34;&lt;/span&gt;) 
  
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(semiclean &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;12-Wired Bird of Paradise&amp;#34;&lt;/span&gt;){
    semiclean &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Twelve-Wired Bird of Paradise&amp;#34;&lt;/span&gt;
  }
  
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(semiclean &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;3-Banded Armadillo&amp;#34;&lt;/span&gt;){
    semiclean &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Three-Banded Armadillo&amp;#34;&lt;/span&gt;
  }
  stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_remove_all&lt;/span&gt;(semiclean, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[0-9]&amp;#34;&lt;/span&gt;)
}


animals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(animals, animal_clean &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(animal, clean))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Using the &lt;a href=&#34;https://github.com/ropensci/taxize&#34;&gt;rOpenSci &lt;code&gt;taxize&lt;/code&gt;
package&lt;/a&gt; that has a handy
&lt;code&gt;comm2sci&lt;/code&gt; function. This function works for anyone, but it’s better
to request a key for the database used, EOL by default (see e.g.
&lt;code&gt;taxize::use_eol()&lt;/code&gt; for more info).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Not being too optimistic since the databases &lt;code&gt;taxize&lt;/code&gt; queries cannot
do wonders, no matter how good they are.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note that for each species, the first scientific name returned is
selected, because there’s no other criterion to go by. That’s how I’ll
end up with a Salmon catfish for Salmon, too bad.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;animal_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(animals&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;animal_clean)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# scientific names&lt;/span&gt;
good_comm2sci &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; memoise&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;memoise&lt;/span&gt;(taxize&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;comm2sci)

get_name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(common_name){
  sci_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;good_comm2sci&lt;/span&gt;(common_name)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# don&amp;#39;t get the name of who defined the species&lt;/span&gt;
  sci_name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;word&lt;/span&gt;(sci_names[[1]][1], start&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, end &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;)
  
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(common_name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; common_name,
                 sci_name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; sci_name)
}
scientific_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(animal_names, get_name)

animals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(animals,
                            scientific_names,
                            by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;animal_clean&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;common_name&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I got names for 694 books, out of 1134, getting 555 animals. It’s not
bad, but this number also needs to be treated with caution. See for
instance:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;animals &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(animal, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Galapagos&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;book&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;animal&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;animal_clean&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;sci_name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;PHP Cookbook&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Galapagos Land Iguana&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Galapagos Land Iguana&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Conolophus marthae&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Upgrading to PHP 5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Galapagos Tortoise&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Galapagos Tortoise&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chelonoidis nigra&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I noticed the iguana while perusing my results, and a quick internet
search taught me that there are &lt;em&gt;three&lt;/em&gt; species of terrestrial iguanas
in the Galapagos, the most common one, and the one probably present on
the book cover, being Conolophus subcristatus, not Conolophus marthae!
I’ve noticed a few other mistakes, so I’ll need to handle the results
with care. I now wish the menagerie had a bit more Latin in it!&lt;/p&gt;
&lt;h1 id=&#34;querying-the-iucn-red-list&#34;&gt;Querying the IUCN Red List&lt;/h1&gt;
&lt;p&gt;Indeed, scientific names of species are the key to a wealth of data!
&lt;a href=&#34;https://github.com/ropensci/traits&#34;&gt;Traits data&lt;/a&gt;, &lt;a href=&#34;https://github.com/ropensci/taxize&#34;&gt;taxonomic
information&lt;/a&gt;… and conservation
status thanks to the &lt;a href=&#34;http://www.iucnredlist.org/&#34;&gt;IUCN Red List&lt;/a&gt;, an
impressive assessment of species at the global scale. One can
programmatically query it using the &lt;a href=&#34;https://github.com/ropensci/traits&#34;&gt;rOpenSci &lt;code&gt;rredlist&lt;/code&gt;
package&lt;/a&gt;! That’s what I did, adding
a waiting time of 2 seconds between API calls, &lt;a href=&#34;https://github.com/ropensci/rredlist#rate-limiting&#34;&gt;as recommended by the
IUCN folks&lt;/a&gt;. Note
that I have an API key because I asked for it, see more info by typing
&lt;code&gt;rredlist::rl_use_iucn()&lt;/code&gt; after installing &lt;code&gt;rredlist&lt;/code&gt;, and be patient
since it can last a few days before one gets one.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;slow_rl_search &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ratelimitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;limit_rate&lt;/span&gt;(rredlist&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;rl_search,
                                         rate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; ratelimitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rate&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;))

get_status &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(sci_name){
  &lt;span style=&#34;color:#06287e&#34;&gt;message&lt;/span&gt;(sci_name)
  results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;slow_rl_search&lt;/span&gt;(sci_name)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;result
  
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.null&lt;/span&gt;(results)){
    results&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;sci_name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; sci_name
  }
  
  results
}

animals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(animals, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(sci_name))
purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(animals&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;sci_name), get_status) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;oreilly_animals_status.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;status &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;oreilly_animals_status.csv&amp;#34;&lt;/span&gt;)

animals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;oreilly_animals_scientific.csv&amp;#34;&lt;/span&gt;)

status &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(status, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(category))
animals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(animals, status, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sci_name&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;str&lt;/span&gt;(animals)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Classes &#39;tbl_df&#39;, &#39;tbl&#39; and &#39;data.frame&#39;:    1134 obs. of  32 variables:
##  $ book              : chr  &amp;quot;Mobile Design and Development&amp;quot; &amp;quot;Windows PowerShell for Developers&amp;quot; &amp;quot;Jakarta Commons Cookbook&amp;quot; &amp;quot;Clojure Cookbook&amp;quot; ...
##  $ animal            : chr  &amp;quot;12-Wired Bird of Paradise&amp;quot; &amp;quot;3-Banded Armadillo&amp;quot; &amp;quot;Aardvark&amp;quot; &amp;quot;Aardwolf&amp;quot; ...
##  $ animal_clean      : chr  &amp;quot;Twelve-Wired Bird of Paradise&amp;quot; &amp;quot;Three-Banded Armadillo&amp;quot; &amp;quot;Aardvark&amp;quot; &amp;quot;Aardwolf&amp;quot; ...
##  $ sci_name          : chr  &amp;quot;Seleucidis melanoleuca&amp;quot; &amp;quot;Tolypeutes tricinctus&amp;quot; &amp;quot;Cucumis humifructus&amp;quot; &amp;quot;Proteles cristata&amp;quot; ...
##  $ taxonid           : int  NA 21975 NA 18372 NA 22697721 NA 41589 22692046 22692046 ...
##  $ scientific_name   : chr  NA &amp;quot;Tolypeutes tricinctus&amp;quot; NA &amp;quot;Proteles cristata&amp;quot; ...
##  $ kingdom           : chr  NA &amp;quot;ANIMALIA&amp;quot; NA &amp;quot;ANIMALIA&amp;quot; ...
##  $ phylum            : chr  NA &amp;quot;CHORDATA&amp;quot; NA &amp;quot;CHORDATA&amp;quot; ...
##  $ class             : chr  NA &amp;quot;MAMMALIA&amp;quot; NA &amp;quot;MAMMALIA&amp;quot; ...
##  $ order             : chr  NA &amp;quot;CINGULATA&amp;quot; NA &amp;quot;CARNIVORA&amp;quot; ...
##  $ family            : chr  NA &amp;quot;CHLAMYPHORIDAE&amp;quot; NA &amp;quot;HYAENIDAE&amp;quot; ...
##  $ genus             : chr  NA &amp;quot;Tolypeutes&amp;quot; NA &amp;quot;Proteles&amp;quot; ...
##  $ main_common_name  : chr  NA &amp;quot;Brazilian Three-banded Armadillo&amp;quot; NA &amp;quot;Aardwolf&amp;quot; ...
##  $ authority         : chr  NA &amp;quot;(Linnaeus, 1758)&amp;quot; NA &amp;quot;(Sparrman, 1783)&amp;quot; ...
##  $ published_year    : int  NA 2014 NA 2015 NA 2016 NA 2015 2016 2016 ...
##  $ category          : chr  NA &amp;quot;VU&amp;quot; NA &amp;quot;LC&amp;quot; ...
##  $ criteria          : chr  NA &amp;quot;A2cd&amp;quot; NA NA ...
##  $ marine_system     : logi  NA FALSE NA FALSE NA FALSE ...
##  $ freshwater_system : logi  NA FALSE NA FALSE NA TRUE ...
##  $ terrestrial_system: logi  NA TRUE NA TRUE NA TRUE ...
##  $ assessor          : chr  NA &amp;quot;Miranda, F., Moraes-Barros, N., Superina, M. &amp;amp; Abba, A.M.&amp;quot; NA &amp;quot;Green, D.S.&amp;quot; ...
##  $ reviewer          : chr  NA &amp;quot;Loughry, J.&amp;quot; NA &amp;quot;Dloniak, S.M.D. &amp;amp; Holekamp, E.&amp;quot; ...
##  $ aoo_km2           : chr  NA NA NA NA ...
##  $ eoo_km2           : chr  NA &amp;quot;937000&amp;quot; NA NA ...
##  $ elevation_upper   : int  NA NA NA 2000 NA 550 NA 2500 NA NA ...
##  $ elevation_lower   : int  NA NA NA 0 NA 0 NA 0 0 0 ...
##  $ depth_upper       : num  NA NA NA NA NA NA NA NA NA NA ...
##  $ depth_lower       : int  NA NA NA NA NA NA NA NA NA NA ...
##  $ errata_flag       : logi  NA NA NA NA NA NA ...
##  $ errata_reason     : chr  NA NA NA NA ...
##  $ amended_flag      : logi  NA NA NA NA NA NA ...
##  $ amended_reason    : chr  NA NA NA NA ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are 1134 books, 499 with a conservation status from the IUCN Red
List, although this includes “DD” meaning “Data Deficient”. I am
hesitant to actually show the proportion of species in each category for
those for which I got data for, because the resolution of common names
to scientific names isn’t certain… Take the following table with a pinch
of salt!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(animals, category) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;category&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;CR&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;DD&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;EN&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;EW&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;EX&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;LC&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;348&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;LR/cd&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;LR/lc&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;LR/nt&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;NT&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;VU&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;48&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;635&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;See &lt;a href=&#34;https://en.wikipedia.org/wiki/IUCN_Red_List#IUCN_Red_List_Categories&#34;&gt;the following page for more precise information about
categories&lt;/a&gt;.
LC is least concern. Let’s have a look at the extinct species.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;animals &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(category &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;EX&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(book, animal, sci_name) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;book&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;animal&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;sci_name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Java Data Objects&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bilby, Rabbit-eared Bandicoot (Macrotis lagotis)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Macrotis leucura&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Building and Testing with Gradle&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bush Wren&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Xenicus longipes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Designing Mobile Payment Experiences&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Crested Pigeon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Microgoura meeki&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;SSH, The Secure Shell: The Definitive Guide&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Land Snail&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Amastra crassilabrum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Java NIO&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Pigfooted Bandicoot&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chaeropus ecaudatus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Java I/O&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;White Rabbit&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Macrotis leucura&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I searched for the covers and names and could assess that in that table,
there are 4 false positives due to the ambiguity of common names! Only
the Bush wren and the Pigfooted Bandicoot got scientific names
corresponding to what they look like, and are extinct, which is quite
sad.&lt;/p&gt;
&lt;p&gt;Now, to reverse-engineer what Edie Freedman wrote in the short history of
O’Reilly animals, “Many of the animals that appear on our covers are
critically endangered—the tarsier from Learning the vi &amp;amp; Vim Editors,
the lorises from sed &amp;amp; awk, the Hawksbill turtle from Getting Started
with CouchDB, the tiger from Running Mac OS X Tiger, and the African
elephant on Hadoop: The Definitive Guide, just to name a few.”, let’s
look at what we got for them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;animals &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(book &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt;
                  &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Hadoop: The Definitive Guide&amp;#34;&lt;/span&gt;,
                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Learning the vi and Vim Editors&amp;#34;&lt;/span&gt;,
                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sed &amp;amp; awk&amp;#34;&lt;/span&gt;,
                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Getting Started with CouchDB&amp;#34;&lt;/span&gt;,
                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Running Mac OS X Tiger&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(book, animal, sci_name, category) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;book&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;animal&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;sci_name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;category&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Hadoop: The Definitive Guide&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;African Elephant, young&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Elephantulus rozeti&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Getting Started with CouchDB&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hawksbill Turtle&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Eretmochelys imbricata&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;CR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sed &amp;amp; awk&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Slender Loris “Awk”&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Running Mac OS X Tiger&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Sumatran Tiger&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Parantica tityoides&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LR/nt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Learning the vi and Vim Editors&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tarsier, full-body, standing on hind feet, b/w engraving&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tarsius pelengensis&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;EN&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Again, our name resolution wasn’t very good!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The elephant should be Loxondota africana, &lt;a href=&#34;http://www.iucnredlist.org/details/12392/0&#34;&gt;vulnerable
species&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The turtle is right.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For the loris we should have gotten &lt;a href=&#34;http://www.iucnredlist.org/details/12375/0&#34;&gt;this
species&lt;/a&gt; that’s
endangered.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Sumatran tiger, Panthera tigris ssp. sumatrae , is &lt;a href=&#34;http://www.iucnredlist.org/details/15966/0&#34;&gt;critically
endangered&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There are several Tarsier species, I’m not sure which one is the
right one.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So all in all, we got some truth but also some wrong names and hence
wrong conservation statuses!&lt;/p&gt;
&lt;h1 id=&#34;conclusion-hoping-for-a-menagerie-of-scientific-names&#34;&gt;Conclusion: hoping for a menagerie of scientific names&lt;/h1&gt;
&lt;p&gt;In this post, I exemplified responsible webscraping with the use of &lt;a href=&#34;https://github.com/dmi3kno/polite&#34;&gt;the
&lt;code&gt;polite&lt;/code&gt; package&lt;/a&gt; to get a table of
all animals on O’Reilly book covers from the dedicated menagerie. I
tried resolving the common names to scientific names using
&lt;a href=&#34;https://github.com/ropensci/taxize&#34;&gt;&lt;code&gt;taxize::comm2sci&lt;/code&gt;&lt;/a&gt;, which was only
partly successful. I got conservation status for the scientific names
using the &lt;a href=&#34;https://github.com/ropensci/rredlist&#34;&gt;&lt;code&gt;rredlist&lt;/code&gt; package&lt;/a&gt;,
programmatic interface to the IUCN Red List. The results would be better
if O’Reilly published scientific names of animals, but nonetheless this
workflow helped me identify two extinct species, the Bush wren of
&lt;a href=&#34;http://shop.oreilly.com/product/0636920019909.do&#34;&gt;Building and Testing with
Gradle&lt;/a&gt; and the
Pigfooted Bandicoot of &lt;a href=&#34;http://shop.oreilly.com/product/9780596002886.do&#34;&gt;Java
NIO&lt;/a&gt;. I can’t but hope
the list of such now sad book covers won’t grow any longer…&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>ALLSTATisticians in decline? A polite look at ALLSTAT email Archives</title>
      <link>https://masalmon.eu/2018/07/31/alldatascience/</link>
      <pubDate>Tue, 31 Jul 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/07/31/alldatascience/</guid>
      <description>&lt;div id=&#34;webscraping-allstat&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Webscraping ALLSTAT&lt;/h1&gt;
&lt;div id=&#34;life-on-the-edge-of-easy-responsible-webscraping&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Life on the edge of easy responsible webscraping&lt;/h2&gt;
&lt;p&gt;As underlined in &lt;a href=&#34;https://towardsdatascience.com/ethics-in-web-scraping-b96b18136f01&#34;&gt;The Ethical Scraper’s principles by James Densmore&lt;/a&gt; (that I found in the &lt;a href=&#34;https://hanjostudy.github.io/Presentations/UseR2018/Rvest/rvest.html#1&#34;&gt;slides of Hanjo Odendaal’s useR! 2018 webscraping tutorial&lt;/a&gt;), a first step is to research whether you can get the data without webscraping (I found no API). Note that an ideal case would be to have received emails since the list’s creation in 1998, and having stored them, so that one could use this local copy. Or one could email the list maintainers of course!&lt;/p&gt;
&lt;p&gt;Then, there is some good practice to keep in mind whilst webscraping, also underlined in the principles list, and most importantly all encompassed in the &lt;a href=&#34;https://github.com/dmi3kno/polite&#34;&gt;awesome new package &lt;code&gt;polite&lt;/code&gt; by Dmytro Perepolkin&lt;/a&gt;! I knew the packages wrapped by Dmytro, but tended to only use &lt;code&gt;robotstxt&lt;/code&gt; e.g. &lt;a href=&#34;https://masalmon.eu/2018/06/18/mathtree/&#34;&gt;here&lt;/a&gt; when webscraping, (but &lt;a href=&#34;https://itsalocke.com/blog/some-web-api-package-development-lessons-from-hibpwned/&#34;&gt;using others in API packages&lt;/a&gt;). Now with very little effort, with &lt;code&gt;polite&lt;/code&gt; you will&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Seek permissions via &lt;a href=&#34;https://github.com/ropensci/robotstxt&#34;&gt;&lt;code&gt;robotstxt&lt;/code&gt;&lt;/a&gt;,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Introduce yourself with an &lt;a href=&#34;https://en.wikipedia.org/wiki/User_agent&#34;&gt;user agent&lt;/a&gt;, by default the package’s name and URL,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Take it slowly&lt;/em&gt; thanks to &lt;a href=&#34;https://github.com/tarakc02/ratelimitr&#34;&gt;&lt;code&gt;ratelimitr&lt;/code&gt;&lt;/a&gt;,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Never ask twice&lt;/em&gt; thanks to &lt;a href=&#34;https://github.com/r-lib/memoise&#34;&gt;&lt;code&gt;memoise&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;polite&lt;/code&gt; package is brand-new, still in development, which in general means you might want to stay away from it for a while, but I was eager to try it and pleased by its working very well! Being an early adopter also means I saw &lt;a href=&#34;https://github.com/dmi3kno/polite/issues?utf8=%E2%9C%93&amp;amp;q=is%3Aissue+author%3Amaelle+&#34;&gt;my issues&lt;/a&gt; promptly closed with some solution/new code by Dmytro!&lt;/p&gt;
&lt;p&gt;I started work by &lt;em&gt;bowing&lt;/em&gt; which in &lt;code&gt;polite&lt;/code&gt;’s workflow means both creating a session (with user-agent, delay between calls) and checking that the path is allowed.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;home_url &amp;lt;- &amp;quot;https://www.jiscmail.ac.uk/cgi-bin/webadmin&amp;quot;

session &amp;lt;- polite::bow(home_url,
                       user_agent = &amp;quot;Maëlle Salmon https://masalmon.eu/&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then it was time to scrape and parse…&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;actual-webscraping-a.k.a-solving-xpath-puzzles&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Actual webscraping a.k.a solving XPath puzzles&lt;/h2&gt;
&lt;p&gt;When confronted with a page I’d like to extract info from, I try to identify how I can write &lt;a href=&#34;https://www.w3schools.com/xml/xpath_intro.asp&#34;&gt;XPath&lt;/a&gt; to get the elements I want, which means looking at the page source. I used to transform whole pages to text before using regexp on them, which was clearly suboptimal, thanks to &lt;a href=&#34;https://twitter.com/expersso/&#34;&gt;Eric Persson&lt;/a&gt; for &lt;a href=&#34;https://masalmon.eu/2017/04/23/radioswissclassic/&#34;&gt;making me switch to XPath&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My strategy here was to get the subject, date, sender and size of each email from archive pages. &lt;a href=&#34;https://www.jiscmail.ac.uk/cgi-bin/webadmin?A1=ind0703&amp;amp;L=ALLSTAT&#34;&gt;Here&lt;/a&gt; is such an archive page. Nowadays there is one archive page by month, but there used to be one by year, so I got the list of archive pages from &lt;a href=&#34;https://www.jiscmail.ac.uk/cgi-bin/webadmin?A0=ALLSTAT&#34;&gt;this general page&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(&amp;quot;magrittr&amp;quot;)

polite::scrape(session, params = &amp;quot;?A0=ALLSTAT&amp;quot;) %&amp;gt;%
  rvest::xml_nodes(&amp;quot;li&amp;quot;) %&amp;gt;%
  rvest::xml_nodes(&amp;quot;a&amp;quot;) %&amp;gt;%
  rvest::html_attr(&amp;quot;href&amp;quot;) %&amp;gt;%
  purrr::keep(function(x) stringr::str_detect(x, &amp;quot;\\/cgi-bin\\/webadmin\\?A1\\=&amp;quot;)) %&amp;gt;%
  stringr::str_remove(&amp;quot;\\/cgi\\-bin\\/webadmin\\?A1\\=ind&amp;quot;) %&amp;gt;%
  stringr::str_remove(&amp;quot;\\&amp;amp;L\\=ALLSTAT&amp;quot;) -&amp;gt; date_strings&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is not very elegant but this got me only the “1807” and such I needed for the rest of the scraping. &lt;code&gt;polite::scrape&lt;/code&gt; is a wrapper to both &lt;code&gt;httr::GET&lt;/code&gt; and &lt;code&gt;httr::content&lt;/code&gt; and does the rate limiting (by default 1 call every 5 seconds, &lt;code&gt;delay&lt;/code&gt; parameter of &lt;code&gt;polite::bow&lt;/code&gt;) and memoising. I actually ended up only scraping emails metadata from 2007 because it took ages to parse the 2006 page. It made me, according to a search via the website, miss these data scientists job openings: &lt;a href=&#34;https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind00&amp;amp;L=ALLSTAT&amp;amp;P=R80005&amp;amp;1=ALLSTAT&amp;amp;9=A&amp;amp;I=-3&amp;amp;J=on&amp;amp;K=8&amp;amp;d=No+Match%3BMatch%3BMatches&amp;amp;z=4&#34;&gt;one in 2000&lt;/a&gt; and &lt;a href=&#34;https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind04&amp;amp;L=ALLSTAT&amp;amp;P=R83293&amp;amp;1=ALLSTAT&amp;amp;9=A&amp;amp;I=-3&amp;amp;J=on&amp;amp;K=8&amp;amp;d=No+Match%3BMatch%3BMatches&amp;amp;z=4&#34;&gt;one in 2004&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;date_strings &amp;lt;- date_strings[stringr::str_length(date_strings) != 2]
# or
date_strings &amp;lt;- purrr::discard(date_strings, function(x) stringr::str_length(x) == 2)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I created a function getting the metadata out of each archive page. The trickiest points here were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;That the rows of the archive table could have two classes, which is the way alternate coloring was obtained. I therefore used &lt;code&gt;|&lt;/code&gt; in XPath &lt;code&gt;&#39;//tr[@class=&amp;quot;normalgroup&amp;quot;]|//tr[@class=&amp;quot;emphasizedgroup&amp;quot;]&#39;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;That there was no different class/formatting for subject, date, sender, so I got all of them at once, and then used the modulo operator, &lt;code&gt;%%&lt;/code&gt;, to assign them to the right vector.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;get_emails_meta_by_date &amp;lt;- function(date_string, session){
  message(date_string)
  params &amp;lt;- glue::glue(&amp;quot;?A1=ind{date_string}&amp;amp;L=ALLSTAT&amp;amp;F=&amp;amp;S=&amp;amp;O=T&amp;amp;H=0&amp;amp;D=0&amp;amp;T=0&amp;quot;)
  
  everything &amp;lt;- try(polite::scrape(session, params = params),
                    silent = TRUE)
  
  # at the time of writing one couldn&amp;#39;t pass encoding to scrape
  # but now one can https://github.com/dmi3kno/polite/issues/6#issuecomment-409268730
  if(is(everything, &amp;quot;try-error&amp;quot;)){
    everything &amp;lt;- httr::GET(paste0(home_url,
                                   params)) %&amp;gt;%
      httr::content(encoding = &amp;quot;latin1&amp;quot;)
  }
  
  everything &amp;lt;- everything %&amp;gt;%
    # there are two classes that correspond
    # to the table having two colours of rows!
    rvest::xml_nodes(XPath = &amp;#39;//tr[@class=&amp;quot;normalgroup&amp;quot;]|//tr[@class=&amp;quot;emphasizedgroup&amp;quot;]&amp;#39;) %&amp;gt;%
    rvest::xml_nodes(&amp;quot;span&amp;quot;)
  
  everything %&amp;gt;%
    rvest::xml_nodes(XPath = &amp;quot;//td&amp;quot;) %&amp;gt;%
    rvest::xml_nodes(&amp;quot;span&amp;quot;) %&amp;gt;%
    rvest::xml_nodes(&amp;quot;a&amp;quot;) %&amp;gt;%
    rvest::html_text() -&amp;gt; subjects
  
  everything %&amp;gt;%
    rvest::xml_nodes(XPath = &amp;quot;//td[@nowrap]&amp;quot;) %&amp;gt;%
    rvest::xml_nodes(XPath = &amp;quot;p[@class=&amp;#39;archive&amp;#39;]&amp;quot;) %&amp;gt;%
    rvest::html_text() -&amp;gt; big_mess
  
  senders &amp;lt;- big_mess[seq_along(big_mess) %% 3 == 1]
  senders &amp;lt;- stringr::str_remove(senders, &amp;quot; \\&amp;lt;\\[log in to unmask\\]\\&amp;gt;&amp;quot;)
  
  dates &amp;lt;- big_mess[seq_along(big_mess) %% 3 == 2]
  dates &amp;lt;- lubridate::dmy_hms(dates, tz = &amp;quot;UTC&amp;quot;)
  
  sizes &amp;lt;- big_mess[seq_along(big_mess) %% 3 == 0]
  sizes &amp;lt;- stringr::str_remove(sizes, &amp;quot; lines&amp;quot;)
  sizes &amp;lt;- as.numeric(sizes)
  
  tibble::tibble(subject = subjects,
                 sender = senders,
                 date = dates,
                 size = sizes) %&amp;gt;%
    readr::write_csv(glue::glue(&amp;quot;data/emails_meta{date_string}.csv&amp;quot;))
  
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I chose to save the metadata of each archive page in its own csv in order to make my workflow less breakable. I could have used &lt;code&gt;purrr::map_df&lt;/code&gt; but then it’d be harder to re-start, and it was hard on memory apparently.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;fs::dir_create(&amp;quot;data&amp;quot;)
purrr::walk(date_strings,
              get_emails_meta_by_date,
              session = session)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;analyzing-allstat-jobs&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Analyzing ALLSTAT jobs&lt;/h1&gt;
&lt;div id=&#34;filtering-jobs&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Filtering jobs&lt;/h2&gt;
&lt;p&gt;ALLSTAT encourages you to use keywords in emails’ subjects, so many job openings contain some variant of “job”, and that’s the sample on which I shall work.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(&amp;quot;magrittr&amp;quot;)
library(&amp;quot;magrittr&amp;quot;)

fs::dir_ls(&amp;quot;../../static/data/allstat&amp;quot;) %&amp;gt;%
  purrr::map_df(readr::read_csv) -&amp;gt; emails

jobs &amp;lt;- dplyr::filter(emails, 
                      stringr::str_detect(subject,
                                          &amp;quot;[Jj][Oo][Bb]&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Out of 32761 emails I got 9245 job openings.&lt;/p&gt;
&lt;p&gt;I created two dummy variables to indicate the presence of data scientist or statistician in the description. With the definition below, the “statistician” category might contain “biostatitisticians” which is fine by me.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;jobs &amp;lt;- dplyr::mutate(jobs,
                      data_scientist = stringr::str_detect(subject, 
                                                           &amp;quot;[Dd]ata [Ss]cientist&amp;quot;),
                      statistician = stringr::str_detect(subject, 
                                                          &amp;quot;[Ss]tatistician&amp;quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;176 subjects contain the word “data scientist”, 2546 the word “statistician.”, 20 both.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dplyr::filter(jobs, data_scientist, statistician) %&amp;gt;%
  dplyr::select(subject, sender, date) %&amp;gt;%
  knitr::kable()&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&#34;header&#34;&gt;
&lt;th align=&#34;left&#34;&gt;subject&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;sender&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;date&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;JOB: Statisticians/Data Scientists with Unilever&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Murray, Peter&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2008-02-12 08:47:56&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Jobs: Senior Data Scientists/Statisticians&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Cox, Trevor&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2008-03-12 16:24:48&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;20 new job ads for data scientists, statisticians&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Vincent Granville&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-06-16 00:18:27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;23 new jobs for statisticians, data scientists&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Vincent Granville&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-07-27 20:05:48&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;19 new job ads for statisticians and data scientists&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Vincent Granville&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-10-12 23:21:23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Job Data scientist / Statistician&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Andrea Schirru&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-07-22 16:38:59&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;JOB: Computational Statistician / Data Scientist&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;David Hastie&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-07-16 11:36:34&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Job Openings: Statisticians and Data Scientists at Open Analytics (Belgium)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tobias Verbeke&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-06-30 09:53:21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;JOBS x 2: Data Scientist/Medical Statistician at University of Manchester&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Matthew Sperrin&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-07-28 10:42:52&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;JOB: Data scientist - Statistician (KTP associate) @ University of Essex&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aris Perperoglou&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-09-12 10:33:32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;JOB: Principal Statistician/ Data Scientist- Pharma - Perm - Centralised Monitoring- Data Safety - Global Search-UK&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Sabrina Andresen&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-10-17 16:05:12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;JOB: Research Associate - Statistician / Data Scientist, University of Manchester (Centre for Musculoskeletal Research)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Jamie Sergeant&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-11-01 10:21:07&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;JOB - Statistician / Data Scientist at Cefas, UK&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;David Maxwell&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-04 16:15:25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Job: Data Scientist/Statistician at Essex University&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aris Perperoglou&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-21 13:43:43&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Job: Statistician/Data Scientist&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Roisin McCarthy&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-06 16:49:18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Job Openings: Statisticians and Data Scientists at Open Analytics (Belgium)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tobias Verbeke&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-05 20:48:39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;JOB | StatsJobs - Data Scientist/Statistician, Zurich Insurance&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;James Phillips&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-30 08:59:49&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;JOB | Junior Medical statistician / Real-world data scientist - Centre of Excellence for Retrospective Studies, IQVIA (London)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Venerus, Alessandra&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-05 10:33:09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;odd&#34;&gt;
&lt;td align=&#34;left&#34;&gt;JOB | Senior Medical statistician / Real-world data scientist - Centre of Excellence for Retrospective Studies, IQVIA (London)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Venerus, Alessandra&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-05 10:32:51&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&#34;even&#34;&gt;
&lt;td align=&#34;left&#34;&gt;Job: Catalyst Project Research Data Scientist / Statistician&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aris Perperoglou&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-06-25 14:17:18&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Are the job titles synonymous for the organizations using slashes? I am especially puzzled by “Senior Medical statistician / Real-world data scientist”! I filtered them out and created a &lt;code&gt;category&lt;/code&gt; variable.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;jobs &amp;lt;- dplyr::filter(jobs,
                      !(data_scientist&amp;amp;statistician))
jobs &amp;lt;- dplyr::mutate(jobs,
                      category = dplyr::case_when(data_scientist ~ &amp;quot;data scientist&amp;quot;,
                                                  statistician ~ &amp;quot;statistician&amp;quot;,
                                                  TRUE ~ &amp;quot;other&amp;quot;),
                      category = factor(category,
                                        levels = c(&amp;quot;statistician&amp;quot;,
                                                   &amp;quot;data scientist&amp;quot;,
                                                   &amp;quot;other&amp;quot;),
                                        ordered = TRUE))

jobs &amp;lt;- dplyr::mutate(jobs,
                      year = lubridate::year(date),
                      year = as.factor(year))&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here are some examples of positions for each:&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;head(jobs$subject[jobs$category==&amp;quot;statistician&amp;quot;])&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;FW: JOB: Senior/Lead Statistician - GlaxoSmithKline&amp;quot;                   
## [2] &amp;quot;JOB - Clinical Trial Statisticians and SAS Programmers&amp;quot;                
## [3] &amp;quot;JOB - Medical statistician in Salvador, Brazil (2-3 years)&amp;quot;            
## [4] &amp;quot;JOB - Medical Statistician, Oxford&amp;quot;                                    
## [5] &amp;quot;JOB OPPORTUNITY - 39408 - Entry-Level Statisticians - GSK&amp;quot;             
## [6] &amp;quot;JOB: Biostatistician - Contract/Consultancy Opportunity - Switzer land&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;head(jobs$subject[jobs$category==&amp;quot;data scientist&amp;quot;])&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;JOB: Data Scientist, Unilever&amp;quot;                                 
## [2] &amp;quot;JOB: Data Scientist, Unilever&amp;quot;                                 
## [3] &amp;quot;JOB: Data Scientist / Machine Learning (BELFAST)&amp;quot;              
## [4] &amp;quot;JOB: Data Scientists in Belfast&amp;quot;                               
## [5] &amp;quot;JOBS: Data Scientists&amp;quot;                                         
## [6] &amp;quot;[Job] Hacker or Botnet Developer, Data Scientist (Telecommute)&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;head(jobs$subject[jobs$category==&amp;quot;other&amp;quot;])&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Job - Data manager Dept of Haematology, Imperial College, London&amp;quot;                  
## [2] &amp;quot;Re: JOB - Health Economic Modelling and Value Demonstrations&amp;quot;                      
## [3] &amp;quot;JOB - Lectureship / readership&amp;quot;                                                    
## [4] &amp;quot;JOB - Mathematical Modeller at the Health Protection Agency, Centre for Infections&amp;quot;
## [5] &amp;quot;JOB - PhD position&amp;quot;                                                                
## [6] &amp;quot;JOB - SAS Senior Statistical Programmer, Oxford&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div id=&#34;are-data-scientists-on-the-rise&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Are data scientists on the rise?&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(&amp;quot;ggplot2&amp;quot;)

ggplot(jobs) +
  geom_bar(aes(year, fill = category)) +
  viridis::scale_fill_viridis(discrete = TRUE) +
  theme(legend.position = &amp;quot;bottom&amp;quot;) +
  hrbrthemes::theme_ipsum(base_size = 14) +
  xlab(&amp;quot;Year (2018 not complete yet)&amp;quot;) +
  ylab(&amp;quot;Number of job openings&amp;quot;) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
  ggtitle(&amp;quot;ALLSTAT mailing list 2007-2018&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/post/2018-07-31-alldatascience_files/figure-html/unnamed-chunk-6-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;I like this bar plot that shows how the total number of job openings fluctuates, but it’s hard to see differences in proportions.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;ggplot(jobs) +
  geom_bar(aes(year, fill = category),
           position = &amp;quot;fill&amp;quot;) +
  viridis::scale_fill_viridis(discrete = TRUE) +
  theme(legend.position = &amp;quot;bottom&amp;quot;) +
  hrbrthemes::theme_ipsum(base_size = 14) +
  xlab(&amp;quot;Year (2018 not complete yet)&amp;quot;) +
  ylab(&amp;quot;Number of job openings&amp;quot;)  +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))+
  ggtitle(&amp;quot;ALLSTAT mailing list 2007-2018&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/post/2018-07-31-alldatascience_files/figure-html/unnamed-chunk-7-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;According to this plot, although there seems to be more and more data scientists’ jobs advertised on ALLSTAT… Statisticians don’t need to get worried just yet.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;who-offers-data-scientists-jobs&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;Who offers data scientists’ jobs?&lt;/h2&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;dplyr::count(jobs, category,
                sender) %&amp;gt;%
  dplyr::group_by(category) %&amp;gt;%
  dplyr::arrange(category, - n) %&amp;gt;%
  dplyr::filter(sender %in% sender[1:5])&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;## # A tibble: 15 x 3
## # Groups:   category [3]
##    category       sender                     n
##    &amp;lt;ord&amp;gt;          &amp;lt;chr&amp;gt;                  &amp;lt;int&amp;gt;
##  1 statistician   James Phillips           106
##  2 statistician   Sabrina Andresen          82
##  3 statistician   James Miller              45
##  4 statistician   Angela Smythe             40
##  5 statistician   Helena Newman-Mitchell    37
##  6 data scientist James Phillips            86
##  7 data scientist Sportradar HR              5
##  8 data scientist Jason Howlin               4
##  9 data scientist Deborah Gee                3
## 10 data scientist Christos Mitas             2
## 11 other          James Phillips           671
## 12 other          Angela Smythe            223
## 13 other          Helena Newman-Mitchell   103
## 14 other          Jason Howlin              91
## 15 other          James Miller              85&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Seeing James Phillips’ name so often made me have a look at their emails: this person sends emails on the behalf of a website called StatsJobs.com! We can also assume that other super-senders actually work for job aggregators of some sort.&lt;/p&gt;
&lt;/div&gt;
&lt;div id=&#34;what-are-the-openings-about&#34; class=&#34;section level2&#34;&gt;
&lt;h2&gt;What are the openings about?&lt;/h2&gt;
&lt;p&gt;To make a more thorough description of the different categories, one would need to get the email bodies, which I decided against for this post. I simply used the subjects, and compared word usage between the “data scientist” and “statistician” categories as &lt;a href=&#34;https://www.tidytextmining.com/twitter.html&#34;&gt;in this chapter of the Tidy text mining book by Julia Silge and David Robinson&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&#34;r&#34;&gt;&lt;code&gt;library(&amp;quot;tidytext&amp;quot;)
data(&amp;quot;stop_words&amp;quot;)
words &amp;lt;- dplyr::filter(jobs, category != &amp;quot;other&amp;quot;) %&amp;gt;%
  unnest_tokens(word, subject, token = &amp;quot;words&amp;quot;) %&amp;gt;%
  dplyr::filter(!word %in% stop_words$word,
                !word %in% c(&amp;quot;job&amp;quot;, &amp;quot;statistician&amp;quot;, 
                             &amp;quot;jobs&amp;quot;, &amp;quot;statisticians&amp;quot;,
                             &amp;quot;data&amp;quot;, &amp;quot;scientist&amp;quot;,
                             &amp;quot;scientists&amp;quot;,
                             &amp;quot;datascientistjobs&amp;quot;))

word_ratios &amp;lt;- words %&amp;gt;%
  dplyr::count(word, category) %&amp;gt;%
  dplyr::group_by(word) %&amp;gt;%
  dplyr::filter(sum(n) &amp;gt;= 10) %&amp;gt;%
  dplyr::ungroup() %&amp;gt;%
  tidyr::spread(category, n, fill = 0) %&amp;gt;%
  dplyr::mutate_if(is.numeric, dplyr::funs((. + 1) / sum(. + 1))) %&amp;gt;%
  dplyr::mutate(logratio = log(`data scientist` / statistician)) %&amp;gt;%
  dplyr::arrange(desc(logratio))

word_ratios %&amp;gt;%
  dplyr::group_by(logratio &amp;lt; 0) %&amp;gt;%
  dplyr::top_n(15, abs(logratio)) %&amp;gt;%
  dplyr::ungroup() %&amp;gt;%
  dplyr::mutate(word = reorder(word, logratio)) %&amp;gt;%
  ggplot(aes(word, logratio, fill = logratio &amp;lt; 0)) +
  geom_col(show.legend = FALSE) +
  coord_flip() +
  ylab(&amp;quot;log odds ratio (data scientist / statistician)&amp;quot;) +
  scale_fill_manual(name = &amp;quot;&amp;quot;, 
                    values = c(&amp;quot;#21908CFF&amp;quot;, &amp;quot;#440154FF&amp;quot;),
                    labels = c(&amp;quot;data scientist&amp;quot;, &amp;quot;statistician&amp;quot;)) +
  hrbrthemes::theme_ipsum(base_size = 11)+
  ggtitle(&amp;quot;ALLSTAT mailing list 2007-2018&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/post/2018-07-31-alldatascience_files/figure-html/unnamed-chunk-9-1.png&#34; width=&#34;672&#34; /&gt;&lt;/p&gt;
&lt;p&gt;What does this figure show? On the left are words more frequent in statistician job openings, on the right words more frequent in data scientist job openings. Well, there might be geographical clusters for each of the category, which I don’t believe though: is the data scientist vs. statistician debate a Cambridgeshire vs. Oxford battle? I was surprised that no word related to academia made an appearance because I thought “university” or an equivalent word would be more representative of statisticians. I am less surprised, though, by words such as “trials”, “medical”, “clinical” being more prevalent in the “statistician” category. The word “fixed” as in “fixed-term” contract is more prevalent for data scientist job openings, which doesn’t sound too cool?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&#34;conclusion&#34; class=&#34;section level1&#34;&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In this post, I had the pleasure to use the brand-new &lt;code&gt;polite&lt;/code&gt; package that made responsible webscraping very smooth! Armed with that tool, I extracted metadata of job openings posted on the ALLSTAT mailing lists. I made no &lt;em&gt;statistical&lt;/em&gt; analyses, but the main take-away is that statisticians aren’t in danger of extinction just yet.&lt;/p&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Where to get help with your R question?</title>
      <link>https://masalmon.eu/2018/07/22/wheretogethelp/</link>
      <pubDate>Sun, 22 Jul 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/07/22/wheretogethelp/</guid>
      <description>&lt;p&gt;Last time I blogged, I offered &lt;a href=&#34;https://masalmon.eu/2018/07/16/soapbox/&#34;&gt;my &lt;s&gt;obnoxious&lt;/s&gt; helpful advice for blog content and promotion&lt;/a&gt;. Today, let me again be the agony aunt you didn&amp;rsquo;t even write to! Imagine you have an &lt;em&gt;R question&lt;/em&gt;, i.e. a question related to how you can do something with R, and your search engine efforts haven&amp;rsquo;t been too successful: where should you ask it to increase your chance of its getting answered? You could see this post as my future answer to stray suboptimal Twitter R questions, or as a more general version of Scott Chamberlain&amp;rsquo;s excellent talk about how to get help related to rOpenSci software in the &lt;a href=&#34;http://communitycalls.ropensci.org/&#34;&gt;2017-03-07 rOpenSci comm call&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I think that the general journey to getting answers to your R questions is first trying your best to get answers locally in the documentation of R, then to use a search engine, and then to post a well-formulated question &lt;em&gt;somewhere&lt;/em&gt;. My post is aimed at helping you find that &lt;em&gt;somewhere&lt;/em&gt;. Note that &lt;a href=&#34;https://community.rstudio.com/t/faq-is-it-ok-if-i-cross-post/5218&#34;&gt;it&amp;rsquo;s considered best practice to ask in one &lt;em&gt;somewhere&lt;/em&gt; at once&lt;/a&gt;, and to then move on to another &lt;em&gt;somewhere&lt;/em&gt; if you haven&amp;rsquo;t got any answer&amp;hellip; or if someone kindly redirects you to a better venue!&lt;/p&gt;
&lt;p&gt;One thing this post isn&amp;rsquo;t about is &lt;em&gt;how&lt;/em&gt; to ask for help to &lt;em&gt;humans&lt;/em&gt;, which is a topic that&amp;rsquo;s e.g. covered very well in &lt;a href=&#34;https://vimeo.com/208749032&#34;&gt;Jenny Bryan&amp;rsquo;s talk about &lt;code&gt;reprex&lt;/code&gt;&lt;/a&gt; in the &lt;a href=&#34;http://communitycalls.ropensci.org/&#34;&gt;same 2017-03-07 rOpenSci comm call&lt;/a&gt;, but I&amp;rsquo;ll link out to useful resources I&amp;rsquo;ve found. This post is also not about &lt;em&gt;how&lt;/em&gt; to ask for help to e.g. Google, and I don&amp;rsquo;t know of a good search engine guide yet although e.g. &amp;ldquo;It can be particularly helpful to paste an error message into a search engine to find out whether others have solved a problem that you encountered.&amp;rdquo; in &lt;a href=&#34;https://www.r-project.org/help.html&#34;&gt;https://www.r-project.org/help.html&lt;/a&gt; is true.&lt;/p&gt;
&lt;h1 id=&#34;public-question-platforms-vs-safe-spaces&#34;&gt;Public question platforms vs. safe spaces?&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll start this post with a general comment for newbies who aren&amp;rsquo;t at ease enough yet to post their question, no matter what type of questions (see later), to anywhere public: find your safe and friendly space!&lt;/p&gt;
&lt;h2 id=&#34;lean-on-your-current-friends&#34;&gt;Lean on your current friend(s)&lt;/h2&gt;
&lt;p&gt;Do you have an R friend? Maybe this colleague who actually convinced you to start using R? Well, ask this person for help! Remind them it&amp;rsquo;s their fault you&amp;rsquo;re struggling now.&lt;/p&gt;
&lt;p&gt;And if you&amp;rsquo;re not a newbie but are reading this now, be this R friend! Mentor newbies on their way to be better R users and askers.&lt;/p&gt;
&lt;h2 id=&#34;find-new-friends&#34;&gt;Find new friends&lt;/h2&gt;
&lt;p&gt;Join a community, and ask your questions there. More specifically, you can join the &lt;a href=&#34;https://www.jessemaegan.com/post/r4ds-the-next-iteration/&#34;&gt;R4DS community&lt;/a&gt;; your &lt;a href=&#34;https://rladies.org/&#34;&gt;local&lt;/a&gt;/&lt;a href=&#34;http://eepurl.com/dy1bm1&#34;&gt;remote&lt;/a&gt; R-Ladies community (as a reminder, &lt;a href=&#34;https://rladies.org/about-us/&#34;&gt;this doesn&amp;rsquo;t mean women only&lt;/a&gt; but instead &amp;ldquo;minority genders (including but not limited to cis/trans women, trans men, non-binary, genderqueer, agender)&amp;quot;); this &lt;a href=&#34;https://lstu.fr/rgrrr&#34;&gt;French-speaking community&lt;/a&gt;. Such communities most often have Slack workspaces or equivalent, with an r-help channel, as well as a code of conduct and a general friendly attitude. Build your confidence there, and soon, you&amp;rsquo;ll be out asking (and answering!) R questions in the wilderness as well.&lt;/p&gt;
&lt;p&gt;Note, if you know of any list of such friendly communities, please tell me. I only know of &lt;a href=&#34;http://blog.revolutionanalytics.com/local-r-groups.html&#34;&gt;this list (of lists) of R User Groups and Conferences by David Smith&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;spotlight-on-my-typology-of-r-questions&#34;&gt;Spotlight on my typology of R questions&lt;/h1&gt;
&lt;p&gt;One thing I especially like about Scott Chamberlain&amp;rsquo;s slidedeck is his typology of methods to get help, &lt;a href=&#34;https://scotttalks.info/qropensci/#/good-for&#34;&gt;&amp;ldquo;methods and what they&amp;rsquo;re good for&amp;rdquo;&lt;/a&gt;. I&amp;rsquo;ll build this post based on a typology of questions, that also intersects with a typology of your newbiness-nervousness.&lt;/p&gt;
&lt;p&gt;I tend to think of R questions as pertaining to one of these categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;is this a bug, why am I stuck with this code? how do I install &lt;code&gt;rJava&lt;/code&gt; on my laptop? (problem!) Problems encompass actual bugs, and problems where the problem is your code rather than the package (I&amp;rsquo;ll admit that I find joy in my code&amp;rsquo;s sometimes not being the problem, although this doesn&amp;rsquo;t solve the problem.).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;is there a tool in R for doing &lt;code&gt;foo&lt;/code&gt;? how do I learn about &lt;code&gt;bar&lt;/code&gt;? (question!)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;what&amp;rsquo;s the best plotting library in R? dependencies, is less more? (debate!)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I agree that the difference between &lt;em&gt;debate&lt;/em&gt; and &lt;em&gt;question&lt;/em&gt; might be thin, in my mind &lt;em&gt;question&lt;/em&gt; questions have more of a trivia aspect, with answers being easier.&lt;/p&gt;
&lt;h1 id=&#34;where-to-ask-your-_problem_-question&#34;&gt;Where to ask your &lt;em&gt;problem&lt;/em&gt; question&lt;/h1&gt;
&lt;p&gt;Scenario: you wrote R code, and it doesn&amp;rsquo;t do what you expected it to, which includes the glorious cases of not running at all or of using packages you haven&amp;rsquo;t even been able to install. What do you do then?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If your problem is linked to a package in particular, i.e. you know the function that&amp;rsquo;s causing you sorrow comes from the &lt;code&gt;foo&lt;/code&gt; package, then your question is a &lt;code&gt;foo&lt;/code&gt; question or bug report. So what you need to find now is the platform to report bugs and ask questions about &lt;code&gt;foo&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;It might be written in &lt;code&gt;foo&lt;/code&gt; docs/metadata. Have a look in the docs, and observe the website or development repository of the package. E.g. if you use &lt;code&gt;blogdown&lt;/code&gt;, its BugReports URL is &lt;a href=&#34;https://github.com/rstudio/blogdown/issues&#34;&gt;https://github.com/rstudio/blogdown/issues&lt;/a&gt; and if you were to try and open an issue there with your bug or other problem, you&amp;rsquo;d get to see &lt;a href=&#34;https://github.com/rstudio/blogdown/blob/master/.github/ISSUE_TEMPLATE.md#consider-stackoverflow-first&#34;&gt;the template that tells you to use Stack Overflow first for general questions&lt;/a&gt;. GitHub repos can also contain question guidance as part of their CONTRIBUTING.md. If you use &lt;code&gt;INLA&lt;/code&gt; and have questions, you&amp;rsquo;ll find &lt;a href=&#34;http://www.r-inla.org/help&#34;&gt;http://www.r-inla.org/help&lt;/a&gt; useful. I remember having many questions about &lt;code&gt;INLA&lt;/code&gt; during my PhD, and sometimes having to ask them in the mailing list when the docs couldn&amp;rsquo;t help me any further.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You&amp;rsquo;ll rarely have to email the maintainer of a package, but you might have to, e.g. if you wonder whether the package will be further maintained or &lt;a href=&#34;https://scotttalks.info/qropensci/#/good-for&#34;&gt;as Scott said here, if your problem is specific to some sensitive data and an rOpenSci package&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sometimes &lt;code&gt;foo&lt;/code&gt; provider can also be a clue. If &lt;code&gt;foo&lt;/code&gt; is an &lt;a href=&#34;https://ropensci.org/packages/&#34;&gt;rOpenSci package&lt;/a&gt;, you can ask for help on &lt;a href=&#34;https://discuss.ropensci.org/&#34;&gt;rOpenSci&amp;rsquo;s forum&lt;/a&gt; or on Stack Overflow using the &amp;ldquo;ropensci&amp;rdquo; tag. If &lt;code&gt;foo&lt;/code&gt; is an RStudio package, you can ask for help on &lt;a href=&#34;https://community.rstudio.com/&#34;&gt;RStudio&amp;rsquo;s forum&lt;/a&gt;&amp;hellip; You get the gist.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When there&amp;rsquo;s no other indication or you&amp;rsquo;re not sure &lt;code&gt;foo&lt;/code&gt; or &lt;code&gt;bar&lt;/code&gt; is the actual culprit, use a more general site like &lt;a href=&#34;https://stackoverflow.com/&#34;&gt;Stack Overflow&lt;/a&gt;, tagging your question with &amp;ldquo;r&amp;rdquo; and other relevant labels. I was pleased to see that the bottom of &lt;a href=&#34;https://www.r-project.org/help.html&#34;&gt;https://www.r-project.org/help.html&lt;/a&gt; includes a list of question venues including Stack Overflow, but also &lt;a href=&#34;https://www.r-project.org/mail.html&#34;&gt;all R mailing lists&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;where-to-ask-your-_question_-or-_debate_-question&#34;&gt;Where to ask your &lt;em&gt;question&lt;/em&gt; or &lt;em&gt;debate&lt;/em&gt; question&lt;/h1&gt;
&lt;p&gt;How to find out whether there&amp;rsquo;s a tool to do image manipulation in R? How to know what&amp;rsquo;s best practice for your special package development challenge? How to get a book recommendation?&lt;/p&gt;
&lt;p&gt;Maybe Twitter, to which I&amp;rsquo;ll dedicate a whole section a bit later. But a good guess is also trying to locate where the experts, or people interested in the answer, normally interact. Your finding your happy place will probably be a bit of a trial-and-error process, so while asking your first question might be more difficult, things should be easier as you learn to navigate the different communities and their activity. Here is some inspiration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.r-project.org/mail.html&#34;&gt;The R SIG (special interest group) mailing lists&lt;/a&gt;. Now &lt;em&gt;I&lt;/em&gt; don&amp;rsquo;t use them at all because I&amp;rsquo;m not keen on receiving and sending many emails, but I can see there&amp;rsquo;s a great diversity of groups, maybe one that&amp;rsquo;ll suit your interests!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If your question is related to open science, reproducibility, documenting data, extracting data out of something (a PDF! a PNG!), package development, &lt;a href=&#34;https://discuss.ropensci.org/&#34;&gt;rOpenSci&amp;rsquo;s discuss forum&lt;/a&gt; might be the right venue.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;a href=&#34;https://community.rstudio.com/&#34;&gt;RStudio community forum&lt;/a&gt; has many categories including the &lt;code&gt;tidyverse&lt;/code&gt; and the RStudio IDE of course but also about package development; R in production, at scale, and in complex environments, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For a question related to outbreak analytics and R programming, check out &lt;a href=&#34;http://www.repidemicsconsortium.org/forum/&#34;&gt;the R Epidemics Consortium mailing list or Slack&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;what-is-twitter-good-for&#34;&gt;What is Twitter good for?&lt;/h1&gt;
&lt;p&gt;Anyone can use Twitter for what they want, depending on the accounts they follow and on their way to consume their timelines and hashtags, so the following is probably even more personal to me than the rest. I think Twitter questions that have higher chances to be answered (because I like answering them!) are the trivia ones, i.e. &amp;ldquo;is there something to do &lt;code&gt;foo&lt;/code&gt;&amp;rdquo;, and the more controversial ones if only for having fun. That said, if you don&amp;rsquo;t have a huge following yet, or post at the &amp;ldquo;wrong&amp;rdquo; time, even when using the right hashtags or so your question might be ignored, keep that in mind.&lt;/p&gt;
&lt;p&gt;What Twitter is not good for is, in my opinion:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Asking a question about a package by tagging the maintainer especially when the package docs state there&amp;rsquo;s another venue for that. But then, as a maintainer, one should probably handle such mistakes gracefully (like Yihui did &lt;a href=&#34;https://twitter.com/xieyihui/status/1015079496427491328&#34;&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Too much code I think, even if tools like &lt;a href=&#34;https://github.com/ropenscilabs/codefinch&#34;&gt;Sean Kross&amp;rsquo; &lt;code&gt;codefinch&lt;/code&gt;&lt;/a&gt; can help. Your tweet with a question can circumvent the difficulty by advertising a gist like codefinch makes you do (i.e. a tweet with an &amp;ldquo;attachment&amp;rdquo;), or by being a link to your actual question on Stack Overflow (i.e. a tweet to try and draw attention to your question).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Building an archive of questions and answers. It won&amp;rsquo;t be easy at all to search whether a question has already been answered. You can counteract this loss of knowledge by asking questions somewhere else, or building something out of the answers you&amp;rsquo;ve been given, e.g. a &lt;a href=&#34;https://itsalocke.com/blog/r-spatial-resources/&#34;&gt;blog post listing resources for geospatial analysis in R&lt;/a&gt; or &lt;a href=&#34;https://www.stephdesilva.com/post/the-keys-to-the-kingdom/&#34;&gt;resources about transport and GIS in R&lt;/a&gt; like Steph Locke and Steph de Silva, respectively, did after getting answers on Twitter.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Surprise questions. At least I am scared of questions phrased like this: &amp;ldquo;Who has time to help me with &lt;insert very general term here&gt;?&amp;rdquo; (e.g. XML, web scraping). They sound like a trap to me! I&amp;rsquo;d rather know more precisely what the person wants.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;I think it&amp;rsquo;s as important to ask your questions in the right place as it is to ask them in the right way. I hope this post provided some clues as to know where to ask R questions. I&amp;rsquo;d like to make an important remark from &lt;a href=&#34;https://maraaverick.rbind.io/&#34;&gt;Mara Averick&lt;/a&gt; here: &amp;ldquo;You should not take being redirected to a different forum as a criticism! It&amp;rsquo;s 100% a means of helping you get the help you need!&amp;rdquo;. Truth!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll round up this post with a few links of resources to learn &lt;em&gt;how&lt;/em&gt; to ask your question:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The guidelines and code of conduct of the venues where you&amp;rsquo;ve chosen to post your question, if there are some!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;the &lt;a href=&#34;http://communitycalls.ropensci.org/&#34;&gt;2017-03-07 rOpenSci comm call&lt;/a&gt; &amp;ldquo;How to Ask Questions so they get Answered! Possibly by Yourself!&amp;rdquo; was so, so good. I&amp;rsquo;ve already mentioned the talk by Jenny Bryan about &lt;code&gt;reprex&lt;/code&gt; and Scott Chamberlain&amp;rsquo;s talk about getting help about rOpenSci&amp;rsquo;s software. Furthermore, JD Long reviewed the historical challenges of getting R help.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I&amp;rsquo;ve seen very useful posts on RStudio Community forum when browsing the FAQ tag. In particular, I like &lt;a href=&#34;https://community.rstudio.com/t/faq-tips-for-introducing-non-programming-problem-discussions/6871&#34;&gt;&amp;ldquo;Tips for Introducing Non-Programming-Problem Discussions&amp;rdquo;&lt;/a&gt; and &lt;a href=&#34;https://community.rstudio.com/t/frequently-asked-questions/35&#34;&gt;this more general list of FAQs&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Good luck with your questions! The Disqus thingy below is good for suggestions and questions about this post!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Get on your soapbox! R blog content and promotion</title>
      <link>https://masalmon.eu/2018/07/16/soapbox/</link>
      <pubDate>Mon, 16 Jul 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/07/16/soapbox/</guid>
      <description>&lt;p&gt;This year I had the chance to speak at two R-Ladies meetups (I might have invited myself to those meetups to make the most of being in town, create your own happiness!), &lt;a href=&#34;https://www.meetup.com/rladies-cape-town/events/248425726/&#34;&gt;one in Cape Town in March&lt;/a&gt;, &lt;a href=&#34;https://www.meetup.com/rladies-seattle/events/250073046/&#34;&gt;one in Seattle in May&lt;/a&gt;. It was a blast both times! I gave the same talk twice, and decided it was about time to write it up.&lt;/p&gt;
&lt;p&gt;My talk in March was aimed at pairing, well tripleting, with &lt;a href=&#34;https://mcdussault.netlify.com/&#34;&gt;Marie Dussault&lt;/a&gt;&amp;rsquo;s &lt;a href=&#34;https://github.com/mcdussault/RLadies&#34;&gt;talk about setting up your blogdown website&lt;/a&gt;, and &lt;a href=&#34;http://on-the-t.com/&#34;&gt;Stephanie Kovalchik&lt;/a&gt;&amp;rsquo;s &lt;a href=&#34;https://github.com/skoval/satRday/tree/master/rladies&#34;&gt;talk about sports blogging&lt;/a&gt; so it is &lt;em&gt;not&lt;/em&gt; about these topics. What it is is my non data-driven, quite personal view on blog content and promotion, which hopefully features some useful tips for any wannabe R blogger!&lt;/p&gt;
&lt;h1 id=&#34;why-r-blogging-and-why-blogging-about-r-blogging&#34;&gt;Why R blogging and why blogging about R blogging&lt;/h1&gt;
&lt;p&gt;The reason why I suggested the topic of the Cape Town R-Ladies meetup to be blogging is that it helped &lt;em&gt;me&lt;/em&gt; get plugged in into the R community, so I liked the idea of sharing my experience, especially with R-Ladies. I don&amp;rsquo;t have Google analytics for my blog so I don&amp;rsquo;t actually know how successful my blog is, but I&amp;rsquo;ve got enough positive feedback to consider I&amp;rsquo;m doing something right. That said, given my lack of data to support anything I&amp;rsquo;ll say, please take everything with a pinch of salt!&lt;/p&gt;
&lt;h1 id=&#34;r-blog-content&#34;&gt;R Blog content&lt;/h1&gt;
&lt;h2 id=&#34;what-to-blog-about&#34;&gt;What to blog about?&lt;/h2&gt;
&lt;p&gt;There are plenty of R things you could blog about!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Your latest R obsession? Me in &lt;a href=&#34;https://www.masalmon.eu/2018/02/22/hexcombine/&#34;&gt;https://www.masalmon.eu/2018/02/22/hexcombine/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Something you&amp;rsquo;ve just implemented? Omayma Said &lt;a href=&#34;http://omaymas.github.io/prophet_explore/&#34;&gt;http://omaymas.github.io/prophet_explore/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Something &lt;em&gt;you&lt;/em&gt; like! Kasia Kulma &lt;a href=&#34;https://kkulma.github.io/2017-12-16-star-wars-vs-star-trek-word-battle/&#34;&gt;https://kkulma.github.io/2017-12-16-star-wars-vs-star-trek-word-battle/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fun packages?  Find inspiration in Mine Çetinkaya-Rundel&amp;rsquo;s list  &lt;a href=&#34;http://www2.stat.duke.edu/courses/Fall17/sta112.01/assignment/08-mini-hw.html&#34;&gt;http://www2.stat.duke.edu/courses/Fall17/sta112.01/assignment/08-mini-hw.html&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I especially like the point Edwin Thoen made &lt;a href=&#34;https://edwinth.github.io/blog-new-things/&#34;&gt;in this post&lt;/a&gt;: you can blog about things you&amp;rsquo;ve just learnt, it&amp;rsquo;s actually a good thing!&lt;/p&gt;
&lt;p&gt;Then, an important aspect of R blogging is that you don&amp;rsquo;t need to blog about R code! Examples of relevant R content I&amp;rsquo;ve seen include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A list of things that helped you learn Lorna Maria Aine in &lt;a href=&#34;https://medium.com/@lornamariak/r-libraries-to-aid-you-learn-data-science-in-2018-30eaaf7cc050&#34;&gt;https://medium.com/@lornamariak/r-libraries-to-aid-you-learn-data-science-in-2018-30eaaf7cc050&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Your experience at an event e.g. Jasmine Dumas in &lt;a href=&#34;https://jasdumas.github.io/2017-05-28-runconf17-experience/&#34;&gt;https://jasdumas.github.io/2017-05-28-runconf17-experience/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Your experience at work e.g. Julia Silge in &lt;a href=&#34;https://juliasilge.com/blog/one-year-at-stack/&#34;&gt;https://juliasilge.com/blog/one-year-at-stack/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, if you still have trouble finding ideas, you can find inspiration by&amp;hellip; reading other blogs! I&amp;rsquo;d particularly recommend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;R Weekly newsletter &lt;a href=&#34;https://rweekly.org/&#34;&gt;https://rweekly.org/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;#rstats on Twitter &lt;a href=&#34;https://twitter.com/search?q=%23rstats&amp;amp;src=savs&#34;&gt;https://twitter.com/search?q=%23rstats&amp;amp;src=savs&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;how-to-get-stuff-done&#34;&gt;How to get stuff done?&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m not a self-help master so I&amp;rsquo;ll be very brief here. It&amp;rsquo;s obviously important to proofread and do your best but don&amp;rsquo;t let stress and perfectionism spoil the &lt;em&gt;fun&lt;/em&gt;. Most often you won&amp;rsquo;t get paid for blogging, so you should enjoy it! Do not get too ambitious in each post, and at some point, just ship it. Each post needs to be good enough, just good enough. I particularly liked this article of Kasia Kulma&amp;rsquo;s about getting stuff done when blogging and recommend it for better phrased thoughts than mine: &lt;a href=&#34;https://kkulma.github.io/2017-12-29-end-of-year-thoughts/&#34;&gt;https://kkulma.github.io/2017-12-29-end-of-year-thoughts/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Another aspect of getting blogging done is I think not losing your precious ideas. I used to have an empty GitHub repo with issues, just for the pleasure of then closing them, now I tend to write ideas in a notebook, maybe for the pleasure of striking through them. Other strategies I&amp;rsquo;ve heard of include having a &lt;a href=&#34;https://twitter.com/d4tagirl/status/943494515536617477&#34;&gt;Trello board&lt;/a&gt; or &lt;a href=&#34;https://twitter.com/SuzanBaert/status/943524440024997888&#34;&gt;taping sticky notes on a cupboard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Besides, when you have an idea, explore it by googling it. If you find similar work, link it in your post.
Last but not least, use your own authentic voice when blogging. I think it makes blogging easier, and more enjoyable for readers, at least &lt;em&gt;I&lt;/em&gt; like how informal blogging can be and laugh as much as I learn when reading &lt;a href=&#34;https://blog.brooke.science&#34;&gt;e.g. Brooke Watson&lt;/a&gt;. As regards the language, if you&amp;rsquo;re not an English native speaker, you can choose to blog in English or your own language, or both like Daniela Vázquez &lt;a href=&#34;https://d4tagirl.com/&#34;&gt;https://d4tagirl.com/&lt;/a&gt; !&lt;/p&gt;
&lt;h1 id=&#34;blog-promotion&#34;&gt;Blog promotion&lt;/h1&gt;
&lt;p&gt;Promoting your posts is crucial, because no matter how good your blog is, you need to help it find its audience!&lt;/p&gt;
&lt;h2 id=&#34;how-to-tweet-about-your-post&#34;&gt;How to tweet about your post&lt;/h2&gt;
&lt;p&gt;Twitter is an important medium for publicizing your work. If you don&amp;rsquo;t have an account, consider getting one. Here is my recipe for tweeting a blog post.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Title of your post, maybe a short intro, but do not add a self-deprecatory comment here. Please, don&amp;rsquo;t.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Link to your post.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;#rstats and other hashtags if needed, but do not use too many hashtags, in particular because it creates visual clutter (and in my opinion can give the (wrong) impression of being too thirsty).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A figure or a gif, to make your tweet stand out (in the timelines of Twitter users, in the #rstats timeline)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Emojis! If you like them of course.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You can tag people who inspired you, or whose great package is featured in your post, but proceed with caution. Tagging someone whose package isn&amp;rsquo;t too popular (e.g. me, ahah) will result in making this person&amp;rsquo;s happy and often in your tweet getting re-tweeted by them. Also keep in mind that having too many Twitter handles in your tweet is like having too many hashtags, it doesn&amp;rsquo;t always look good.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;add-your-blog-to-lists-and-feeds-aggregator&#34;&gt;Add your blog to lists and feeds aggregator!&lt;/h2&gt;
&lt;p&gt;There are lists of blogdown blogs where you can list your blog:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/sellorm/awesome-blogdown&#34;&gt;https://github.com/sellorm/awesome-blogdown&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://support.rbind.io/about/&#34;&gt;https://support.rbind.io/about/&lt;/a&gt; if you use their domain name (I don&amp;rsquo;t know much about rbind.io)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You should also create an RSS feed for your blog if it doesn&amp;rsquo;t have one yet. Since this post of mine isn&amp;rsquo;t too technical, I&amp;rsquo;d recommend googling the name of your website tool and &amp;ldquo;RSS feed&amp;rdquo;. Once you have an RSS feed featuring the entire content of your posts, your readers will be able to subscribe, and you can submit your RSS feed to aggregators!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;My favorite one, maybe because I&amp;rsquo;m an R-Weekly team member &lt;a href=&#34;https://rweekly.org/submit&#34;&gt;https://rweekly.org/submit&lt;/a&gt; (you can also submit individual links to R Weekly, see &lt;a href=&#34;https://github.com/rweekly/rweekly.org#r-weekly&#34;&gt;https://github.com/rweekly/rweekly.org#r-weekly&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The most famous one, and oldest one, where my own blog is featured, maintained by Tal Galili &lt;a href=&#34;https://www.r-bloggers.com/add-your-blog/&#34;&gt;https://www.r-bloggers.com/add-your-blog/&lt;/a&gt; It might take a while for your feed to be added, don&amp;rsquo;t take it personally.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;take-advantages-of-networks-and-other-voice-amplifying-opportunities&#34;&gt;Take advantages of networks and other voice-amplifying opportunities&lt;/h2&gt;
&lt;p&gt;First of all, depending on the topic of your post or of your blog in general, share links to your posts with your potential (niche) audience!&lt;/p&gt;
&lt;p&gt;Then, if you&amp;rsquo;re an R-Lady (as a reminder, &lt;a href=&#34;https://rladies.org/about-us/&#34;&gt;this doesn&amp;rsquo;t mean women only&lt;/a&gt; but instead &amp;ldquo;minority genders (including but not limited to cis/trans women, trans men, non-binary, genderqueer, agender)&amp;quot;), share your posts with your local chapter or &lt;a href=&#34;https://www.r-bloggers.com/introducing-r-ladies-remote-chapter/&#34;&gt;R-Ladies remote&lt;/a&gt; and don&amp;rsquo;t hesitate to ping R-Ladies Global (quoting your tweet, not adding the handle in your tweet, in order to keep it clean).&lt;/p&gt;
&lt;p&gt;If you use one of &lt;a href=&#34;https://ropensci.org/packages/&#34;&gt;rOpenSci&amp;rsquo;s packages&lt;/a&gt;, please post the link to rOpenSci&amp;rsquo;s &lt;a href=&#34;https://discuss.ropensci.org/c/usecases&#34;&gt;discussion forum in the Use Cases category&lt;/a&gt; and tag Scott Chamberlain (&lt;code&gt;@sckott&lt;/code&gt;) for inclusion in the &lt;a href=&#34;https://news.ropensci.org/&#34;&gt;rOpenSci biweekly newsletter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last but not least, I&amp;rsquo;m getting (even more) preachy and recommend being the blog reader you want to see&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Leave comments: compliments, questions, suggestions, corrections.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Share links with your network!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Link it back on your blog.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;rsquo;s all from me, now I&amp;rsquo;ll follow my own advice and ship this post! Happy R blogging!&lt;/p&gt;
&lt;p&gt;Edited to add: I didn&amp;rsquo;t mention Search Engine Optimization because I don&amp;rsquo;t know much about that, but wanted to add a link to the blogdown book relevant section: &lt;a href=&#34;https://bookdown.org/yihui/blogdown/useful-resources.html#helping-people-find-your-site&#34;&gt;https://bookdown.org/yihui/blogdown/useful-resources.html#helping-people-find-your-site&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Really not a fish? Scraping my mathematical family tree</title>
      <link>https://masalmon.eu/2018/06/18/mathtree/</link>
      <pubDate>Mon, 18 Jun 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/06/18/mathtree/</guid>
      <description>&lt;p&gt;It&amp;rsquo;s nearly been two years since I defended &lt;a href=&#34;https://edoc.ub.uni-muenchen.de/19877/&#34;&gt;my PhD thesis&lt;/a&gt;! On top of allowing me to call myself &lt;em&gt;doctor&lt;/em&gt;, having a PhD in &lt;em&gt;statistics&lt;/em&gt; gives me the honour to feature in the data of the &lt;a href=&#34;https://www.genealogy.math.ndsu.nodak.edu/&#34;&gt;Mathematics Genealogy Project&lt;/a&gt;. Today, I decided to webscrape my mathematical ancestors.&lt;/p&gt;
&lt;h1 id=&#34;my-blogging-ancestors&#34;&gt;My blogging ancestors?&lt;/h1&gt;
&lt;p&gt;Before blogging, following &lt;a href=&#34;https://maelle.github.io/rladiesseattle/slides#14&#34;&gt;my own advice&lt;/a&gt; I googled my idea and found these similar efforts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nathalie Vialaneix scraped her own mathematical tree using the R &lt;code&gt;XML&lt;/code&gt; package and drew it using the &lt;code&gt;igraph&lt;/code&gt; package and &lt;code&gt;GraphViz&lt;/code&gt;. My post is basically a remix of &lt;a href=&#34;http://tuxette.nathalievilla.org/?p=1292&#34;&gt;her post&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.genealogy.math.ndsu.nooodak.edu/id.php?id=46503&#34;&gt;Heike Hofmann&lt;/a&gt; started writing &lt;a href=&#34;https://github.com/heike/mathGen&#34;&gt;a package to scrape the Mathematical Genealogy Project&lt;/a&gt;, and apparently abandoned it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://www.genealogy.math.ndsu.nodak.edu/id.php?id=202169&#34;&gt;Thibault Vatter&lt;/a&gt; published a &lt;a href=&#34;https://github.com/tvatter/mgpancestry&#34;&gt;GitHub repo mixing R, Python and a tool called Scrapy to scrape the website&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I wrote my own version of the webscraping because I wanted to use &lt;a href=&#34;https://github.com/hadley/rvest&#34;&gt;&lt;code&gt;rvest&lt;/code&gt;&lt;/a&gt; like I usually do these days.&lt;/p&gt;
&lt;h1 id=&#34;scraping-the-mathematical-genealogy-project&#34;&gt;Scraping the Mathematical Genealogy Project&lt;/h1&gt;
&lt;p&gt;Now that I have added &lt;a href=&#34;https://masalmon.eu/tags/&#34;&gt;tags to all my old blog posts&lt;/a&gt;, I can look back at my &lt;a href=&#34;https://masalmon.eu/tags/webscraping/&#34;&gt;previous webscraping efforts&lt;/a&gt; and use my recent scripts&amp;hellip; as well as see how much progress I made since my reckless webscraping days, when I didn&amp;rsquo;t check I was allowed to webscrape, and when I used on string manipulation rather than XPath and friends.&lt;/p&gt;
&lt;p&gt;Nowadays before webscraping I use &lt;a href=&#34;https://github.com/ropensci/robotstxt&#34;&gt;the rOpenSci &lt;code&gt;robotstxt&lt;/code&gt; package&lt;/a&gt; to read what the website owners will let me do.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; robotstxt&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;robotstxt&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.genealogy.math.ndsu.nodak.edu&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text
User&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;agent&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt; msnbot
Crawl&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;delay&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;30&lt;/span&gt;

User&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;agent&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt; Browsershots
Disallow&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt; 

User&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;agent&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;
Disallow&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;submit&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;data.php
&lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; robotstxt&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;paths_allowed&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.genealogy.math.ndsu.nodak.edu/id.php&amp;#34;&lt;/span&gt;)

 www.genealogy.math.ndsu.nodak.edu
[1] &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From the above I deduced that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;there is no recommended delay for scrapers that are not msnbot, so I used 5 seconds between calls, which seemed &lt;a href=&#34;https://en.wikipedia.org/wiki/Lagom&#34;&gt;&lt;em&gt;lagom&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I was allowed to scrape mathematicians&amp;rsquo; pages. Hooray!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, I looked at the code of my &lt;a href=&#34;https://masalmon.eu/2018/05/06/dsstock/&#34;&gt;most recent webscraping blog post&lt;/a&gt; that was building on &lt;a href=&#34;https://gist.github.com/hrbrmstr/4cabe4af87bd2c5fe664b0b44a574366&#34;&gt;code by Bob Rudis&lt;/a&gt;: after looking at the source of one mathematician&amp;rsquo;s page, I used &lt;code&gt;html_attrs&lt;/code&gt; and &lt;code&gt;html_text&lt;/code&gt; to extract the elements I needed from each page.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;.get_advisors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(id_string, sleep_time){
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# small break to be nice&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(sleep_time)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# try to get the page&lt;/span&gt;
  page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.genealogy.math.ndsu.nodak.edu/{id_string}&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;GET&lt;/span&gt;() 
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# try until it works but not more than 5 times&lt;/span&gt;
  try &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;while&lt;/span&gt;(httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;status_code&lt;/span&gt;(page) &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;200&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; try &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;){
    &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(sleep_time)
    page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.genealogy.math.ndsu.nodak.edu/{id_string}&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
      httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;GET&lt;/span&gt;() 
    try &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; try &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
  }
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Now get student&amp;#39;s name&lt;/span&gt;
  student_name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;content&lt;/span&gt;(page) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_nodes&lt;/span&gt;(xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;//h2[@style=&amp;#34;text-align: center; margin-bottom: 0.5ex; margin-top: 1ex&amp;#34;]&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;html_text&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_remove&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\\n&amp;#34;&lt;/span&gt;)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Get all nodes corresponding to advisors&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Thanks to their... formatting but it works&lt;/span&gt;
  all_advisors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;content&lt;/span&gt;(page) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_nodes&lt;/span&gt;(xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;//p[@style=&amp;#39;text-align: center; line-height: 2.75ex&amp;#39;]&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt;)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Export results&lt;/span&gt;
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(student_name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; student_name,
                 id_string_student &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; id_string,
                 name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(all_advisors, rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;html_text),
                 id_string &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(all_advisors, rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;html_attr,
                                            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;href&amp;#34;&lt;/span&gt;))
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, since sometimes advisors will be encountered more than once in the data, I used &lt;code&gt;memoise&lt;/code&gt; to create a handy function wrapper that will cache results.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Cache results in case a mathematician comes up several times&lt;/span&gt;
get_advisors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; memoise&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;memoise&lt;/span&gt;(.get_advisors)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, to get all my ancestors, I had to iteratively get the ancestors of each of my ancestors&amp;hellip; until when? Heike Hofmann wrote a function working a given number of steps, Nathalie Vialaneix stopped when there was no advisor on an advisor&amp;rsquo;s page, I stopped when the data.frame stopped growing because that&amp;rsquo;s what I found the easiest to implement.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;me &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;id.php?id=207686&amp;#34;&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# initial data.frame&lt;/span&gt;
df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_advisors&lt;/span&gt;(me, &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;)
new_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; df
keep_growing &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;while&lt;/span&gt;(keep_growing){
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get size to compare to size after a bit more scraping&lt;/span&gt;
  nrow1 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(df)
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get advisors for all new lines &lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# from the previous iterations&lt;/span&gt;
  new_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(new_df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;id_string, get_advisors, sleep_time &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;30&lt;/span&gt;)
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;rbind&lt;/span&gt;(df, new_df))
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# if the data.frame didn&amp;#39;t grow, stop&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(df) &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; nrow1){
    keep_growing &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;
  }
}

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# save results&lt;/span&gt;
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(df, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;math_ancestry.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I tested the above on very ancient mathematicans who didn&amp;rsquo;t have too many ancestors to check it was working, and stopping.&lt;/p&gt;
&lt;p&gt;At the end of my data gathering, I had a nice table of 261 mathematicians including yours truly! By the way, the Mathematical Genealogy Project maintainers &lt;a href=&#34;https://www.genealogy.math.ndsu.nodak.edu/mission.php&#34;&gt;state&lt;/a&gt; &amp;ldquo;Throughout this project when we use the word &amp;ldquo;mathematics&amp;rdquo; or &amp;ldquo;mathematician&amp;rdquo; we mean that word in a very inclusive sense. Thus, all relevant data from mathematics education, statistics, computer science, or operations research is welcome.&amp;rdquo; which is the reason why I feel fine calling myself a mathematician in this post.&lt;/p&gt;
&lt;h1 id=&#34;showing-off-my-mathematical-family-tree&#34;&gt;Showing (off) my mathematical family tree&lt;/h1&gt;
&lt;p&gt;The approach I used below, defining nodes and edges for integration by &lt;a href=&#34;https://github.com/rich-iannone/DiagrammeR&#34;&gt;&lt;code&gt;DiagrammeR&lt;/code&gt;&lt;/a&gt; before exporting to &lt;a href=&#34;https://github.com/igraph/rigraph&#34;&gt;&lt;code&gt;igraph&lt;/code&gt;&lt;/a&gt; and then to &lt;a href=&#34;http://www.graphviz.org/&#34;&gt;&lt;code&gt;GraphViz&lt;/code&gt;&lt;/a&gt; (not an R package, but interfaced by both &lt;code&gt;DiagrammeR&lt;/code&gt; and &lt;code&gt;igraph&lt;/code&gt;), might seem a bit complicated since the &lt;code&gt;DiagrammeR&lt;/code&gt; package itself exports to &lt;code&gt;GraphViz&lt;/code&gt; format&amp;hellip; but not with the classic default look I liked on Nathalie&amp;rsquo;s Vialaneix blog.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;DiagrammeR&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# create nodes&lt;/span&gt;
labels &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt;  &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;student_name, df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;name))
nodes_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;create_node_df&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(labels))
nodes_df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;label &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; labels

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# create edges&lt;/span&gt;
edges_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; df[, &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;student_name&amp;#34;&lt;/span&gt;)]
edges_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(edges_df, nodes_df,
                             by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;))
edges_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rename&lt;/span&gt;(edges_df, from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; id)
edges_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(edges_df, nodes_df,
                             by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;student_name&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;))
edges_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rename&lt;/span&gt;(edges_df, to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; id)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# special character that&amp;#39;d make GraphViz throw an error&lt;/span&gt;
nodes_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(nodes_df,
                   label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(label, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#39;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;))

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# create a DiagrammeR dgr_graph object&lt;/span&gt;
dgr &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;create_graph&lt;/span&gt;(nodes_df &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; nodes_df,
                    edges_df &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; edges_df[, &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;to&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;from&amp;#34;&lt;/span&gt;)],
                    directed &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# export the object to igraph format&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# and then write it to a GraphViz DOT file&lt;/span&gt;
DiagrammeR&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;to_igraph&lt;/span&gt;(dgr) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  igraph&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write.graph&lt;/span&gt;(file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;graph.dot&amp;#34;&lt;/span&gt;,
                      format &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dot&amp;#34;&lt;/span&gt;) 

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I vaguely got the ambition to use some sort of htmlwidget to have a zoomable and pretty network but didn&amp;rsquo;t want to spent too much time doing it, so PNGs it is! Here is how I hacked my way to a PNG.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;DiagrammeR&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;grViz&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;graph.dot&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  htmlwidgets&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;saveWidget&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lala.html&amp;#34;&lt;/span&gt;)

webshot&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;webshot&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lala.html&amp;#34;&lt;/span&gt;,
                 selector&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#htmlwidget_container&amp;#34;&lt;/span&gt;,
                 file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tree.png&amp;#34;&lt;/span&gt;,
                 zoom &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;file.remove&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lala.html&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then cropped two zooms by hand!&lt;/p&gt;
&lt;p&gt;So here is my whole tree&amp;hellip;&lt;/p&gt;
&lt;img src=&#34;https://masalmon.eu/figure/source/2018-06-18-mathtree/tree.png&#34; alt=&#34;my math family tree&#34; width=&#34;600&#34;&gt;
&lt;p&gt;It is unreadable unless you open it in its own tab and zoom. Like Nathalie Vialaneix, I think I only have male mathematical ancestors.&lt;/p&gt;
&lt;img src=&#34;https://masalmon.eu/figure/source/2018-06-18-mathtree/zoom1.png&#34; alt=&#34;zoom 1 on my math family tree&#34; width=&#34;600&#34;&gt;
&lt;p&gt;The most recent part of the tree obviously features my PhD advisor &lt;a href=&#34;https://www.genealogy.math.ndsu.nodak.edu/id.php?id=168176&#34;&gt;Michael Höhle&lt;/a&gt;, who by the way has &lt;a href=&#34;http://staff.math.su.se/hoehle/blog/&#34;&gt;a very smart statistics blog&lt;/a&gt;! I also see I&amp;rsquo;m related to CRAN&amp;rsquo;s &lt;a href=&#34;https://www.genealogy.math.ndsu.nodak.edu/id.php?id=79783&#34;&gt;Kurt Hornik&lt;/a&gt;, which doesn&amp;rsquo;t mean I get my packages on CRAN whilst bypassing gatekeeping though.&lt;/p&gt;
&lt;img src=&#34;https://masalmon.eu/figure/source/2018-06-18-mathtree/zoom2.png&#34; alt=&#34;zoom 2 on my math family tree&#34; width=&#34;600&#34;&gt;
&lt;p&gt;I was then very pleased to recognize some famous mathematicians&amp;rsquo; names, not the most ancient ones I&amp;rsquo;m afraid, but look, Poisson! I was very excited about this because my PhD thesis featured count data, and because Poisson means fish in French&amp;hellip; So maybe I&amp;rsquo;m a fish after all. Besides, seeing Carl Friedrich Gauß also made me happy&amp;hellip; I had no idea the picture below was actually a family portrait!&lt;/p&gt;
&lt;h1 id=&#34;growing-this-post&#34;&gt;Growing this post?&lt;/h1&gt;
&lt;p&gt;In conclusion, I scraped and drew my mathematical family tree using data from the Mathematical Genealogy Project. Extensions of my post could include making a package like Heike Hofmann&amp;rsquo;s one to make it easier for anyone to get their data; preparing a nicer visualization (note that you can buy posters to support the project as explained on &lt;a href=&#34;https://www.genealogy.math.ndsu.nodak.edu/posters.php&#34;&gt;this page&lt;/a&gt;), and getting more data from each mathematician&amp;rsquo;s page to draw once&amp;rsquo;s ancestry on a map, summarize thesis topics with tidy text analysis&amp;hellip; Now, I&amp;rsquo;ll probably remain the black sheep of my mathematical family by blogging about &lt;a href=&#34;https://masalmon.eu/tags/kitsch-plot/&#34;&gt;kitsch plots&lt;/a&gt;!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Bad Stock Photos of My Job? Data Science on Pexels</title>
      <link>https://masalmon.eu/2018/05/06/dsstock/</link>
      <pubDate>Sun, 06 May 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/05/06/dsstock/</guid>
      <description>&lt;p&gt;I couldn&amp;rsquo;t miss the fun Twitter hashtag &lt;a href=&#34;https://twitter.com/hashtag/BadStockPhotosOfMyJob?src=hash&#34;&gt;#BadStockPhotosOfMyJob&lt;/a&gt; thanks to a &lt;a href=&#34;https://twitter.com/juliasilge/status/992952211201130497&#34;&gt;tweet by Julia Silge&lt;/a&gt;  and &lt;a href=&#34;https://twitter.com/_ColinFay/status/993055416266436608&#34;&gt;another one by Colin Fay&lt;/a&gt;. The latter inspired me to actually go and look for what makes a data science photo&amp;hellip; What characterizes &amp;ldquo;data science&amp;rdquo; stock photos?&lt;/p&gt;
&lt;h1 id=&#34;my-not-bad-stock-photo-source&#34;&gt;My (not bad) stock photo source&lt;/h1&gt;
&lt;h2 id=&#34;pexels-metadata-for-the-win&#34;&gt;Pexels metadata for the win&lt;/h2&gt;
&lt;p&gt;Where to find information related to stock photos? In &lt;a href=&#34;https://masalmon.eu/2018/01/04/bubblegumpuppies/&#34;&gt;two&lt;/a&gt; &lt;a href=&#34;https://masalmon.eu/2018/01/07/rainbowing/&#34;&gt;previous&lt;/a&gt; blog posts of mine I used Pexels, a website providing CC0 pictures which is quite nice. My goal was to obtain the titles and the tags of stock photos of &amp;ldquo;data science&amp;rdquo;: for instance if you look at &lt;a href=&#34;https://www.pexels.com/photo/black-laptop-beside-black-computer-mouse-inside-room-669996/&#34;&gt;this picture&lt;/a&gt;, its tags are &amp;ldquo;business&amp;rdquo;, &amp;ldquo;contemporary&amp;rdquo;, &amp;ldquo;computer&amp;rdquo;, etc. Pexels tags are very useful metadata, saving me the effort to use machine learning methods to analyse images.&lt;/p&gt;
&lt;h2 id=&#34;responsible-webscraping&#34;&gt;Responsible webscraping&lt;/h2&gt;
&lt;p&gt;When researching this post I discovered that Pexels has an API, documented &lt;a href=&#34;https://www.pexels.com/api/documentation/&#34;&gt;here&lt;/a&gt; but this API does not get you the title nor the tags associated to a picture so only webscraping could get me what I needed.&lt;/p&gt;
&lt;p&gt;Webscraping is a powerful tool allowing one to &lt;a href=&#34;https://speakerdeck.com/jennybc/data-rectangling&#34;&gt;rectangle&lt;/a&gt; webpages but with great power comes great responsability. Being &lt;em&gt;able&lt;/em&gt; to scrape a webpage does not mean you are &lt;em&gt;allowed&lt;/em&gt; to. You could get sued or your IP could get blocked. I am far from being an expert but I often read &lt;a href=&#34;https://rud.is/b/&#34;&gt;Bob Rudis&amp;rsquo; blog&lt;/a&gt; where I learnt about rOpenSci&amp;rsquo;s &lt;a href=&#34;https://github.com/ropenscilabs/robotstxt&#34;&gt;&lt;code&gt;robotstxt&lt;/code&gt; package&lt;/a&gt; that does &amp;ldquo;robots.txt file parsing and checking for R&amp;rdquo; which in plain language means it checks for you what a webpage legally allows you to do. See below,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# how I&amp;#39;ll find pictures&lt;/span&gt;
robotstxt&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;paths_allowed&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.pexels.com/search&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] TRUE
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# where tags live&lt;/span&gt;
robotstxt&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;paths_allowed&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.pexels.com/photo&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] TRUE
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;robots.txt files often also tell you how often you can hit a page by defining a &amp;ldquo;crawling delay&amp;rdquo;. Sadly Pexels robots.txt doesn&amp;rsquo;t:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;robotstxt&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;get_robotstxt&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.pexels.com&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Sitemap: https://s3.amazonaws.com/pexels/sitemaps/sitemap.xml.gz
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But Bob Rudis, who was patient and nice enough to answer my questions, told me that I should probably respect the rate limit defined in &lt;a href=&#34;https://www.pexels.com/api/documentation/&#34;&gt;Pexels API docs&lt;/a&gt;. &amp;ldquo;Do not abuse the API. The API is rate-limited to 200 requests per hour and 20,000 requests per month.&amp;rdquo; As I recently explained in &lt;a href=&#34;https://itsalocke.com/blog/some-web-api-package-development-lessons-from-hibpwned/&#34;&gt;a post on Locke Data&amp;rsquo;s blog&lt;/a&gt;, these days to limit rate of a function I use &lt;a href=&#34;https://github.com/tarakc02/ratelimitr&#34;&gt;the very handy &lt;code&gt;ratelimitr&lt;/code&gt; package&lt;/a&gt; by &lt;a href=&#34;https://tarakc02.github.io/&#34;&gt;Tarak Shah&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;limited_get &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ratelimitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;limit_rate&lt;/span&gt;(httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;GET,
                                      ratelimitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rate&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;200&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;60&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;60&lt;/span&gt;),&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# not more than 200 times an hour&lt;/span&gt;
                                      ratelimitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rate&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;))&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#not more than 1 time every 5 seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;elegant-webscraping&#34;&gt;Elegant webscraping&lt;/h2&gt;
&lt;p&gt;At the time of the two aforelinked blog posts I had used &lt;a href=&#34;https://github.com/ropensci/RSelenium&#34;&gt;&lt;code&gt;RSelenium&lt;/code&gt;&lt;/a&gt; to scroll down and get the download link of many pictures, but Bob Rudis wrote &lt;a href=&#34;https://gist.github.com/hrbrmstr/4cabe4af87bd2c5fe664b0b44a574366&#34;&gt;an elegant and cool alternative&lt;/a&gt; using query parameters, on which I&amp;rsquo;ll build in this post.&lt;/p&gt;
&lt;p&gt;I first re-wrote the function to get all 15 pictures of each page of results.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;get_page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(num &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, seed &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) {
  &lt;span style=&#34;color:#06287e&#34;&gt;message&lt;/span&gt;(num)
  &lt;span style=&#34;color:#06287e&#34;&gt;limited_get&lt;/span&gt;(
    url &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.pexels.com/search/data science/&amp;#34;&lt;/span&gt;,
    query &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(
      page&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;num,
      seed&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;seed
    )
  ) &lt;span style=&#34;color:#666&#34;&gt;-&amp;gt;&lt;/span&gt; res
  
  httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;stop_for_status&lt;/span&gt;(res)
  
  pg &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;content&lt;/span&gt;(res)
  
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(
    url &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;html_attr&lt;/span&gt;(rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(pg, xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;//a[@class=&amp;#39;js-photo-link&amp;#39;]&amp;#34;&lt;/span&gt;), &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;href&amp;#34;&lt;/span&gt;),
    title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;html_attr&lt;/span&gt;(rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(pg, xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;//a[@class=&amp;#39;js-photo-link&amp;#39;]&amp;#34;&lt;/span&gt;), &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;),
    tags &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(url, get_tags)
  )
  
} 

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I re-wrote it because I needed the &amp;ldquo;href&amp;rdquo; and because it seems that the structure of each page changed a bit since the day on which the gist was written. To find out I had to write &amp;ldquo;a[@class=&#39;js-photo-link&amp;rsquo;]&amp;rdquo; I inspected the source of a page.&lt;/p&gt;
&lt;p&gt;Then I wrote a function getting tags for each picture.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;get_tags &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(url){
  &lt;span style=&#34;color:#06287e&#34;&gt;message&lt;/span&gt;(url)
  url &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.pexels.com&amp;#34;&lt;/span&gt;, url)
  res &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;limited_get&lt;/span&gt;(url)
  httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;stop_for_status&lt;/span&gt;(res)
  pg &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;content&lt;/span&gt;(res)
  nodes &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(pg, xpath &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;//a[@data-track-label=&amp;#34;tag&amp;#34; ]&amp;#39;&lt;/span&gt;)
  rvest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;html_text&lt;/span&gt;(nodes)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally I got results for 20 pages. I chose 20 without thinking too much. It seemed enough for my needs, and each of these pages had pictures.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;ds_stock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;, get_page)
ds_stock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(ds_stock)
ds_stock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;unnest&lt;/span&gt;(ds_stock, tags)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I got 300 unique pictures.&lt;/p&gt;
&lt;h1 id=&#34;whats-in-a-data-science-stock-photo&#34;&gt;What&amp;rsquo;s in a data science stock photo?&lt;/h1&gt;
&lt;p&gt;Now that I have all this information at hand, I can describe data science stock photos!&lt;/p&gt;
&lt;h2 id=&#34;data-science-tags&#34;&gt;Data science tags&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggalt&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)
tag_counts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(ds_stock, tags, sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,]

dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(tag_counts,
              tags &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;reorder&lt;/span&gt;(tags, n)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_lollipop&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(tags, n),
                size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;, col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;salmon&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  hrbrthemes&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;,
                          axis_title_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Tag&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;300 data science stock photos&amp;#34;&lt;/span&gt;,
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Most frequent tags. Source: https://www.pexels.com&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;coord_flip&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2018-05-06-dsstock/unnamed-chunk-4-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-4&#34;&gt;&lt;/p&gt;
&lt;p&gt;So the most common tags are data, technology, business and computer. Not too surprising!&lt;/p&gt;
&lt;h2 id=&#34;data-science-scenes&#34;&gt;Data science scenes&lt;/h2&gt;
&lt;p&gt;Now, let&amp;rsquo;s have a look at &lt;em&gt;titles&lt;/em&gt; that are in general more descriptive of what&amp;rsquo;s happening/present on the photo (i.e. is the computer near a cup of coffee or is someone working on it). I tried using a technique described in &lt;a href=&#34;https://juliasilge.com/&#34;&gt;Julia Silge&lt;/a&gt;&amp;rsquo;s and &lt;a href=&#34;http://varianceexplained.org/&#34;&gt;David Robinson&lt;/a&gt;&amp;rsquo;s &lt;a href=&#34;https://www.tidytextmining.com&#34;&gt;Tidy text mining book&lt;/a&gt;: &amp;ldquo;Counting and correlating pairs of words with the &lt;code&gt;widyr&lt;/code&gt; package&amp;rdquo; described in &lt;a href=&#34;https://www.tidytextmining.com/ngrams.html#counting-and-correlating-pairs-of-words-with-the-widyr-package&#34;&gt;this section of the book&lt;/a&gt; but it wasn&amp;rsquo;t too interesting because most correlation values were too low. One issue was probably my having too few titles: only half of pictures have titles! So I&amp;rsquo;ll resort to plotting most common bigrams, which I learnt in the &lt;a href=&#34;https://www.tidytextmining.com&#34;&gt;Tidy text mining book&lt;/a&gt; as well.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;stopwords &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rcorpora&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;corpora&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;words/stopwords/en&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;stopWords

ds_stock &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(title)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(title) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  tidytext&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(bigram, title,
                          token &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ngrams&amp;#34;&lt;/span&gt;, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;)  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;separate&lt;/span&gt;(bigram, &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;word1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;word2&amp;#34;&lt;/span&gt;), sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;,
                  remove &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;word1 &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; stopwords) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;word2 &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; stopwords)&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(bigram, sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(bigram &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;reorder&lt;/span&gt;(bigram, n)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_lollipop&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(bigram, n),
                size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;, col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;salmon&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  hrbrthemes&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;,
                          axis_title_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;300 data science stock photos&amp;#34;&lt;/span&gt;,
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Most frequent bigrams in titles. Source: https://www.pexels.com&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;coord_flip&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2018-05-06-dsstock/unnamed-chunk-5-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-5&#34;&gt;&lt;/p&gt;
&lt;p&gt;So there&amp;rsquo;s a lot of holding computer happening, and these laptops are either black or white&amp;hellip; And well Macbook Pro probably looks more professional?&lt;/p&gt;
&lt;h1 id=&#34;hold-my-laptop-and-watch&#34;&gt;Hold my laptop and watch&amp;hellip;&lt;/h1&gt;
&lt;p&gt;my trying to find a good post conclusion! In this post, I tried to responsibly and elegantly scrape rich photo metadata from Pexels to characterize stock photos of data science. Using tags, and most common bigrams in titles, I found that data science stock photos are associated with data, business and computers; and that they often show people holding computers. Now, you&amp;rsquo;ll excuse me while I try and comfort my poor pink laptop that feels a bit too un-data-sciency.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Lintr Bot, lintr&#39;s Hester egg</title>
      <link>https://masalmon.eu/2018/03/30/lintr-bot/</link>
      <pubDate>Fri, 30 Mar 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/03/30/lintr-bot/</guid>
      <description>&lt;p&gt;Remember my blog post about &lt;a href=&#34;https://masalmon.eu/2017/06/17/automatictools/&#34;&gt;automatic tools for improving R packages&lt;/a&gt;? One of these tools is &lt;a href=&#34;https://github.com/jimhester/lintr&#34;&gt;Jim Hester&amp;rsquo;s &lt;code&gt;lintr&lt;/code&gt;&lt;/a&gt;, a package that performs static code analysis. In my experience it mostly helps identifying too long code lines and missing space, although it&amp;rsquo;s a bit more involved than that. In any case, &lt;code&gt;lintr&lt;/code&gt; helps you maintain good code style, and as mentioned in that now old post of mine, you can add a &lt;code&gt;lintr&lt;/code&gt; unit test to your package which will ensure you don&amp;rsquo;t get lazy over time.&lt;/p&gt;
&lt;p&gt;Now say your package has a &lt;code&gt;lintr&lt;/code&gt; unit test and lives on GitHub. What happens if someone makes a pull request and writes looong code lines? Continuous integration builds will fail but not only that&amp;hellip; The contributor will get to know Lintr Bot, lintr&amp;rsquo;s Hester (&lt;a href=&#34;https://en.wikipedia.org/wiki/Easter_egg_(media)&#34;&gt;Easter&lt;/a&gt;) egg!&lt;/p&gt;
&lt;h1 id=&#34;lintr-bot-a-lazy-little-thing&#34;&gt;Lintr Bot, a lazy little thing?&lt;/h1&gt;
&lt;p&gt;Lintr Bot has a &lt;a href=&#34;https://github.com/lintr-bot&#34;&gt;GitHub profile&lt;/a&gt;. I am actually responsible for its avatar, because when I discovered it a while back I offered Jim to design it based &lt;a href=&#34;https://pixabay.com/en/cute-cartoon-robot-funny-character-807306/&#34;&gt;on this free image&lt;/a&gt;. Now, Lintr Bot has a face but if you look at its GitHub activity, you might wonder, what does it even do? It&amp;rsquo;s perfectly fine for a human to have nearly no GitHub activity, but remember that Lintr Bot lives on GitHub only, so what does it do all day?&lt;/p&gt;
&lt;p&gt;Well Lintr Bot goes around and comments on Pull Requests in R packages, see for instance &lt;a href=&#34;https://github.com/ropensci/drake/pull/342#issuecomment-375929172&#34;&gt;this comment&lt;/a&gt;. As mentioned earlier, a contributor who forgets even a slight code style mistake will be reminded of it by Lintr Bot if the package has a &lt;code&gt;lintr&lt;/code&gt; unit test. This is quite useful!&lt;/p&gt;
&lt;p&gt;We might also wonder how often Lintr Bot actually works? After all, since GitHub activity timeline doesn&amp;rsquo;t show comments on Pull Requests, we&amp;rsquo;re at a loss when it comes to estimating how active this bot is&amp;hellip;&lt;/p&gt;
&lt;h1 id=&#34;lintr-bots-year-in-review&#34;&gt;Lintr Bot&amp;rsquo;s year in review&lt;/h1&gt;
&lt;p&gt;That&amp;rsquo;s where my &lt;a href=&#34;https://masalmon.eu/2018/03/04/hrbrpkgs/&#34;&gt;&lt;code&gt;ghrecipes&lt;/code&gt; package&lt;/a&gt;, presented in &lt;a href=&#34;https://masalmon.eu/2018/03/04/hrbrpkgs/&#34;&gt;my blog post about Bob Rudis&amp;rsquo; R packages&lt;/a&gt;, will come into play. I&amp;rsquo;ve been working on a function called &lt;code&gt;spy&lt;/code&gt; which can return either Pull Requests or Issues an user commented on during a given period of time. As creepy as it might sound, it could help you trace back all the desperate comments you wrote when debugging something last week for instance, without your having had to track them in the first place. &lt;code&gt;ghrecipe::spy&lt;/code&gt; is &lt;a href=&#34;https://github.com/ropenscilabs/ghrecipes/blob/master/R/spy.R&#34;&gt;a work in progress&lt;/a&gt;, but let&amp;rsquo;s see what it can return me for Lintr Bot!&lt;/p&gt;
&lt;p&gt;Note that there&amp;rsquo;s no way to filter for comments between a date range, well as far as I understand the &amp;ldquo;search&amp;rdquo; functionalities of GitHub V4 API, so I can only filter Pull Requests updated in a given range.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;lintrbot_act &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ghrecipes&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;spy&lt;/span&gt;(user &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lintr-bot&amp;#34;&lt;/span&gt;, type &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;PullRequest&amp;#34;&lt;/span&gt;,
                               updated_after &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-03-30&amp;#34;&lt;/span&gt;,
                               updated_before &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2018-03-30&amp;#34;&lt;/span&gt;)
lintrbot_act &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(lintrbot_act,
                              &lt;span style=&#34;color:#06287e&#34;&gt;as.Date&lt;/span&gt;(created_at) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;=&lt;/span&gt; anytime&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;anydate&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-03-30&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We get 228 pull requests in one year! Lintr Bot is definitely &lt;em&gt;not&lt;/em&gt; a lazy little thing!&lt;/p&gt;
&lt;p&gt;Here are 5 Pull Requests that got a visit from Lintr Bot.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(lintrbot_act[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;owner&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;repo&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;title&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;created_at&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;state&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;author&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;url&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;no_comments&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;id&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;PredictiveEcology&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;reproducible&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mergeCache&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-29 18:29:33&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;MERGED&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;eliotmcintire&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/PredictiveEcology/reproducible/pull/18&#39;&gt;&lt;a href=&#34;https://github.com/PredictiveEcology/reproducible/pull/18&#34;&gt;https://github.com/PredictiveEcology/reproducible/pull/18&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;PredictiveEcology&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;SpaDES.core&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;change objectSize to objSize &amp;ndash; name conflict with R.oo::objectSize&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-26 23:48:22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;MERGED&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;eliotmcintire&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/PredictiveEcology/SpaDES.core/pull/57&#39;&gt;&lt;a href=&#34;https://github.com/PredictiveEcology/SpaDES.core/pull/57&#34;&gt;https://github.com/PredictiveEcology/SpaDES.core/pull/57&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;57&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;PredictiveEcology&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;reproducible&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;memoise &amp;ndash; loadFromRepo&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-26 17:41:25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;MERGED&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;eliotmcintire&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/PredictiveEcology/reproducible/pull/17&#39;&gt;&lt;a href=&#34;https://github.com/PredictiveEcology/reproducible/pull/17&#34;&gt;https://github.com/PredictiveEcology/reproducible/pull/17&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;PredictiveEcology&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;quickPlot&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;thin fixes &amp;ndash; bugfixes, SpatialPolygonsDataFrames&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-26 05:32:12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;MERGED&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;eliotmcintire&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/PredictiveEcology/quickPlot/pull/13&#39;&gt;&lt;a href=&#34;https://github.com/PredictiveEcology/quickPlot/pull/13&#34;&gt;https://github.com/PredictiveEcology/quickPlot/pull/13&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ptl93&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;AEDA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;added getEps&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-25 17:12:44&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;MERGED&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;MiGraber&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/ptl93/AEDA/pull/39&#39;&gt;&lt;a href=&#34;https://github.com/ptl93/AEDA/pull/39&#34;&gt;https://github.com/ptl93/AEDA/pull/39&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;39&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at the time series of comments.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(lintrbot_act) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_segment&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; created_at, xend &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; created_at),
               y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, yend &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;,
              strip_text_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Lintr Bot&amp;#39;s work events&amp;#34;&lt;/span&gt;,
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Each vertical line indicates Lintr Bot&amp;#39;s commenting on a pull request&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2018-03-30-lintr-bot/unnamed-chunk-3-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-3&#34;&gt;&lt;/p&gt;
&lt;p&gt;So it seems that Lintr Bot works quite regularly, with some intense periods! I won&amp;rsquo;t look at the number of repos over time to differentiate activity due to more activity in a few repos or due to several repos, but I&amp;rsquo;m curious to see who was helped by Lintr Bot.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(lintrbot_act, owner) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(repos &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(repo)), 
                   n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; n) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;owner&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;repos&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;RTMC&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;tmc-rstudio, tmc-r-tester, tmc-r&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;mlr-org&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mlr&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;38&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;PredictiveEcology&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;reproducible, SpaDES.core, quickPlot, SpaDES.tools, SpaDES.shiny&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Azure&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;doAzureParallel&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;HealthCatalyst&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;healthcareai-r&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;neuropsychology&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;psycho.R&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ropensci&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;drake&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hbc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;bcbioRNASeq, bcbioSingleCell&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I must say that besides the recently onboarded rOpenSci package &lt;code&gt;drake&lt;/code&gt; by Will Landau, I don&amp;rsquo;t know any of these repos!&lt;/p&gt;
&lt;h1 id=&#34;hire-lintr-bot&#34;&gt;Hire Lintr Bot?&lt;/h1&gt;
&lt;p&gt;What about you? Would you let that cute little bot help you?&lt;/p&gt;
&lt;p&gt;Note, a good package to improve code style automatically is &lt;a href=&#34;https://github.com/r-lib/styler&#34;&gt;&lt;code&gt;styler&lt;/code&gt;&lt;/a&gt; by Kirill Müller and Lorenz Walthert, so if Lintr Bot has a lot to tell you, give &lt;code&gt;styler::style_pkg()&lt;/code&gt; a try!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Storrrify #satRdayCapeTown 2018</title>
      <link>https://masalmon.eu/2018/03/24/satrdaycapetown/</link>
      <pubDate>Sat, 24 Mar 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/03/24/satrdaycapetown/</guid>
      <description>&lt;p&gt;One week ago I was in Cape Town for the &lt;a href=&#34;https://capetown2017.satrdays.org/&#34;&gt;local satRday conference&lt;/a&gt;, where I had the honor to be one of the two keynote speakers, the other one being sports analytics extraordinaire &lt;a href=&#34;http://on-the-t.com/&#34;&gt;Stephanie Kovalchik&lt;/a&gt; (You can read Stephanie Kovalchik&amp;rsquo;s account of the conference in &lt;a href=&#34;http://on-the-t.com/2018/03/16/satrday-capetown/&#34;&gt;this blog post&lt;/a&gt;). It was a fantastic experience! The event was very well organized, and 100% corresponds to its description as a &amp;ldquo;one day conference packed with R goodness&amp;rdquo;. You can watch all talks &lt;a href=&#34;https://www.youtube.com/watch?v=NiMqIMKY3RA&amp;amp;list=PLQPtslMzGu4oDr6hjKm1aQ2XN7P35vCbk&#34;&gt;on Youtube&lt;/a&gt;. In &lt;a href=&#34;https://www.youtube.com/watch?v=lZ3deq52qCk&#34;&gt;my talk&lt;/a&gt;, I presented &lt;a href=&#34;https://github.com/ropensci/onboarding/&#34;&gt;rOpenSci onboarding system of packages&lt;/a&gt; and&amp;hellip; wore a hard hat!&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;d be a bit hard for me to really write a good recap of satRday that&amp;rsquo;d do it justice! Instead, I&amp;rsquo;ll use &lt;code&gt;rtweet&lt;/code&gt; and a bit of html hacking to storrrify it (like &lt;a href=&#34;https://storify.com/&#34;&gt;Storify&lt;/a&gt;, but in R) using my live tweets!&lt;/p&gt;
&lt;h1 id=&#34;getting-my-satrday-tweets&#34;&gt;Getting my satRday tweets&lt;/h1&gt;
&lt;p&gt;To get my own satRday Cape Town tweets, I&amp;rsquo;ll first get my timeline and then filter tweets containing the official conference hashtag, &lt;a href=&#34;https://twitter.com/search?q=%23satrdaycapetown&amp;amp;src=tyah&#34;&gt;&amp;quot;#SatRdayCapeTown&amp;rdquo;&lt;/a&gt;. I shall only keep &lt;em&gt;my&lt;/em&gt; tweets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;my_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rtweet&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;get_timeline&lt;/span&gt;(user &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ma_salmon&amp;#34;&lt;/span&gt;, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;5000&lt;/span&gt;)
my_satrday_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(my_tweets,
                                   stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[sS]at[rR]day[cC]ape[tT]own&amp;#34;&lt;/span&gt;),
                                   &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;is_retweet)
my_satrday_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(my_satrday_tweets, created_at)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I got 54 tweets.&lt;/p&gt;
&lt;h1 id=&#34;embedding-tweets&#34;&gt;Embedding tweets&lt;/h1&gt;
&lt;p&gt;I wanted to &lt;em&gt;embed&lt;/em&gt; tweets, not to &lt;code&gt;rtweet::tweet_shot&lt;/code&gt; them, because I wanted to display clickable links. I used the Twitter API embed endpoint after &lt;a href=&#34;https://dev.twitter.com/web/embedded-tweets&#34;&gt;reading this webpage&lt;/a&gt;. This endpoint isn&amp;rsquo;t currently included in &lt;code&gt;rtweet&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
embed_tweet &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(tweet_id){
  url &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt;glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://twitter.com/ma_salmon/status/{tweet_id}&amp;#34;&lt;/span&gt;) 
  
  httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;GET&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://publish.twitter.com/oembed&amp;#34;&lt;/span&gt;,
            query &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(url &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; url,
                         hide_thread &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;content&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    .$html
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ll now write all html chunks in an html file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;fs&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;file_create&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;satrdaycapetown.html&amp;#34;&lt;/span&gt;)
embed_and_save &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(tweet_id){
  &lt;span style=&#34;color:#06287e&#34;&gt;embed_tweet&lt;/span&gt;(tweet_id) 
}

purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(my_satrday_tweets&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;status_id, embed_tweet) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;writeLines&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;satrdaycapetown.html&amp;#34;&lt;/span&gt;, useBytes &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;and-voilà&#34;&gt;And voilà!&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll include all tweets below (via a &lt;a href=&#34;https://stackoverflow.com/questions/28030858/jekyll-include-html-partial-inside-markdown-file&#34;&gt;Jekyll include&lt;/a&gt;, with the html living in _includes, this is probably very hacky&amp;hellip;), happy reading! Thanks again to the organizers, participants and sponsors of SatRday Cape Town for making it such an enjoyable experience!&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;&amp;quot;GitHub is a treasure trove of public activity just waiting to be analyzed&amp;quot; YES! More on my own 💙 for GH data at &lt;a href=&#34;https://twitter.com/hashtag/satRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#satRdayCapeTown&lt;/a&gt; in a few days! 🛫 &lt;a href=&#34;https://t.co/O7n4EIqpbj&#34;&gt;https://t.co/O7n4EIqpbj&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/973532076908695552?ref_src=twsrc%5Etfw&#34;&gt;March 13, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;💯 Things are getting real down here! &lt;a href=&#34;https://twitter.com/hashtag/satRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#satRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/V74HhcVZ9c&#34;&gt;https://t.co/V74HhcVZ9c&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974011430264606722?ref_src=twsrc%5Etfw&#34;&gt;March 14, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;A good way to get familiar with my accent, dear &lt;a href=&#34;https://twitter.com/hashtag/satRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#satRdayCapeTown&lt;/a&gt; attendees 😉 poke &lt;a href=&#34;https://twitter.com/DataWookie?ref_src=twsrc%5Etfw&#34;&gt;@DataWookie&lt;/a&gt; &lt;a href=&#34;https://t.co/HOGoWIqF6I&#34;&gt;https://t.co/HOGoWIqF6I&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974207625465344000?ref_src=twsrc%5Etfw&#34;&gt;March 15, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/theoni_p?ref_src=twsrc%5Etfw&#34;&gt;@theoni_p&lt;/a&gt; wrote a legend for the sticky notes at my &lt;a href=&#34;https://twitter.com/hashtag/satRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#satRdayCapeTown&lt;/a&gt; package dev workshop! (&lt;a href=&#34;https://twitter.com/thecarpentries?ref_src=twsrc%5Etfw&#34;&gt;@thecarpentries&lt;/a&gt; style!) 👩
🎨&lt;br&gt;&lt;br&gt;The nearby &lt;a href=&#34;https://twitter.com/thecarpentries?ref_src=twsrc%5Etfw&#34;&gt;@thecarpentries&lt;/a&gt; workshop uses pink for &amp;quot;confused&amp;quot; so a helper was scared when she came in &amp;amp; saw all the pink notes in our room 😂 &lt;a href=&#34;https://t.co/H0ubBpZYNF&#34;&gt;pic.twitter.com/H0ubBpZYNF&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974606612773163008?ref_src=twsrc%5Etfw&#34;&gt;March 16, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Now I exactly know what to improve next time I teach &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; package development in case someone wants me to do that again! 😀&lt;br&gt;&lt;br&gt;Thanks &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; participants for a great day and insightful feedback! 🚦 &lt;a href=&#34;https://t.co/l6h6GCYvyx&#34;&gt;pic.twitter.com/l6h6GCYvyx&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974661418850058240?ref_src=twsrc%5Etfw&#34;&gt;March 16, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;And thanks a lot to the helpers, &lt;a href=&#34;https://twitter.com/jonmcalder?ref_src=twsrc%5Etfw&#34;&gt;@jonmcalder&lt;/a&gt; &amp;amp;co who made everything run smoothly! 🌟🌟🌟 &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/mxVGpK8oqn&#34;&gt;https://t.co/mxVGpK8oqn&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974675797054316544?ref_src=twsrc%5Etfw&#34;&gt;March 16, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Material for my &lt;a href=&#34;https://twitter.com/hashtag/satRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#satRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; 📦 development workshop &lt;a href=&#34;https://t.co/lGnaBXaHYy&#34;&gt;https://t.co/lGnaBXaHYy&lt;/a&gt;&lt;br&gt;&lt;br&gt;Slides &lt;a href=&#34;https://t.co/lZmUHnWzVv&#34;&gt;https://t.co/lZmUHnWzVv&lt;/a&gt; &lt;a href=&#34;https://t.co/YuYse37zo6&#34;&gt;pic.twitter.com/YuYse37zo6&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974683971467476992?ref_src=twsrc%5Etfw&#34;&gt;March 16, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Roberto Benetto opening &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; with an overview of &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; sf! 🌐🗺 And a pun that made everyone laugh 👏 (wait for the recording to hear it 😜) &lt;a href=&#34;https://t.co/lxRoQkDKMR&#34;&gt;pic.twitter.com/lxRoQkDKMR&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974901803383951360?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;He&amp;#39;s a fan of reading GitHub issues of &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; packages to see what problems and ideas people have. So am I! 🕵️
♂️🕵️
♀️ &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974903554489143296?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;⚡talks time at &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;! 🏃
♂️🏃
♀️&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974906278131654656?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Christopher Waspe about the flowcar package. Nothing to do with 🚗! It&amp;#39;s about ecological networks! (No URL found/given sorry 😢) ⚡ &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974907833446752256?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; speakers please mention your Twitter handle if you have one &amp;amp; don&amp;#39;t have it on your title slide 😉&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974908340424839168?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Vishalin Pillay about automatic report generation! RMarkdown 💙💚💛 &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974908691903283200?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Maphale Matlala about testing the IUCN Red List 🚦 for Ecosystems methodology on 🇿🇦 datasets &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; using the redlistr &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; package &lt;a href=&#34;https://t.co/e8QhgwEcKd&#34;&gt;https://t.co/e8QhgwEcKd&lt;/a&gt; &lt;a href=&#34;https://t.co/yI18oNhUyg&#34;&gt;pic.twitter.com/yI18oNhUyg&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974910580531318784?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Slides for my &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; talk about the &lt;a href=&#34;https://twitter.com/rOpenSci?ref_src=twsrc%5Etfw&#34;&gt;@rOpenSci&lt;/a&gt; onboarding process of &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; packages 📦&lt;a href=&#34;https://t.co/OOPepRT2G3&#34;&gt;https://t.co/OOPepRT2G3&lt;/a&gt;&lt;br&gt;&lt;br&gt;Poke co-editors &lt;a href=&#34;https://twitter.com/_inundata?ref_src=twsrc%5Etfw&#34;&gt;@_inundata&lt;/a&gt; &lt;a href=&#34;https://twitter.com/noamross?ref_src=twsrc%5Etfw&#34;&gt;@noamross&lt;/a&gt; &lt;a href=&#34;https://twitter.com/sckottie?ref_src=twsrc%5Etfw&#34;&gt;@sckottie&lt;/a&gt; &lt;br&gt;&lt;br&gt;And here are the faces of onboarded packages! &lt;a href=&#34;https://t.co/TAXqxr21A1&#34;&gt;pic.twitter.com/TAXqxr21A1&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974930652050182145?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/painblogR?ref_src=twsrc%5Etfw&#34;&gt;@painblogR&lt;/a&gt; is showing us how to make data analysis purrr with 🥕🥕🥕 data as an example &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/sCeRMFcfCd&#34;&gt;pic.twitter.com/sCeRMFcfCd&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974934793858232320?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/painblogR?ref_src=twsrc%5Etfw&#34;&gt;@painblogR&lt;/a&gt; &amp;#39;s code &lt;a href=&#34;https://t.co/23C6Puqxm8&#34;&gt;https://t.co/23C6Puqxm8&lt;/a&gt;&lt;br&gt;&lt;br&gt;And 🥕🥕🥕 dataset &lt;a href=&#34;https://t.co/CiwKJks3im&#34;&gt;https://t.co/CiwKJks3im&lt;/a&gt;&lt;br&gt;&lt;br&gt;A really neat intro to purrr, including pros and cons (nesting hell anecdote 😂) 👌&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974938130485792768?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Sean Soutar showing us how to gather data from dynamic web forms with Docker &amp;amp; the &lt;a href=&#34;https://twitter.com/rOpenSci?ref_src=twsrc%5Etfw&#34;&gt;@rOpenSci&lt;/a&gt; RSelenium &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; package &lt;a href=&#34;https://t.co/WdTgaSzJZe&#34;&gt;https://t.co/WdTgaSzJZe&lt;/a&gt; ⭐ &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974939668579082246?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Futurology! (extreme risk prediction) with Alice Elizabeth Coyne 📈🔮 &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/2G3HPOxT1g&#34;&gt;pic.twitter.com/2G3HPOxT1g&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974941369616740353?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Super &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; organizer-in-chief &lt;a href=&#34;https://twitter.com/DataWookie?ref_src=twsrc%5Etfw&#34;&gt;@DataWookie&lt;/a&gt; speaking about productivity hacks, we&amp;#39;d better all take notes! 🗒✏&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974942461746442242?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/DataWookie?ref_src=twsrc%5Etfw&#34;&gt;@DataWookie&lt;/a&gt; productivy hacks&lt;br&gt;✅ configure ahead &lt;br&gt;✅ ditch RStudio 😱 &amp;amp; use the shell/R command line instead (now I want to debate functions&amp;amp;pkgs vs parameterized scripts with him 😁🤺)&lt;br&gt;✅ use the ☁️&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974946034802679809?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Now listening to &lt;a href=&#34;https://twitter.com/realseem?ref_src=twsrc%5Etfw&#34;&gt;@realseem&lt;/a&gt; about his journey from Python🐍 to R, with game making as motivator 🎮&lt;br&gt;&lt;br&gt;Very entertaining and enlightening lightning talk! &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/pl7QaNSNzx&#34;&gt;pic.twitter.com/pl7QaNSNzx&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974948780180230145?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Schalk Heunis about using R for racing! &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;br&gt;Using R to train the ConvNet of a self-driving RC 🚗&lt;br&gt;&lt;br&gt;Find his project at &lt;a href=&#34;https://t.co/eyPS2gLKnL&#34;&gt;https://t.co/eyPS2gLKnL&lt;/a&gt;&lt;br&gt;&lt;br&gt;He mentioned&lt;br&gt;⭐ &lt;a href=&#34;https://t.co/yzhQX9qvSe&#34;&gt;https://t.co/yzhQX9qvSe&lt;/a&gt;&lt;br&gt;⭐ &lt;a href=&#34;https://t.co/M6xzQOX4rC&#34;&gt;https://t.co/M6xzQOX4rC&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974950699275612160?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Neil Rankin says satRday 2017 changed his life, he discovered useful 🛠! He e.g. mentions &lt;a href=&#34;https://twitter.com/JennyBryan?ref_src=twsrc%5Etfw&#34;&gt;@JennyBryan&lt;/a&gt; &amp;#39;s &lt;a href=&#34;https://t.co/G8vxGml00t&#34;&gt;https://t.co/G8vxGml00t&lt;/a&gt;&lt;br&gt;&lt;br&gt;He&amp;#39;s now talking about identifying bias in 🇿🇦 graduate recruitment&lt;br&gt;&lt;br&gt; &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974973634279337984?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Such a fascinating talk about bias. 😮&lt;br&gt;&lt;br&gt;Neil Rankin used tidy text analysis to analyze personal biographies by self assigned race (thanks to &lt;a href=&#34;https://twitter.com/juliasilge?ref_src=twsrc%5Etfw&#34;&gt;@juliasilge&lt;/a&gt; &amp;#39;s presence last year).&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974976465644261376?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Jed Stephens walked us through some scary factors data 😉 &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974979382967242752?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Deveshnie Mudaly, SQL wiz &amp;amp;engaging speaker, uses a cool example in her talk about using SQL from &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; ☄&lt;br&gt;&lt;br&gt;PSA! She&amp;#39;s looking for collaborators on a Harry Potter R package! Find her at &lt;a href=&#34;https://t.co/oUJZ1unLH0&#34;&gt;https://t.co/oUJZ1unLH0&lt;/a&gt;&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/1pAjcC3zRC&#34;&gt;pic.twitter.com/1pAjcC3zRC&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974980960432345089?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Unsurprisingly &lt;a href=&#34;https://twitter.com/rugbystatsguy?ref_src=twsrc%5Etfw&#34;&gt;@rugbystatsguy&lt;/a&gt; is presenting about 🏈! Either put your Twitter handle on your title slide or... have one people can guess 😉&lt;br&gt;&lt;br&gt;He mentioned the &lt;a href=&#34;https://twitter.com/rOpenSci?ref_src=twsrc%5Etfw&#34;&gt;@rOpenSci&lt;/a&gt; plotly package &lt;a href=&#34;https://t.co/zKD6YuxRv5&#34;&gt;https://t.co/zKD6YuxRv5&lt;/a&gt;&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974982467273752576?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Time for &lt;a href=&#34;https://twitter.com/StatsOnTheT?ref_src=twsrc%5Etfw&#34;&gt;@StatsOnTheT&lt;/a&gt; &amp;#39;s keynote at &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; ! 🎾 &lt;a href=&#34;https://t.co/qPDQywiOPr&#34;&gt;pic.twitter.com/qPDQywiOPr&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974982892781793281?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/StatsOnTheT?ref_src=twsrc%5Etfw&#34;&gt;@StatsOnTheT&lt;/a&gt; works for GIG that will revolutionize 🎾 through data science&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974985754345660416?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;If you are into 🎾 &amp;amp; &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; check out &lt;a href=&#34;https://twitter.com/StatsOnTheT?ref_src=twsrc%5Etfw&#34;&gt;@StatsOnTheT&lt;/a&gt; &amp;#39;s impressive package produced by her collecting tons of data from the web!&lt;a href=&#34;https://t.co/mueGjGXyVc&#34;&gt;https://t.co/mueGjGXyVc&lt;/a&gt;&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974986149822427137?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;This shows &lt;br&gt;&lt;br&gt;✅ numbers calculated by &lt;a href=&#34;https://twitter.com/StatsOnTheT?ref_src=twsrc%5Etfw&#34;&gt;@StatsOnTheT&lt;/a&gt;&amp;#39;s group (win probability computed before and during events!)&lt;br&gt;&lt;br&gt;✅ one of the reasons she 💙s her job!&lt;br&gt; &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/iDwrnGBGfF&#34;&gt;pic.twitter.com/iDwrnGBGfF&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974987597977092097?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Now we&amp;#39;ll get to see how &lt;a href=&#34;https://twitter.com/StatsOnTheT?ref_src=twsrc%5Etfw&#34;&gt;@StatsOnTheT&lt;/a&gt; &amp;#39;s group gets there 👌&lt;br&gt;&lt;br&gt;📽🔩&lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; ☁️🗃&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/quQaUmES2E&#34;&gt;pic.twitter.com/quQaUmES2E&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974988810038767621?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Live demo by &lt;a href=&#34;https://twitter.com/StatsOnTheT?ref_src=twsrc%5Etfw&#34;&gt;@StatsOnTheT&lt;/a&gt; 😎 Here is my own metrics XML 😉&lt;br&gt;&lt;br&gt;&amp;lt;talk&amp;gt;&lt;br&gt;  &amp;lt;content&amp;gt;fascinating&amp;lt;/content&amp;gt;&lt;br&gt;  &amp;lt;speaking&amp;gt;extremely engaging&amp;lt;/speaking&amp;gt;&lt;br&gt;&amp;lt;/talk&amp;gt;&lt;a href=&#34;https://twitter.com/hashtag/satRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#satRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974992497406595072?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/StatsOnTheT?ref_src=twsrc%5Etfw&#34;&gt;@StatsOnTheT&lt;/a&gt; tips for &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; software for real time&lt;br&gt;&lt;br&gt;🎾 Think modularly&lt;br&gt;&lt;br&gt;🎾 Profile bottlenecks using lineprof &lt;a href=&#34;https://t.co/L8zfOoN7aX&#34;&gt;https://t.co/L8zfOoN7aX&lt;/a&gt;&lt;br&gt;&lt;br&gt;🎾Embrace the &lt;a href=&#34;https://twitter.com/hashtag/tidyverse?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#tidyverse&lt;/a&gt;&lt;br&gt;&lt;br&gt;🎾Further optimize with e.g. datatable, parallel/foreach/other parallel processing tools, Rcpp&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974994325569523714?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/StatsOnTheT?ref_src=twsrc%5Etfw&#34;&gt;@StatsOnTheT&lt;/a&gt; : GIG reports are generated automatically &amp;amp; in &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; RMarkdown&lt;br&gt;&lt;br&gt;She shows us an example of a parameterized report cf &lt;a href=&#34;https://t.co/U6HoKDoIwJ&#34;&gt;https://t.co/U6HoKDoIwJ&lt;/a&gt;&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/Py5S0o7RSZ&#34;&gt;pic.twitter.com/Py5S0o7RSZ&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974996206517661696?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/StatsOnTheT?ref_src=twsrc%5Etfw&#34;&gt;@StatsOnTheT&lt;/a&gt;&amp;#39;s tips for real time &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; RMarkdown&lt;br&gt;&lt;br&gt;⚾️ Doc as function&lt;br&gt;&lt;br&gt;⚾️ Make your summaries and plots generalizable&lt;br&gt;&lt;br&gt;⚾️ Separate content from style with a CSS style sheet&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974997120221696000?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Find the material for &lt;a href=&#34;https://twitter.com/StatsOnTheT?ref_src=twsrc%5Etfw&#34;&gt;@StatsOnTheT&lt;/a&gt; awesome talk here &lt;a href=&#34;https://t.co/VvAk7wSODo&#34;&gt;https://t.co/VvAk7wSODo&lt;/a&gt; 💁
♀️&lt;br&gt;&lt;br&gt;Pro tip, nagivate to the repo root &lt;a href=&#34;https://t.co/qviYxENses&#34;&gt;https://t.co/qviYxENses&lt;/a&gt; for even more &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; goodness from her workshop 👩
🏫 and her &lt;a href=&#34;https://twitter.com/RLadiesCapeTown?ref_src=twsrc%5Etfw&#34;&gt;@RLadiesCapeTown&lt;/a&gt; talk about sports blogging 💜💁
♀️&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/974999395237285890?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;It was good promotion of sf, with nice examples! The joke wasn&amp;#39;t about sf though.&lt;br&gt;&lt;br&gt;Roberto Benetto&amp;#39;s code lives here &lt;a href=&#34;https://t.co/IRY46TN4RP&#34;&gt;https://t.co/IRY46TN4RP&lt;/a&gt;&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975004308797296643?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/UbuntR314?ref_src=twsrc%5Etfw&#34;&gt;@UbuntR314&lt;/a&gt; said &lt;a href=&#34;https://twitter.com/juliasilge?ref_src=twsrc%5Etfw&#34;&gt;@juliasilge&lt;/a&gt;&amp;#39;s last year inspired him to use sentiment analysis!&lt;br&gt;&lt;br&gt;He developed an internal package for analysing news survey data and will soon blog about it at &lt;a href=&#34;https://t.co/XUYYSrHQbM&#34;&gt;https://t.co/XUYYSrHQbM&lt;/a&gt;&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/EWcVP3yCxT&#34;&gt;pic.twitter.com/EWcVP3yCxT&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975009361901780992?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/naasvanheerden?ref_src=twsrc%5Etfw&#34;&gt;@naasvanheerden&lt;/a&gt; explains his workflow at work using R packages and Shiny apps... and says the packages will be improved thanks to my workshop yesterday 😎😊&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975010294069112832?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;In his nice talk &lt;a href=&#34;https://twitter.com/naasvanheerden?ref_src=twsrc%5Etfw&#34;&gt;@naasvanheerden&lt;/a&gt; mentioned &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; coming to the rescue... ICYMI &lt;a href=&#34;https://twitter.com/alice_data?ref_src=twsrc%5Etfw&#34;&gt;@alice_data&lt;/a&gt; made a real logo for that! 😉&lt;a href=&#34;https://t.co/zCre4ZWyGG&#34;&gt;https://t.co/zCre4ZWyGG&lt;/a&gt;&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/CSYdqERUA1&#34;&gt;pic.twitter.com/CSYdqERUA1&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975010953678020609?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;The very energetic &lt;a href=&#34;https://twitter.com/SaintlyVi?ref_src=twsrc%5Etfw&#34;&gt;@SaintlyVi&lt;/a&gt; 🏃
♀️ is now introducing CKAN &amp;amp; &lt;a href=&#34;https://twitter.com/hashtag/OpenData?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#OpenData&lt;/a&gt; portals&lt;br&gt;&lt;br&gt;She mentioned the &lt;a href=&#34;https://twitter.com/rOpenSci?ref_src=twsrc%5Etfw&#34;&gt;@rOpenSci&lt;/a&gt; ckanr &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; package &lt;a href=&#34;https://t.co/fWLm4YNrIj&#34;&gt;https://t.co/fWLm4YNrIj&lt;/a&gt;&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/GhS4Qm4zyb&#34;&gt;pic.twitter.com/GhS4Qm4zyb&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975012813591777280?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Why did I say &amp;quot;mentioned&amp;quot;?! &lt;a href=&#34;https://twitter.com/SaintlyVi?ref_src=twsrc%5Etfw&#34;&gt;@SaintlyVi&lt;/a&gt; has now walked us through an example of &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; &lt;a href=&#34;https://twitter.com/rOpenSci?ref_src=twsrc%5Etfw&#34;&gt;@rOpenSci&lt;/a&gt; ckanr use &amp;amp; is now presenting us a typical ckanr workflow! &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/dWyzxrs5jh&#34;&gt;pic.twitter.com/dWyzxrs5jh&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975014065205637120?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Here is &lt;a href=&#34;https://twitter.com/SaintlyVi?ref_src=twsrc%5Etfw&#34;&gt;@SaintlyVi&lt;/a&gt; intro code to &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; &lt;a href=&#34;https://twitter.com/rOpenSci?ref_src=twsrc%5Etfw&#34;&gt;@rOpenSci&lt;/a&gt; ckanr &lt;a href=&#34;https://t.co/QNonaMT6aJ&#34;&gt;https://t.co/QNonaMT6aJ&lt;/a&gt; 🏃
♀️&lt;br&gt;&lt;br&gt;I also liked her promotion of &lt;a href=&#34;https://twitter.com/RLadiesCapeTown?ref_src=twsrc%5Etfw&#34;&gt;@RLadiesCapeTown&lt;/a&gt;! 💜&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975014804732694529?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/OpenSourceQuant?ref_src=twsrc%5Etfw&#34;&gt;@OpenSourceQuant&lt;/a&gt; 📈📉 on blotter &lt;a href=&#34;https://t.co/BMjUgWvDQW&#34;&gt;https://t.co/BMjUgWvDQW&lt;/a&gt;&lt;br&gt;&lt;br&gt;Hey it doesn&amp;#39;t have a README nor a repo description yet 😱😜&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975017892013072384?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/pssGuy?ref_src=twsrc%5Etfw&#34;&gt;@pssGuy&lt;/a&gt; about creating interactive plots in 5 minutes ⏱ starring &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; 🛠&lt;br&gt;&lt;br&gt;✅ the &lt;a href=&#34;https://twitter.com/hashtag/tidyverse?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#tidyverse&lt;/a&gt;&lt;br&gt;✅ &lt;a href=&#34;https://twitter.com/rOpenSci?ref_src=twsrc%5Etfw&#34;&gt;@rOpenSci&lt;/a&gt; plotly &lt;a href=&#34;https://t.co/zKD6YuxRv5&#34;&gt;https://t.co/zKD6YuxRv5&lt;/a&gt;&lt;br&gt;✅ &lt;a href=&#34;https://twitter.com/MilesMcBain?ref_src=twsrc%5Etfw&#34;&gt;@MilesMcBain&lt;/a&gt; datapasta that he tried to pronounce à la 🇦🇺 😉 &lt;a href=&#34;https://t.co/lyjnUOcKTH&#34;&gt;https://t.co/lyjnUOcKTH&lt;/a&gt;&lt;a href=&#34;https://t.co/tO3ME03c9R&#34;&gt;https://t.co/tO3ME03c9R&lt;/a&gt;&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/VfrNcX8RON&#34;&gt;pic.twitter.com/VfrNcX8RON&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975019829328478208?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Last talk, by David Lubinsky, is about profiling using &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; profvis! (poke &lt;a href=&#34;https://twitter.com/_ColinFay?ref_src=twsrc%5Etfw&#34;&gt;@_ColinFay&lt;/a&gt;)&lt;a href=&#34;https://t.co/Ol2KfeBwcQ&#34;&gt;https://t.co/Ol2KfeBwcQ&lt;/a&gt; &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975021332957188096?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Why profile &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; code according to David Lubinsky&lt;br&gt;&lt;br&gt;▶️ not wasting resources in production&lt;br&gt;▶️ often easy to get improvements&lt;br&gt;▶️ R is more than a prototyping language&lt;br&gt;▶️ especially useful with Shiny&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/l34yKrqML1&#34;&gt;pic.twitter.com/l34yKrqML1&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975022195310321664?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Such an interesting, clear and enjoyable live demo of &lt;a href=&#34;https://twitter.com/winston_chang?ref_src=twsrc%5Etfw&#34;&gt;@winston_chang&lt;/a&gt; &amp;#39;s profvis package by David Lubinsky 👌&lt;a href=&#34;https://t.co/Ol2KfeBwcQ&#34;&gt;https://t.co/Ol2KfeBwcQ&lt;/a&gt;&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/RSnNdihuuq&#34;&gt;pic.twitter.com/RSnNdihuuq&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975024277757091842?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;.&lt;a href=&#34;https://twitter.com/realseem?ref_src=twsrc%5Etfw&#34;&gt;@realseem&lt;/a&gt; won a book signed by &lt;a href=&#34;https://twitter.com/hadleywickham?ref_src=twsrc%5Etfw&#34;&gt;@hadleywickham&lt;/a&gt; thanks to his great ⚡talk this morning! Well deserved!&lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; &lt;a href=&#34;https://t.co/4pVymr8wDe&#34;&gt;pic.twitter.com/4pVymr8wDe&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975028215348645888?ref_src=twsrc%5Etfw&#34;&gt;March 17, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Flying home today&amp;amp;tomorrow from &lt;a href=&#34;https://twitter.com/hashtag/SatRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#SatRdayCapeTown&lt;/a&gt; after a great conference, thx a ton to the organizers, participants &amp;amp;sponsors! 🌴✈⛄ &lt;a href=&#34;https://t.co/OQWa650oF3&#34;&gt;pic.twitter.com/OQWa650oF3&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975275576788439040?ref_src=twsrc%5Etfw&#34;&gt;March 18, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-conversation=&#34;none&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Not sure if relevant but it seems that sports analytics extraordinaire &lt;a href=&#34;https://twitter.com/StatsOnTheT?ref_src=twsrc%5Etfw&#34;&gt;@StatsOnTheT&lt;/a&gt;&lt;br&gt; presented such models at her &lt;a href=&#34;https://twitter.com/hashtag/satRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#satRdayCapeTown&lt;/a&gt; workshop &lt;a href=&#34;https://t.co/YyQyUKFaxP&#34;&gt;https://t.co/YyQyUKFaxP&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/975671735340158978?ref_src=twsrc%5Etfw&#34;&gt;March 19, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;New &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; post! &amp;quot;Storrrify &lt;a href=&#34;https://twitter.com/hashtag/satRdayCapeTown?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#satRdayCapeTown&lt;/a&gt; 2018&amp;quot;&lt;a href=&#34;https://t.co/1HimAko2yf&#34;&gt;https://t.co/1HimAko2yf&lt;/a&gt;&lt;br&gt;&lt;br&gt;Thanks again to the organizers, participants and sponsors of this great conference! &lt;a href=&#34;https://t.co/HHJjhLUUR9&#34;&gt;pic.twitter.com/HHJjhLUUR9&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/977529134019641344?ref_src=twsrc%5Etfw&#34;&gt;March 24, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;</description>
    </item>
    
    <item>
      <title>hrbrpkgs: list Bob Rudis&#39; packages</title>
      <link>https://masalmon.eu/2018/03/04/hrbrpkgs/</link>
      <pubDate>Sun, 04 Mar 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/03/04/hrbrpkgs/</guid>
      <description>&lt;p&gt;Recently I needed to count lines of code for a project at work work (this is an expression of the person honored in this post), and happened to discover that Bob Rudis had started &lt;a href=&#34;https://github.com/hrbrmstr/cloc&#34;&gt;an R package&lt;/a&gt; wrapping the &lt;a href=&#34;https://github.com/AlDanial/cloc&#34;&gt;Perl CLOC script&lt;/a&gt;. Of course! He has packages for a lot of things! And he&amp;rsquo;s always ready to help: after I asked him a question about the package, and made a pull request to renew its wrapped CLOC script, he made it all pretty and ready-to-go!&lt;/p&gt;
&lt;p&gt;He himself defined his Stack Overflow Driven-Development (SODD) workflow &lt;a href=&#34;https://rud.is/b/2017/09/28/sodd-stackoverflow-driven-development/&#34;&gt;in a blog post&lt;/a&gt;: someone will ask him a question on Stack Overflow, and he&amp;rsquo;ll write a long answer eventually becoming a package, that will or will not make it to CRAN&amp;hellip; Which is the motivation of this blog post. How can I output a list of all packages Bob has on GitHub?&lt;/p&gt;
&lt;h1 id=&#34;the-magic-of-github-api-v4-ghql-and-jqjqr&#34;&gt;The magic of GitHub API V4, &lt;code&gt;ghql&lt;/code&gt; and jq/&lt;code&gt;jqr&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve recently started using GitHub API V4 instead of V3, that you might have seen on this blog in &lt;a href=&#34;https://masalmon.eu/2017/04/12/seeds/&#34;&gt;my post about random seeds&lt;/a&gt; and &lt;a href=&#34;https://masalmon.eu/2017/02/21/firstcommit/&#34;&gt;my post about initial commit messages&lt;/a&gt;. I&amp;rsquo;ll probably introduce my workflow more formally and extensively elsewhere but here are a few appetizers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Find out &lt;a href=&#34;https://developer.github.com/v4/#why-is-github-using-graphql&#34;&gt;why GitHub is using GraphQL&lt;/a&gt;. I was particularly receptive to the idea of getting &lt;em&gt;just&lt;/em&gt; the data I needed from the API.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;rOpenSci has a very good general purpose GraphQL R client, &lt;a href=&#34;https://github.com/ropensci/ghql&#34;&gt;&lt;code&gt;ghql&lt;/code&gt;&lt;/a&gt; by Scott Chamberlain, that includes R6 classes of course (being a package of Scott&amp;rsquo;s) and whose doc examples are for&amp;hellip; GitHub API V4!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;One can build queries in &lt;a href=&#34;https://developer.github.com/v4/explorer/&#34;&gt;GitHub V4 explorer&lt;/a&gt; that has auto-completion and the docs on the right so it made, and still makes, things easier for me as a GraphQL n00b.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;One can wrangle JSON using jq via the rOpenSci &lt;a href=&#34;https://github.com/ropensci/jqr&#34;&gt;&lt;code&gt;jqr&lt;/code&gt; package&lt;/a&gt; which is a real gem. Carl Boettiger wrote about it &lt;a href=&#34;http://www.carlboettiger.info/2017/12/11/data-rectangling-with-jq/&#34;&gt;here&lt;/a&gt;, I trusted him and gave it a try and my mind was blown. Now I do not find the syntax intuitive but guess what, there&amp;rsquo;s &lt;a href=&#34;https://jqplay.org/&#34;&gt;an explorer&lt;/a&gt; for that too! So I could &lt;code&gt;writeClipboard&lt;/code&gt; JSON output from the API and use the explorer to write code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The results of my recent discoveries, and my using the API for work work stuff, can be found in my very nascent/work-in-progress &lt;a href=&#34;https://github.com/maelle/ghrecipes&#34;&gt;&lt;code&gt;ghrecipes&lt;/code&gt; package&lt;/a&gt;. By the way if you&amp;rsquo;re after something similar i.e. high-level, but for GitHub API V3, check &lt;a href=&#34;https://github.com/coatless/ghapi&#34;&gt;&lt;code&gt;ghapi&lt;/code&gt;&lt;/a&gt; out.&lt;/p&gt;
&lt;h1 id=&#34;using-my-own-github-package&#34;&gt;Using my own GitHub package&lt;/h1&gt;
&lt;p&gt;I first retrieved all GitHub repositories of Bob&amp;rsquo;s. My &lt;code&gt;ghrecipes&lt;/code&gt; package iterates for you thanks to a piece of code by Scott Chamberlain.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You&amp;rsquo;ll note some things could be made easier if the output of my own functions was a bit different so you can imagine that yes, I&amp;rsquo;ll break my own package from time to time, but at least this gives a taste of what can be done.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You can read the code of my &lt;code&gt;ghrecipes::get_repos&lt;/code&gt; function &lt;a href=&#34;https://github.com/maelle/ghrecipes/blob/master/R/get_repos.R&#34;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
repos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ghrecipes&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;get_repos&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrmstr&amp;#34;&lt;/span&gt;)
repos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;separate&lt;/span&gt;(repos, name, into &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;owner&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;repo&amp;#34;&lt;/span&gt;),
                         remove &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;, sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# remove forks&lt;/span&gt;
repos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(repos, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;is_fork)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I found 274 repos.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(repos) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;owner&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;repo&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;created_at&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;updated_at&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;description&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;is_fork&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmstr/dbClone&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmstr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dbClone&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2011-04-17 03:04:54&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12 15:07:47&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;OS X native-port of Moloch&amp;rsquo;s dbClone utility (&lt;a href=&#34;http://marcoramilli.blogspot.com/2011/04/dropbox-cloner.html&#34;&gt;http://marcoramilli.blogspot.com/2011/04/dropbox-cloner.html&lt;/a&gt;)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmstr/slopegraph&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmstr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;slopegraph&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2012-05-29 01:15:20&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-19 08:00:32&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;A &amp;lsquo;slopegraph&amp;rsquo; (&amp;lsquo;table-chart&amp;rsquo;) generator in Python using Cairo/RaphaÃ«l. Currently handles a two column chart with &lt;em&gt;many&lt;/em&gt; output options. Look at the &amp;lsquo;/examples&amp;rsquo; directory for sample configurations, data files and output formats.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmstr/sandy&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmstr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sandy&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2012-10-28 13:09:36&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-07-04 11:42:37&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;An example of how to plot path &amp;amp; cone of Hurricane SANDY in Râ€¦&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;vz-risk/veris&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;vz-risk&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;veris&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-01-04 17:19:19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-02 11:41:31&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Vocabulary for Event Recording and Incident Sharing (VERIS)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmstr/netintel&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmstr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;netintel&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-02-08 17:21:15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-12 18:08:53&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;A collection of &amp;ldquo;network intelligence&amp;rdquo; utilities for R. ASN info, IP reputation, etc.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;vz-risk/public-data&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;vz-risk&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;public-data&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-03-07 13:46:19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-07 20:40:36&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;data from publicly disclosed incidents&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Now as you see I&amp;rsquo;m nearly done since my own function returns the GitHub description of the repo (I had forgotten about that when starting to write this post!) and since Bob seems to often write a description for his repos which we should all do; but I only want &lt;em&gt;packages&lt;/em&gt;. Fear not, I already have a recipe for this as well, &lt;a href=&#34;https://github.com/maelle/ghrecipes/blob/master/R/is_package.R&#34;&gt;&lt;code&gt;is_package_repo&lt;/code&gt;&lt;/a&gt;! It looks whether a repo contains man, R, DESCRIPTION and NAMESPACE. Now I&amp;rsquo;m pretty sure the code below could be hugely simplified, but I&amp;rsquo;m in a hurry.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;is_pkg &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
  &lt;span style=&#34;color:#06287e&#34;&gt;message&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;name)
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(owner &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;owner,
                 repo &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;repo,
                 is_pkg &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; ghrecipes&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is_package_repo&lt;/span&gt;(owner, repo))
}

are_pkgs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;split&lt;/span&gt;(repos, repos&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;name) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(is_pkg)

are_pkgs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(repos, are_pkgs, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;owner&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;repo&amp;#34;&lt;/span&gt;))
hrbrpkgs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(are_pkgs, is_pkg)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I found 170 packages whose whole table I&amp;rsquo;ll put at the very end of this post. I can&amp;rsquo;t wait to browse it!&lt;/p&gt;
&lt;h1 id=&#34;the-end&#34;&gt;The end?&lt;/h1&gt;
&lt;p&gt;What can &lt;em&gt;you&lt;/em&gt; do with this list? Explore it to find the package(s) you didn&amp;rsquo;t know you needed, or the package(s) you&amp;rsquo;d like to contribute to, because I can recommend contributing to Bob&amp;rsquo;s packages, and he encourages people to!&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;ca&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;I’ve got a GH full of diverse &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; 📦 repos that all need tweaks/enhancements ranging from docs to ƒ()s. I’ll gladly help anyone — esp new PRers — contribute.&lt;/p&gt;&amp;mdash; hrbr&amp;#39;Challa (@hrbrmstr) &lt;a href=&#34;https://twitter.com/hrbrmstr/status/952162899472146432?ref_src=twsrc%5Etfw&#34;&gt;13 de gener de 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;And as promised here is the table!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
hrbrpkgs &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# thanks https://stackoverflow.com/questions/30901027/convert-a-column-of-text-urls-into-active-hyperlinks-in-shiny&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(link &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://github.com/hrbrmstr/{repo}&amp;#34;&lt;/span&gt;),
                link &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; glue&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;glue&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;a href=&amp;#39;{link}&amp;#39;&amp;gt;{link}&amp;lt;/a&amp;gt;&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(created_at &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;as_date&lt;/span&gt;(created_at),
                updated_at &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;as_date&lt;/span&gt;(updated_at)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rename&lt;/span&gt;(package &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; repo) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(package, description, created_at, updated_at, link) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(package) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;package&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;description&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;created_at&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;updated_at&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;link&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;adobecolor&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Use Adobe swatch files as R color palettes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-03-20&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-05-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/adobecolor&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/adobecolor&#34;&gt;https://github.com/hrbrmstr/adobecolor&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;albersusa&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools, shapefiles &amp;amp; data to work with an &amp;ldquo;AlbersUSA&amp;rdquo; composite projection in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-28&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/albersusa&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/albersusa&#34;&gt;https://github.com/hrbrmstr/albersusa&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;algorithmia&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R interface to the Algorithmia API&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-07-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/algorithmia&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/algorithmia&#34;&gt;https://github.com/hrbrmstr/algorithmia&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;asam&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;⚓ R package providing tools to access, download, update, process and visualize Anti-shipping Activity Messages (ASAM) Database Files&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-09-19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/asam&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/asam&#34;&gt;https://github.com/hrbrmstr/asam&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;berate&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Provide Insightful Motivation During Interactive R Sessions&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-10-29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-09-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/berate&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/berate&#34;&gt;https://github.com/hrbrmstr/berate&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;bismer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Generate Shakespearean Insults with R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-07-19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/bismer&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/bismer&#34;&gt;https://github.com/hrbrmstr/bismer&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;blocklist&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;💂‍♂️ Tools to Work with the &amp;lt;blocklist.de&amp;gt; &amp;lsquo;API&amp;rsquo; in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-04-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-04-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/blocklist&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/blocklist&#34;&gt;https://github.com/hrbrmstr/blocklist&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;bloomsky&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Work with &amp;lsquo;BloomSky&amp;rsquo; Weather Station Data in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-04-19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/bloomsky&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/bloomsky&#34;&gt;https://github.com/hrbrmstr/bloomsky&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;bom&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Identify and Work with Byte Order Marks in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-10-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-30&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/bom&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/bom&#34;&gt;https://github.com/hrbrmstr/bom&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;burrp&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🔖 Tools to Import and Process &amp;lsquo;PortSwigger&amp;rsquo; &amp;lsquo;Burp&amp;rsquo; Proxy Data&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-07-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/burrp&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/burrp&#34;&gt;https://github.com/hrbrmstr/burrp&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;cdcfluview&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;😷 R package to Retrieve U.S. Flu Season Data from the CDC FluView Portal (WHO &amp;amp; ILINet)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-01-11&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-27&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/cdcfluview&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/cdcfluview&#34;&gt;https://github.com/hrbrmstr/cdcfluview&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;censys&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R interface to the Censys &amp;ldquo;cyber&amp;rdquo;/scans search engine â€¢ &lt;a href=&#34;https://www.censys.io/tutorial&#34;&gt;https://www.censys.io/tutorial&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-01-11&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/censys&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/censys&#34;&gt;https://github.com/hrbrmstr/censys&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;cfhttr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;👷‍♂️ Workaround Cloudflare Anti-DDoS Protection&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/cfhttr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/cfhttr&#34;&gt;https://github.com/hrbrmstr/cfhttr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;cloc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R package to the perl cloc script (which counts blank lines, comment lines, and physical lines of source code in source files/trees/archives)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-07-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/cloc&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/cloc&#34;&gt;https://github.com/hrbrmstr/cloc&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;cloudcidrs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Obtain and Work with Cloud Provider CIDR Blocks in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-10-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-11-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/cloudcidrs&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/cloudcidrs&#34;&gt;https://github.com/hrbrmstr/cloudcidrs&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;crafter&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🔬 An R package to work with PCAPs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-13&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/crafter&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/crafter&#34;&gt;https://github.com/hrbrmstr/crafter&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;curlconverter&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;➰ ➡️ ➖ Translate cURL command lines into parameters for use with httr or actual httr calls (R)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-01-28&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/curlconverter&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/curlconverter&#34;&gt;https://github.com/hrbrmstr/curlconverter&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;cymruservices&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🐉 package that provides interfaces to various Team Cymru Services&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-07-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/cymruservices&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/cymruservices&#34;&gt;https://github.com/hrbrmstr/cymruservices&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;czdaptools&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R tools for downloading zone data from ICANN&amp;rsquo;s CZDS application&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-10-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-13&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/czdaptools&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/czdaptools&#34;&gt;https://github.com/hrbrmstr/czdaptools&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;darksky&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;☁️ R interface to the Dark Sky API&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-09-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/darksky&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/darksky&#34;&gt;https://github.com/hrbrmstr/darksky&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;databox&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Work with the databox API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-08-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/databox&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/databox&#34;&gt;https://github.com/hrbrmstr/databox&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ddsecblog&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;knitr format for ddsec blog posts&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-10-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-10-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/ddsecblog&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/ddsecblog&#34;&gt;https://github.com/hrbrmstr/ddsecblog&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;decapitated&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Headless &amp;lsquo;Chrome&amp;rsquo; Orchestration in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-13&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/decapitated&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/decapitated&#34;&gt;https://github.com/hrbrmstr/decapitated&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;decapitated&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chrome headless but rly websockets&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/decapitated&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/decapitated&#34;&gt;https://github.com/hrbrmstr/decapitated&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;devd&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Install, Start and Stop &amp;lsquo;devd&amp;rsquo; Instances from R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-04-29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/devd&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/devd&#34;&gt;https://github.com/hrbrmstr/devd&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;dmarc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Machinate &amp;lsquo;DMARC&amp;rsquo; in R (WIP libopendmarc wrapper)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-07&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-07&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/dmarc&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/dmarc&#34;&gt;https://github.com/hrbrmstr/dmarc&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;docxtractr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;✂️ Extract Tables from Microsoft Word Documents with R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-24&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/docxtractr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/docxtractr&#34;&gt;https://github.com/hrbrmstr/docxtractr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;domaintools&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R API interface to the DomainTools API&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-01-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/domaintools&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/domaintools&#34;&gt;https://github.com/hrbrmstr/domaintools&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;dtupdate&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;The dtupdate package has functions that try to make it easier to keep up with the non-CRAN universe&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-08-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-24&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/dtupdate&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/dtupdate&#34;&gt;https://github.com/hrbrmstr/dtupdate&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;epidata&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📉 Tools to Retrieve Economic Policy Institute Data Library Extracts in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-28&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/epidata&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/epidata&#34;&gt;https://github.com/hrbrmstr/epidata&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;exiv&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📷 Read and Write &amp;lsquo;Exif&amp;rsquo; Image/Media Tags with R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/exiv&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/exiv&#34;&gt;https://github.com/hrbrmstr/exiv&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;fishpals&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;A package to generate fish color palettes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-09-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/fishpals&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/fishpals&#34;&gt;https://github.com/hrbrmstr/fishpals&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;flowdockr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R package to work with the Flowdock API&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-02-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/flowdockr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/flowdockr&#34;&gt;https://github.com/hrbrmstr/flowdockr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;forceaccounted&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;The Force, Accounted (in R)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-01-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/forceaccounted&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/forceaccounted&#34;&gt;https://github.com/hrbrmstr/forceaccounted&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;freepst&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;An &amp;lsquo;rJava&amp;rsquo; wrapper around &amp;lsquo;java-libpst&amp;rsquo; &lt;a href=&#34;https://github.com/rjohnsondev/java-libpst&#34;&gt;https://github.com/rjohnsondev/java-libpst&lt;/a&gt; to read PST/OST files&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/freepst&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/freepst&#34;&gt;https://github.com/hrbrmstr/freepst&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;gdns&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to work with the Google DNS over HTTPS API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-04-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-07-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/gdns&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/gdns&#34;&gt;https://github.com/hrbrmstr/gdns&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;getdns&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ðŸ•µðŸ½â€â™€ï¸ Query Domain Name System Using the &amp;lsquo;getdns&amp;rsquo; Application Programming Interface&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/getdns&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/getdns&#34;&gt;https://github.com/hrbrmstr/getdns&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ggalt&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🌎 Extra Coordinate Systems, Geoms,  Statistical Transformations &amp;amp; Scales for &amp;lsquo;ggplot2&amp;rsquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-09-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/ggalt&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/ggalt&#34;&gt;https://github.com/hrbrmstr/ggalt&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ggcounty&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🌐 Generate ggplot2 geom_map county maps&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-04-17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/ggcounty&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/ggcounty&#34;&gt;https://github.com/hrbrmstr/ggcounty&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;gghazard&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Improved Base and Grid Plots for Survival Hazard Cox Regression&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-31&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/gghazard&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/gghazard&#34;&gt;https://github.com/hrbrmstr/gghazard&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;greynoise&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Query &amp;lsquo;GreyNoise Intelligence &amp;lsquo;API&amp;rsquo; in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-13&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/greynoise&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/greynoise&#34;&gt;https://github.com/hrbrmstr/greynoise&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;gzmem&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;⏫⏬ Partial resurrection of the Rcompression package since memCompress/memDecompress are brain dead&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-09-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-30&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/gzmem&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/gzmem&#34;&gt;https://github.com/hrbrmstr/gzmem&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;harbor&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;An R package for controlling docker containers on local and remote hosts&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-10-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/harbor&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/harbor&#34;&gt;https://github.com/hrbrmstr/harbor&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hgr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🏃 Tools to Work with the &amp;lsquo;Postlight&amp;rsquo; &amp;lsquo;Mercury&amp;rsquo; &amp;lsquo;API&amp;rsquo; â€” &lt;a href=&#34;https://mercury.postlight.com/web-parser/&#34;&gt;https://mercury.postlight.com/web-parser/&lt;/a&gt; â€” in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-04-19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/hgr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/hgr&#34;&gt;https://github.com/hrbrmstr/hgr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hilbert&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;super basic non-vectorized hilbert Rcpp example for an SO question&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/hilbert&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/hilbert&#34;&gt;https://github.com/hrbrmstr/hilbert&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hilbertv4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Create and Annotate &amp;lsquo;Hilbert Curve&amp;rsquo; &amp;lsquo;IPv4&amp;rsquo; Heatmaps in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/hilbertv4&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/hilbertv4&#34;&gt;https://github.com/hrbrmstr/hilbertv4&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hrbraddins&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Additional Addins for RStudio&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/hrbraddins&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/hrbraddins&#34;&gt;https://github.com/hrbrmstr/hrbraddins&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmisc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;personal R pkg&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/hrbrmisc&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/hrbrmisc&#34;&gt;https://github.com/hrbrmstr/hrbrmisc&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmiscpp&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;C/C++-backed R functions that have no real home yet&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-06-30&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/hrbrmiscpp&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/hrbrmiscpp&#34;&gt;https://github.com/hrbrmstr/hrbrmiscpp&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmrkdn&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Personal R Markdown templates&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-01-20&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-12-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/hrbrmrkdn&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/hrbrmrkdn&#34;&gt;https://github.com/hrbrmstr/hrbrmrkdn&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hrbrthemes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🔏 Opinionated, typographic-centric ggplot2 themes and theme components&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-11&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/hrbrthemes&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/hrbrthemes&#34;&gt;https://github.com/hrbrmstr/hrbrthemes&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hrbrthemeslite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;hrbrthemes w/o spell check&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-27&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-27&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/hrbrthemeslite&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/hrbrthemeslite&#34;&gt;https://github.com/hrbrmstr/hrbrthemeslite&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;htmltidy&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🚯 Tidy Up and Test XPath Queries on HTML and XML Content in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-05-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/htmltidy&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/htmltidy&#34;&gt;https://github.com/hrbrmstr/htmltidy&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hubway&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R interface to the Hubway &amp;ldquo;API&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/hubway&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/hubway&#34;&gt;https://github.com/hrbrmstr/hubway&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;humanparser&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;👱‍♂️ R package to decompose full (human) names into component parts&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-20&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-11-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/humanparser&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/humanparser&#34;&gt;https://github.com/hrbrmstr/humanparser&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hyphenatr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R interface to Hunspell hyphenation&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-04-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/hyphenatr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/hyphenatr&#34;&gt;https://github.com/hrbrmstr/hyphenatr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;infermedica&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;(migrated from gitlab to keep a copy in the event intermedica decides to be stupid and violate AGPL)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/infermedica&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/infermedica&#34;&gt;https://github.com/hrbrmstr/infermedica&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ipapi&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;An R package to geolocate IPv4/6 addresses and/or domain names using ip-api.com&amp;rsquo;s API&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-03-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/ipapi&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/ipapi&#34;&gt;https://github.com/hrbrmstr/ipapi&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;iptools&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🍴 A toolkit for manipulating, validating and testing IP addresses and ranges, along with datasets relating to IP addresses. While it primarily has support for the IPv4 address space, more extensive IPv6 support is intended.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-08-29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/iptools&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/iptools&#34;&gt;https://github.com/hrbrmstr/iptools&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;irced&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;☎️ Putting the &amp;ldquo;R&amp;rdquo; into IRC&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-09-24&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/irced&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/irced&#34;&gt;https://github.com/hrbrmstr/irced&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;jasmine&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;simple json parser (just a parser)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-04-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-09-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/jasmine&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/jasmine&#34;&gt;https://github.com/hrbrmstr/jasmine&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;jericho&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📔 Extract plain or structured text from HTML content in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-09-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/jericho&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/jericho&#34;&gt;https://github.com/hrbrmstr/jericho&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;jerichojars&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Java Archive Wrapper Supporting the &amp;lsquo;jericho&amp;rsquo; R Package&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-09-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/jerichojars&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/jerichojars&#34;&gt;https://github.com/hrbrmstr/jerichojars&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Johnson&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/Johnson&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/Johnson&#34;&gt;https://github.com/hrbrmstr/Johnson&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;jsonview&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;JSON pretty printer &amp;amp; viewer in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-01-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/jsonview&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/jsonview&#34;&gt;https://github.com/hrbrmstr/jsonview&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;jwatjars&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Java &amp;lsquo;.jar&amp;rsquo; Files for &amp;lsquo;jwatr&amp;rsquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/jwatjars&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/jwatjars&#34;&gt;https://github.com/hrbrmstr/jwatjars&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;jwatr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📇 Tools to Query and Create Web Archive Files Using the Java Web Archive Toolkit in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-24&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/jwatr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/jwatr&#34;&gt;https://github.com/hrbrmstr/jwatr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;keybase&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🏯 Tools to Work with the &amp;lsquo;Keybase&amp;rsquo; &amp;lsquo;API&amp;rsquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-11&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/keybase&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/keybase&#34;&gt;https://github.com/hrbrmstr/keybase&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;knitrengines&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;An R package to collect and seamlessly add new language engines to knitr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-09-07&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/knitrengines&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/knitrengines&#34;&gt;https://github.com/hrbrmstr/knitrengines&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;kumo&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;wordclouds (more info soon)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/kumo&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/kumo&#34;&gt;https://github.com/hrbrmstr/kumo&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;kumojars&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;wordclouds (more info soon)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/kumojars&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/kumojars&#34;&gt;https://github.com/hrbrmstr/kumojars&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;lineworkmaps&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Use Project Linework maps easily in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-07-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/lineworkmaps&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/lineworkmaps&#34;&gt;https://github.com/hrbrmstr/lineworkmaps&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;localgeo&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;small R package for geocoding of US city/state to lon/lat&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-01-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/localgeo&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/localgeo&#34;&gt;https://github.com/hrbrmstr/localgeo&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;lodes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Retrieve Data from LEHD Origin-Destination Employment Statistics Server in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-20&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/lodes&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/lodes&#34;&gt;https://github.com/hrbrmstr/lodes&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;longurl&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ℹ️ Small R package for the URL Expander API&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-06-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/longurl&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/longurl&#34;&gt;https://github.com/hrbrmstr/longurl&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;maRalago&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Is ðŸŠ at Mar-a-Lago&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-04-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/maRalago&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/maRalago&#34;&gt;https://github.com/hrbrmstr/maRalago&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;markdowntemplates&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;✅🔻 A collection of alternate R markdown templates&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-02-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/markdowntemplates&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/markdowntemplates&#34;&gt;https://github.com/hrbrmstr/markdowntemplates&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;melting5jars&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;MELTING 5 jars&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/melting5jars&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/melting5jars&#34;&gt;https://github.com/hrbrmstr/melting5jars&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;metis&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Helpers for Accessing and Querying Amazon Athena using R, Including a lightweight RJDBC shim&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/metis&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/metis&#34;&gt;https://github.com/hrbrmstr/metis&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;metricsgraphics&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📈 htmlwidget interface to the MetricsGraphics.js D3 chart library&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-01-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/metricsgraphics&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/metricsgraphics&#34;&gt;https://github.com/hrbrmstr/metricsgraphics&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;mgrs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🌐 An R Package to Convert &amp;lsquo;MGRS&amp;rsquo; (Military Grid Reference System) References To and From Other Coordiante Systems&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-04-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-30&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/mgrs&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/mgrs&#34;&gt;https://github.com/hrbrmstr/mgrs&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;mhn&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🍯 Analyze and Visualize Data from Modern Honey Network Servers with R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/mhn&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/mhn&#34;&gt;https://github.com/hrbrmstr/mhn&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;moviemeter&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to work with the MovieMeter API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-10-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-10-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/moviemeter&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/moviemeter&#34;&gt;https://github.com/hrbrmstr/moviemeter&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;mqtt&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📞 Interoperate with &amp;lsquo;MQTT&amp;rsquo; Message Brokers with R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-20&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/mqtt&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/mqtt&#34;&gt;https://github.com/hrbrmstr/mqtt&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;mrt&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Retrieve and Process &amp;lsquo;BGP&amp;rsquo; Files in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-07-18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/mrt&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/mrt&#34;&gt;https://github.com/hrbrmstr/mrt&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;msgxtractr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📇 Extract contents from Outlook &amp;lsquo;.msg&amp;rsquo; files in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-24&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/msgxtractr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/msgxtractr&#34;&gt;https://github.com/hrbrmstr/msgxtractr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;mtblr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R package to work with mtbls&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-04-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-04-24&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/mtblr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/mtblr&#34;&gt;https://github.com/hrbrmstr/mtblr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;myip&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Determine Your Public &amp;lsquo;IP&amp;rsquo; Address in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-07-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/myip&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/myip&#34;&gt;https://github.com/hrbrmstr/myip&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;mywx&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Query the &amp;lsquo;MetMalaysia&amp;rsquo; Web Service &amp;lsquo;API&amp;rsquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-13&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/mywx&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/mywx&#34;&gt;https://github.com/hrbrmstr/mywx&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ndjson&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;♨️ Wicked-Fast Streaming &amp;lsquo;JSON&amp;rsquo; (&amp;lsquo;ndjson&amp;rsquo;) Reader in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-09-07&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/ndjson&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/ndjson&#34;&gt;https://github.com/hrbrmstr/ndjson&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;netintel&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;A collection of &amp;ldquo;network intelligence&amp;rdquo; utilities for R. ASN info, IP reputation, etc.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-02-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/netintel&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/netintel&#34;&gt;https://github.com/hrbrmstr/netintel&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;newsflash&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Work with the Internet Archive and GDELT Television Explorer in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/newsflash&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/newsflash&#34;&gt;https://github.com/hrbrmstr/newsflash&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;newsfreq&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R package to search for keyword frequencies in news articles via newsfreq.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-01-31&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/newsfreq&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/newsfreq&#34;&gt;https://github.com/hrbrmstr/newsfreq&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;nifffty&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Small R package to post events to IFTTT Maker channel/recipes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-06-19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/nifffty&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/nifffty&#34;&gt;https://github.com/hrbrmstr/nifffty&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;nominatim&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🌏 Tools for Working with the &amp;lsquo;Nominatim&amp;rsquo; API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-07-28&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/nominatim&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/nominatim&#34;&gt;https://github.com/hrbrmstr/nominatim&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;notary&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🔏📦 Signing &amp;amp; verification of R packages&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-24&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/notary&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/notary&#34;&gt;https://github.com/hrbrmstr/notary&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ohby&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R interface to the &amp;lsquo;ohby&amp;rsquo; URL &amp;amp; content shortener&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-06-13&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-06-13&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/ohby&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/ohby&#34;&gt;https://github.com/hrbrmstr/ohby&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;omdbapi&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R package to access the OMDB API (&lt;a href=&#34;http://www.omdbapi.com/&#34;&gt;http://www.omdbapi.com/&lt;/a&gt;)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-06-16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/omdbapi&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/omdbapi&#34;&gt;https://github.com/hrbrmstr/omdbapi&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;opengraph&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Mine &amp;lsquo;Open Graph&amp;rsquo;-like Tags From &amp;lsquo;HTML&amp;rsquo; Content&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/opengraph&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/opengraph&#34;&gt;https://github.com/hrbrmstr/opengraph&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;overpass&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ℹ️ Tools to Work With the OpenStreetMap (OSM) Overpass API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/overpass&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/overpass&#34;&gt;https://github.com/hrbrmstr/overpass&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;pantone&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R package for Pantone colors of the year&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-12-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/pantone&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/pantone&#34;&gt;https://github.com/hrbrmstr/pantone&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;passivetotal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Useful tools for working with the PassiveTotal API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-06-11&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/passivetotal&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/passivetotal&#34;&gt;https://github.com/hrbrmstr/passivetotal&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;passwordrandom&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🔒 Access the PasswordRandom.com API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/passwordrandom&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/passwordrandom&#34;&gt;https://github.com/hrbrmstr/passwordrandom&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;pastebin&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📋 Tools to work with the pastebin API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/pastebin&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/pastebin&#34;&gt;https://github.com/hrbrmstr/pastebin&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;pdfbox&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Create, Maniuplate and Extract Data from PDF Files (R Apache PDFBox wrapper)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/pdfbox&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/pdfbox&#34;&gt;https://github.com/hrbrmstr/pdfbox&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;pdfboxjars&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Java &amp;lsquo;.jar&amp;rsquo; Files for &amp;lsquo;pdfbox&amp;rsquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/pdfboxjars&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/pdfboxjars&#34;&gt;https://github.com/hrbrmstr/pdfboxjars&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;pigeon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🐴 Parse Portable Game Notation (&amp;lsquo;PGN&amp;rsquo;) Files in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-09-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/pigeon&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/pigeon&#34;&gt;https://github.com/hrbrmstr/pigeon&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;pluralize&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;An R package to &amp;ldquo;Pluralize and Singularize Any Word&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-01-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/pluralize&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/pluralize&#34;&gt;https://github.com/hrbrmstr/pluralize&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;porc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🐗 Tools to Work with &amp;lsquo;Snort&amp;rsquo; Rules, Logs and Data&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-30&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/porc&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/porc&#34;&gt;https://github.com/hrbrmstr/porc&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;pressur&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ä·® Query and Orchestrate the &amp;lsquo;WordPress&amp;rsquo; &amp;lsquo;API&amp;rsquo; with R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-27&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/pressur&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/pressur&#34;&gt;https://github.com/hrbrmstr/pressur&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;punycode&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R code to work with punycode domains&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-06-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/punycode&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/punycode&#34;&gt;https://github.com/hrbrmstr/punycode&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;qrencoder&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🔳 Make QR codes in R via libqrencode&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-24&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/qrencoder&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/qrencoder&#34;&gt;https://github.com/hrbrmstr/qrencoder&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;r7snr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R tools to work with Rapid7 Sonar scans&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-07-15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/r7snr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/r7snr&#34;&gt;https://github.com/hrbrmstr/r7snr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;radb&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🔬 Tools to Query the &amp;lsquo;Merit&amp;rsquo; &amp;lsquo;RADb&amp;rsquo; Network Route Server&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-04-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-04-07&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/radb&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/radb&#34;&gt;https://github.com/hrbrmstr/radb&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;radviz&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R htmlwidget for radviz!&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/radviz&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/radviz&#34;&gt;https://github.com/hrbrmstr/radviz&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;rappalyzer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🔬 :: WIP :: R port of Wappalyzer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-09-22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/rappalyzer&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/rappalyzer&#34;&gt;https://github.com/hrbrmstr/rappalyzer&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;RBerkeley&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🐱 Oracle &amp;lsquo;Berkeley DB&amp;rsquo; Interface for R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-07-27&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/RBerkeley&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/RBerkeley&#34;&gt;https://github.com/hrbrmstr/RBerkeley&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;rdatainfo&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;helper pkg for the macOS QuickLook plugin&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-08-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-08-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/rdatainfo&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/rdatainfo&#34;&gt;https://github.com/hrbrmstr/rdatainfo&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;resolv&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ldns DNS resolver wrapper libary for R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-04-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/resolv&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/resolv&#34;&gt;https://github.com/hrbrmstr/resolv&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Rforecastio&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;☁️ Simple R interface to forecast.io weather data&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-09-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/Rforecastio&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/Rforecastio&#34;&gt;https://github.com/hrbrmstr/Rforecastio&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;rgeocodio&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Work with the &lt;a href=&#34;https://geocod.io/&#34;&gt;https://geocod.io/&lt;/a&gt; API&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/rgeocodio&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/rgeocodio&#34;&gt;https://github.com/hrbrmstr/rgeocodio&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;rosette&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Work with the Rosette API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-10-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/rosette&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/rosette&#34;&gt;https://github.com/hrbrmstr/rosette&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;rpwnd&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🙅‍♀️ The Most Benignly Malicious R Package on the Internet&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-31&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-31&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/rpwnd&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/rpwnd&#34;&gt;https://github.com/hrbrmstr/rpwnd&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;safebrowsing&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R interface to the XHR Google Safe Browsing &amp;ldquo;API&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/safebrowsing&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/safebrowsing&#34;&gt;https://github.com/hrbrmstr/safebrowsing&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sanders&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;WIP!!! â€” Web-scraping and Web-crawling Content Parsing, Validation and Sanitization Helpers&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-09-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/sanders&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/sanders&#34;&gt;https://github.com/hrbrmstr/sanders&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;satcat&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🛰️ Tools to Work with the &amp;lsquo;CelesTrak&amp;rsquo; Satellite Catalog API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/satcat&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/satcat&#34;&gt;https://github.com/hrbrmstr/satcat&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saucy&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Searching for Automorphisms in Underlying CNF, yes?&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-27&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/saucy&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/saucy&#34;&gt;https://github.com/hrbrmstr/saucy&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;scamtracker&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R pacakge interface to the BBB ScamTracker : &lt;a href=&#34;https://www.bbb.org/scamtracker/us&#34;&gt;https://www.bbb.org/scamtracker/us&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-01-11&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-04-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/scamtracker&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/scamtracker&#34;&gt;https://github.com/hrbrmstr/scamtracker&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;scimple&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;➖➖➖🔶➖➖ Tidy Simultaneous Confidence Intervals for Multinomial Proportions&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/scimple&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/scimple&#34;&gt;https://github.com/hrbrmstr/scimple&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;securitytxt&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ðŸ” Identify and Parse Web Security Policies Files in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/securitytxt&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/securitytxt&#34;&gt;https://github.com/hrbrmstr/securitytxt&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sentimental&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Work with the &amp;lsquo;text-processing.com&amp;rsquo; API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-07-24&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-20&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/sentimental&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/sentimental&#34;&gt;https://github.com/hrbrmstr/sentimental&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sergeant&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;💂‍♂️ Tools to Transform and Query Data with &amp;lsquo;Apache&amp;rsquo; &amp;lsquo;Drill&amp;rsquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-06-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/sergeant&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/sergeant&#34;&gt;https://github.com/hrbrmstr/sergeant&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;shodan&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🌑 R package to work with the Shodan API&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-07&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/shodan&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/shodan&#34;&gt;https://github.com/hrbrmstr/shodan&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;slackr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#️⃣ A package to send webhook API messages to Slack.com channels/users from R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-09-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/slackr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/slackr&#34;&gt;https://github.com/hrbrmstr/slackr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;SnakeCharmR&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;SnakeCharmR - R and Python Integration&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-05-18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-04-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/SnakeCharmR&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/SnakeCharmR&#34;&gt;https://github.com/hrbrmstr/SnakeCharmR&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;speedtest&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📐 Measure upload/download speed/bandwidth for your network with R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/speedtest&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/speedtest&#34;&gt;https://github.com/hrbrmstr/speedtest&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;spiderbar&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lightweight R wrapper around rep-cpp for robot.txt (Robots Exclusion Protocol) parsing and path testing in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/spiderbar&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/spiderbar&#34;&gt;https://github.com/hrbrmstr/spiderbar&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;splashr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;💦 Tools to Work with the &amp;lsquo;Splash&amp;rsquo; JavaScript Rendering Service in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/splashr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/splashr&#34;&gt;https://github.com/hrbrmstr/splashr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ssllabs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Work with the SSL Labs API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-06-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-07-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/ssllabs&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/ssllabs&#34;&gt;https://github.com/hrbrmstr/ssllabs&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sslsaran&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Work with Certificate Transparency (&amp;lsquo;CT&amp;rsquo;) Logs and Various &amp;lsquo;CT&amp;rsquo; &amp;lsquo;APIs&amp;rsquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-20&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/sslsaran&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/sslsaran&#34;&gt;https://github.com/hrbrmstr/sslsaran&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;statebins&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Alternative to choropleths of US States ala &lt;a href=&#34;http://bit.ly/statebins&#34;&gt;http://bit.ly/statebins&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-08-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/statebins&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/statebins&#34;&gt;https://github.com/hrbrmstr/statebins&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;streamgraph&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;〰️ htmlwidget for creating streamgraph visualizations in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-02-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/streamgraph&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/streamgraph&#34;&gt;https://github.com/hrbrmstr/streamgraph&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;stringore&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tidy Regular Expression Operations with Extensive Character Encoding Support&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/stringore&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/stringore&#34;&gt;https://github.com/hrbrmstr/stringore&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;swatches&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ðŸŽ¨ Read, Inspect, and Manipulate Color Swatch Files&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-03-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/swatches&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/swatches&#34;&gt;https://github.com/hrbrmstr/swatches&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;taucharts&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📊 An R htmlwidget interface to the TauCharts javascript library&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-09-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/taucharts&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/taucharts&#34;&gt;https://github.com/hrbrmstr/taucharts&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;terminator&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rcpp implementation of day/night terminator generator&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-27&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/terminator&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/terminator&#34;&gt;https://github.com/hrbrmstr/terminator&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;threatcrowd&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R tools to work with the ThreatCrowd API&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-01-20&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/threatcrowd&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/threatcrowd&#34;&gt;https://github.com/hrbrmstr/threatcrowd&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;tidyweb&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Easily Install and Load Modern Web-Scraping Packages&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-07-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/tidyweb&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/tidyweb&#34;&gt;https://github.com/hrbrmstr/tidyweb&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;tinyjs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;tinyjs R wrapper pkg&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-04-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-10-29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/tinyjs&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/tinyjs&#34;&gt;https://github.com/hrbrmstr/tinyjs&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;tlsobs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🔭 Tools to Work with the &amp;lsquo;Mozilla&amp;rsquo; &amp;lsquo;TLS&amp;rsquo; Observatory &amp;lsquo;API&amp;rsquo; in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-11&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/tlsobs&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/tlsobs&#34;&gt;https://github.com/hrbrmstr/tlsobs&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;triage&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Aid in Debugging Issues Across R Sessions&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/triage&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/triage&#34;&gt;https://github.com/hrbrmstr/triage&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;uaparserjs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Parse Browser &amp;lsquo;User-Agent&amp;rsquo; Strings into R Data Frames&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-08-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/uaparserjs&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/uaparserjs&#34;&gt;https://github.com/hrbrmstr/uaparserjs&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;urltools&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Elegant URL handling in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-12-07&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/urltools&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/urltools&#34;&gt;https://github.com/hrbrmstr/urltools&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;vegalite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R ggplot2 &amp;ldquo;bindings&amp;rdquo; for Vega-Lite&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-02-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/vegalite&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/vegalite&#34;&gt;https://github.com/hrbrmstr/vegalite&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;verisr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R package for working with VERIS data&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-06-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/verisr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/verisr&#34;&gt;https://github.com/hrbrmstr/verisr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;verisr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;R package for working with data stored within VERIS framework&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-09-20&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/verisr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/verisr&#34;&gt;https://github.com/hrbrmstr/verisr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;voteogram&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;U.S. House and Senate Voting Cartogram Generators in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-05-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/voteogram&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/voteogram&#34;&gt;https://github.com/hrbrmstr/voteogram&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;waffle&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🍁 Make waffle (square pie) charts in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-03-18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-03-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/waffle&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/waffle&#34;&gt;https://github.com/hrbrmstr/waffle&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;wand&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🎩 R interface to libmagic - returns file mime type&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-08-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-24&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/wand&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/wand&#34;&gt;https://github.com/hrbrmstr/wand&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;warc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📇 Tools to Work with the Web Archive Ecosystem in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-09-07&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/warc&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/warc&#34;&gt;https://github.com/hrbrmstr/warc&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;wayback&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;⏪ Tools to Work with the Various Internet Archive Wayback Machine APIs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-01-28&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/wayback&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/wayback&#34;&gt;https://github.com/hrbrmstr/wayback&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;webhose&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;🔨 Tools to Work with the &amp;lsquo;webhose.io&amp;rsquo; &amp;lsquo;API&amp;rsquo; in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-09-27&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/webhose&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/webhose&#34;&gt;https://github.com/hrbrmstr/webhose&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;whoisxmlapi&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;❔ R package to interface with the WhoisXMLAPI.com service&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-08-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/whoisxmlapi&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/whoisxmlapi&#34;&gt;https://github.com/hrbrmstr/whoisxmlapi&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;wondr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Work with there CDC WONDER API in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-10-04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/wondr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/wondr&#34;&gt;https://github.com/hrbrmstr/wondr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;xlsxtractr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Extract Things From Excel (xlsx) Files in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-09-16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2018-02-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/xlsxtractr&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/xlsxtractr&#34;&gt;https://github.com/hrbrmstr/xlsxtractr&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;xmlview&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;📃 Format, Query and Pretty Print &amp;lsquo;HTML&amp;rsquo;/&amp;lsquo;XML&amp;rsquo; Content in R (RStudio viewer or browser)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-01-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/xmlview&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/xmlview&#34;&gt;https://github.com/hrbrmstr/xmlview&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;xslt&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lightweight XSLT processing package for R based on xmlwrapp&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-07-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/xslt&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/xslt&#34;&gt;https://github.com/hrbrmstr/xslt&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;zellingenach&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;A visual exploration of the spatial patterns in the endings of German town and village names in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-01-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/zellingenach&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/zellingenach&#34;&gt;https://github.com/hrbrmstr/zellingenach&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;zkcmd&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tools to Administer &amp;lsquo;Zookeeper&amp;rsquo; Instances with Four-letter Commands in R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/zkcmd&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/zkcmd&#34;&gt;https://github.com/hrbrmstr/zkcmd&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;zoneparser&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;A V8-powered R package to parse Domain Name System (DNS) zone files&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-10-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-10-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#39;https://github.com/hrbrmstr/zoneparser&#39;&gt;&lt;a href=&#34;https://github.com/hrbrmstr/zoneparser&#34;&gt;https://github.com/hrbrmstr/zoneparser&lt;/a&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
    </item>
    
    <item>
      <title>Combine your hex stickers with magic(k)</title>
      <link>https://masalmon.eu/2018/02/22/hexcombine/</link>
      <pubDate>Thu, 22 Feb 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/02/22/hexcombine/</guid>
      <description>&lt;p&gt;Hex stickers remind me of &lt;a href=&#34;https://en.wikipedia.org/wiki/Milk_caps_(game)&#34;&gt;Pogs&lt;/a&gt;, except they&amp;rsquo;re cooler because you can combine them together! Some people do that very smartly.&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;ca&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Now when I forget how to do an &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; analysis I can just check the back of my laptop &lt;a href=&#34;https://twitter.com/hashtag/runconf16?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#runconf16&lt;/a&gt; &lt;a href=&#34;https://t.co/DY7UgeBzYV&#34;&gt;pic.twitter.com/DY7UgeBzYV&lt;/a&gt;&lt;/p&gt;&amp;mdash; David Robinson (@drob) &lt;a href=&#34;https://twitter.com/drob/status/715694466707750913?ref_src=twsrc%5Etfw&#34;&gt;1 d’abril de 2016&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;ve got a pretty random hex stickers combination on my laptop, but after all it could be worse&amp;hellip;&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;ca&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;My boyfriend decided he is post-hex / post-&lt;a href=&#34;https://twitter.com/hashtag/tidyverse?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#tidyverse&lt;/a&gt; &lt;a href=&#34;https://t.co/ADtyORMxHL&#34;&gt;pic.twitter.com/ADtyORMxHL&lt;/a&gt;&lt;/p&gt;&amp;mdash; Hilary Parker (@hspter) &lt;a href=&#34;https://twitter.com/hspter/status/908102841323188225?ref_src=twsrc%5Etfw&#34;&gt;13 de setembre de 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;Now since I&amp;rsquo;m a &lt;code&gt;magick&lt;/code&gt;/collage fan, you can bet I&amp;rsquo;ve wondered how to use R in order to combine stickers automatically! Say I have a bunch of sticker PNGs, how could I produce a map to design my laptop style? Read to find out more&amp;hellip;&lt;/p&gt;
&lt;h1 id=&#34;getting-some-hex-stickers-to-play-with&#34;&gt;Getting some hex stickers to play with&lt;/h1&gt;
&lt;p&gt;I do agree that in real life you&amp;rsquo;ll most often not have PNGs of the stickers but hey I can dream&amp;hellip; especially since I&amp;rsquo;m sure that one will soon be able to identify stickers on a conference haul pic in the blink of an eye with the &lt;a href=&#34;https://github.com/swarm-lab/Rvision&#34;&gt;&lt;code&gt;Rvision&lt;/code&gt; package&lt;/a&gt;. I got stickers from &lt;a href=&#34;http://hexb.in/&#34;&gt;hex.bin&lt;/a&gt; whose existence I learnt from this tweet:&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;ca&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;A plea to my favorite &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; 📦 developers: please submit your BIG hex sticker image files (with vector versions 🙏) to &lt;a href=&#34;https://t.co/7KWg3d2fZA&#34;&gt;https://t.co/7KWg3d2fZA&lt;/a&gt;!  &lt;a href=&#34;https://twitter.com/old_man_chester?ref_src=twsrc%5Etfw&#34;&gt;@old_man_chester&lt;/a&gt; &lt;a href=&#34;https://twitter.com/nj_tierney?ref_src=twsrc%5Etfw&#34;&gt;@nj_tierney&lt;/a&gt; &lt;a href=&#34;https://twitter.com/samfirke?ref_src=twsrc%5Etfw&#34;&gt;@samfirke&lt;/a&gt; they will be right at home 👇 &lt;a href=&#34;https://t.co/AIqgnBIx1X&#34;&gt;pic.twitter.com/AIqgnBIx1X&lt;/a&gt;&lt;/p&gt;&amp;mdash; Alison Hill (@apreshill) &lt;a href=&#34;https://twitter.com/apreshill/status/966397975328038912?ref_src=twsrc%5Etfw&#34;&gt;21 de febrer de 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;And well if more R packages are added to it my &lt;code&gt;Rvision&lt;/code&gt; dream could come true.&lt;/p&gt;
&lt;p&gt;Note: When I say I got them from hex.bin, I mean I lazily downloaded the &amp;ldquo;hexagons/&amp;rdquo; folder of &lt;a href=&#34;https://github.com/maxogden/hexbin&#34;&gt;this GitHub repository&lt;/a&gt; by using &lt;a href=&#34;https://stackoverflow.com/a/38879691&#34;&gt;a link as explained in this SO answer&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;combining-a-few-of-them-at-random&#34;&gt;Combining a few of them at random&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll sample &lt;a href=&#34;https://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker%27s_Guide_to_the_Galaxy#Answer_to_the_Ultimate_Question_of_Life,_the_Universe,_and_Everything_(42)&#34;&gt;42&lt;/a&gt; stickers from my nice little internet haul.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;)
ultimate_sample &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; fs&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;dir_ls&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hexagons&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;sample&lt;/span&gt;(size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After that I&amp;rsquo;ll create rows which is pretty straightforward.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;no_row &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;
no_col &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;7&lt;/span&gt;

row_paths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;split&lt;/span&gt;(ultimate_sample, &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;no_col, each &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; no_row))

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# let&amp;#39;s be crazy&lt;/span&gt;

read_append &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; . &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_append&lt;/span&gt;()

rows &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(row_paths, read_append)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now rows have to be combined together, not just stacked, with a small shift. This will depend on the size of pics. They seem to be the same size which is great. Note that the thing that gets displayed below is what &lt;code&gt;magick::image_info&lt;/code&gt; gives you about any &lt;code&gt;magick&lt;/code&gt; object, so I&amp;rsquo;ll use that.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(ultimate_sample[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;])
info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(ultimate_sample[1]) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_info&lt;/span&gt;()
height &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;height
width &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;width
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;col&lt;/code&gt; parameter below is my laptop background &lt;em&gt;hex code&lt;/em&gt;. I needed it before pasting the &lt;em&gt;hex stickers&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;my_laptop &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_blank&lt;/span&gt;(width &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; width &lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt; no_col,
                    height &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; height &lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt; no_row &lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.9&lt;/span&gt;,
                    col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#FF6987&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;for&lt;/span&gt;(i in &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;no_row){
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(i&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;floor&lt;/span&gt;(i&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;)){
    offset1 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;
  }else{
    offset1 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; (width&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;) 
  }
  
  offset2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; (i&lt;span style=&#34;color:#40a070&#34;&gt;-1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;(height&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;0.75&lt;/span&gt;)
  
  my_laptop &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_composite&lt;/span&gt;(my_laptop, rows[[i]],
                                       offset &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;+&amp;#34;&lt;/span&gt;, offset1,
                                                       &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;+&amp;#34;&lt;/span&gt;, offset2))
}

magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(my_laptop, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/my_laptop.png&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/my_laptop.png&#34; alt=&#34;my laptop&#34; width=&#34;700&#34;&gt;
&lt;p&gt;This looks fine, the only reason why it&amp;rsquo;s not perfect is probably the stickers not having exactly the same dimensions. Moreover, one of them doesn&amp;rsquo;t have transparent borders! That&amp;rsquo;s a mean design. &lt;a href=&#34;https://github.com/jeroen&#34;&gt;Jeroen Ooms&lt;/a&gt; told me I could correct it by smartly using &lt;code&gt;image_fill&lt;/code&gt; with color = “transparent” and some fuzz and &lt;code&gt;image_trim&lt;/code&gt; before that to remove margins but I was lazy.&lt;/p&gt;
&lt;p&gt;Now, what could one do? One could order hex stickers by color using the code in my &lt;a href=&#34;https://masalmon.eu/2018/01/07/rainbowing/&#34;&gt;blog post about rainbowing a set of pictures&lt;/a&gt;. Or one could just combine all hex stickers together, then make them gray and use the resulting image as a place to collect stickers. #goals&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_convert&lt;/span&gt;(my_laptop, colorspace &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Gray&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/my_laptop_goals.png&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/my_laptop_goals.png&#34; alt=&#34;laptop goals&#34; width=&#34;700&#34;&gt;</description>
    </item>
    
    <item>
      <title>Galentine&#39;s day cards</title>
      <link>https://masalmon.eu/2018/01/26/galentinesday/</link>
      <pubDate>Fri, 26 Jan 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/01/26/galentinesday/</guid>
      <description>&lt;p&gt;Remember the &lt;a href=&#34;https://masalmon.eu/2017/11/05/newborn-serie/&#34;&gt;nascent series of blog posts about Parks and recreation&lt;/a&gt;? Well, we&amp;rsquo;re still at one post, but don&amp;rsquo;t worry, here is a new one, and I&amp;rsquo;m sure the series will eventually be a real one. I&amp;rsquo;m looking at you, my R-Ladies friends. That said, today is not a day for passive agressive hints, because I&amp;rsquo;ve decided it&amp;rsquo;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Galentine%27s_Day&#34;&gt;Galentine&amp;rsquo;s day&lt;/a&gt; and I&amp;rsquo;ll show you how to craft cards for your R-Ladies friends from your R prompt!&lt;/p&gt;
&lt;p&gt;Galentine&amp;rsquo;s day is a celebration Leslie Knope throws every year for her female friends, showering them with love and gifts. Since she&amp;rsquo;s very talented, she can even write them poems, but in the R version of Galentine&amp;rsquo;s day, we&amp;rsquo;ll make do with simple cards featuring Lesliesque compliments. Indeed, Leslie Knope is also known for her &lt;a href=&#34;https://www.theodysseyonline.com/14-leslie-knope-compliments-ann-perkins-life&#34;&gt;creative complimenting&lt;/a&gt; of her best friend Ann. I&amp;rsquo;ve decided to adopt her tone by using three praising adjectives followed by an animal name, and to dedicate them to imaginary friends called Ann, Donna, April and Shauna. Had I not decided to steal names from the TV show, I could have used the &lt;code&gt;charlatan::ch_name()&lt;/code&gt; from the &lt;a href=&#34;https://github.com/ropensci/charlatan&#34;&gt;rOpenSci &lt;code&gt;charlatan&lt;/code&gt; package&lt;/a&gt;, possibly extracting first names thanks to the &lt;a href=&#34;https://cran.r-project.org/web/packages/humaniformat/index.html&#34;&gt;&lt;code&gt;humaniformat&lt;/code&gt; package&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;create-the-compliments&#34;&gt;Create the compliments&lt;/h1&gt;
&lt;p&gt;Here I need animal names and praising adjectives for a pretty frivolous use case. Now sometimes you could want to randomly draw words to make identifiers for, say, participants in your epidemiological study because that&amp;rsquo;d be easier to deal with than numbers. The &lt;a href=&#34;https://github.com/richfitz/ids&#34;&gt;&lt;code&gt;ids&lt;/code&gt; package&lt;/a&gt; actually provides human readable identifiers in the style &lt;code&gt;&amp;lt;adjective&amp;gt;_&amp;lt;animal&amp;gt;&lt;/code&gt; (following &lt;a href=&#34;https://gfycat.com/&#34;&gt;gfycat.com&lt;/a&gt;) but sadly that adjective wouldn&amp;rsquo;t necessary be positive, so I&amp;rsquo;ll use the &lt;a href=&#34;https://github.com/rladies/praise&#34;&gt;&lt;code&gt;praise&lt;/code&gt; package&lt;/a&gt; to get adjectives and the &lt;a href=&#34;https://github.com/gaborcsardi/rcorpora&#34;&gt;&lt;code&gt;rcorpora&lt;/code&gt; package&lt;/a&gt; to get animal names. I&amp;rsquo;ll set the &lt;a href=&#34;https://masalmon.eu/2017/04/12/seeds/&#34;&gt;random seed&lt;/a&gt; to ensure reproducibility, not forgetting to be careful about &lt;a href=&#34;http://livefreeordichotomize.com/2018/01/22/a-set-seed-ggplot2-adventure/&#34;&gt;where to generate it&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;123&lt;/span&gt;)

compliment &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(name, animal){
  praise&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;praise&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;, you ${adjective}, ${adjective}, ${adjective} &amp;#34;&lt;/span&gt;, animal))
}

compliments &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Ann&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;April&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Donna&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Shauna&amp;#34;&lt;/span&gt;),
                              animal &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sample&lt;/span&gt;(rcorpora&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;corpora&lt;/span&gt;(which &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;animals/common&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;animals, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;),
                              compliment &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map2_chr&lt;/span&gt;(name, animal, compliment))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;create-the-cards&#34;&gt;Create the cards&lt;/h1&gt;
&lt;p&gt;I first thought I could use cute animal pics for the cards, my husband even suggested I use the animal from the compliment which I could have done using Pexels as in my &lt;a href=&#34;https://masalmon.eu/2018/01/04/bubblegumpuppies/&#34;&gt;bubblegum puppies post&lt;/a&gt; or my &lt;a href=&#34;https://masalmon.eu/2018/01/07/rainbowing/&#34;&gt;rainbowing post&lt;/a&gt;, using the &lt;a href=&#34;https://gist.github.com/hrbrmstr/4cabe4af87bd2c5fe664b0b44a574366&#34;&gt;gist posted by Bob Rudis to avoid using &lt;code&gt;RSelenium&lt;/code&gt;&lt;/a&gt;, but I decided to go a simpler route (which I&amp;rsquo;ll call &lt;a href=&#34;https://kkulma.github.io/2017-12-29-end-of-year-thoughts/&#34;&gt;using Kasia&amp;rsquo;s strategy to get stuff done&lt;/a&gt;), generating random colours, and putting text on a single-colour background. Let&amp;rsquo;s assume Leslie Knope would have written a poem on the other side, which you could do using &lt;a href=&#34;http://katiejolly.io/blog/2018-01-05/random-rupi-markov-chain-poems&#34;&gt;Katie Jolly&amp;rsquo;s approach&lt;/a&gt;. Anyway, how did I generate random colours? Well, using &lt;code&gt;charlatan&lt;/code&gt;! Really, a quite useful package by Scott Chamberlain, peer-reviewed by Brooke Anderson and TJ Mahr at &lt;a href=&#34;https://github.com/ropensci/onboarding/issues/94&#34;&gt;rOpenSci onboarding repo&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;123&lt;/span&gt;)
compliments &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(compliments, 
                             background &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; charlatan&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ch_hex_color&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;), 
                             text_colour &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; charlatan&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ch_hex_color&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then I could use &lt;a href=&#34;https://github.com/ropensci/magick&#34;&gt;&lt;code&gt;magick&lt;/code&gt;&lt;/a&gt;! I&amp;rsquo;ve convinced myself that although I use &lt;code&gt;magick&lt;/code&gt; for non serious stuff, I could use these skills on scientific image data one day. Note that I could have packed the whole code of the post in a single function, but I wanted to progressively build the card (compliments, then colours, then the image).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)

create_card &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(who, compliments){
  compliments &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(compliments, name &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; who)
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_blank&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;600&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;400&lt;/span&gt;,
                      color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; compliments&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;background) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_annotate&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; compliments&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;compliment,
                           color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; compliments&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text_colour,
                           location &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;+50+100&amp;#34;&lt;/span&gt;,
                           boxcolor &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;white&amp;#34;&lt;/span&gt;,
                           size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_annotate&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Love, Leslie&amp;#34;&lt;/span&gt;,
                           color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; compliments&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text_colour,
                           location &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;+200+300&amp;#34;&lt;/span&gt;,
                           boxcolor &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;white&amp;#34;&lt;/span&gt;,
                           size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_annotate&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;HAPPY GALENTINE&amp;#39;S DAY!&amp;#34;&lt;/span&gt;,
                           boxcolor &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; compliments&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text_colour,
                           location &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;+100+200&amp;#34;&lt;/span&gt;,
                           color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;white&amp;#34;&lt;/span&gt;,
                           size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/galentines&amp;#34;&lt;/span&gt;, who, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;))
}

purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;walk&lt;/span&gt;(compliments&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;name, create_card, compliments)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yes, I signed the cards &amp;ldquo;Leslie&amp;rdquo;. I know the text could be centered more but I don&amp;rsquo;t really care.&lt;/p&gt;
&lt;h1 id=&#34;display-the-cards&#34;&gt;Display the cards&lt;/h1&gt;
&lt;p&gt;In real life, you&amp;rsquo;d print and send these cards to your friends, but since my imaginary friends Ann, April, Donna and Shauna probably read my blog, I&amp;rsquo;ll let the cards here for them to see!&lt;/p&gt;
&lt;img src=&#34;https://masalmon.eu/figure/galentinesAnn.png&#34; alt=&#34;galentines Ann&#34; width=&#34;700&#34;&gt;
&lt;img src=&#34;https://masalmon.eu/figure/galentinesApril.png&#34; alt=&#34;galentines April&#34; width=&#34;700&#34;&gt;
&lt;img src=&#34;https://masalmon.eu/figure/galentinesDonna.png&#34; alt=&#34;galentines Donna&#34; width=&#34;700&#34;&gt;
&lt;img src=&#34;https://masalmon.eu/figure/galentinesShauna.png&#34; alt=&#34;galentines Shauna&#34; width=&#34;700&#34;&gt;
&lt;p&gt;Not too shabby for random text and colours!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Rainbowing a set of pictures</title>
      <link>https://masalmon.eu/2018/01/07/rainbowing/</link>
      <pubDate>Sun, 07 Jan 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/01/07/rainbowing/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve now done a few collages from R using &lt;code&gt;magick&lt;/code&gt;: &lt;a href=&#34;https://masalmon.eu/2017/03/19/facesofr/&#34;&gt;the faces of #rstats Twitter&lt;/a&gt;, &lt;a href=&#34;http://livefreeordichotomize.com/2017/07/18/the-making-of-we-r-ladies/&#34;&gt;We R-Ladies&lt;/a&gt; with Lucy D&amp;rsquo;Agostino McGowan, and &lt;a href=&#34;https://github.com/rladies/rladies_holidays&#34;&gt;a holiday card for R-Ladies&lt;/a&gt;. The faces of #rstats Twitter and holiday card collages were arranged at random, while the We R-Ladies one was a mosaic forming the R-Ladies logo. I got the idea to up my collage skills by trying to learn how to arrange pics by their main colour, like a rainbow. The verb rainbow doesn&amp;rsquo;t exist, and &lt;a href=&#34;https://en.wikipedia.org/wiki/Rainbowing&#34;&gt;&amp;ldquo;rainbowing&amp;rdquo;&lt;/a&gt; doesn&amp;rsquo;t mean ordering by colour, but I didn&amp;rsquo;t let this stop me.&lt;/p&gt;
&lt;p&gt;It was the occasion to grab some useful knowledge about colours, not useless for someone who did not even know about &lt;a href=&#34;https://en.wikipedia.org/wiki/Pantone#Color_of_the_Year&#34;&gt;Pantone&amp;rsquo;s Colors of the Year&lt;/a&gt; a few weeks ago&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This post has nothing to do with Kesha&amp;rsquo;s new album. However, you can listen to it while reading since it&amp;rsquo;s so good, but maybe switch to something older from her when I use &amp;ldquo;$&amp;rdquo;.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;getting-some-pics-to-play-with&#34;&gt;Getting some pics to play with&lt;/h1&gt;
&lt;p&gt;The first pictures I tried to arrange were all the pictures ever posted by R-Ladies local chapters on their Twitter account. While it was fun to grab them all, it was not very interesting to play with them as so many of them were pictures of screens. I therefore grabbed &amp;ldquo;nature&amp;rdquo; pictures from &lt;a href=&#34;https://www.pexels.com/&#34;&gt;Pexels&lt;/a&gt; using the same method [as when creating the Bubblegum Puppies] following &lt;a href=&#34;https://stackoverflow.com/questions/29861117/r-rvest-scraping-a-dynamic-ecommerce-page&#34;&gt;this Stack Overflow thread&lt;/a&gt;. I chose &amp;ldquo;nature&amp;rdquo; as a keyword because 1) it lead to many hits 2) it offered a good variety of colours.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rvest&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;RSelenium&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)

rD &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rsDriver&lt;/span&gt;()
remDr &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rD[[&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;client&amp;#34;&lt;/span&gt;]]


&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# open the webpage&lt;/span&gt;
remDr&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;navigate&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.pexels.com/search/nature/&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# scroll down&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;for&lt;/span&gt;(i in &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;130&lt;/span&gt;){      
  remDr&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;executeScript&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;scroll(0,&amp;#34;&lt;/span&gt;,i&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10000&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;);&amp;#34;&lt;/span&gt;),
                      args &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dummy&amp;#34;&lt;/span&gt;))
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# be nice and wait&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)    
}

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# https://www.pexels.com/faq/&lt;/span&gt;

page_content &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; remDr&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;getPageSource&lt;/span&gt;() 
remDr&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;close&lt;/span&gt;()

get_link_from_src &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(node){
  xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_attrs&lt;/span&gt;(node)[&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\?h.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  
}

xtract_pic_links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(source) {
  css &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;.photo-item__img&amp;#39;&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;read_html&lt;/span&gt;(source[[1]]) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(css) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(get_link_from_src)    
}

links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;xtract_pic_links&lt;/span&gt;(page_content)
links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; links[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1400&lt;/span&gt;]

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# save&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;dir.create&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;nature&amp;#34;&lt;/span&gt;)
save_pic &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(url){
  &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
  name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(url, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.*\\/&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  
  &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(url) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
        magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;nature/&amp;#34;&lt;/span&gt;, name)),
      silent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
}

purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;walk&lt;/span&gt;(links, save_pic)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;extracting-the-main-colour-and-making-pics-size-compatible&#34;&gt;Extracting the main colour and making pics size-compatible&lt;/h1&gt;
&lt;p&gt;In the following code, I extracted the main colour from each pic using &lt;a href=&#34;http://www.mepheoscience.com/colourful-ecology-part-1-extracting-colours-from-an-image-and-selecting-them-using-community-phylogenetics-theory/&#34;&gt;Russel Dinnage&amp;rsquo;s method&lt;/a&gt; as presented &lt;a href=&#34;http://blog.revolutionanalytics.com/2015/03/color-extraction-with-r.html&#34;&gt;in this blog post from David Smith&lt;/a&gt;. Before that I had to install two packages from Github, &lt;a href=&#34;https://github.com/ramnathv/rblocks&#34;&gt;&lt;code&gt;rblocks&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/woobe/rPlotter&#34;&gt;&lt;code&gt;rPlotter&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This code also serves another role: since I wanted to paste pics together at some point, I decided to make them all of the same dimensions by adding a border with &lt;code&gt;magick&lt;/code&gt;. I had learnt how to do that when preparing &lt;a href=&#34;https://github.com/rladies/rladies_holidays&#34;&gt;R-Ladies Global holiday card&lt;/a&gt;, but this time instead of using the same colour every time (R-Ladies&amp;rsquo; official purple), I used the main colour I&amp;rsquo;d just extracted. The most important points to make a picture a square are to know &lt;code&gt;magick::image_info&lt;/code&gt; gives you the height and width of an image&amp;hellip; and to somehow understand geometry which was embarrassingly a hurdle when I did that.&lt;/p&gt;
&lt;p&gt;The code to extract colours didn&amp;rsquo;t work in a few cases which I did not investigate a lot: I had downloaded more pics than what I needed because I had experienced the issue when working with R-Ladies meetups pics, and had seen it was because of seemingly bicolor pics.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;dir.create&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;formatted_pics&amp;#34;&lt;/span&gt;)

format_image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(path){
  image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(path)
  info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_info&lt;/span&gt;(image)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# find in which direction I need to add pixels&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# to make this a square&lt;/span&gt;
  direction &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;height &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;width,
                      &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;height&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;width&amp;#34;&lt;/span&gt;)
  scale_number &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(info[direction]&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;500&lt;/span&gt;)
  image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_scale&lt;/span&gt;(image, &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(info[&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;width&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;scale_number,
                                             &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt;, 
                                             info[&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;height&amp;#34;&lt;/span&gt;]&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;scale_number))
  newinfo &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_info&lt;/span&gt;(image)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# colours&lt;/span&gt;
  colours &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(rPlotter&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;extract_colours&lt;/span&gt;(path, num_col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;), silent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# one pic at least was problematic &lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is&lt;/span&gt;(colours, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;try-error&amp;#34;&lt;/span&gt;)){
    colour &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; colours[1]
    
    image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_border&lt;/span&gt;(image, colour, &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;((&lt;span style=&#34;color:#40a070&#34;&gt;500&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;newinfo&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;width)&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt;,
                                                        (&lt;span style=&#34;color:#40a070&#34;&gt;500&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;newinfo&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;height)&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;))
    info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_info&lt;/span&gt;(image)
    &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# odd numbers out!&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;height&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;floor&lt;/span&gt;(info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;height&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;)){
      image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_crop&lt;/span&gt;(image, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;0x500+0&amp;#34;&lt;/span&gt;)
    }
    &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;width&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;floor&lt;/span&gt;(info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;width&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;)){
      image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_crop&lt;/span&gt;(image, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;500x0+0&amp;#34;&lt;/span&gt;)
    }
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(image,
                        stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(path, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;nature&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;formatted_pics&amp;#34;&lt;/span&gt;))
    tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; path,
                   colour &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colour)
  }else{
    &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
  }
  
  
  
}

pics_main_colours &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;dir&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;nature&amp;#34;&lt;/span&gt;, full.names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;), format_image)
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(pics_main_colours, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pics_main_colours.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And because I&amp;rsquo;m apparently a bad planner, I had to reduce pictures afterwards.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# we need smaller images&lt;/span&gt;
reduce_image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(path){
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(path) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_scale&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;50x50!&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(path)
}

purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;walk&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;dir&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;formatted_pics&amp;#34;&lt;/span&gt;, full.names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;),
            reduce_image)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;preparing-a-function-to-order-and-paste-pictures&#34;&gt;Preparing a function to order and paste pictures&lt;/h1&gt;
&lt;p&gt;This function has a collage part which you might recognize from my &lt;a href=&#34;https://masalmon.eu/2017/03/19/facesofr/&#34;&gt;the faces of #rstats Twitter&lt;/a&gt; blog post, and a ordering pictures according to a variable part that&amp;rsquo;s new and uses a bit of tidy eval&amp;hellip;  Maybe I&amp;rsquo;ll really learn tidy eval this year! &lt;code&gt;pics_info&lt;/code&gt; needs to be a data.frame with the path to pictures and well the variable one wants to use to order them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rlang&amp;#34;&lt;/span&gt;)

make_column &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(i, files, no_rows){
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(files&lt;span style=&#34;color:#06287e&#34;&gt;[&lt;/span&gt;(i&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;no_rows&lt;span style=&#34;color:#40a070&#34;&gt;+1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;((i&lt;span style=&#34;color:#40a070&#34;&gt;+1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;no_rows)]) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_append&lt;/span&gt;(stack &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols/&amp;#34;&lt;/span&gt;, i, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.jpg&amp;#34;&lt;/span&gt;))
}


make_collage &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(pics_info, no_rows, no_cols, ordering_col){
  pics_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(pics_info, &lt;span style=&#34;color:#666&#34;&gt;!!!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;syms&lt;/span&gt;(ordering_col))
  pics_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pics_info[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(no_rows&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;no_cols),]
  pics_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(pics_info, column &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;no_cols, each &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; no_rows))
  pics_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(pics_info, column) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!!!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;syms&lt;/span&gt;(ordering_col)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(row &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;no_rows) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;()
  
  pics_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(pics_info, column, row)
  
  &lt;span style=&#34;color:#06287e&#34;&gt;dir.create&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols&amp;#34;&lt;/span&gt;)
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;walk&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(no_cols&lt;span style=&#34;color:#40a070&#34;&gt;-1&lt;/span&gt;), make_column, files &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; pics_info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;path,
              no_rows &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; no_rows)
  
  banner &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;dir&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols/&amp;#34;&lt;/span&gt;, full.names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_append&lt;/span&gt;(stack &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;) 
  
  &lt;span style=&#34;color:#06287e&#34;&gt;unlink&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols&amp;#34;&lt;/span&gt;, recursive &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(banner)
  
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The function returns a &lt;code&gt;magick&lt;/code&gt; object that one can then write to disk as a PNG for instance.&lt;/p&gt;
&lt;p&gt;I first tested it using a random approach added to the data.frame created in the next section, and show the result here to give an idea of the variety of pictures. For many of them, however, the main colour that you can see in their border is greyish.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;)
pics_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(pics_info, random &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sample&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(pics_info), &lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(pics_info)))
&lt;span style=&#34;color:#06287e&#34;&gt;make_collage&lt;/span&gt;(pics_info, &lt;span style=&#34;color:#40a070&#34;&gt;19&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;59&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;random&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2018-01-07-rainbowing-banner_random.png&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/2018-01-07-rainbowing-banner_random.png&#34; alt=&#34;rainbow banner random&#34; width=&#34;700&#34;&gt;
&lt;h1 id=&#34;testing-a-first-bad-approach-using-hue&#34;&gt;Testing a first (bad) approach: using hue&lt;/h1&gt;
&lt;p&gt;Once I had the main colour as an hex code, I had no idea how to order the colours and thought a good idea would be to use hue, which is the main wave length in a colour. Most observed colours are a mix of wave lengths unless you&amp;rsquo;re using a laser for instance. To get hue from a colour identified by its hex code, one needs two functions: &lt;code&gt;colorspace::hex2rgb&lt;/code&gt; and &lt;code&gt;grDevices::rgb2hsv&lt;/code&gt;. The latter one outputs hue, saturation and value. Hue is the main wavelength, saturation the amount of that wavelength in the colour and value the amount of light in the colour. The smaller the saturation, the less representative the hue is of the main colour. Add to that the fact that the main colour can also be only a little representative of your original picture&amp;hellip; Ordering by hue isn&amp;rsquo;t too perfect, but I tried that anyway.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# now work on getting the hue and value for all pics&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# create a data.frame with path, hue, value &lt;/span&gt;
get_values &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(path, pics_main_colours){
  &lt;span style=&#34;color:#06287e&#34;&gt;print&lt;/span&gt;(path)
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get main color&lt;/span&gt;
  colour &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pics_main_colours&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;colour[pics_main_colours&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;path &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(path,
                                                                      &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;formatted_pics&amp;#34;&lt;/span&gt;,
                                                                      &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;nature&amp;#34;&lt;/span&gt;)]
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# translate it&lt;/span&gt;
  rgb &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; colorspace&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;hex2RGB&lt;/span&gt;(colour)
  values &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; grDevices&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rgb2hsv&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;t&lt;/span&gt;(rgb&lt;span style=&#34;color:#666&#34;&gt;@&lt;/span&gt;coords))
  
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; path,
                 hue &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; values[1,&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;],
                 saturation &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; values [2,&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;],
                 value &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; values[3,&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;])
}

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# all values&lt;/span&gt;
pics_col &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;dir&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;formatted_pics&amp;#34;&lt;/span&gt;, full.names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;),
                          get_values, pics_main_colours)
                          



&lt;span style=&#34;color:#06287e&#34;&gt;make_collage&lt;/span&gt;(pics_info, &lt;span style=&#34;color:#40a070&#34;&gt;19&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;59&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hue&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;banner_hue.png&amp;#34;&lt;/span&gt;)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/2018-01-07-rainbowing-banner_hue.png&#34; alt=&#34;rainbow banner hue&#34; width=&#34;700&#34;&gt;
&lt;p&gt;So this is not too pretty. Blue and green pictures seem to cluster together but there are very dark pictures which we&amp;rsquo;d intuitively put aside.&lt;/p&gt;
&lt;p&gt;So I thought a bit more and decided to first assign main colours to a reference colour and then order pictures based on this&amp;hellip;&lt;/p&gt;
&lt;h1 id=&#34;choosing-a-better-approach-rgb-and-distances&#34;&gt;Choosing a better approach: RGB and distances&lt;/h1&gt;
&lt;p&gt;The first challenge was to choose reference colours which&amp;rsquo;d be a rainbow slices. I could have looked up RGB codes corresponding to &lt;a href=&#34;https://en.wikipedia.org/wiki/ROYGBIV&#34;&gt;ROYGBIV (red, orange, yellow, green, blue, indigo and violet.)&lt;/a&gt; but I had read about &lt;a href=&#34;https://blog.xkcd.com/2010/05/03/color-survey-results/&#34;&gt;xkcd colors survey&lt;/a&gt; in &lt;a href=&#34;https://blog.algolia.com/how-we-handled-color-identification/&#34;&gt;this interesting post&lt;/a&gt; and therefore decided to use XKCD colors, available in R via the &lt;code&gt;xkcdcolors&lt;/code&gt; package. I chose to use the 18 most common ones, and add black to that lot. It was no longer really a rainbow, I agree. The colors present in the pictures were ordered by hand by my husband, and I like his choices.&lt;/p&gt;
&lt;p&gt;Then to assign each pic to a reference colour via its main colour, I calculated the Euclidian distance between that colour and all reference colours to find the closes reference colours, using the RGB values.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;xkcdcolors&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# version of colorspace::hex2RGB returning a df&lt;/span&gt;
hex2rgb &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(hex){
  result &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; colorspace&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;hex2RGB&lt;/span&gt;(hex)&lt;span style=&#34;color:#666&#34;&gt;@&lt;/span&gt;coords
}

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# https://stackoverflow.com/questions/45328221/unnest-one-column-list-to-many-columns-in-tidyr&lt;/span&gt;
colors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;xcolors&lt;/span&gt;()[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;18&lt;/span&gt;], &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;black&amp;#34;&lt;/span&gt;),
                         hex &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;name2color&lt;/span&gt;(name),
                         rgb &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(hex, hex2rgb)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rgb &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(rgb, tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;as_tibble)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;unnest&lt;/span&gt;()

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# for each colour I want the closest one.&lt;/span&gt;
find_closest_colour &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(hex, colors){
  test &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(hex &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; hex) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rgb &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(hex, hex2rgb),
                  rgb &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(rgb, tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;as_tibble)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;unnest&lt;/span&gt;() 
  
  distance &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stats&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;dist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;rbind&lt;/span&gt;(test[, &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;R&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;G&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;B&amp;#34;&lt;/span&gt;)],
                                colors[, &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;R&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;G&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;B&amp;#34;&lt;/span&gt;)]))
  
  colors&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;name&lt;span style=&#34;color:#06287e&#34;&gt;[which.min&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;as.matrix&lt;/span&gt;(distance)[,&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;][2&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(colors) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)])]
}

imgs_col &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(pics_main_colours,
                          xkcd_col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(colour, find_closest_colour,
                                                    colors &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colors))


readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(imgs_col, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;imgs_xkcd_col.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once I had this information about each pic, I could order the pictures, after having defined the order of the reference colours.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;pics_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;imgs_xkcd_col.csv&amp;#34;&lt;/span&gt;)
pics_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(pics_info, 
                           path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(path, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;nature&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;formatted_pics&amp;#34;&lt;/span&gt;))

pics_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(pics_info,
                           xkcd_col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;factor&lt;/span&gt;(xkcd_col, ordered &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;,
                                             levels &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;black&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;brown&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;red&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magenta&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pink&amp;#34;&lt;/span&gt;,
                                                        &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lime green&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;green&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dark green&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;teal&amp;#34;&lt;/span&gt;,
                                                        &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;light blue&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sky blue&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;blue&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purple&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;grey&amp;#34;&lt;/span&gt;)))

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/2018-01-07-rainbowing-banner_xkcd.png&#34; alt=&#34;rainbow banner xkcd&#34; width=&#34;700&#34;&gt;
&lt;p&gt;This looks much better, but of course the initial set (and maybe the used extraction method as well) don&amp;rsquo;t provide for enough colours to make this extremely pretty. I&amp;rsquo;m not sure how useful this end product is, but hey I got to look at pretty landscapes full of colours from my grey rainy city, and learnt a lot along the way&amp;hellip; Besides, maybe &lt;em&gt;you&lt;/em&gt; will find a cool use case of some of the colour methods featured here and will tell me about it in the comments?&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Cheer up, Black Metal Cats! Bubblegum Puppies</title>
      <link>https://masalmon.eu/2018/01/04/bubblegumpuppies/</link>
      <pubDate>Thu, 04 Jan 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/01/04/bubblegumpuppies/</guid>
      <description>&lt;p&gt;Do you know the &lt;a href=&#34;https://twitter.com/evilbmcats&#34;&gt;Black Metal Cats Twitter account&lt;/a&gt;? As explained &lt;a href=&#34;https://nerdist.com/cats-twitter-heavy-metal-lyrics/&#34;&gt;in this great introduction&lt;/a&gt;, it &amp;ldquo;combines kitties with heavy metal lyrics&amp;rdquo;. I know the account because I follow &lt;a href=&#34;https://twitter.com/sckottie&#34;&gt;Scott Chamberlain&lt;/a&gt; who retweets them a lot, which I enjoy as far as one can enjoy such a dark mood. Speaking of which, I decided to try and transform Black Metal Cat tweets into something more positive&amp;hellip; The &lt;a href=&#34;https://twitter.com/cheerful_doggos&#34;&gt;Bubblegum Puppies&lt;/a&gt; were born!&lt;/p&gt;
&lt;h1 id=&#34;getting-black-metal-cats-tweets&#34;&gt;Getting Black Metal Cats tweets&lt;/h1&gt;
&lt;p&gt;It won&amp;rsquo;t come as a surprise for the loyal readers of this blog that I just had to use &lt;code&gt;rtweet&lt;/code&gt;. I kept only original standalone tweets and removed the picture link from the tweet.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;black_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rtweet&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;get_timeline&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;evilbmcats&amp;#34;&lt;/span&gt;)
black_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(black_tweets, &lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(reply_to_user_id), &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;is_retweet, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;is_quote)
black_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(black_tweets, text, created_at, status_id)
black_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(black_tweets, text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(black_tweets, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2018-01-03-bubblegumpuppies_cats.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that the dark material is ready, let&amp;rsquo;s sweeten it&amp;hellip;&lt;/p&gt;
&lt;h1 id=&#34;modifying-the-tweet-text&#34;&gt;Modifying the tweet text&lt;/h1&gt;
&lt;p&gt;Black Metal Cats tweet heavy metal lyrics so as you can imagine, they&amp;rsquo;re sad. How to make them happy while keeping the text similar enough to the original one? And this without too much effort? My simplistic strategy was to identify negative words via sentiment analysis and to replace them with positive words.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note, had I not wanted to stay close to the original tweet, I could have just chosen lyrics picked from &lt;a href=&#34;https://www.rdocumentation.org/packages/billboard/versions/0.1.0/topics/lyrics&#34;&gt;this dataset&lt;/a&gt; for instance, and filtered them by sentiment via the sentimentr package.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;finding-negative-words&#34;&gt;Finding negative words&lt;/h2&gt;
&lt;p&gt;I computed sentiment using &lt;code&gt;tidytext&lt;/code&gt; copy-pasting code from &lt;a href=&#34;https://masalmon.eu/2017/10/02/guardian-experience/&#34;&gt;this post of mine&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidytext&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
bing &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_sentiments&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bing&amp;#34;&lt;/span&gt;)

sentiment &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(black_tweets, text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(saved_text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(word, text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;inner_join&lt;/span&gt;(bing, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;word&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(sentiment &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;negative&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It was a bit disappointing since out of the 97 only 63 were represented in that data.frame. But well, this shall do! I just looked rapidly at some non included tweets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(black_tweets, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;text &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; sentiment&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;saved_text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;text&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;created_at&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;status_id&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Black covfefe cats.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-29 21:01:06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;946848575446663168&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Black coffee cats.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-28 00:15:48&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;946172798203916288&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Say goodbye to the light.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-26 15:50:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;945683121336344576&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;The storm will never end.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-23 15:49:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;944595705204678656&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Satan, your time has come. This world must end.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-18 22:36:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;942886191107575808&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Timely.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-13 00:43:30&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;940743951287504896&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Ok so some of them are probably negative tweets that the &lt;a href=&#34;https://cran.r-project.org/web/packages/sentimentr/README.html&#34;&gt;&lt;code&gt;sentimentr&lt;/code&gt; package&lt;/a&gt; would help detect but that do not contain negative words.&lt;/p&gt;
&lt;h2 id=&#34;replacing-words&#34;&gt;Replacing words&lt;/h2&gt;
&lt;p&gt;I seriously considered using the &lt;a href=&#34;https://cran.r-project.org/web/packages/wordnet/index.html&#34;&gt;&lt;code&gt;wordnet&lt;/code&gt; package&lt;/a&gt; because of this &lt;a href=&#34;https://stackoverflow.com/questions/19360107/getting-antonyms-using-the-r-wordnet-package&#34;&gt;Stack Overflow question &amp;ldquo;Getting antonyms using the &lt;code&gt;wordnet&lt;/code&gt; package&amp;rdquo;&lt;/a&gt; but I was not brave enough, my strength failed me in front of the Java needs of that package.&lt;/p&gt;
&lt;p&gt;I decided to use &lt;code&gt;praise&lt;/code&gt; to get positive words, and &lt;code&gt;cleanNLP&lt;/code&gt; (as in &lt;a href=&#34;https://masalmon.eu/2017/12/05/badderb/&#34;&gt;this post&lt;/a&gt;) to try and identify correctly negative words as adjective or verbs for instance in order to be able to replace them. The right annotation for that is a &lt;em&gt;token&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cleanNLP&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;init_spaCy&lt;/span&gt;()

get_token_with_text &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x){
  obj &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;run_annotators&lt;/span&gt;(x, as_strings &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  entities &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_token&lt;/span&gt;(obj)
  entities&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; x
  entities
}

possibly_get_tokens &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;possibly&lt;/span&gt;(get_token_with_text,
                                         otherwise &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;)

tokens &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(sentiment&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;saved_text, possibly_get_tokens)
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(tokens) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;id&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;sid&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;tid&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;word&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;lemma&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;upos&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;pos&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;cid&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;text&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;We&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;-PRON-&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;PRON&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;PRP&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;We are the creatures you fear.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;are&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;be&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VERB&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VBP&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;We are the creatures you fear.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;the&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;the&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;DET&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;DT&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;We are the creatures you fear.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;creatures&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;creature&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NOUN&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NNS&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;We are the creatures you fear.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;you&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;-PRON-&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;PRON&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;PRP&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;We are the creatures you fear.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fear&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fear&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VERB&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VBP&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;We are the creatures you fear.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Once here, I joined sentiment and tokens.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tokens &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(tokens, word &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;enc2native&lt;/span&gt;(word))
tokens &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(tokens, word &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tolower&lt;/span&gt;(word))
tokens &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(sentiment, tokens, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;saved_text&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;word&amp;#34;&lt;/span&gt;))
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(tokens) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;saved_text&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;word&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;sentiment&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;id&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;sid&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;tid&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;lemma&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;upos&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;pos&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;cid&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;We are the creatures you fear.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fear&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;negative&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fear&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VERB&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VBP&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;In darkness we walk.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;darkness&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;negative&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;darkness&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NOUN&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NN&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Standing tall, side by side, we shall build thy throne upon the burning ashes.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;burning&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;negative&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;burn&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VERB&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VBG&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;This is the dawn of the infernal reign.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;infernal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;negative&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;infernal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ADJ&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;JJ&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A breath of the past so distant and so unreal. A soul condemned to haunt a frozen burial ground.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;condemned&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;negative&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;condemn&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VERB&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VBD&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;54&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A breath of the past so distant and so unreal. A soul condemned to haunt a frozen burial ground.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;condemned&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;negative&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;condemn&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VERB&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;VBD&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;54&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The &lt;code&gt;praise&lt;/code&gt; package provides adjectives that I&amp;rsquo;ll use to replace adjectives and to add an exclamation at the beginning of each text. Nouns, present and preterit verbs will be replaced with love/loves/loved because hey, this is pop music inspiration. I&amp;rsquo;ll lose capital letters and won&amp;rsquo;t bother too much, puppies probably do not care either. What I prepare below is what Hilary Parker called a dictionary table &lt;a href=&#34;https://twitter.com/hspter/status/948646331677118465&#34;&gt;in this tweet&lt;/a&gt;. &lt;code&gt;VBZ&lt;/code&gt; is for instance a verb in the present form like &amp;ldquo;haunts&amp;rdquo;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;modifiers &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(pos &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;( &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;NN&amp;#34;&lt;/span&gt;,  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;VBG&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;JJ&amp;#34;&lt;/span&gt;, 
                                     &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;VBD&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;VB&amp;#34;&lt;/span&gt;,  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;NNS&amp;#34;&lt;/span&gt;, 
                                     &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;VBP&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;VBN&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;NNP&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;VBZ&amp;#34;&lt;/span&gt;),
                            modifier &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;love&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;${adjective}&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;${adjective}&amp;#34;&lt;/span&gt;,
                                         &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;loved&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;love&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lovers&amp;#34;&lt;/span&gt;,
                                         &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;love&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;${adjective}&amp;#34;&lt;/span&gt;,
                                         &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;love&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;loves&amp;#34;&lt;/span&gt;))
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(modifiers)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;pos&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;modifier&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;NN&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;love&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;VBG&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;${adjective}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;JJ&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;${adjective}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;VBD&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;loved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;VB&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;love&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;NNS&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lovers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;VBP&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;love&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;VBN&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;${adjective}&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;NNP&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;love&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;VBZ&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;loves&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Now let&amp;rsquo;s get to work on the sweetening of the texts at last! Some occurrences of &amp;ldquo;hate&amp;rdquo; and &amp;ldquo;evil&amp;rdquo; remained, and I removed them by hand.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# praise has some randomness, let&amp;#39;s make it reproducible&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;)

modifiable_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(tokens, black_tweets, 
                                      by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;saved_text&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;))

modifiable_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(modifiable_tweets, modifiers, 
                                      by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pos&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# for easier use with map&lt;/span&gt;
replace_all &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(pattern, replacement, x){
  stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(x, pattern &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; pattern,
                           replacement &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; replacement)
}

modified_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(modifiable_tweets, saved_text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(praise_template &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map2_chr&lt;/span&gt;(word, modifier, replace_all,
                                                  x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tolower&lt;/span&gt;(saved_text[1]))[1],
                   praise_template &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;${exclamation}!&amp;#34;&lt;/span&gt;, praise_template),
                   praise_template &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(praise_template,
                                                              &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hate&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;love&amp;#34;&lt;/span&gt;),
                   praise_template &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(praise_template,
                                                              &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;evil&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;love&amp;#34;&lt;/span&gt;),
                   new_text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; praise&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;praise&lt;/span&gt;(praise_template)) 

modified_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(modified_tweets, saved_text, new_text)

puppies_and_cats &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(modified_tweets, black_tweets, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;saved_text&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;))
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(puppies_and_cats) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;saved_text&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;new_text&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;created_at&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;status_id&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A breath of the past so distant and so unreal. A soul condemned to haunt a frozen burial ground.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;yikes! a breath of the past so distant and so unreal. a soul loved to haunt a frozen burial ground.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-28 20:35:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;946479619020115968&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Be very afraid.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;yippie! be very fine.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-11-18 21:02:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;931990900523307008&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Beware of the cat.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;yay! love of the cat.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-11 14:54:02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;940233218204172288&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Beware the legions of Satan, they&amp;rsquo;re ready for attack!&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ole! love the legions of satan, they&amp;rsquo;re ready for attack!&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-05 22:48:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;938178169399422976&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Born by the nothingness into eternal blasphemy.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mm! born by the nothingness into eternal love.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-03 04:15:01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;937173299448221696&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Born on a day of curses and damnation, I was doomed to hate.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;whoa! born on a day of lovers and damnation, i was doomed to love.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-12-04 21:40:01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;937798672347226113&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;So although some new lyrics do not look that cheerful, they&amp;rsquo;re at least grammatically correct.&lt;/p&gt;
&lt;h1 id=&#34;replacing-the-picture&#34;&gt;Replacing the picture&lt;/h1&gt;
&lt;p&gt;I recently discovered &lt;a href=&#34;https://www.pexels.com/&#34;&gt;Pexels&lt;/a&gt;, a website with CC-0 pictures, that I even learnt to scrape for an unpublished (yet) project. So many photographs you can use and modify for free without any attribution! Quite cool, really. To scrape the page I first had to scroll down to get enough pictures, which I did following &lt;a href=&#34;https://stackoverflow.com/questions/29861117/r-rvest-scraping-a-dynamic-ecommerce-page&#34;&gt;this Stack Overflow thread&lt;/a&gt; with &lt;code&gt;RSelenium&lt;/code&gt;. I tried using &lt;code&gt;seleniumPipes&lt;/code&gt; instead but had trouble setting up the server and not too much time to dwell on that.&lt;/p&gt;
&lt;p&gt;Yes, you got it right, the code below automatically downloads pics of puppies into your laptop. Happy New Year.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rvest&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;RSelenium&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# https://stackoverflow.com/questions/29861117/r-rvest-scraping-a-dynamic-ecommerce-page&lt;/span&gt;
rD &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rsDriver&lt;/span&gt;()
remDr &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rD[[&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;client&amp;#34;&lt;/span&gt;]]


&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# open the webpage&lt;/span&gt;
remDr&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;navigate&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.pexels.com/search/puppies/&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# scroll down&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;for&lt;/span&gt;(i in &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;30&lt;/span&gt;){      
  remDr&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;executeScript&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;scroll(0,&amp;#34;&lt;/span&gt;,i&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10000&lt;/span&gt;,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;);&amp;#34;&lt;/span&gt;),
                      args &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dummy&amp;#34;&lt;/span&gt;))
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# be nice and wait&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)    
}

page_content &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; remDr&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;getPageSource&lt;/span&gt;() 
remDr&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;close&lt;/span&gt;()

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# functiosn for getting the pic links&lt;/span&gt;
get_link_from_src &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(node){
  xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_attrs&lt;/span&gt;(node)[&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;] &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\?h.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  
}

xtract_pic_links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(source) {
  css &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;.photo-item__img&amp;#39;&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;read_html&lt;/span&gt;(source[[1]]) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(css) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(get_link_from_src)    
}

links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;xtract_pic_links&lt;/span&gt;(page_content)
links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; links[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(puppies_and_cats)]

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# save&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;dir.create&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/puppies&amp;#34;&lt;/span&gt;)
save_pic &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(url, name){
  &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
  name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;puppy&amp;#34;&lt;/span&gt;, name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;)
  
  &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(url) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
        magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/puppies/&amp;#34;&lt;/span&gt;, name)),
      silent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
}

purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;walk2&lt;/span&gt;(links, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(puppies_and_cats), save_pic)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I took a moment to browse the 66 pics. Carpe diem, carpe canes (I learnt Latin for 6 years as a teen(ager) and had to check the plural of &lt;em&gt;canem&lt;/em&gt;&amp;hellip;).&lt;/p&gt;
&lt;p&gt;The pics were a bit too big so I resized them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;resize &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(pic){
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(pic) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_resize&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;300x300&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(pic)
}
purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;walk&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;dir&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/puppies/&amp;#34;&lt;/span&gt;, full.names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;), resize)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;tweeting-the-cheerful-tweets----dont-do-it-like-i-did&#34;&gt;Tweeting the cheerful tweets &amp;ndash; DON&amp;rsquo;T DO IT LIKE I DID!&lt;/h1&gt;
&lt;p&gt;I created &lt;a href=&#34;https://twitter.com/cheerful_doggos&#34;&gt;a Twitter account for the Bubblegum Puppies&lt;/a&gt; so that they could interact with the Black Metal Cats in their natural environment. I was asked by Scott whether I&amp;rsquo;d make a bot out of my idea and I don&amp;rsquo;t intend to especially since my simplistic strategy can only answer tweets with negative words detected, but I&amp;rsquo;d be glad to let someone adopt the account, especially since I did not educate my puppies well to begin with as you see below! &lt;a href=&#34;https://www.wjakethompson.com/post/tidyverse-tweets/&#34;&gt;Here&lt;/a&gt; is a tutorial for making a Twitter bot with &lt;code&gt;rtweet&lt;/code&gt;. In the meantime, I simply decided to tweet the answers I had created&amp;hellip; without enough thinking.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: It has been a long since I last obtained Twitter access tokens, so I refered to &lt;a href=&#34;http://rtweet.info/articles/auth.html&#34;&gt;the vignette&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Then I wrote the code to send replies, an important point being that you need to mention the username you answer to in your tweet otherwise the &lt;code&gt;in_reply_to_status_id&lt;/code&gt; argument is ignored. It was a dangerous code because it sent too many replies, which made it a spam bot&amp;hellip; Don&amp;rsquo;t do that. So if you ever need an example of a very stupid spammer, think of me. Lesson learnt, I&amp;rsquo;ll never be that reckless again, because I do not want to spam anyone.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;post_a_reply &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df, pic){
  rtweet&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;post_tweet&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;@evilbmcats&amp;#34;&lt;/span&gt;, df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;new_text), in_reply_to_status_id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;status_id,
                     media &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; pic)
  &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
}

pics &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;dir&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/puppies/&amp;#34;&lt;/span&gt;, full.names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;walk2&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;split&lt;/span&gt;(puppies_and_cats, puppies_and_cats&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;status_id), pics,
            post_a_reply)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So how would I use the tweets if I could do it again? Well, I&amp;rsquo;d post them with a faaar bigger delay. And I think the account would be fun as a bot which&amp;rsquo;d reply only when the cats account tweets again. That way the puppies would be cute, not cute and annoying. Live and learn! Thanks to Bob Rudis to encourage me to post this!&lt;/p&gt;
&lt;h1 id=&#34;ending-with-some-cuteness&#34;&gt;Ending with some cuteness&lt;/h1&gt;
&lt;p&gt;And now, because I do not want you to think I&amp;rsquo;m now as depressed as a Black Metal Cat, I&amp;rsquo;ll end this post by showing you a few replies thanks to the brand new &lt;code&gt;rtweet::tweet_shot&lt;/code&gt; function added in the dev version of &lt;code&gt;rtweet&lt;/code&gt; by &lt;a href=&#34;https://twitter.com/hrbrmstr?lang=en&#34;&gt;Bob Rudis&lt;/a&gt; after he saw my &lt;a href=&#34;https://masalmon.eu/2017/12/30/best9of2017/&#34;&gt;#best9of2017 post&lt;/a&gt;. I resorted to saving the files and add the Markdown code to show them by hand but in a normal Rmd, not in a website, the images (&lt;code&gt;magick&lt;/code&gt; objects) actually render very well. &lt;a href=&#34;https://twitter.com/cheerful_doggos/with_replies&#34;&gt;Head to Twitter&lt;/a&gt; to see the rest!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;save_one_tweet &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(status_id){
  rtweet&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tweet_shot&lt;/span&gt;(status_id) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2018-01-04-&amp;#34;&lt;/span&gt;,
                               status_id, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;))
}

&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;948942337912328192&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;948942293272334336&amp;#34;&lt;/span&gt;,
  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;948942240713531392&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;walk&lt;/span&gt;(save_one_tweet)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/2018-01-04-948942337912328192.png&#34; alt=&#34;tweet&#34;&gt;
&lt;img src=&#34;https://masalmon.eu/figure/2018-01-04-948942293272334336.png&#34; alt=&#34;tweet&#34;&gt;
&lt;img src=&#34;https://masalmon.eu/figure/2018-01-04-948942240713531392.png&#34; alt=&#34;tweet&#34;&gt;</description>
    </item>
    
    <item>
      <title>Are #python users more likely to get into Slytherin?</title>
      <link>https://masalmon.eu/2018/01/01/sortinghat/</link>
      <pubDate>Mon, 01 Jan 2018 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2018/01/01/sortinghat/</guid>
      <description>&lt;p&gt;&lt;em&gt;This post requires some familiarity with the Harry Potter books but I&amp;rsquo;m committed to making this blog friendly to everyone, even Muggles/Nomajes.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Have you seen &lt;a href=&#34;http://blog.sellorm.com/2017/12/18/learn-to-write-command-line-utilities-in-r/&#34;&gt;Mark Sellors&amp;rsquo; blog post series&lt;/a&gt; about writing command line utilities in R? It&amp;rsquo;s a great one but I was a bit puzzled by his using randomness to assign houses in his sorting hat example (he added a &lt;a href=&#34;http://blog.sellorm.com/2017/12/21/command-line-utilities-in-r-pt-4/&#34;&gt;new method based on name &lt;code&gt;digest&lt;/code&gt;-ing&lt;/a&gt; in the meantime).&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;ca&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;This is a really cool &lt;a href=&#34;https://twitter.com/hashtag/rstats?src=hash&amp;amp;ref_src=twsrc%5Etfw&#34;&gt;#rstats&lt;/a&gt; tutorial... but since when does the sorting hat assign a random Hogwarts house?! 🧙
♀️🎩🎲➡️🏠🤔 &lt;a href=&#34;https://t.co/Ff8CHR6jb9&#34;&gt;https://t.co/Ff8CHR6jb9&lt;/a&gt;&lt;/p&gt;&amp;mdash; Maëlle Salmon 🐟 (@ma_salmon) &lt;a href=&#34;https://twitter.com/ma_salmon/status/943094156695670784?ref_src=twsrc%5Etfw&#34;&gt;19 de desembre de 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;This prompted a reply by David Hood who later came up with R code to assign you to a Hogwarts house based on your Twitter activity!&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;ca&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;It should be possible to assign House on the basis of Twitter analysis (among R using tweeters). Quatitatively: &lt;br&gt;Original posts - opinionated - Gryffindor&lt;br&gt;Replies - social - Slytherin&lt;br&gt;posts links out of Twitter - homework - Ravenclaw&lt;br&gt;Retweets- keeping it all working - Hufflepuff&lt;/p&gt;&amp;mdash; David Hood (@Thoughtfulnz) &lt;a href=&#34;https://twitter.com/Thoughtfulnz/status/943237103151849473?ref_src=twsrc%5Etfw&#34;&gt;19 de desembre de 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;I was thrilled to &lt;a href=&#34;https://github.com/thoughtfulbloke/sorting_stat&#34;&gt;see David Hood&amp;rsquo;s sorting hat Github repo&lt;/a&gt; and thought it&amp;rsquo;d be the perfect occasion to answer that fascinating question: are #python users more likely to get into Slytherin than #rstats users?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Another note: I do not care about any Python vs. R fights except for Quidditch games, so go away trolls.&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;getting-twitter-users&#34;&gt;Getting Twitter users&lt;/h1&gt;
&lt;p&gt;In his repo, David Hood used accounts sampled from their posting on the #rstats hashtag, and uses their scores as a scale against which to rate any user. I had to take a different approach because I wanted to compare R against Python posting on a basis that wouldn&amp;rsquo;t be R. I chose to use JavaScript posters as a reference set, because you can&amp;rsquo;t randomly search Twitter users and even that wouldn&amp;rsquo;t necessarily give me a &amp;ldquo;representative&amp;rdquo; set. Therefore, I had to assume something, and I chose to assume the Sorting hat would have chosen JavaScript tweeps as a reference set. I wanted more than 200 JavaScript tweeps and more than 100 R and Python tweeps, respectively, and asked for a bit more from Twitter API because I knew there&amp;rsquo;d be duplicates from people tweeting about more than one of these languages (like &lt;a href=&#34;https://twitter.com/arnicas&#34;&gt;Lynn Cherny&lt;/a&gt; for instance). I didn&amp;rsquo;t do any sample size calculation. Here is how I got users:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get users&lt;/span&gt;
languages &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;javascript&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;python&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rstats&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# a bit more than what we want because of exclusion criterion: duplicate&lt;/span&gt;
no &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;260&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;130&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;130&lt;/span&gt;)
get_users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(language, no){
  users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rtweet&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;search_users&lt;/span&gt;(q &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#&amp;#34;&lt;/span&gt;, language),
                                n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; no)
  users&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;language &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; language
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(users)
}

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# remove duplicates&lt;/span&gt;
users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map2_df&lt;/span&gt;(languages, no, get_users)
users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(users, screen_name) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(duplicate_user &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;duplicate_user)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here is the number of accounts I got:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;users &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(language) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;language&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;javascript&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;258&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;python&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;126&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;rstats&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;128&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I had actually overestimated the amount of overlap between accounts. Well this does not mean any of these accounts is exclusively related to one of the languages, I have for instance seen &lt;code&gt;rtweet&lt;/code&gt; creator &lt;a href=&#34;https://twitter.com/kearneymw&#34;&gt;Mike Kearney&lt;/a&gt; himself tweet about Python and he&amp;rsquo;s still in my R sample. It&amp;rsquo;s because the rank in Twitter Python set might be different than the Twitter R rank, but I&amp;rsquo;ll go on and assume that if an account was returned for R rather than Python, then it&amp;rsquo;s not a bad representant of R.&lt;/p&gt;
&lt;h1 id=&#34;computing-the-sorting-metrics&#34;&gt;Computing the sorting metrics&lt;/h1&gt;
&lt;p&gt;David Hood calculates a metric for each house, with the logic explained in his &lt;a href=&#34;https://github.com/thoughtfulbloke/sorting_stat&#34;&gt;Github repo&lt;/a&gt; (I feel a heart pinch every time I write that because it is such a great repo that its creator should &lt;em&gt;blog&lt;/em&gt;, don&amp;rsquo;t you think?). I simply used his code after updating &lt;code&gt;rtweet&lt;/code&gt; when I realized the output I got from the package had different column names. I probably should have cared a bit more about (Non) Standard Evaluation when wrapping the code in a function but anyway I&amp;rsquo;m relying on magic!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(users, screen_name, language)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# function to get scores&lt;/span&gt;
get_scores &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(screen_name){
  &lt;span style=&#34;color:#06287e&#34;&gt;print&lt;/span&gt;(screen_name)
  data &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(rtweet&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;get_timeline&lt;/span&gt;(user &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; screen_name, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1000&lt;/span&gt;),
              silent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
   &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is&lt;/span&gt;(data, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;try-error&amp;#34;&lt;/span&gt;)){
     data &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
       dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(has_external_links &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(urls_url),
                     has_reply &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(reply_to_screen_name),
                     has_reply_to_self &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; screen_name &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; reply_to_screen_name &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(reply_to_screen_name),
                     has_retweet &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(quoted_status_id) &lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(retweet_status_id)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
       dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(screen_name) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
       dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(
         slyth &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sum&lt;/span&gt;(has_reply &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;has_reply_to_self) &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;(),
         huffl &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sum&lt;/span&gt;(has_retweet) &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;(),
         raven &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sum&lt;/span&gt;(has_external_links &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;has_retweet) &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;(),
         griff &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sum&lt;/span&gt;(has_reply &lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;
                              has_retweet &lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;
                              has_external_links &lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;
                              has_reply_to_self)
         ) &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()
       ) 
   }else{
     &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
   }
  
}

scores &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(users&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;screen_name, get_scores)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s have a look at the distribution of scores in the different populations.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(users, screen_name, language)
scores &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(scores, users, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;screen_name&amp;#34;&lt;/span&gt;)
scores &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;gather&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;house&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;metric&amp;#34;&lt;/span&gt;, slyth&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;griff) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_density&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(metric)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;facet_grid&lt;/span&gt;(language &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; house)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2018-01-01-sortinghat/unnamed-chunk-4-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-4&#34;&gt;&lt;/p&gt;
&lt;p&gt;The graph above gives an idea of what the results will look like&amp;hellip;&lt;/p&gt;
&lt;h1 id=&#34;applying-the-sorting-hat&#34;&gt;Applying the sorting hat&lt;/h1&gt;
&lt;p&gt;For each R or Python account, the sorting hat as written by David Hood will compute a score by house obtained by sorting this account and all JavaScript users by the house metric, and then dividing the judged account&amp;rsquo;s rank by the total number of JavaScript users. The chosen house is the one with the highest score. Note that this script does not ensure that each house has the same size, but in real life the Sorting hat might use other information than Twitter like Instagram or Github activity, and other programming languages might help fill all houses.&lt;/p&gt;
&lt;p&gt;I think copy pasting the same code for all houses was the quickest method for David Hood which is fine but I decided I&amp;rsquo;d re-format the code a little bit to 1) avoid repetitions, 2) getting acquainted with tidy eval (I know, I know, I&amp;rsquo;m really late) with &lt;a href=&#34;http://www.onceupondata.com/2017/08/12/my-first-steps-into-the-world-of-tidyeval/&#34;&gt;Omayma&amp;rsquo;s blog post&lt;/a&gt; as a guide. I also browsed &lt;a href=&#34;https://github.com/tidyverse/dplyr/issues/2944&#34;&gt;this issue&lt;/a&gt; to find an example of the correct syntax for &lt;code&gt;arrange&lt;/code&gt;. I clearly need more practice, which I intend to get this year, using &lt;a href=&#34;https://edwinth.github.io/blog/dplyr-recipes/&#34;&gt;Edwin Thoen&amp;rsquo;s reference&lt;/a&gt; among other things.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rlang&amp;#34;&lt;/span&gt;)
compare_with &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(scores, language &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;javascript&amp;#34;&lt;/span&gt;)
compare_with&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;isSortee &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;

candidates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(scores, language &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;javascript&amp;#34;&lt;/span&gt;)
candidates&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;isSortee &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# function for getting the score for one candidate &amp;amp; one house&lt;/span&gt;
get_score &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(house, fullname, candidate, compare_with){
result &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(compare_with, candidate) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;sym&lt;/span&gt;(house)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!!&lt;/span&gt;house,isSortee)
  score &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;round&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;which&lt;/span&gt;(result&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;isSortee)&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(result),&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;)
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(house &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;quo_name&lt;/span&gt;(fullname),
            score &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; score)
}

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# function for getting the candidate house&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# based on the house scores&lt;/span&gt;

sort_user &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(candidate, compare_with){
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# seed for the case of equal scores&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;)
  
  result &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map2_df&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;slyth&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;huffl&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;raven&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;griff&amp;#34;&lt;/span&gt;),
                          &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Slytherin&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Hufflepuff&amp;#34;&lt;/span&gt;,
                            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Ravenclaw&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Gryffindor&amp;#34;&lt;/span&gt;),
                          get_score,
                          candidate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; candidate, 
                          compare_with &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; compare_with)
  
result &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(score)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(screen_name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; candidate&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;screen_name,
                language &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; candidate&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;language) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(house, screen_name, language)
}

houses &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; candidates &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;split&lt;/span&gt;(candidates&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;screen_name) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(sort_user, compare_with &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; compare_with)

readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(houses, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2018-01-01-sortinghat-houses.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;answering-the-question&#34;&gt;Answering the question&lt;/h1&gt;
&lt;p&gt;So now has come the crucial moment of truth&amp;hellip; Are Python users more likely to get sorted into Slytherin? I&amp;rsquo;ll leave statistical tests as an exercise to the reader and just produce a visualization.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(houses) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_bar&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(language, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; house),
           position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;fill&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;,
              axis_title_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  viridis&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2018-01-01-sortinghat/unnamed-chunk-7-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-7&#34;&gt;&lt;/p&gt;
&lt;p&gt;Oh, what a non-intuitive result!  But maybe this means that the R community is very social on Twitter; or my sample is too small? In any case, I guess this is good news if the R Slytherin sample contain &lt;a href=&#34;http://harrypotter.wikia.com/wiki/Parseltongue&#34;&gt;parsselmouths&lt;/a&gt;: quite a few useRs should then be able to talk to all the terrifying Australian snakes they&amp;rsquo;ll meet in Brisbane during useR! 2018.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>My #Best9of2017 tweets</title>
      <link>https://masalmon.eu/2017/12/30/best9of2017/</link>
      <pubDate>Sat, 30 Dec 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/12/30/best9of2017/</guid>
      <description>&lt;p&gt;You&amp;rsquo;ve probably seen people posting their #Best9of2017, primarily on Instagram I&amp;rsquo;d say. I&amp;rsquo;m not an Instagram user, although I do have an account to spy on my younger sister and cousins, so I don&amp;rsquo;t even have 9 Instagram posts in total but I do love the collage people get to show off&amp;hellip; So what about my best 9 &lt;em&gt;tweets&lt;/em&gt; of 2017?&lt;/p&gt;
&lt;h1 id=&#34;get-my-9-best-tweets-by-number-of-likes&#34;&gt;Get my 9 best tweets by number of likes&lt;/h1&gt;
&lt;p&gt;I first wanted to use &lt;code&gt;rtweet::get_timeline&lt;/code&gt; but it only returned me tweets from July, even when using &lt;code&gt;include_rts = FALSE&lt;/code&gt;, so I downloaded my analytics files from the Twitter website, one per trimester.&lt;/p&gt;
&lt;p&gt;Edited on the 2018-01-01 to add: If you haven&amp;rsquo;t tweeted too much,&lt;code&gt;rtweet::get_timeline&lt;/code&gt; can be enough, this is what I used for &lt;a href=&#34;https://twitter.com/RLadiesGlobal/status/947712245781467136&#34;&gt;R-Ladies Global version&lt;/a&gt;. If it isn&amp;rsquo;t, here are more precise guidelines by Andrew Caines: &amp;quot; first: download 4 tweet analytics files for 2017 quarters which means, go to: &lt;a href=&#34;https://analytics.twitter.com&#34;&gt;https://analytics.twitter.com&lt;/a&gt; then: click on &amp;lsquo;Tweets&amp;rsquo; tab at top, change date range top right, &amp;lsquo;export data&amp;rsquo; (x4)&amp;rdquo;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;my_files &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tweet_activity_metrics_ma_salmon_20170101_20170402_en.csv&amp;#34;&lt;/span&gt;,
              &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tweet_activity_metrics_ma_salmon_20170402_20170702_en.csv&amp;#34;&lt;/span&gt;,
              &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tweet_activity_metrics_ma_salmon_20170702_20171001_en.csv&amp;#34;&lt;/span&gt;,
              &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tweet_activity_metrics_ma_salmon_20171001_20171231_en.csv&amp;#34;&lt;/span&gt;)
paths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/&amp;#34;&lt;/span&gt;, my_files)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# read them all at once&lt;/span&gt;
my_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(paths, readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;read_csv)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# just in case I got some data ranges wrong&lt;/span&gt;
my_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(my_tweets)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get the top 9!&lt;/span&gt;
my_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(my_tweets, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; likes)
my_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; janitor&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;clean_names&lt;/span&gt;(my_tweets)

best9 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; my_tweets&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;tweet_permalink[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;9&lt;/span&gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;My husband advised me to use something more elaborate than number of likes, which is a wise idea, but I was happy with that simple method.&lt;/p&gt;
&lt;h1 id=&#34;take-screenshots-and-paste-them&#34;&gt;Take screenshots and paste them&lt;/h1&gt;
&lt;p&gt;There&amp;rsquo;s a great R package to do screenshots from R, &lt;a href=&#34;https://cran.r-project.org/web/packages/webshot/vignettes/intro.html&#34;&gt;&lt;code&gt;webshot&lt;/code&gt;&lt;/a&gt;. I was a bit annoyed at the  &amp;ldquo;Follow&amp;rdquo; button appearing, but I did not want to have to write Javascript code to first login in the hope to make that thing disappear. I tried using a CSS selector instead of a rectangle, but I was less satisfied. An obvious problem here is that contrary to Instagram images, tweets have different heights depending on the text length and on the size of the optional attached media&amp;hellip; It&amp;rsquo;s a bit sad but not too sad, my collage will still give a look at my Twitter 2017.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)

save_one_file &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(url, name){
  filename &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# save and output filename&lt;/span&gt;
  webshot&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;webshot&lt;/span&gt;(url, filename,
                  cliprect &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;150&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;750&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;750&lt;/span&gt;))
  filename
}

files &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map2_chr&lt;/span&gt;(best9, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;9&lt;/span&gt;, save_one_file)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Regarding the collage part using &lt;code&gt;magick&lt;/code&gt;, I used my &lt;a href=&#34;https://masalmon.eu/2017/03/19/facesofr/&#34;&gt;&amp;ldquo;Faces of R&amp;rdquo; post&lt;/a&gt; as a reference, which is funny since it features in my top 9 tweets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;no_rows &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;
no_cols &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;

make_column &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(i, files, no_rows){
  filename &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;col&amp;#34;&lt;/span&gt;, i, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.jpg&amp;#34;&lt;/span&gt;)

  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(files&lt;span style=&#34;color:#06287e&#34;&gt;[&lt;/span&gt;(i&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;no_rows&lt;span style=&#34;color:#40a070&#34;&gt;+1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;((i&lt;span style=&#34;color:#40a070&#34;&gt;+1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;no_rows)]) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_border&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;salmon&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;20x20&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_append&lt;/span&gt;(stack &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(filename)
  
  filename
}

purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(no_cols&lt;span style=&#34;color:#40a070&#34;&gt;-1&lt;/span&gt;), make_column, files &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; files,
    no_rows &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; no_rows) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_append&lt;/span&gt;(stack &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_border&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;salmon&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;20x20&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  magick&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-12-30-best9of2017.jpg&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And since I&amp;rsquo;m well behaved, I clean after myself.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# clean &lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;file.remove&lt;/span&gt;(files)
&lt;span style=&#34;color:#06287e&#34;&gt;file.remove&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;col&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.jpg&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/2017-12-30-best9of2017.jpg&#34; alt=&#34;best 9 of 2017&#34; width=&#34;700&#34;&gt;
&lt;p&gt;So, apart from fun blog posts (&lt;a href=&#34;https://masalmon.eu/2017/11/16/wheretoliveus/&#34;&gt;Where to live in the US&lt;/a&gt;, &lt;a href=&#34;https://masalmon.eu/2017/03/19/facesofr/&#34;&gt;Faces of #rstats Twitter&lt;/a&gt;, &lt;a href=&#34;https://masalmon.eu/2017/02/18/complot/&#34;&gt;A plot against the CatterPlots complot&lt;/a&gt;) and more serious ones (&lt;a href=&#34;https://masalmon.eu/2017/06/17/automatictools/&#34;&gt;Automatic tools for improving R packages&lt;/a&gt;, &lt;a href=&#34;https://masalmon.eu/2017/12/11/goodrpackages/&#34;&gt;How to develop good R packages (for open science)&lt;/a&gt;, &lt;a href=&#34;https://masalmon.eu/2017/12/21/wherehaveyoubeen/&#34;&gt;Where have you been? Getting my Github activity&lt;/a&gt;), my top 9 tweets include a good &lt;code&gt;ggplot2&lt;/code&gt; tip (&lt;a href=&#34;http://www.ggplot2-exts.org/&#34;&gt;this website&lt;/a&gt;) and above all, the birth of baby Émile! Why have I only included two heart emojis?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: this collage should have been appended the other way round (rows then columns) to correspond to what Instagram produces. Thanks Andrew Caines for telling me!&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;what-about-your-2017&#34;&gt;What about your 2017?&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve now read a few awesome end-of-the-year posts from other R bloggers, from the top of my head:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Bob Rudis posted an &lt;a href=&#34;https://rud.is/rpubs/2017-year-in-review/&#34;&gt;impressive review of his year&lt;/a&gt; on Stack Overflow, Github and Twitter, and even made it reproducible for you to make it with your own data!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mara Averick posted &lt;a href=&#34;https://maraaverick.rbind.io/2017/12/2017-a-year-in-review/&#34;&gt;her top 2 tweets by month&lt;/a&gt;. Note of them praises Mara so let&amp;rsquo;s remind everyone she&amp;rsquo;s the greatest curator of R content ever, and recently became a tidyverse advocate for RStudio!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Thomas Lin Pedersen &lt;a href=&#34;https://www.data-imaginist.com/2017/looking-back-on-2017/&#34;&gt;looked back on his fantastic 2017&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://kkulma.github.io/2017-12-29-end-of-year-thoughts/&#34;&gt;Kasia Kulma&amp;rsquo;s end of year thoughts&lt;/a&gt; include an inspiring description of her journey this year and awesome productivity tips for R bloggers.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What&amp;rsquo;s your take on your 2017, dear reader? In any case, I wish you a happy New Year!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Where have you been? Getting my Github activity</title>
      <link>https://masalmon.eu/2017/12/21/wherehaveyoubeen/</link>
      <pubDate>Thu, 21 Dec 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/12/21/wherehaveyoubeen/</guid>
      <description>&lt;p&gt;On my pretty and up-to-date CV, one of the first things one sees is my Github username, linking to my &lt;a href=&#34;https://github.com/maelle/&#34;&gt;Github profile&lt;/a&gt;. What does a potential employer look at there? &lt;em&gt;Hopefully not my non informative commit messages&amp;hellip;&lt;/em&gt; My imitating a red &lt;a href=&#34;https://en.wikipedia.org/wiki/Ampelm%C3%A4nnchen&#34;&gt;Ampelmann&lt;/a&gt;, my being part of several organizations, my pinned repositories described with emojis&amp;hellip; But how would they know &lt;em&gt;where&amp;amp;how&lt;/em&gt; I&amp;rsquo;ve mostly been active without too much effort?&lt;/p&gt;
&lt;p&gt;A considerable part of my Github work happens in organizations: I&amp;rsquo;m a co-editor at &lt;a href=&#34;https://github.com/ropensci/onboarding&#34;&gt;rOpenSci onboarding of packages&lt;/a&gt;, I contribute content to the &lt;a href=&#34;https://github.com/rweekly/rweekly.org/&#34;&gt;R Weekly newsletter&lt;/a&gt;, etc. Although my profile shows the organizations I belong to, one would need to dig into them for a while before seeing how much or how little I&amp;rsquo;ve done. Which is fine most of the time but less so when trying to profile myself for jobs, right? Let&amp;rsquo;s try and fetch some Github data to create a custom profile.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: yep I&amp;rsquo;m looking for a job and ResearchGate&amp;rsquo;s suggestions are not helpful! Do you need an enthusiastic remote data scientist or research software engineer for your team? I&amp;rsquo;m available up to 24 hours a week! I care a lot about science, health, open source and community. Ideally I&amp;rsquo;d like to keep working in something close to public research but we can talk!&lt;/em&gt;&lt;/p&gt;
&lt;h1 id=&#34;getting-all-my-activity&#34;&gt;Getting all my activity&lt;/h1&gt;
&lt;p&gt;Note: for another look at Github activity, more related to when people work, check out &lt;a href=&#34;https://daattali.com/shiny/visualize-git-commits-time/&#34;&gt;Dean Attali&amp;rsquo;s cool Shiny app&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m a big fan of the simplistic &lt;a href=&#34;https://github.com/r-lib/gh&#34;&gt;&lt;code&gt;gh&lt;/code&gt; package&lt;/a&gt; that I&amp;rsquo;ve used in my &lt;a href=&#34;https://masalmon.eu/2017/02/21/firstcommit/&#34;&gt;blog post about initial/first commits&lt;/a&gt; and in my &lt;a href=&#34;https://masalmon.eu/2017/04/12/seeds/&#34;&gt;blog post about random seeds&lt;/a&gt;. My workflow is reading the &lt;a href=&#34;https://developer.github.com/v3/&#34;&gt;API documentation&lt;/a&gt; to find which endpoints I need to answer my question, then writing code that loops/maps over pages of answers from the API and unnests results, all of this inspired by the package README and now my own old posts. If I used this data more often, I imagine I&amp;rsquo;d need less copy-pasting from my previous uses, but in this situation I&amp;rsquo;m very happy that my past self published this stuff. I&amp;rsquo;m also thankful I set a &lt;code&gt;GITHUB_PAT&lt;/code&gt; environment variable as explained &lt;a href=&#34;http://happygitwithr.com/api-tokens.html&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The problem with the &lt;code&gt;/users/:username/events/public&lt;/code&gt; endpoint of Github API is that it only provides you with the 300 latest events from an user, which is not enough, so I had to branch out and look at another source of data, &lt;a href=&#34;https://www.githubarchive.org/&#34;&gt;Github archive&lt;/a&gt; via &lt;a href=&#34;https://developers.google.com/bigquery/&#34;&gt;Google BigQuery&lt;/a&gt;. I had never touched it and will let Google&amp;rsquo;s own words define it: &amp;ldquo;BigQuery is Google&amp;rsquo;s fully managed, petabyte scale, low cost analytics data warehouse.&amp;rdquo;. To interact with this tool, there are at least two R packages, &lt;a href=&#34;http://code.markedmondson.me/bigQueryR/&#34;&gt;&lt;code&gt;bigQueryR&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/r-dbi/bigrquery&#34;&gt;&lt;code&gt;bigrquery&lt;/code&gt;&lt;/a&gt;. I chose the latter after reading the short comparison from the website of the former. I created a project as explained &lt;a href=&#34;https://github.com/r-dbi/bigrquery#sample-data-and-a-billing-project&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After that, here is the code I ran. I mostly adapted the example from Github archive page to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;ask for all my events in the last two years but not at once because of my quota for query bytes;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ask for &lt;em&gt;my&lt;/em&gt; events either with my current username &amp;ldquo;maelle&amp;rdquo; or the one I had before that, &amp;ldquo;masalmon&amp;rdquo; (by the way I&amp;rsquo;m so happy I could claim &amp;ldquo;maelle&amp;rdquo; because that user was not active! I love having people use my first name to ping me!);&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;get all the events, not only issues opened, and their creation date.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It took me less time as expected to get it, I was helped by my familiarity with Github data and with SQL queries, or my capacity to &lt;a href=&#34;https://masalmon.eu/2017/08/06/p1/&#34;&gt;update existing queries to serve my needs&lt;/a&gt;, ahahah.&lt;/p&gt;
&lt;p&gt;I started out using the basic free tier, but it turned out I was reaching the quota by query all the time, so it was not going to work. I tried changing my query but finally took the plunge and used the free &lt;em&gt;trial&lt;/em&gt;. You get 300$, and one TB of query costs 5$. One day queried by the code below is equivalent to something in the magnitude of 10 gigabytes processed, so I was going to be fine (see the &lt;a href=&#34;https://cloud.google.com/bigquery/pricing&#34;&gt;pricing information&lt;/a&gt;).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# using the very handy anytime package!&lt;/span&gt;
dates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; anytime&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;anydate&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2015-12-20&amp;#34;&lt;/span&gt;),
            to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; anytime&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;anydate&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-12-19&amp;#34;&lt;/span&gt;),
            by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;1 day&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bigrquery&amp;#34;&lt;/span&gt;)

get_one_day_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(day){
  project &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;#projectid here &lt;/span&gt;
  sql &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;/* count of issues opened, closed, and reopened between 1/1/2015 and 2/1/2015 */
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;SELECT type, repo.name, actor.login, created_at,
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;    JSON_EXTRACT(payload, &amp;#39;$.action&amp;#39;) as event, 
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;  FROM (TABLE_DATE_RANGE([githubarchive:day.], 
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;    TIMESTAMP(&amp;#39;&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(day),
    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#39;), 
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;    TIMESTAMP(&amp;#39;&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(day &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;), &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#39;)
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;  )) 
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;  WHERE (actor.login = &amp;#39;maelle&amp;#39; OR actor.login = &amp;#39;masalmon&amp;#39;)
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;;&amp;#34;&lt;/span&gt;)
 results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;query_exec&lt;/span&gt;(sql, project &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; project), silent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
 &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is&lt;/span&gt;(results, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;try-error&amp;#34;&lt;/span&gt;)){
   &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;)
 }else{
   &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(results)
 }
}

my_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(dates, get_one_day_events)
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(my_events, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-12-20-my_events.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I realized after the fact that I had done overlapping queries, well they overlapped in time so I got many events twice&amp;hellip; Stupid me.&lt;/p&gt;
&lt;p&gt;Now we just need to wrangle the data a little bit. In particular, we&amp;rsquo;ll use the &lt;a href=&#34;https://github.com/Tazinho/snakecase&#34;&gt;&lt;code&gt;snakecase&lt;/code&gt; package&lt;/a&gt; to convert the upper camel case of the type column into something prettier (in my opinion).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# no duplicate&lt;/span&gt;
my_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(my_events)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Better format for the type&lt;/span&gt;
my_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(my_events, type &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(type, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Event&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
my_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(my_events, type &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; snakecase&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;to_parsed_case&lt;/span&gt;(type))
my_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(my_events, type &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(type, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;_&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;))
my_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(my_events, type &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tolower&lt;/span&gt;(type))

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get repo owner&lt;/span&gt;
my_events &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(my_events, owner &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(repo_name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;/.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# save with a fantastic filename... sigh&lt;/span&gt;
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(my_events, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-12-20-my_events_clean.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We got 4991 events from 2015-12-28 09:53:23 to 2017-12-20 06:43:44!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;sample_n&lt;/span&gt;(my_events, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;type&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;repo_name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;actor_login&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;created_at&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;event&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;owner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;watch&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lindbrook/cholera&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;maelle&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-08-11 15:25:04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&amp;ldquo;started&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lindbrook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;push&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;maelle/maelle.github.io&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;maelle&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-10-04 17:15:57&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;maelle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;issues&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;masalmon/monkeylearn&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;masalmon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-05-19 08:34:51&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&amp;ldquo;closed&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;masalmon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;issue comment&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ropensci/onboarding&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;maelle&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-06-19 06:57:32&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&amp;ldquo;created&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ropensci&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;issue comment&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;osmdatar/osmdata&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;masalmon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-15 09:09:59&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&amp;ldquo;created&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;osmdatar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;issues&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ropensci/pdftools&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;masalmon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-11-23 14:59:16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&amp;ldquo;opened&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ropensci&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;issue comment&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lockedata/PackageReviewR&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;maelle&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-04-20 12:08:29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&amp;ldquo;created&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lockedata&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;issue comment&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;leeper/colourlovers&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;masalmon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-21 16:30:39&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&amp;ldquo;created&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;leeper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;issue comment&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;osmdatar/osmdata&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;masalmon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-27 10:42:37&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&amp;ldquo;created&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;osmdatar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;push&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;maelle/eml.tools&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;maelle&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-23 11:07:45&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;maelle&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;analysing-my-activity&#34;&gt;Analysing my activity&lt;/h1&gt;
&lt;h2 id=&#34;what-kind-of-events-are-there&#34;&gt;What kind of events are there?&lt;/h2&gt;
&lt;p&gt;Events as defined in this Github data can be for instance&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;commenting in issues (main job as an rOpenSci editor, ahah),&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;pushing stuff (sadly this count as one event no matter the size of the commit, which is a limitation of this dataset, and I&amp;rsquo;m not willing to complete it).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;my_events &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(type) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; n) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;type&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;push&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1872&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;issue comment&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1491&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;issues&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;705&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;watch&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;544&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;create&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;151&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;pull request&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;fork&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;commit comment&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;34&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;release&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;member&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;pull request review comment&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;public&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;delete&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;gollum&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;All event types are defined &lt;a href=&#34;https://developer.github.com/v3/activity/events/types/&#34;&gt;here&lt;/a&gt;. I had no idea what a &lt;a href=&#34;https://developer.github.com/v3/activity/events/types/#gollumevent&#34;&gt;Gollum event&lt;/a&gt; was, but it&amp;rsquo;s not surprising given I almost never updated or created a Wiki. Member events are the ones corresponding to that highly exciting moment when you&amp;rsquo;re added (or well, removed, less exciting) as a collaborator to a repository, or when your permissions are changed.&lt;/p&gt;
&lt;p&gt;Regarding the difference between issues events and issue comments event, according to the API docs,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;an issue event is &amp;ldquo;Triggered when an issue is assigned, unassigned, labeled, unlabeled, opened, edited, milestoned, demilestoned, closed, or reopened.&amp;quot;(at &lt;a href=&#34;https://github.com/ropensci/onboarding&#34;&gt;rOpenSci onboarding&lt;/a&gt;, we use assignments and labelling a lot)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;while an issue comment event is &amp;ldquo;Triggered when an issue comment is created, edited, or deleted.&amp;rdquo;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;how-many-events-over-time&#34;&gt;How many events over time?&lt;/h2&gt;
&lt;p&gt;Although that&amp;rsquo;s clearly not my goal here, I was curious to have a look at time series of counts of events! You can&amp;rsquo;t blame me, time series of counts were the subject of my dissertation, in which I luckily did a bit more than plotting some.&lt;/p&gt;
&lt;p&gt;We shall concentrate on most frequent events.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lubridate&amp;#34;&lt;/span&gt;)

my_events &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(type &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;push&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;issue comment&amp;#34;&lt;/span&gt;, 
                            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;issues&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;watch&amp;#34;&lt;/span&gt;, 
                            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;create&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pull request&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(day &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.Date&lt;/span&gt;(created_at),
                week &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;update&lt;/span&gt;(day, wday &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(week, type) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_line&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(week, n)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;facet_grid&lt;/span&gt;(type &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; ., scales &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;free_y&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;,
              axis_title_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(legend.position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;,
        strip.text.y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;My Github contributions in the two last years&amp;#34;&lt;/span&gt;,
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Data queried from Github archive on Google BigQuery&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-12-21-wherehaveyoubeen/unnamed-chunk-5-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-5&#34;&gt;&lt;/p&gt;
&lt;p&gt;What I notice is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;there&amp;rsquo;s a decrease in my activity, as seen by issue comments and issues created or closed, since the autumn. In September, we moved and had no internet connection for a while, and then we had a baby, with whom I&amp;rsquo;m now on maternity leave, so this is not a surprise!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;the number of pushes seems constant which might be surprising given I do code less in my experience&amp;hellip; but my pushes, and of pull requests by the way, contain many contributions to R Weekly, where I might update the draft each time I see something interesting to be shared! Now that I&amp;rsquo;m a member of the organization, I do not need pull requests for that so the number of pull requests is going down, which might be the reason why they added me to the organization&amp;hellip; no need to merge my contributions anymore!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Speaking of pull requests, this was something I was intimated by (and I haven&amp;rsquo;t used branches a lot in my own projects) until &lt;a href=&#34;https://github.com/jimhester&#34;&gt;Jim Hester&lt;/a&gt; helped me &lt;a href=&#34;http://firstpr.me/#maelle&#34;&gt;create my first PR&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What Github calls watch events are most often starring events in my case.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;a-look-at-the-places-where-ive-been-active&#34;&gt;A look at the places where I&amp;rsquo;ve been active&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s look where most of my events took place.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;my_events &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(owner) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; n) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;40&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;owner&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;masalmon&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1663&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ropensci&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;974&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;maelle&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;421&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ropenscilabs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;364&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;openaq&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;135&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;osmdatar&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;135&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;rweekly&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;113&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;hrbrmstr&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;67&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;openjournals&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;cvitolo&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;44&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;rladies&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;43&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;My events are scattered among 284 owners and 712 repos (I have starred more than 500 repos). I recognize well my two usernames, rOpenSci organizations ropensci and ropenscilabs, R Weekly, etc. I&amp;rsquo;m surprised I have many events in OpenAQ organization, I thought my contributions were nearly all in the repo of &lt;a href=&#34;http://ropensci.github.io/ropenaq/&#34;&gt;my R package&lt;/a&gt; accessing their data! But thinking of it I did participate in conversations in issues. R-Ladies organization is also not one where I felt I had done that much, because my R-Ladies involvement is much more related to the co-founding and organization of the Barcelona chapter, and these days tweeting for R-Ladies Global. I&amp;rsquo;m also glad to see &lt;a href=&#34;https://github.com/hrbrmstr&#34;&gt;&amp;ldquo;hrbrmstr&amp;rdquo; a.k.a Bob Rudis&lt;/a&gt;, in the complete list there were other such owners: people that have fantastic packages &lt;em&gt;and&lt;/em&gt; make it a pleasure to open issues, contribute code, etc.&lt;/p&gt;
&lt;p&gt;Now I&amp;rsquo;d like to look at the breakdown of event types by owner of the repo. We&amp;rsquo;ll change the owner variable a bit to get something more interpretable.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;orgs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(my_events,
                      blog &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; repo_name &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;maelle/maelle.github.io&amp;#34;&lt;/span&gt;,
                     my_code &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; owner &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;maelle&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;masalmon&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;blog,
                     ropensci_onboarding &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; repo_name &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropensci/onboarding&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropensci/onboarding-meta&amp;#34;&lt;/span&gt;),
                     ropensci_misc &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; owner &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropensci&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropenscilabs&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;ropensci_onboarding,
                     rweekly &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; owner &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rweekly&amp;#34;&lt;/span&gt;,
                     work_from_others &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;blog &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;!&lt;/span&gt;my_code &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;ropensci_onboarding &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;ropensci_misc &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;rweekly) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;gather&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;organisation&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;, blog&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;work_from_others) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(value)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again we filter event types, even removing watch/starring events this time.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;orgs  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(type &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;push&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;issue comment&amp;#34;&lt;/span&gt;, 
                            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;issues&amp;#34;&lt;/span&gt;, 
                            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;create&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pull request&amp;#34;&lt;/span&gt;))&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_bar&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(organisation, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; type)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;,
              axis_title_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(strip.text.y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;),
        axis.text.x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;90&lt;/span&gt;, hjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;My Github contributions in the two last years&amp;#34;&lt;/span&gt;,
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Data queried from Github archive on Google BigQuery&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  viridis&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-12-21-wherehaveyoubeen/unnamed-chunk-8-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;orgs  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(type &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;push&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;issue comment&amp;#34;&lt;/span&gt;, 
                            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;issues&amp;#34;&lt;/span&gt;, 
                            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;create&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pull request&amp;#34;&lt;/span&gt;))&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_bar&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(organisation, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; type),
           position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;fill&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;,
              axis_title_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(strip.text.y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;),
        axis.text.x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;90&lt;/span&gt;, hjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;My Github contributions in the two last years&amp;#34;&lt;/span&gt;,
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Data queried from Github archive on Google BigQuery&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  viridis&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-12-21-wherehaveyoubeen/unnamed-chunk-8-2.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;&lt;/p&gt;
&lt;p&gt;It looks as if blogging were a very small part of my work in my own repos but I think it&amp;rsquo;s due to the fact that I mostly push all material related to one blog post at once. Interestingly I seem to only create repositories under my own brand, which I think is true in general, although I did end up transferring a few packages to rOpenSci. Then, clearly in rOpenSci onboarding, I seem to have done a lot of issue commenting/labelling, etc. This is no surprise. I have also done that for miscellaneous repositories that do not belong to me: I have contributed a bit of code but have talked a lot. As mentioned earlier, my R Weekly contributions are mostly my committing one new entry each time I read something good.&lt;/p&gt;
&lt;h1 id=&#34;what-about-you-dear-readers&#34;&gt;What about you, dear readers?&lt;/h1&gt;
&lt;p&gt;I think I have only scraped the surface of how one could use Github data to profile themselves (or others, of course). Not to mention all the things one could do with Github archive&amp;hellip; See &lt;a href=&#34;https://www.githubarchive.org/#resources&#34;&gt;this list&lt;/a&gt; for inspiration; and do not hesitate to add suggestions or links to your work in the comments! Where have &lt;em&gt;you&lt;/em&gt; been?&lt;/p&gt;
&lt;p&gt;Last but not least, if you&amp;rsquo;d like to contribute more to R, for instance on Github, you should check out &lt;a href=&#34;http://cwick.co.nz/talks/collab-code-user17/#/&#34;&gt;these slides&lt;/a&gt; by Charlotte Wickham, they&amp;rsquo;re full of great tips!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Possum magic: mapping an Australian children&#39;s book</title>
      <link>https://masalmon.eu/2017/12/16/possummagic/</link>
      <pubDate>Sat, 16 Dec 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/12/16/possummagic/</guid>
      <description>&lt;p&gt;Our &lt;a href=&#34;https://twitter.com/ma_salmon/status/920660343063490562&#34;&gt;brand-new baby&lt;/a&gt; received a fantastic picture book as a gift: &lt;a href=&#34;https://en.wikipedia.org/wiki/Possum_Magic&#34;&gt;Possum magic&lt;/a&gt;, a classic for Aussie kids. Thanks, &lt;a href=&#34;https://twitter.com/MilesMcBain&#34;&gt;Miles&lt;/a&gt;! In that book, Hush the possum and her Grandma Poss encounter different Australian animals and travel across well eat their way through the country. It is an adorable story with great illustrations! Reading it will make you feel like travelling to Australia, for instance to &lt;a href=&#34;https://user2018.r-project.org/&#34;&gt;useR! 2018&lt;/a&gt;, except you shouldn&amp;rsquo;t because it is a very scary country:&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;ca&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Rough night with 👶. ☕ was a good start but it was the balcony 🐍 capture and release that really 💓&lt;/p&gt;&amp;mdash; Miles McBain (@MilesMcBain) &lt;a href=&#34;https://twitter.com/MilesMcBain/status/900887097631887360?ref_src=twsrc%5Etfw&#34;&gt;25 d’agost de 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;However, you can travel and learn geography without leaving the comfort of a snake-free home&amp;hellip; by mapping Hush&amp;rsquo;s adventures! Which is what I decided to do.&lt;/p&gt;
&lt;p&gt;We shall prepare data for the maps in two main steps: first, looking where one can find the animals mentioned in the book; second, attributing a longitude and latitude to the cities Hush goes to.&lt;/p&gt;
&lt;h1 id=&#34;locating-the-animals-snake-included&#34;&gt;Locating the animals, snake included&lt;/h1&gt;
&lt;p&gt;In the book, we first learn about how the magic of Grandma Poss affects some animals: wombats, kookaburras, dingoes and emus. We then read how Hush&amp;rsquo;s invisibility (sorry, spoiler) makes her interact with koalas, kangaroos and snakes. We can imagine Hush and her grandmother live near these animals, in what is called &amp;ldquo;deep in the Australian bush&amp;rdquo;. We&amp;rsquo;ll map where all these animals live so that we can guess where Hush can live for the story to be credible (I admit that the magic part kind of throws this plan out the window, oh well). Moreover, given what Wikipedia says about &lt;a href=&#34;https://en.wikipedia.org/wiki/The_bush#Australia&#34;&gt;the bush&lt;/a&gt;, Hush and her grandmother could live anywhere in Australia as long as it&amp;rsquo;s not in a city, and since Hush&amp;rsquo;s first city visit is in Adelaide, we can suppose she did not live too far away from there. Let&amp;rsquo;s see!&lt;/p&gt;
&lt;p&gt;In order to map animals, we shall get occurrences from 2011 to 2016 via the rOpenSci  &lt;code&gt;spocc&lt;/code&gt; package, with GBIF as a data source, and using the &lt;code&gt;scrubr&lt;/code&gt; package for cleaning, like in &lt;a href=&#34;https://masalmon.eu/2017/04/08/spocc/&#34;&gt;my blog post visualizing waxwings migration&lt;/a&gt;. When querying data via &lt;code&gt;spocc&lt;/code&gt; one needs a bounding box, so I&amp;rsquo;ll first load an Australian map from the &lt;a href=&#34;https://github.com/ropenscilabs/eechidna&#34;&gt;&lt;code&gt;eechidna&lt;/code&gt; package&lt;/a&gt;, product from the rOpenSci 2016 Oz unconf. I was inspired by the code in &lt;a href=&#34;https://ropensci.org/blog/2017/11/21/ochre/&#34;&gt;this blog post&lt;/a&gt; that&amp;rsquo;s also a product from an Oz unconf.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;eechidna&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;data&lt;/span&gt;(nat_map_2016)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s just draw an empty map.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;ozmap &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
                &lt;span style=&#34;color:#06287e&#34;&gt;geom_map&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(map_id&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;id), data&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;nat_map_2016,
                         map&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;nat_map_2016) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
                &lt;span style=&#34;color:#06287e&#34;&gt;expand_limits&lt;/span&gt;(x&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;nat_map&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;long, y&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;nat_map&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;lat) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
                &lt;span style=&#34;color:#06287e&#34;&gt;theme_map&lt;/span&gt;()
ozmap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-12-16-possummagic/unnamed-chunk-2-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-2&#34;&gt;&lt;/p&gt;
&lt;p&gt;And now, let&amp;rsquo;s prepare the bounding box!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;bbox &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(nat_map&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;long), &lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(nat_map&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;lat), 
          &lt;span style=&#34;color:#06287e&#34;&gt;max&lt;/span&gt;(nat_map&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;long), &lt;span style=&#34;color:#06287e&#34;&gt;max&lt;/span&gt;(nat_map&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;lat))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ll make some assumptions about species and families since the book is not completely clear regarding which animals are meant exactly. Before pondering about this I had no idea there were three species of wombats! For wombats, I&amp;rsquo;m using the two possible families, for kookaburras, emus and kangaroos the whole family and for snake the &lt;a href=&#34;https://twitter.com/MilesMcBain/status/900957549951819776&#34;&gt;one mentioned in that scary thread&lt;/a&gt;. For possums, I&amp;rsquo;m using a family of possums whose Wikipedia page did not indicate they were mostly urban.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;animals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;wombat&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;wombat&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;kookaburra&amp;#34;&lt;/span&gt;, 
                                   &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dingo&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;emu&amp;#34;&lt;/span&gt;,
                                   &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;koala&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;kangaroo&amp;#34;&lt;/span&gt;, 
                                   &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;snake&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;possum&amp;#34;&lt;/span&gt;),
                          latin &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Lasiorhinus&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Vombatus&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Dacelo&amp;#34;&lt;/span&gt;,
                                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Canis lupus dingo&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Dromaius&amp;#34;&lt;/span&gt;,
                                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Phascolarctos cinereus&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Macropus&amp;#34;&lt;/span&gt;, 
                                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Morelia spilota&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Phalangeridae&amp;#34;&lt;/span&gt;))
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(animals)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;latin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;wombat&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lasiorhinus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;wombat&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Vombatus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;kookaburra&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Dacelo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;dingo&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Canis lupus dingo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;emu&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Dromaius&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;koala&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Phascolarctos cinereus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;kangaroo&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Macropus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;snake&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Morelia spilota&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;possum&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Phalangeridae&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Here is the function to get occurrences for one species or family.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;spocc&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;scrubr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
get_ozccurrences &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(latin, year, bbox){
  gbifopts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(year &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; year)
  ozccurrences &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;occ&lt;/span&gt;(query &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; latin,
                      from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;gbif&amp;#39;&lt;/span&gt;), 
                      gbifopts &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; gbifopts,
                      limit &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;200000&lt;/span&gt;,
                      geometry &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; bbox)
  ozccurrences &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;occ2df&lt;/span&gt;(ozccurrences)
  ozccurrences &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ozccurrences &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;coord_impossible&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;coord_incomplete&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;coord_unlikely&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;date_standardize&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;%Y-%m-%d&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;date_missing&lt;/span&gt;()
  ozccurrences&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;latin &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; latin
  ozccurrences
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s test it on kookaburras in 2016, using the whole family. Note, the maps drawn in this section are really meant to just have a look. In a better analysis I&amp;rsquo;d try to define zones based on the occurrences for instance, and I&amp;rsquo;d be more perfectionist regarding the looks of the map.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;kookaburras &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_ozccurrences&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Dacelo&amp;#34;&lt;/span&gt;, bbox &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; bbox, year &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2016&lt;/span&gt;)

ozmap &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; kookaburras,
             &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(longitude, latitude),
             col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;salmon&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-12-16-possummagic/unnamed-chunk-6-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-6&#34;&gt;&lt;/p&gt;
&lt;p&gt;Note that occurrences might be misleading, since to get one you need one observer, so we&amp;rsquo;ll probably get less occurrences when there are less humans without this meaning the density of the animal itself is lower. But since Hush&amp;rsquo;s story is told by a human, we expect Hush to live in an area with at least a few observations of the different animals! Otherwise, how could the author know about all this stuff?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;all_ozcurrences &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map2_df&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(animals&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;latin, &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;), 
                                 &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;2011&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2016&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(animals)), 
                                 get_ozccurrences,
                                 bbox &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; bbox)
all_ozcurrences &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rename&lt;/span&gt;(all_ozcurrences, scientific_name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; name)
all_ozcurrences &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(all_ozcurrences, animals, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;latin&amp;#34;&lt;/span&gt;)
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(all_ozcurrences, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-12-15-all_ozcurrences.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we have a reasonable number of occurrences, we can check where the animals have been seen, hopefully all of them have at least one place in common, preferably not too far from Adelaide (whose location we&amp;rsquo;ll show in the next section). Although colours are not needed here, I&amp;rsquo;ll get a bit artistic and use the pretty &amp;ldquo;healthy reef&amp;rdquo; palette part of the &lt;code&gt;ochRe&lt;/code&gt; package created during the rOpenSci Oz unconf this year, see &lt;a href=&#34;https://ropensci.org/blog/2017/11/21/ochre/&#34;&gt;this blog post&lt;/a&gt;. This palette has 9 colours, so it was handy.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ochRe&amp;#34;&lt;/span&gt;)
ozmap &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; all_ozcurrences,
             &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(longitude, latitude,
                 col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; name)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;facet_wrap&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;name)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
    &lt;span style=&#34;color:#06287e&#34;&gt;scale_colour_ochre&lt;/span&gt;(palette &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;healthy_reef&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(legend.position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-12-16-possummagic/unnamed-chunk-8-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;&lt;/p&gt;
&lt;p&gt;Ok, when you see where Adelaide is you&amp;rsquo;ll agree that it&amp;rsquo;s fine to assume Hush and Grandma Poss live in the bush a bit further North from Adelaide. By the way, the only map of the trip &lt;a href=&#34;http://afieldtriplife.com/wp-content/uploads/2015/04/australian-map-e1427908892939.jpg&#34;&gt;I found online&lt;/a&gt; does not seem to show their home address. Maybe because they do not want the possum stars to have to deal with too many visitors?&lt;/p&gt;
&lt;p&gt;I also notice I only get no occurrence from the &lt;a href=&#34;https://en.wikipedia.org/wiki/Northern_hairy-nosed_wombat&#34;&gt;Northern hairy-nosed wombat&lt;/a&gt; but it seems to be rarer than the common wombat (ok, the name might have been a good clue for me before I got the data).&lt;/p&gt;
&lt;h1 id=&#34;geocoding-the-cities&#34;&gt;Geocoding the cities&lt;/h1&gt;
&lt;p&gt;The cities we need to geocode, and the food eaten by Hush and Grandma Poss while visiting them, are:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;cities &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(city &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Adelaide&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Melbourne&amp;#34;&lt;/span&gt;,
                                  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Sydney&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Brisbane&amp;#34;&lt;/span&gt;,
                                  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Darwin&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Perth&amp;#34;&lt;/span&gt;,
                                  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Hobart&amp;#34;&lt;/span&gt;),
                         food &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Anzac biscuit&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;mornay and Minties&amp;#34;&lt;/span&gt;,
                                  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;steak and salad&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pumpkin scones&amp;#34;&lt;/span&gt;,
                                  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;vegemite&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pavlova&amp;#34;&lt;/span&gt;, 
                                  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lamington&amp;#34;&lt;/span&gt;))

knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(cities)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;city&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;food&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Adelaide&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Anzac biscuit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Melbourne&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mornay and Minties&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Sydney&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;steak and salad&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Brisbane&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;pumpkin scones&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Darwin&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;vegemite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Perth&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;pavlova&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Hobart&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lamington&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;We shall perfom geocoding using my own package &lt;a href=&#34;https://github.com/ropensci/opencage&#34;&gt;&lt;code&gt;opencage&lt;/code&gt;&lt;/a&gt; which is a wrapper for R of the &lt;a href=&#34;https://geocoder.opencagedata.com&#34;&gt;OpenCage API&lt;/a&gt;. This package was &lt;a href=&#34;https://github.com/ropensci/onboarding/issues/36&#34;&gt;reviewed by Julia Silge for rOpenSci&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;opencage&amp;#34;&lt;/span&gt;)
get_lozcation &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(city){
  opencage_results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; opencage&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;opencage_forward&lt;/span&gt;(placename &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; city,
                                                 countrycode &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;AU&amp;#34;&lt;/span&gt;)
  output &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; opencage_results&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;results
  output&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;city &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; city
  output &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; output[&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(output&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;components.city),]
  output &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; output[output&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;components.city &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; city,]
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(output) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;){
    output &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; output[output&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;confidence &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(output&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;confidence),]
  }
  
  output
} 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A small technical note, depending on the font you use in RMarkdown and that sort of encoding joy sources, you now get a flag from the OpenCage API! In my blogging font, it is a bit boring, e.g.:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;adelaide &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_lozcation&lt;/span&gt;(city &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Adelaide&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;adelaide$annotations.flag&lt;/code&gt; gives me 🇦🇺. But still, a cool feature&amp;hellip; among other tons of more useful features OpenCage has like the &lt;a href=&#34;http://blog.opencagedata.com/post/160294347883/shrtr-pls&#34;&gt;&lt;code&gt;abbr&lt;/code&gt; parameter to get shorter names&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s geocode all cities!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;geozcoded_cities &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(cities&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;city, get_lozcation)
geozcoded_cities &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(geozcoded_cities, cities, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;city&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cool, now we can plot them!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;ozmap  &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_label&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; geozcoded_cities,
             &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(geometry.lng, geometry.lat,
                 label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; city))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-12-16-possummagic/unnamed-chunk-13-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-13&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;mapping-the-book&#34;&gt;Mapping the book!&lt;/h1&gt;
&lt;p&gt;In this last section, I&amp;rsquo;ll invent a home address for Hush and Grandma Poss and produce an educative map containing both city names and city food specialties! Having 7 cities and one bush location, I&amp;rsquo;ll use an 8-colour &lt;code&gt;ochRe&lt;/code&gt; palette, &amp;ldquo;namatjira_qual&amp;rdquo; derived from the &lt;a href=&#34;http://www.menziesartbrands.com/items/twin-ghosts&#34;&gt;beautiful watercolour painting “Twin Ghosts”&lt;/a&gt;, by Aboriginal artist Albert Namatjira (again, I&amp;rsquo;m getting info from &lt;a href=&#34;https://ropensci.org/blog/2017/11/21/ochre/&#34;&gt;this blog post&lt;/a&gt;). Here again, no information is conveyed by the color.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggrepel&amp;#34;&lt;/span&gt;)
hush_home &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(geometry.lng &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; adelaide&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;geometry.lng,
                            geometry.lat &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; adelaide&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;geometry.lat &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.01&lt;/span&gt;,
                            city &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;the bush&amp;#34;&lt;/span&gt;,
                            food &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Possum food&amp;#34;&lt;/span&gt;)

hush_places &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(geozcoded_cities, hush_home)

ozmap  &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; hush_places,
              &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(geometry.lng, geometry.lat),
             col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;grey20&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_label_repel&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; hush_places,
                   &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(geometry.lng &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.3&lt;/span&gt;, geometry.lat &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.3&lt;/span&gt;,
                       label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(food, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;in&amp;#34;&lt;/span&gt;, city),
                       fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; city)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
    &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_ochre&lt;/span&gt;(palette &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;namatjira_qual&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(legend.position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Hush&amp;#39;s culinary tour of Australia&amp;#34;&lt;/span&gt;,
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Inspired by the children&amp;#39;s book Possum magic by M. Fox and J. Vivas&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-12-16-possummagic/unnamed-chunk-14-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-14&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now, I&amp;rsquo;ll show this map to our baby as soon as he&amp;rsquo;s old enough to get it, and then we&amp;rsquo;ll plan a culinary tour of Australia together! Probably not on a bike like Hush and Grandma Poss, unless we can whip up some magic!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>How to develop good R packages (for open science)</title>
      <link>https://masalmon.eu/2017/12/11/goodrpackages/</link>
      <pubDate>Mon, 11 Dec 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/12/11/goodrpackages/</guid>
      <description>&lt;p&gt;I was invited to &lt;a href=&#34;https://methodsblog.wordpress.com/2017/11/16/hackathon-challenges/&#34;&gt;an exciting ecology &amp;amp; R hackathon&lt;/a&gt; in my capacity as a co-editor for &lt;a href=&#34;https://github.com/ropensci/onboarding&#34;&gt;rOpenSci onboarding system of packages&lt;/a&gt;. It also worked well geographically since this hackathon was to take place in Ghent (Belgium) which is not too far away from my new city, Nancy (France). The idea was to have me talk about my &amp;ldquo;top tips on how to design and develop high-quality, user-friendly R software&amp;rdquo; in the context of open science, and then be a facilitator at the hackathon.&lt;/p&gt;
&lt;p&gt;The talk topic sounded a bit daunting but as soon as I started preparing the talk I got all excited gathering resources &amp;ndash; and as you may imagine since I was asked to talk about &lt;em&gt;my&lt;/em&gt; tips I did not need to try &amp;amp; be 100% exhaustive. I was not starting from scratch obviously: we at rOpenSci already have &lt;a href=&#34;https://ropensci.github.io/dev_guide&#34;&gt;well-formed opinions&lt;/a&gt; about such software, and I had given a talk about &lt;a href=&#34;https://masalmon.eu/2017/06/17/automatictools/&#34;&gt;automatic tools for package improvement&lt;/a&gt; whose content was part of my top tips.&lt;/p&gt;
&lt;p&gt;As I&amp;rsquo;ve done in the past with my talks, I chose to increase the impact/accessibility of my work by sharing it on this blog. I&amp;rsquo;ll also share this post on the day of the hackathon to provide my audience with a more structured document than my slides, in case they want to keep some trace of what I said (and it helped me build a good narrative for the talk!). Most of these tips will be useful for package development in general, and a few of them specific to scientific software.&lt;/p&gt;
&lt;h1 id=&#34;what-is-a-good-r-package-in-my-opinion&#34;&gt;What is a good R package in my opinion?&lt;/h1&gt;
&lt;p&gt;The answer to this will appear in the blog post but if I had to say this in one sentence, I&amp;rsquo;d say that a good R package for open science is an useful, robust and well-documented package that&amp;rsquo;s easy to find and that users will trust.&lt;/p&gt;
&lt;h1 id=&#34;how-to-plan-your-r-package&#34;&gt;How to plan your R package&lt;/h1&gt;
&lt;h2 id=&#34;should-your-package-even-exist&#34;&gt;Should your package even exist?&lt;/h2&gt;
&lt;p&gt;You probably want to write and publish an R package because you have some sort of scripts or functions that you think would be useful to other people, or you do not even have that but wish the functionality existed. I won&amp;rsquo;t speak about the &lt;a href=&#34;http://r-pkgs.had.co.nz/intro.html&#34;&gt;benefits of building an R package for yourself&lt;/a&gt;, or a &lt;a href=&#34;https://github.com/ropensci/unconf17/issues/5&#34;&gt;research compendium&lt;/a&gt; to make your work reproducible.&lt;/p&gt;
&lt;p&gt;I think you should ask yourself these questions before starting to code away:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Will this piece of software really be useful to someone else than you? If not, building a package will still save you time, but you maybe don&amp;rsquo;t need to put a lot of effort into it. If you doubt, you can ask around you if other people would be interested in using it. Brainstorming package ideas is part of what happened before the hackathon, in a collaborative document.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Is your idea really new, or is there already a package out there performing the exact same task?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If there is one, would your implementation bring something to the market, e.g. an user-friendlier implementation? There are for instance two R packages that interface the Keras Deep Learning Library, &lt;a href=&#34;https://keras.rstudio.com/&#34;&gt;&lt;code&gt;keras&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/statsmaths/kerasR&#34;&gt;&lt;code&gt;kerasR&lt;/code&gt;&lt;/a&gt;. In some cases having several packages will be too much, in some cases it won&amp;rsquo;t because one package will suit some users better.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If there is already a similar package, should you work on your own or collaborate with the author(s) of the original package? The &lt;code&gt;rtweet&lt;/code&gt; package actually completely replaced the &lt;code&gt;twitteR&lt;/code&gt; package after the two maintainers agreed on it. I guess the best thing is to just ask the maintainer, unless their contributing guide already makes clear what&amp;rsquo;s welcome and what&amp;rsquo;s not (more on contributing guides later!).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;what-should-your-package-contain-exactly&#34;&gt;What should your package contain exactly?&lt;/h2&gt;
&lt;p&gt;Then, once you&amp;rsquo;ve really decided that you want to write and publish this R package, you could start planning its development. Two things seem important to me at this point:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Make your package compatible with the workflow of your users. For instance, if your package has something to do with time series, it&amp;rsquo;s probably best to try and make your output compatible with time series classes people are used to, and for which there are other packages available.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do not get too ambitious. For instance, do you want to have a specific plotting method for your output, or can you rely on your users&amp;rsquo; using say &lt;code&gt;ggplot2&lt;/code&gt;, merely giving them an example of how to do so in a vignette? I&amp;rsquo;ve heard that&amp;rsquo;s part of the &lt;a href=&#34;https://en.wikipedia.org/wiki/Unix_philosophy&#34;&gt;Unix philosophy&lt;/a&gt;, small pieces building on top each other. This will save you time, and let you concentrate on the novel and important piece you&amp;rsquo;re providing to the community.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once you&amp;rsquo;ve decided on all of this, maybe sketch a to-do list. If you&amp;rsquo;re already familiar with Github, which you will be after reading some books recommended in the next section, you can have one issue per item, or even take advantage of &lt;a href=&#34;https://guides.github.com/features/issues/&#34;&gt;Github&amp;rsquo;s milestones feature&lt;/a&gt;. You don&amp;rsquo;t need to have a master plan for your whole package life, because one can hope your users will also influence the future features, and well you&amp;rsquo;ll keep getting smarter as time goes by and the ideas will keep flowing.&lt;/p&gt;
&lt;p&gt;If you want to work on your package as a team, make roles clear from the beginning, e.g. who will be the maintainer and keep others right on track&amp;hellip; in particular if you start the project as a hackathon, who will make sure development goes forward once everyone goes home?&lt;/p&gt;
&lt;h2 id=&#34;what-will-your-package-be-called&#34;&gt;What will your package be called?&lt;/h2&gt;
&lt;p&gt;Last but not least in this planning phase, you should call your package something! I&amp;rsquo;d advise names in lower case as recommended by rOpenSci, because this way your user doesn&amp;rsquo;t need to remember where the capital letters are (yes, it is a funny recommendation by an organization called rOpenSci), and because a full capital letter name looks like screaming. I recommend checking your package name via the &lt;a href=&#34;https://github.com/ropenscilabs/available&#34;&gt;&lt;code&gt;available&lt;/code&gt; package&lt;/a&gt; which will tell you whether it&amp;rsquo;s valid, available on the usual packages venues and also whether it has some unintended meanings.&lt;/p&gt;
&lt;h1 id=&#34;how-to-build-an-r-package&#34;&gt;How to build an R package&lt;/h1&gt;
&lt;p&gt;Here I&amp;rsquo;ll list useful resources to learn how to build an R package while respecting best practice. When googling a bit about R package development, I was surprised to see that although there are a ton of R packages out there, there aren&amp;rsquo;t that many guides. Maybe we do not need more than CRAN official guide after all, and &lt;a href=&#34;https://r-pkgs.org/&#34;&gt;Hadley Wickham&amp;rsquo;s and Jenny Bryan&amp;rsquo;s book&lt;/a&gt; is excellent, especially with the corresponding RStudio and &lt;code&gt;devtools&lt;/code&gt; magic combo&amp;hellip; but well diversity of resources is good too!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d recommend your building packages in RStudio making the most of automatic tools like &lt;code&gt;devtools&lt;/code&gt;. Note, in comparison to the content of Hadley&amp;rsquo;s book, some automation is now &lt;a href=&#34;https://www.tidyverse.org/articles/2017/11/usethis-1.0.0/&#34;&gt;supported by &lt;code&gt;usethis&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Using these short and long form resources will help you increase the quality of your package. It&amp;rsquo;ll have the structure it should have for instance.&lt;/p&gt;
&lt;h2 id=&#34;short-tutorials&#34;&gt;Short tutorials&lt;/h2&gt;
&lt;p&gt;To learn the 101 of package building, check out &lt;a href=&#34;https://hilaryparker.com/2014/04/29/writing-an-r-package-from-scratch/&#34;&gt;Hilary Parker&amp;rsquo;s famous blog post &lt;em&gt;Writing an R package from scratch&lt;/em&gt;&lt;/a&gt; that got many R package developers started (I&amp;rsquo;ve for instance seen quite a few tweets of people celebrating their first R package and thanking Hilary!); or &lt;a href=&#34;https://r-mageddon.netlify.com/post/writing-an-r-package-from-scratch/&#34;&gt;its updated version by Tomas Westlake&lt;/a&gt; that shows how to do the same more efficiently using &lt;code&gt;usethis&lt;/code&gt;: &lt;a href=&#34;https://www.hvitfeldt.me/2018/09/usethis-workflow-for-package-development/&#34;&gt;this workflow description by Emil Hvitfeldt&lt;/a&gt;; or &lt;a href=&#34;http://www.mjdenny.com/R_Package_Pictorial.html&#34;&gt;this pictorial by Matthew J Denny&lt;/a&gt;. How someone can be patient enough to do so many screenshots is beyond me but it&amp;rsquo;s really great that he did!&lt;/p&gt;
&lt;h2 id=&#34;books&#34;&gt;Books&lt;/h2&gt;
&lt;p&gt;Then you can read books! I&amp;rsquo;ve mentioned Hadley&amp;rsquo;s book. There&amp;rsquo;s also a very good one called &lt;a href=&#34;https://bookdown.org/rdpeng/RProgDA/&#34;&gt;&lt;em&gt;Mastering Software Development in R&lt;/em&gt; by Roger D. Peng, Sean Kross, and Brooke Anderson&lt;/a&gt;. And I&amp;rsquo;d be damned if I do not mention the bible a.k.a &lt;a href=&#34;http://cran.r-project.org/doc/manuals/r-release/R-exts.html&#34;&gt;&lt;em&gt;Writing R extensions&lt;/em&gt;, the official CRAN guide&lt;/a&gt; which is not really a book but well a (very) long form resource. In all cases you can cherry pick what you need and want to read but be sure you follow the rules when submitting a package to CRAN for instance.&lt;/p&gt;
&lt;h2 id=&#34;moocs&#34;&gt;MOOCs&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re more into MOOCs,  there is a &lt;a href=&#34;https://fr.coursera.org/specializations/r&#34;&gt;Coursera specialization corresponding to the book by Roger Peng, Sean Kross and Brooke Anderson&lt;/a&gt;, with a course specifically about R packages.&lt;/p&gt;
&lt;h2 id=&#34;in-person-training&#34;&gt;In-person training&lt;/h2&gt;
&lt;p&gt;You can also look for in person training! Look up your local R user group or R-Ladies chapter if there&amp;rsquo;s one, maybe book a company, etc. If you happen to be in or near South Africa in March 2018, I&amp;rsquo;ll be teaching &lt;a href=&#34;http://capetown2018.satrdays.org/#workshops&#34;&gt;a workshop about R package development in Cape Town at satRday 2018 on March the 16th&lt;/a&gt;, maybe you can buy a ticket and come!&lt;/p&gt;
&lt;h2 id=&#34;more-precise-guidelines&#34;&gt;More precise guidelines&lt;/h2&gt;
&lt;p&gt;If you want to follow even more precise guidelines than the ones in the resources, check out the &lt;a href=&#34;https://ropensci.github.io/dev_guide&#34;&gt;rOpenSci&amp;rsquo;s gitbook &amp;ldquo;rOpenSci Packages: Development, Maintenance, and Peer Review&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;where-should-your-package-live&#34;&gt;Where should your package live?&lt;/h1&gt;
&lt;h2 id=&#34;open-your-code&#34;&gt;Open your code!&lt;/h2&gt;
&lt;p&gt;I was giving a talk in the context of &lt;em&gt;open&lt;/em&gt; science so this one was obvious. And R is an &lt;em&gt;open-source&lt;/em&gt; language, so if you publish your package there&amp;rsquo;s no black box. On top of that you should make the place where your code is created and modified open to facilitate its browsing, bug reports (if they are open, there&amp;rsquo;s less chance they&amp;rsquo;ll be duplicated, and people can see how fast/whether you respond to them), and collaboration.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve mentioned Github when giving my planning tips earlier. My recommendation is to have the code of your R package live in an open repository with version control. That might be R-Forge and svn if you like, or Github/Gitlab and git. I was introduced to version control basics with svn and R-Forge and found that the small tortoise of the Windows Tortoise svn software was cute, that&amp;rsquo;s all I can tell you about svn, ah! I then learnt git and Github thanks to &lt;a href=&#34;http://r-pkgs.had.co.nz/git.html&#34;&gt;this part of Hadley&amp;rsquo;s book&lt;/a&gt;, which also gives you good reasons to use git and Github. I&amp;rsquo;ve heard good things about &lt;a href=&#34;http://happygitwithr.com/&#34;&gt;this online book by Jenny Bryan&lt;/a&gt; and &lt;a href=&#34;http://ohshitgit.com/&#34;&gt;this website for when bad things happen to you&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;put-your-package-in-one-of-the-official-platforms&#34;&gt;Put your package in one of the official platforms&lt;/h2&gt;
&lt;p&gt;That is, CRAN or Bioconductor, where they&amp;rsquo;re easier to install, and also for the badge of trust it gives your package, although you might already follow stricter guidelines than these platforms.&lt;/p&gt;
&lt;p&gt;By the way regarding trust, &lt;a href=&#34;https://simplystatistics.org/2015/11/06/how-i-decide-when-to-trust-an-r-package/&#34;&gt;this blog post by Jeff Leek, &lt;em&gt;How I decide when to trust an R package&lt;/em&gt;&lt;/a&gt; is an interesting read.&lt;/p&gt;
&lt;p&gt;Special tip specific to CRAN, release your package using &lt;code&gt;devtools::release()&lt;/code&gt; which will help you catch some issues before submitting your package to CRAN, and will allow you to do the whole submission without even leaving R.&lt;/p&gt;
&lt;h2 id=&#34;link-the-two&#34;&gt;Link the two&lt;/h2&gt;
&lt;p&gt;I wrote this with my CRAN experience in mind, but this is probably relevant for Bioconductor too.&lt;/p&gt;
&lt;p&gt;I want to underline one point: please indicate the URL of your code repository and the link to the issues or bug reports page in the DESCRIPTION of your package. This way, once your package is up on CRAN for instance, users can trace it back more easily. Really, do not forget to do that. Also indicate the link to your issue page in DESCRIPTION under BugReports.&lt;/p&gt;
&lt;p&gt;Another important point is that if your package is on CRAN, and your code repository on Github, it&amp;rsquo;s good to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://help.github.com/articles/creating-releases/&#34;&gt;create a release&lt;/a&gt; and attach the corresponding NEWS each time you upload a new version on CRAN (otherwise your release is a surprise release). One reason for having releases is archiving, this way users can download and install a given version quite easily. Another one is that users might use tools such as &lt;a href=&#34;https://about.sibbell.com/&#34;&gt;Sibbell&lt;/a&gt; to be notified of new releases.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;have a &lt;a href=&#34;https://www.r-pkg.org/services#badges&#34;&gt;CRAN badge&lt;/a&gt; in the README, see &lt;a href=&#34;https://github.com/ropensci/ropenaq&#34;&gt;this README for instance&lt;/a&gt;. It&amp;rsquo;s easier to install packages from CRAN so people might want to do that, they can see what the latest CRAN version number is, and well you recognize the hosting on CRAN in a way, because you should be thankful for CRAN work.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;how-to-check-your-package-automatically&#34;&gt;How to check your package automatically&lt;/h1&gt;
&lt;p&gt;Here I will assume your package has &lt;a href=&#34;http://r-pkgs.had.co.nz/tests.html&#34;&gt;unit tests&lt;/a&gt; and is hosted on Github, although the latter isn&amp;rsquo;t a condition for all tips here. If you&amp;rsquo;ve read &lt;a href=&#34;https://masalmon.eu/2017/06/17/automatictools/&#34;&gt;my blog post about automatic tools for improving packages&lt;/a&gt; thoroughly, this will sound quite familiar, and I&amp;rsquo;d advise you to go to this post for more details.&lt;/p&gt;
&lt;p&gt;These tools are all here to help you get a better package before releasing it.&lt;/p&gt;
&lt;h2 id=&#34;r-cmd-check&#34;&gt;R CMD check&lt;/h2&gt;
&lt;p&gt;Use &lt;a href=&#34;http://r-pkgs.had.co.nz/check.html&#34;&gt;&lt;code&gt;devtools::check()&lt;/code&gt;&lt;/a&gt;! The link I&amp;rsquo;ve put here explains why you should, and the efforts you should put in solving the different messages it&amp;rsquo;ll output.&lt;/p&gt;
&lt;h2 id=&#34;continuous-integration&#34;&gt;Continuous integration&lt;/h2&gt;
&lt;p&gt;As a complement to the last sub-section, if your code lives on say Github, you can have R CMD check run on an external platform each time you push changes. This is called continuous integration and will help you spot problems without needing to remember to do the checks. Furthermore, having them run on an external platform allows you to choose the R version so you can check your package works with different R versions without installing them all.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://juliasilge.com/blog/beginners-guide-to-travis/&#34;&gt;This blog post by Julia Silge&lt;/a&gt; is an excellent introduction to continuous integration for beginners.&lt;/p&gt;
&lt;p&gt;To perform checks on say Windows only once in a while, you might want to check &lt;a href=&#34;https://github.com/r-hub&#34;&gt;the R-hub project&lt;/a&gt;. Making sure your package works on several platforms is a condition for CRAN release, and in any case something you&amp;rsquo;ll want to do to have an user-friendly package.&lt;/p&gt;
&lt;h2 id=&#34;style-your-code&#34;&gt;Style your code&lt;/h2&gt;
&lt;p&gt;Style your code for future readers, who will be future you, collaborators and curious users. If your code is pretty, it&amp;rsquo;ll be easier for them to concentrate on its content.&lt;/p&gt;
&lt;p&gt;Use &lt;a href=&#34;https://github.com/jimhester/lintr&#34;&gt;&lt;code&gt;lintr&lt;/code&gt;&lt;/a&gt; for static code analysis.&lt;/p&gt;
&lt;p&gt;To prettify your code, use &lt;a href=&#34;https://github.com/r-lib/styler&#34;&gt;&lt;code&gt;styler&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;get-automatic-advice-about-your-package&#34;&gt;Get automatic advice about your package&lt;/h2&gt;
&lt;p&gt;Install and run &lt;a href=&#34;https://github.com/mangothecat/goodpractice&#34;&gt;&lt;code&gt;goodpractice&lt;/code&gt;&lt;/a&gt; for “Advice (that) includes functions and syntax to avoid, package structure, code complexity, code formatting, etc.”.&lt;/p&gt;
&lt;h2 id=&#34;remove-typos&#34;&gt;Remove typos!&lt;/h2&gt;
&lt;p&gt;Use the &lt;code&gt;devtools::spell_check()&lt;/code&gt; function. Typos in documentation are not the end of the world but can annoy the user, and it&amp;rsquo;s not hard to remove them thanks to this tool, so do it when you get a chance.&lt;/p&gt;
&lt;p&gt;All these tools provide you with a list of things to change. This means they create a to-do list without your needing to think too much, so if you&amp;rsquo;re a bit tired but want to improve your package, you can let them fix the agenda!&lt;/p&gt;
&lt;h1 id=&#34;bring-the-package-to-its-users-and-get-feedback&#34;&gt;Bring the package to its users and get feedback&lt;/h1&gt;
&lt;p&gt;These two aspects are linked because your users will help you make your package better for them, but for that to happen they need to know about your package and to understand it.&lt;/p&gt;
&lt;h2 id=&#34;documentation&#34;&gt;Documentation!&lt;/h2&gt;
&lt;p&gt;You know how your package works but the users don&amp;rsquo;t (and future you might forget as well!). Document your parameters, functions, add examples, and also write &lt;a href=&#34;http://r-pkgs.had.co.nz/vignettes.html&#34;&gt;vignettes&lt;/a&gt;. At least one vignette will show your users how the different functions of your package interact.&lt;/p&gt;
&lt;p&gt;At the beginning of this document I mentioned that when planning your package you should think about making it compatible with your users workflow. One of the vignettes can be an example of just that. Otherwise, it&amp;rsquo;ll be hard for users to see how useful your package is&amp;hellip; and when writing the example workflow, you might find your package lacks some functionality.&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;ve written all these documentation parts, create a website for your package using &lt;a href=&#34;http://hadley.github.io/pkgdown/&#34;&gt;&lt;code&gt;pkgdown&lt;/code&gt;&lt;/a&gt;. &lt;a href=&#34;http://enpiar.com/2017/11/21/getting-down-with-pkgdown/&#34;&gt;This tutorial&lt;/a&gt; is excellent.&lt;/p&gt;
&lt;h2 id=&#34;user-friendly-programming&#34;&gt;User-friendly programming&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ll give four tips here, partly inspired by &lt;a href=&#34;https://blog.keras.io/user-experience-design-for-apis.html&#34;&gt;this essay by François Chollet&lt;/a&gt;. I want to share these two sentences from the essay with you: &amp;quot; In the long run, good design wins, because it makes its adepts more productive and more impactful, thus spreading faster than user-hostile undesign. Good design is infectious.&amp;rdquo;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Have error and warning messages that are easy to understand. For instance, if communicating with an API, then translate http errors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Check the input. For instance, If a parameter provided to a function should be a positive number, check it is and if it is not, return a friendly error message.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Offer shortcuts. For instance, if your function relies on an API key being provided, you can silently search for it in environment variables without the user doing anything, provided you explain how to store an environment variable in the documentation. This is how my &lt;a href=&#34;https://github.com/ropensci/opencage&#34;&gt;&lt;code&gt;opencage&lt;/code&gt;&lt;/a&gt; works if you want an example. Noam Ross made the PR that added this functionality, and I agree that it makes the package user-friendler. Likewise, have good default values of other parameters if possible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose a good naming scheme that will allow your users to more easily remember the names of functions. You could choose to have a prefix for all the functions of your package, which is recommended by rOpenSci, and &lt;a href=&#34;http://joncalder.co.za/2017-12-04-naming-things-is-hard/&#34;&gt;discussed in this very interesting and nuanced blog post by Jon Calder&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;promotion&#34;&gt;Promotion&lt;/h2&gt;
&lt;p&gt;Now that you have a well-documented error-friendly package&amp;hellip; how are your end users going to learn that it exists? Note that you should have a good idea of your potential users when planning your package (or at least part of them, who knows who else might find it useful?). One way to define good venues for promotion is to think of how &lt;em&gt;you&lt;/em&gt; learn about R packages, but as an R developer you&amp;rsquo;re probably more into R and R news than your future average user! For information you can also see the results of &lt;a href=&#34;https://juliasilge.com/blog/package-search/&#34;&gt;Julia Silge&amp;rsquo;s survey about how people discover packages&lt;/a&gt; &lt;a href=&#34;https://app.doopoll.co/poll/FGZqTL7vpaaCgpWCM/live-results&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Obvious venues for promotion are social media, for instance Twitter with the #rstats hashtag in the form of a carefully crafted tweet including a link and a cool image like a figure or screenshot and maybe emojis, but that might not be enough for your niche package. If you write an ecology package and you have a well-recognized blog in that area blog about your package of course. You could also ask someone to let you guest post on their well-recognized niche field blog.&lt;/p&gt;
&lt;p&gt;If your package is an interface to an existing tool or internet resource, try to have your package listed on that tool or resource webpage.&lt;/p&gt;
&lt;p&gt;As a scientist, you can write a paper about your package and publish it to a journal well known in your field like &lt;a href=&#34;http://besjournals.onlinelibrary.wiley.com/hub/journal/10.1111/(ISSN)2041-210X/&#34;&gt;Methods in Ecology and Evolution&lt;/a&gt;. By the way when you use R and packages in such a paper or any other paper do not forget to cite them (using the output of &lt;code&gt;citation()&lt;/code&gt; for instance) to acknowledge their usefulness and help their authors feel their work is valued (furthermore if they&amp;rsquo;re academics having their work cited is quite crucial for their career advancement).&lt;/p&gt;
&lt;h2 id=&#34;review&#34;&gt;Review&lt;/h2&gt;
&lt;p&gt;As a scientist you&amp;rsquo;re used to having papers peer-reviewed. In general if you submit a paper about your package, your paper will be reviewed more than your package, but you can actually get the benefits of peer-review for your package itself! This is a fantastic way to improve the quality and user-friendliness of your package.&lt;/p&gt;
&lt;p&gt;Where to have your package reviewed?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You don&amp;rsquo;t need anything formal, maybe you can ask someone you know and who could for instance be an user of your package? You can ask them to review the code or its documentation or both, depending on their skills and time of course.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://journal.r-project.org/&#34;&gt;The R Journal&lt;/a&gt; asks reviewers of papers to have a look at the package, as does &lt;a href=&#34;https://www.jstatsoft.org/index&#34;&gt;The Journal of Statistical Software&lt;/a&gt;. That said, you&amp;rsquo;ll need to write a whole paper to go with your package which is maybe something you don&amp;rsquo;t want to.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;http://joss.theoj.org/&#34;&gt;The Journal of Open Science Software, JOSS&lt;/a&gt; asks reviewers to check some points in your package and you to write a very minimal paper about your package. The review process is minimal but you can still get useful feedback.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;At &lt;a href=&#34;https://www.numfocus.org/blog/how-ropensci-uses-code-review-to-promote-reproducible-science/&#34;&gt;rOpenSci we review&lt;/a&gt; packages that fit in &lt;a href=&#34;https://github.com/ropensci/onboarding/blob/master/policies.md&#34;&gt;our categories&lt;/a&gt;. Your package will be reviewed by two people. We have a partnership with the Journal of Open Source Software so that if your package fits in both venues, the review over at JOSS will be a breeze after the rOpenSci reviews. We also have a partnership with MEE, allowing a duo paper-package to be reviewed by MEE and rOpenSci respectively, see &lt;a href=&#34;https://methodsblog.wordpress.com/2017/11/29/software-review/&#34;&gt;this post&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Needless to say, but I&amp;rsquo;ll write it anyway, all these review systems work both ways&amp;hellip; Offer your reviewing services! You&amp;rsquo;ll actually learn so much that you&amp;rsquo;ll find ideas to improve your own packages.&lt;/p&gt;
&lt;h2 id=&#34;make-your-repo-a-friendly-place&#34;&gt;Make your repo a friendly place&lt;/h2&gt;
&lt;p&gt;Another way to improve the quality of your package and make it more user friendly is to put people at ease when they have a question, a bug report, or a suggestion for improvement. Adding a code of conduct (use &lt;code&gt;devtools::use_code_of_conduct&lt;/code&gt; as a starting point) and a contributing guide (with issue and PR templates if you want, in any case making clear what kind of contributions you welcome) to your package repository will help ensuring that. Also try to respond timeously to requests.&lt;/p&gt;
&lt;p&gt;On top of having a contributing guide you could also add a &lt;a href=&#34;https://github.com/RMHogervorst/badgecreatr&#34;&gt;status badge&lt;/a&gt; for your repository so that any visitor might see at a glance whether your package is still in an early development stage.&lt;/p&gt;
&lt;p&gt;If people actually start contributing to the package, try being generous with acknowledgements. A selfish reason is that it&amp;rsquo;ll motivate people to keep contributing to your package. A less selfish reason is that it makes the whole R community more welcoming to new contributors. So you can add discoverers and solvers of bugs for instance as ctb in DESCRIPTION and add a line about their contribution in NEWS.md.&lt;/p&gt;
&lt;h2 id=&#34;package-analytics&#34;&gt;Package analytics&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re curious, you can get an idea of the number of downloads of your package via the &lt;a href=&#34;https://cranlogs.r-pkg.org/&#34;&gt;&lt;code&gt;cranlogs&lt;/code&gt; package&lt;/a&gt;. Using it you can compare your package popularity to similar packages, and check whether there was a peak after a course you&amp;rsquo;ve given for instance.&lt;/p&gt;
&lt;p&gt;Similarly, if your package repository is hosted on Github, using the &lt;a href=&#34;https://github.com/r-lib/gh&#34;&gt;&lt;code&gt;gh&lt;/code&gt; package&lt;/a&gt; you can do similar analyses, looking at the number of stars over time for instance.&lt;/p&gt;
&lt;h1 id=&#34;the-end&#34;&gt;The end&lt;/h1&gt;
&lt;p&gt;This is the end of my list of tips, do not hesitate to add suggestions in the comments!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Names of b.....s badder than Taylor Swift, a class in women&#39;s studies?</title>
      <link>https://masalmon.eu/2017/12/05/badderb/</link>
      <pubDate>Tue, 05 Dec 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/12/05/badderb/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://masalmon.eu/2016/10/02/first7jobs-repost/&#34;&gt;Once&lt;/a&gt; &lt;a href=&#34;https://masalmon.eu/2017/02/05/actuallivingscientists/&#34;&gt;again&lt;/a&gt;, a Twitter trend sent me to my R prompt&amp;hellip; Here is a &lt;a href=&#34;http://knowyourmeme.com/memes/name-a-badder-bitch-than-taylor-swift&#34;&gt;bit of context&lt;/a&gt;. My summary: Taylor Swift apparently plays the bad girl in her new album and a fan of hers asked a question&amp;hellip;&lt;/p&gt;
&lt;blockquote class=&#34;twitter-tweet&#34; data-lang=&#34;ca&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Name a bitch badder than Taylor Swift 😍😛😤 &lt;a href=&#34;https://t.co/AkSyQBUIME&#34;&gt;pic.twitter.com/AkSyQBUIME&lt;/a&gt;&lt;/p&gt;&amp;mdash; Nutella (@xnulz) &lt;a href=&#34;https://twitter.com/xnulz/status/928857792982781952?ref_src=twsrc%5Etfw&#34;&gt;10 de novembre de 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;p&gt;The tweet was then quoted by many people mentioning badass women, and I decided to have a look at these heroes!&lt;/p&gt;
&lt;h1 id=&#34;name-tweets-badder-than-nutellas&#34;&gt;Name tweets badder than Nutella&amp;rsquo;s&lt;/h1&gt;
&lt;p&gt;I was a bit lazy and asked Mike Kearney, &lt;code&gt;rtweet&lt;/code&gt; maintainer, how to find tweets quoting a tweet, to which &lt;a href=&#34;https://twitter.com/hrbrmstr/status/937340032456814592&#34;&gt;Bob Rudis answered&lt;/a&gt;. Now that I even had the code, it was no trouble at all getting the data. I added the filtering steps myself, see, I&amp;rsquo;m not &lt;em&gt;that&lt;/em&gt; lazy. I also removed the link to the quoted tweet that was at the end of each tweet.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;question_tweet &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;928857792982781952&amp;#34;&lt;/span&gt;
badass &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt;  rtweet&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;search_tweets&lt;/span&gt;(question_tweet, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;18000&lt;/span&gt;, include_rts &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)
badass &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(badass, is_quote_status, quote_status_id &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; question_tweet)
badass &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(badass, text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://t\\.co/.*$&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
badass &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(badass, text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(text))
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(badass, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-12-03-badderb_badass.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I obtained 15653 tweets. Not bad!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;20171015&lt;/span&gt;)

indices &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sample.int&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(badass), size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;7&lt;/span&gt;)
badass&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text[indices]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Carmina Barrios&amp;quot;                                                                                                                                                                                                      
## [2] &amp;quot;Anyone&amp;quot;                                                                                                                                                                                                               
## [3] &amp;quot;Shirley Temple&amp;quot;                                                                                                                                                                                                       
## [4] &amp;quot;So a lot of people have shared some bad ass women in repsonse to the tweet below. I hope someone is compiling those responses for one kick ass book.&amp;quot;                                                                 
## [5] &amp;quot;Mary Bowers was a slave with a photographic memory who pretended to be \&amp;quot;slow-witted\&amp;quot; in order to spy on confederate soldiers in the house worked, and pass intel she gathered to Union forces during the Civil War.&amp;quot;
## [6] &amp;quot;Ramona Quimby, age 8&amp;quot;                                                                                                                                                                                                 
## [7] &amp;quot;Snow White. Sleeping Beauty. Cinderella, Elsa, Ariel bec the category example is obvs mediocre Disney caricatures allowed by the patriarchy, right?&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;unnamed-badder-bs-your-mother-and-grand-mother&#34;&gt;Unnamed badder b&amp;hellip;..s: your mother and grand-mother&lt;/h1&gt;
&lt;p&gt;Out of 15653, 570 contained the word &amp;ldquo;mother&amp;rdquo; &amp;ndash; I haven&amp;rsquo;t looked for the word &amp;ldquo;mum&amp;rdquo; and haven&amp;rsquo;t checked for the fact that it is someone from the family of the tweet author. Here a few of the personal stories (or not) identified with this quick and dirty method.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;20171015&lt;/span&gt;)
mothers &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(badass, stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;mother&amp;#34;&lt;/span&gt;))
indices &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sample.int&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;15&lt;/span&gt;)
mothers&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text[indices]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;##  [1] &amp;quot;My grandmother struggled through poverty her entire life, in a family prone to depression, addiction, and suicide. She had so many Caesarian sections that when she reached menopause she didnt have a belly button anymore.&amp;quot;                                                       
##  [2] &amp;quot;Mom married my dad. He had been married 2X before with a total of 10 kids. His first wife left him and the kid.  2nd wife died after their divorce.  He had custody of all 10, judge asked my mother if she would take them in, she did. Raised his 10 and had 3 with dad. 13 in all&amp;quot;
##  [3] &amp;quot;Each of my grandmothers raised 11 kids &amp;lt;f0&amp;gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+0098&amp;gt;&amp;lt;U+008F&amp;gt;&amp;quot;                                                                                                                                                                                                                 
##  [4] &amp;quot;My mother&amp;quot;                                                                                                                                                                                                                                                                           
##  [5] &amp;quot;My grandmother.&amp;quot;                                                                                                                                                                                                                                                                     
##  [6] &amp;quot;My mother in law, who isnt a bitch in any way, shape, or form, and raised three girls on her own (and who are all bad asses in their own way) without the help of a deadbeat ex.&amp;quot;                                                                                                 
##  [7] &amp;quot;.@RuPaul for starters. And my great grandmother who drove a car when she was 12. My dog, too. She is definitely a bad bitch.&amp;quot;                                                                                                                                                        
##  [8] &amp;quot;My grandmother escaped from the Tsar with nothing but the clothes on her back.&amp;quot;                                                                                                                                                                                                      
##  [9] &amp;quot;My mother&amp;quot;                                                                                                                                                                                                                                                                           
## [10] &amp;quot;Almost any woman alive today,@xnulz \n\nAnd - Heres another one, for sure (PLUS shes a good mother):\n\nTonya Harding; @ITonyaMovie \n\n&amp;lt;U+26F8&amp;gt;&amp;lt;f0&amp;gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+00A5&amp;gt;&amp;lt;U+008A&amp;gt;&amp;lt;U+26F8&amp;gt;&amp;lt;f0&amp;gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+00A5&amp;gt;&amp;lt;U+008A&amp;gt;&amp;lt;U+2764&amp;gt;&amp;lt;U+FE0F&amp;gt;&amp;lt;f0&amp;gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+00A5&amp;gt;&amp;lt;U+008A&amp;gt;&amp;lt;U+26F8&amp;gt;&amp;lt;f0&amp;gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+00A5&amp;gt;&amp;lt;U+008A&amp;gt;&amp;lt;U+26F8&amp;gt;&amp;quot;
## [11] &amp;quot;all of the single mothers doing the most they can for their children&amp;quot;                                                                                                                                                                                                                
## [12] &amp;quot;My grandmother was married off at the age of 14 to an older man who had already been married once, dealt with an abusive marriage but stuck around for the kids and went back to school after having 5 children and worked for 20 years to support her family&amp;quot;                       
## [13] &amp;quot;my grandmother was an army nurse in WW2.\ntaught me how to tourniquet a leg and bandage it using only gauze&amp;quot;                                                                                                                                                                         
## [14] &amp;quot;My wife birthed a goddamn child. My mother and grandmother both birthed multiple. This is too easy.&amp;quot;                                                                                                                                                                                 
## [15] &amp;quot;My grandmother worked for the OSS in London during WW2 as a code breaker.&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Can we talk about that belly button thing?! I&amp;rsquo;m also happy to see a diversity of things they were recognized for.&lt;/p&gt;
&lt;h1 id=&#34;names-of-the-badder-bs&#34;&gt;Names of the badder b&amp;hellip;..s&lt;/h1&gt;
&lt;p&gt;Quite a few of the tweets from this trend contained the name of someone. In order to extract these names, I resorted to a language processing method called entity extraction, the entity here being a person. For that, I could have used an &lt;a href=&#34;https://app.monkeylearn.com/main/extractors/ex_isnnZRbS/&#34;&gt;extractor module&lt;/a&gt; of the Monkeylearn platform &lt;a href=&#34;https://github.com/ropensci/monkeylearn&#34;&gt;via my own &lt;code&gt;monkeylearn&lt;/code&gt; package&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Instead, I chose to illustrate a different method: using the &lt;a href=&#34;https://github.com/statsmaths/cleanNLP&#34;&gt;&lt;code&gt;cleanNLP&lt;/code&gt; package&lt;/a&gt; that I know from &lt;a href=&#34;https://journal.r-project.org/archive/2017/RJ-2017-035/RJ-2017-035.pdf&#34;&gt;the excellent R Journal paper presenting it&lt;/a&gt;. Among other things, it serves as an interface between R and the &lt;a href=&#34;https://spacy.io/&#34;&gt;Python library spaCy&lt;/a&gt; and also as an interface between R and &lt;a href=&#34;https://stanfordnlp.github.io/CoreNLP/&#34;&gt;the coreNLP Java library&lt;/a&gt;. Installing these tools is the painful part of the setup, but 1) you only need to install one of them 2) there are detailed instructions &lt;a href=&#34;https://github.com/statsmaths/cleanNLP#backends&#34;&gt;here&lt;/a&gt; 3) once your tool is installed, using the package is a breeze (and well independent of any rate limit contrary to &lt;code&gt;monkeylearn&lt;/code&gt; use). I am at that breeze stage, you can be jealous.&lt;/p&gt;
&lt;p&gt;There were a few tweets with infuriating encoding issues, BOM or something like that, and I decided to just ignore them by using &lt;code&gt;purrr::possibly&lt;/code&gt;. I obviously did this to illustrate the use of this &lt;code&gt;purrr&lt;/code&gt; function, not out of laziness.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cleanNLP&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;init_spaCy&lt;/span&gt;()
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# we need to remove characters like &amp;#34;\u0098&amp;#34;&lt;/span&gt;
badass &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(badass, text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;enc2native&lt;/span&gt;(text))

get_entities_with_text &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x){
  obj &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;run_annotators&lt;/span&gt;(x, as_strings &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  entities &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_entity&lt;/span&gt;(obj)
  entities&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; x
  entities
}

possibly_get_entities &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;possibly&lt;/span&gt;(get_entities_with_text,
                                         otherwise &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;)

entities &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(badass&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text, possibly_get_entities)

readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(entities, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-12-03-badderb_entities.csv&amp;#34;&lt;/span&gt;)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I got at least one entity for 7504 out of 15653 tweets, and at least one &lt;em&gt;person&lt;/em&gt; for 4664. I am very satisfied with this.&lt;/p&gt;
&lt;h1 id=&#34;so-who-are-you-badder-bs&#34;&gt;So, who are you, badder b&amp;hellip;..s?&lt;/h1&gt;
&lt;p&gt;We get this kind of entities: NORP, CARDINAL, LANGUAGE, GPE, DATE, ORG, PERSON, TIME, LOC, MONEY, WORK_OF_ART, EVENT, FAC, QUANTITY, LAW, PRODUCT, ORDINAL, PERCENT. I&amp;rsquo;m more interested in PERSON and no, I&amp;rsquo;m not shouting. I chose to look at the top 12 in order to get a top 10 excluding Taylor Swift herself.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;entities &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(entity_type &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;PERSON&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(entity) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; n) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;entity&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Taylor Swift&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;213&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Taylor&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;145&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Rosa Parks&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;140&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Harriet Tubman&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;109&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Dora&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;90&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Rose West&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lyudmila Pavlichenko&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;77&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Joan&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;71&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Marie Curie&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;57&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Myra Hindley&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Nancy Wake&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Hillary Clinton&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;41&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;At that point I did feel like bursting out laughing though. Dora! And I checked, we&amp;rsquo;re talking about Dora the explorer! Joan is Joan of arc. Interestingly in that top 10 we&amp;rsquo;re mixing really bad persons, e.g. Myra Hindley was a serial killer, and really badass persons, like Rosa Parks. My husband will be happy to see Marie Curie in this list, since he&amp;rsquo;s a big fan of hers, having even guided a few tours about her life in Paris.&lt;/p&gt;
&lt;p&gt;Looking at the most frequently mentioned women obviously makes us loose well wrongly written names, and most importantly personal stories of badass mothers and the like, and of native women for instance, although I have the impression of having read about a few but probably because of my following &lt;a href=&#34;https://twitter.com/RallidaeRule&#34;&gt;Auriel Fournier&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;writing-history&#34;&gt;Writing history?&lt;/h1&gt;
&lt;p&gt;I saw someone said they&amp;rsquo;d use the tweets as basis for history lessons. In order to get a view of a person, one could concatenate the tweets about them. Take Marie Curie for instance.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;entities &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(entity_type &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;PERSON&amp;#34;&lt;/span&gt;, entity &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Marie Curie&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(text)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  .$text
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Rachel Carson, Marie Curie, Ruth Bader Ginsberg, Madeleine Albright, Diane Fossey, Helen Keller, Gloria Steinem, Madonna, Aretha Franklin, Margot Lee Shetterly, Malala Yousafzai, and a whole lot more., Rosa Parks. Harriet Tubman. Anne Frank. Malala Yousafazi, Susan B. Anthony, Sally Ride, Marie Curie. Margaret Thatcher, Indira Ghandi, Golda Meier., ...its not bitch. Its woman.\n\nMarie Curie\n\nRosa Parks\n\nEleanor Roosevelt\n\nHedy Lamar\n\nSappho\n\nAbagail Adams\n\nFlorence Nightingale\n\nSally Ride\n\nMargaret Chase Smith\n\nAnne Frank\n\nMargaret Thatcher \n\nSandra Day OConnor\n\nOprah\n\nLilith\n\nMarilyn Monroe\n\nDita Von Teese, Ruby Bridges, Barbara Jordan, Marie Curie, Rosa Parks, Ida B Wells, Susan B Anthony, Harriet Tubman, ..., Lorde. Etc., I mean, off hand, Marie Curie was denied access to University because she was a woman, educated herself, served as a surgeon in WW1 and became the only person ever to earn two Nobel prizes, Emmeline Pankhurst, Amelia Earhart, Florence Nightingale, Rosa Parks, Joan of Arc, Marie Curie, Lilian Ngoyi, Helen Suzman, Katherine Johnson,  Frida Khalo, Catherine the Great, Eleanor Roosevelt, Mary Wollstonecraft, Valentina Tereshkova.., lmao Elizabeth Schuyler-Hamilton, Hedy Lamar, Amelia Earhart, Marie Curie, Sophie Scholl, Katherine Johnson, Dorothy Vaughn, Mary Jackson, Margaret Hamilton, Ada Lovelace, Anne Bonny, Calamity Jane, George Eliot, Mary Read, Mary Wolstncraft, Mary Shelley... need I go on?! &amp;lt;f0&amp;gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+0098&amp;gt;&amp;lt;U+00A1&amp;gt;, Marie Curie, Rose Parks\nFrancis Perkins\nJeanette Rankin\nSally Ride\nMarie Curie\nJK Rowling\n\nShall I go on?, Marie Curie: she invented radioactivity, got the Nobel prize twice and found polonium and radium., Well I would start with not calling a woman a bitch.\nAfter that I would say Hedy Lamarr, Susan B. Anthony, any of the @HiddenFigures, Marie Curie, Sally Ride, Molly Pitcher, Clara Barton  shall I continue?, Marie Curie literally died doing Nobel Prize winning research., Harriet Tubman, Shirley Chisholm, Rosa Parks, Ida B. Wells, Marie Curie, Maxine Waters, Lena Horne,  Ruby Dee, Angela Davis, My grandmama, my great-aunt Priscilla, my mama, my sister..., Marie Curie. Mother of radioactivity. First and only woman to win the nobel prize twice. Died due to radiation exposure., Rosa Parks, Freya Stark, Ida B Wells, Sally Ride, Marie Curie, Margaret Heafield, Amelia Earheart, Ruth Bader Ginsburg, Abigail Adams, Jane Goodall, Malala how much time you got?, Marie Curie made mobile x-ray unit, learned anatomy &amp;amp;amp; auto repairs, trained women, raised money, ran IRC&#39;s medical x-ray division in WWI., Marie Curie. No explanation needed., Rosa Parks, Katherine Johnson, Dorothy Vaughn, Mary Jackson, Bettie Page, Emma Watson, Malala Yousafzai, Emily Pankhurst, Anne Frank, Marie Curie, Joan of Arc, Boudicca... need I go on?, Marie Curie., Malala, Michelle Obama, Frida Kahlo, Emma Watson, Maya Angelou, Marie Curie, Lady Gaga, JK Rowling, Princess Diana, Carrie Fisher, Anne Frank, Laverne Cox...\n\n literally so many women... I could go on for weeks..., Marie Curie, Mary Anning, Dorothy Hodgkin, Jane Austin, Katherine Johnson, my GCSE geography and A Level geology teacher Sheila Tanner...., Marie Curie. She handled radioactive materials with barehand and won the Nobel Prize. How bout that? #RealTimeChem, Rosa Parks, Nellie Bly, Harriet Tubman, Jane Adams, Eleanor Roosevelt, Elizabeth Blackwell, Marie Curie, Amelia Earhart, Cleopatra, Queen Elizabeth I, Ella Fitzgerald, Grace Hopper, Dolores Huerta, Shirley Jackson, Joan of Arc, Helen Keller, Sacagawea, Sappho the Greek poet..., Marie Curie., Marie Curie., Marie Curie, Maya Angelou, Rosa Parks, Michelle Obama, my  grandma, my neuroscientist mum, Danica Patrick, the Queen of England, Angela Merkel,  @chrissyteigen @BrookeBCNN @KateBolduan - Me, Rosa Parks, Harriet Tubman, Shirley Chisholm, Ella Fitzgerald, Ruth Bader Ginsburg, Esperonza Spaulding, Sister Rossetta Tharpe, Sarah Vaughn, Aretha Franklin, Eartha Kitt, Carrie Fisher, Patti Smith, Jane Goodall, Marie Curie, Sally Ride, Leontyne Price, Princess Diana, etc..., Whoa hey now, Marie Curie won Nobel Prizes in two different sciences, only person to have done that. Probably had a lovely singing voice, too, before it got demolished by the radioactivity she was discovering for the betterment of humanity., Rosa Parks. Laura Secord. Hillary Rodham Clinton. Nellie McClung. Queen Victoria. Joan of Arc. Myrlie Evers-Williams. Tina Turner. Jane Goodall. Ruth Bader Ginsburg. Viola Desmond. Jennie Trout. Malala  Yousafzai. Margret Atwood. Ameila Earhart. J.K. Rowling. Marie Curie., Marie Curie. Won the Nobel Prize. Twice., Just off the top of my head: Elizabeth Cady Stanton, Clara Barton, Marie Curie, Amelia Earhart, Elizabeth I, Joan of Arc, Helen Keller., Amelia Earhart, Rosa Parks, Sacagawea, Pocahontas, Susan B. Anthony, Noor Inayat Khan, Marie Curie, Alice Paul, Margaret Thatcher, Harriet Tubman, Maya Angelou, Lucy Stone, Eleanor Roosevelt ..... just to name a few., Marie Curie., The kashariyot. Shirley Chisholm. bell hooks. Golda Meir. Edith Bunker. Hedy Lamar. Marie Curie. Bella Abzug. Michelle Obama. Judith Halberstam. Jo March. Hillary Rodham Clinton., Hedy Lamarr. Marie Curie. Mae Jemison. Sally Ride. Sonia Sotomayor. Ruth Bader Ginsburg. Beyoncé. Mulan. My wife., Marie Curie is the only person to win two Nobel Prizes in two separate scientific fields and died of leukaemia as a result of her research into radionuclides which are used in medicine to save thousands of lives a year, Marie Curie.\n2 Nobel Prizes., Marie Curie who died discovering two elements and isolated radioactive isotopes., Rosa Parks, Marie Curie, Charlize Theron, Noor Inayat Khan, Rihanna, Serena Williams, Ruth Bader Ginsberg, basically all these women on this list:, Marie Curie developed the theory of radioactivity, techniques for isolating isotopes, and discovered two chemical elements. She died of aplastic anemia from exposure to radiation over the course of her research and her work at field hospitals during WWI., Marie Curie won two Nobel prizes for two different fields of science and her notebook is so radioactive that exposure to it would be lethal., How much time have you got? How about Marie Curie, or Amelia Earhart, Nancy Hart? Arlene Limas? Tomoe Gozen? Lucretia Mott? Irina Sendler? Nothing against Ms. Swift, but we could do this all day, Marie Curie, Nobel prizes in Physics and Chemistry., Marie Curie? 1st woman in Europe to get a PhD and 1st woman to win a Nobel Prize (which she did twice, in Physics and Chemistry). She also developed a theory of a radioactivity &amp;amp;amp; found the elements radium and polonium. A pretty bad bitch., Marie Curie was a badass scientist who won two Nobel prizes and ate radium for breakfast. #thatlastpartwasntsogood, Rosa Parks? Harriet Tubman? Louisa May Alcott? Susan B. Anthony? Marie Curie? Amelia Earhart? Cleopatra? Frida Khalo? Mother Theresa? Sandra Day OConnor? Oprah Winfrey? Sally Ride? Margaret Sanger? Anne Frank? Joan of Arc? Sacajawea? Sappho? Sojourner Truth? Malala Yousafzai?, Cleopatra. Mata Hari. Marie Curie. Susan B. Anthony. Hannah Arendt. . . . \n\nIt&#39;s really not hard, 1. Malala Yousafzai, Marie Curie, Rosa Parks, Georgia O&#39;Keeffe, Maria Mitchell, Tanya Tagaq, Billie Holiday, Valentina Tereshkova, Sally Ride, Anne Frank, Maya Angelou, Sacheen Littlefeather, Frida Kahlo, Harper Lee, Marsha P Johnson, Sylvia Rivera, Helen Keller, Margaret Sanger,, Marie Curie, Marie Curie., Ada Lovelace, Jane Austen, Helen Sharman, Margaret Atwood, Mary Beard, Rosalind Franklin, Hedy Lamarr, Marie Curie, Helen Keller, Emmeline Pankhurst, Rosa Parks, Florence Nightingale, Brenda Hale, QE1, Boudicca, Amy Johnson, Elizabeth Fry, Octavia Hill, Mary Wollstonecraft, &amp;amp;amp;c.&amp;lt;f0&amp;gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+0096&amp;gt;&amp;lt;U+00A4&amp;gt;, Marie Curie. Most people are lucky to have 1 Nobel prize, or share it. She has 2., Sojourner Truth, Khutulun, Marie Curie, Queen Lillikulani, Hedy Lamar, Empress Wu Zetain, Hellen Mirren, Raden Ajeng Kartini, Ida B. Wells, Artemisia Gentileschi, Nancy Wake, Tomoe Gozen, Yaa Asantewaa, Boudicca, Juana Inés de la Cruz..., Marie Curie, whose greatest discovery and lifes work also ended up being what killed her and who is the only person to win a Nobel Prize in two different sciences., Joan of Arc, Marie Curie, Queen Elizabeth, Cleopatra, my mom, the lady in front of me on line at the grocery store...\n\nIt&#39;s a pretty long list., Rosa Parks. All of the women from Hidden Figures. Marie Curie. Any woman in STEM fields., Marie Curie \nThat&#39;s where the list starts&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Doing this one also gets the name of many other women. Moreover, if writing history lessons, one should have several sources, right? What about Wikidata &lt;a href=&#34;https://masalmon.eu/2017/08/06/p1/&#34;&gt;like in this other blog post of mine&lt;/a&gt;? It should have data for at least the most famous badass women.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# add a function for getting a silent answer&lt;/span&gt;
quietly_query &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;quietly&lt;/span&gt;(WikidataQueryServiceR&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;query_wikidata)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# function for getting someone&amp;#39;s data&lt;/span&gt;
get_wikidata &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(name, pb &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;){
  &lt;span style=&#34;color:#06287e&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.null&lt;/span&gt;(pb)) pb&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tick&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;print&lt;/span&gt;()
  &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
  item &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; WikidataR&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;find_item&lt;/span&gt;(name, language &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# sometimes people have no Wikidata entry so I need this condition&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(item) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;){
    entity_code &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; item[[1]]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;id
    query &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt;  &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;PREFIX entity: &amp;lt;http://www.wikidata.org/entity/&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     #partial results
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     SELECT ?propUrl ?propLabel ?valUrl ?valLabel ?picture
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     WHERE
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     {
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     hint:Query hint:optimizer &amp;#39;None&amp;#39; .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     {	BIND(entity:&amp;#34;&lt;/span&gt;,entity_code,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; AS ?valUrl) .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     BIND(\&amp;#34;N/A\&amp;#34; AS ?propUrl ) .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     BIND(\&amp;#34;identity\&amp;#34;@en AS ?propLabel ) .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     }
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     UNION
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     {	entity:&amp;#34;&lt;/span&gt;, entity_code,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; ?propUrl ?valUrl .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     ?property ?ref ?propUrl .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     ?property rdf:type wikibase:Property .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     ?property rdfs:label ?propLabel
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     }
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     ?valUrl rdfs:label ?valLabel
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     FILTER (LANG(?valLabel) = &amp;#39;en&amp;#39;) .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     OPTIONAL{ ?valUrl wdt:P18 ?picture .}
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     FILTER (lang(?propLabel) = &amp;#39;en&amp;#39; )
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     }
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     ORDER BY ?propUrl ?valUrl
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     LIMIT 200&amp;#34;&lt;/span&gt;)
    results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;quietly_query&lt;/span&gt;(query) 
    results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; results&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;result
    results&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;name&lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; name
    results
  }else{
    &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
  }
   
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yes, I just had to replace all occurrences of &amp;ldquo;sv&amp;rdquo; with &amp;ldquo;en&amp;rdquo; to get a function for this post. I&amp;rsquo;d like to try to write an automatic text about badass women.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;get_a_string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(prop, prep, wikidata){
  answer &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(wikidata, propLabel &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; prop) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    .$valLabel &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    toString
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(answer &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;){
    &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  }else{
    &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(prep, answer))
  }
}

tell_me_about &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(name){
  wikidata &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_wikidata&lt;/span&gt;(name)
  questions &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;occupation&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;country of citizenship&amp;#34;&lt;/span&gt;,
                 &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;field of work&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;award received&amp;#34;&lt;/span&gt;)
  
  words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;from&amp;#34;&lt;/span&gt;, 
             &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;known from her work in&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;and who was awarded&amp;#34;&lt;/span&gt;)
  
  strings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map2_chr&lt;/span&gt;(questions, words, 
                            get_a_string,
                            wikidata &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; wikidata)
  
  strings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; strings[strings &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;]
  
  sentence &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;was&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(strings))
  sentence &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(sentence, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(sentence)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ok, let&amp;rsquo;s try our automatic history writing function. It won&amp;rsquo;t work for Dora and Joan, sadly.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tell_me_about&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Lyudmila Pavlichenko&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Lyudmila Pavlichenko was a historian, sniper, military personnel, from Soviet Union, and who was awarded Medal \&amp;quot;For the Defence of Sevastopol\&amp;quot;, Medal \&amp;quot;For the Defence of Odessa\&amp;quot;, Hero of the Soviet Union, Order of Lenin, Medal \&amp;quot;For Battle Merit\&amp;quot;, Gold Star, Medal \&amp;quot;For the Victory over Germany in the Great Patriotic War 19411945\&amp;quot;.&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tell_me_about&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Myra Hindley&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Myra Hindley was a criminal, from United Kingdom.&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tell_me_about&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Harriet Tubman&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Harriet Tubman was a writer, from United States of America, and who was awarded New Jersey Hall of Fame, National Women&#39;s Hall of Fame, Maryland Women&#39;s Hall of Fame.&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Not many details clearly, but not too bad for a quickly written history hum bot, if I can call it so.&lt;/p&gt;
&lt;h1 id=&#34;so-happy-nutella&#34;&gt;So, happy, Nutella?&lt;/h1&gt;
&lt;p&gt;This was my contribution to the meme following Nutella&amp;rsquo;s viral tweet. I am thankful for the badass women I did end up discovering thanks to the tweets, and am waiting for someone to replace the lyrics of all Taylor Swift&amp;rsquo;s songs with gems from this Twitter trend.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Where to live in the US</title>
      <link>https://masalmon.eu/2017/11/16/wheretoliveus/</link>
      <pubDate>Thu, 16 Nov 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/11/16/wheretoliveus/</guid>
      <description>&lt;p&gt;I was fascinated by this &lt;a href=&#34;https://xkcd.com/1916/&#34;&gt;xkcd comic&lt;/a&gt; about where to live based on your temperature preferences. I also thought it&amp;rsquo;d be fun to try to make a similar one from my R session! Since I&amp;rsquo;m no meteorologist and was a bit unsure of how to define winter and summer, and of their relevance in countries like, say, India which has monsoon, I decided to focus on a single country located in one hemisphere only and big enough to offer some variety&amp;hellip; the USA! So, dear American readers, where should you live based on your temperature preferences?&lt;/p&gt;
&lt;h1 id=&#34;defining-data-sources&#34;&gt;Defining data sources&lt;/h1&gt;
&lt;h2 id=&#34;weather-data&#34;&gt;Weather data&lt;/h2&gt;
&lt;p&gt;The data for the original xkcd graph comes from &lt;a href=&#34;http://www.weatherbase.com/&#34;&gt;weatherbase&lt;/a&gt;. I changed sources because 1) I was not patient enough to wait for weatherbase to send me a custom dataset which I imagine is what xkcd author did and 2) I&amp;rsquo;m the creator of &lt;a href=&#34;http://ropensci.github.io/riem/&#34;&gt;a cool package accessing airport weather data&lt;/a&gt; for the whole word including the US! My package is called &amp;ldquo;riem&amp;rdquo; like &amp;ldquo;R Iowa Environmental Mesonet&amp;rdquo; (the source of the data, a &lt;a href=&#34;https://mesonet.agron.iastate.edu/request/download.phtml?network=IN__ASOS&#34;&gt;fantastic website&lt;/a&gt;) and &amp;ldquo;we laugh&amp;rdquo; in Catalan (at the time I wrote the package I was living in Barcelona and taking 4 hours of Catalan classes a week!). It&amp;rsquo;s a simple but good package which underwent &lt;a href=&#34;https://github.com/ropensci/onboarding/issues/39&#34;&gt;peer-review&lt;/a&gt; at rOpenSci onboarding, thank you &lt;a href=&#34;https://twitter.com/gbwanderson&#34;&gt;Brooke&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;I based my graph on data from the last winter and the last summer. I reckon that one should average over more years, but nothing important is at stake here, right?&lt;/p&gt;
&lt;h2 id=&#34;cities-sample&#34;&gt;Cities sample&lt;/h2&gt;
&lt;p&gt;My package has a function for downloading weather data for a given airport based on its ID. For instance Los Angeles airport is LAX. At that point I just needed a list of cities in the US with their airport code. Indeed with my package you can get all airport weather networks, one per US state, and all the stations within that network&amp;hellip; this is a lot of airports with no way to automatically determine how big they are! And to get the city name since it&amp;rsquo;d be so hard to parse the airport name I&amp;rsquo;d have resorted to geocoding with &lt;a href=&#34;https://github.com/ropensci/opencage&#34;&gt;e.g. this package&lt;/a&gt;. A bit complicated for a simple fun graph!&lt;/p&gt;
&lt;p&gt;So I went to the &lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_the_busiest_airports_in_the_United_States&#34;&gt;Wikipedia page of the busiest airports in the US&lt;/a&gt; and ended up getting &lt;a href=&#34;https://www.bts.gov/content/passengers-boarded-top-50-us-airports&#34;&gt;this dataset&lt;/a&gt; from the US Department of Transportation (such a weird open data format by the way&amp;hellip; I basically copy-pasted the first two columns in a spreadsheet!). This is not perfect, getting a list of major cities in every state would be more fair but hey reader I want you to live in a really big city so that I might know where it is.&lt;/p&gt;
&lt;h2 id=&#34;ok-so-lets-get-the-data&#34;&gt;Ok so let&amp;rsquo;s get the data&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;us_airports &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-11-16_wheretoliveus_airports.csv&amp;#34;&lt;/span&gt;)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(us_airports[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;Name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Atlanta, GA (Hartsfield-Jackson Atlanta International)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ATL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Los Angeles, CA (Los Angeles International)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LAX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Chicago, IL (Chicago O&amp;rsquo;Hare International)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ORD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Dallas/Fort Worth, TX (Dallas/Fort Worth International)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;DFW&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;New York, NY (John F. Kennedy International)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;JFK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Denver, CO (Denver International)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;DEN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;San Francisco, CA (San Francisco International)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;SFO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Charlotte, NC (Charlotte Douglas International)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;CLT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Las Vegas, NV (McCarran International)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LAS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Phoenix, AZ (Phoenix Sky Harbor International)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;PHX&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I first opened my table of 50 airports. Then, I made the call to the Iowa Environment Mesonet.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;summer_weather &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(us_airports&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;Code, riem&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;riem_measures,
                                date_start &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-06-01&amp;#34;&lt;/span&gt;,
                                date_end &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-08-31&amp;#34;&lt;/span&gt;)
winter_weather &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(us_airports&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;Code, riem&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;riem_measures,
                                date_start &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2016-12-01&amp;#34;&lt;/span&gt;,
                                date_end &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-02-28&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We then remove the lines that will be useless for further computations (The xkcd graph uses average temperature in the winter and average Humidex in the summer which uses both temperature and &lt;a href=&#34;https://en.wikipedia.org/wiki/Dew_point&#34;&gt;dew point&lt;/a&gt;).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;
summer_weather &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(summer_weather,
                                &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(tmpf), &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(dwpf))

winter_weather &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(winter_weather,
                                &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(tmpf))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I quickly checked that there was &amp;ldquo;nearly no missing data&amp;rdquo; so I didn&amp;rsquo;t remove any station nor day but if I were doing this analysis for something serious I&amp;rsquo;d do more checks including the time difference between measures for instance. Note that I end up with 48 airports only, there was no measure for Honolulu, HI (Honolulu International), San Juan, PR (Luis Munoz Marin International). Too bad!&lt;/p&gt;
&lt;h1 id=&#34;calculating-the-two-weather-values&#34;&gt;Calculating the two weather values&lt;/h1&gt;
&lt;p&gt;I started by converting all temperatures to Celsius degrees because although I like you, American readers, Fahrenheit degrees do not mean anything to me which is problematic for checking results plausibility for instance. I was lazy and just used Brooke Anderson&amp;rsquo;s (yep the same Brooke who reviewed &lt;code&gt;riem&lt;/code&gt; for rOpenSci) &lt;a href=&#34;https://github.com/geanders/weathermetrics/&#34;&gt;&lt;code&gt;weathermetrics&lt;/code&gt; package&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;summer_weather &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(summer_weather,
                                tmpc &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; weathermetrics&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;convert_temperature&lt;/span&gt;(tmpf, 
                                                                           old_metric &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;f&amp;#34;&lt;/span&gt;, new_metric &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;c&amp;#34;&lt;/span&gt;),
                                dwpc &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; weathermetrics&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;convert_temperature&lt;/span&gt;(dwpf, 
                                                                           old_metric &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;f&amp;#34;&lt;/span&gt;, new_metric &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;c&amp;#34;&lt;/span&gt;)) 

winter_weather &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(winter_weather,
                                tmpc &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; weathermetrics&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;convert_temperature&lt;/span&gt;(tmpf, 
                                                                           old_metric &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;f&amp;#34;&lt;/span&gt;, new_metric &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;c&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;summer-values&#34;&gt;Summer values&lt;/h2&gt;
&lt;p&gt;Summer values are Humidex values. The author explained Humidex &amp;ldquo;combines heat and &lt;a href=&#34;https://en.wikipedia.org/wiki/Dew_point&#34;&gt;dew point&lt;/a&gt;&amp;rdquo;. Once again I went to &lt;a href=&#34;https://en.wikipedia.org/wiki/Humidex&#34;&gt;Wikipedia&lt;/a&gt; and found the formula. I&amp;rsquo;m not in a mood to fiddle with formula writing on the blog so please go there if you want to see it. There&amp;rsquo;s also a package with a &lt;a href=&#34;https://www.rdocumentation.org/packages/comf/versions/0.1.7/topics/calcHumidity&#34;&gt;function returning the Humidex&lt;/a&gt;. I was feeling adventurous and therefore wrote my own function and checked the results with the numbers from Wikipedia. It was first wrong because I wrote a &amp;ldquo;+&amp;rdquo; instead of a &amp;ldquo;-&amp;rdquo;&amp;hellip; checking one&amp;rsquo;s code is crucial.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;calculate_humidex &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(temp, dewpoint){
  temp &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5555&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;6.11&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;exp&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;5417.7530&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;273.16&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;273.15&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; dewpoint))) &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;)
}

&lt;span style=&#34;color:#06287e&#34;&gt;calculate_humidex&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;30&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;15&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] 33.969
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;calculate_humidex&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;30&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;25&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] 42.33841
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And then calculating the summer Humidex values by station was quite straightforward&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
summer_weather &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(summer_weather,
                                humidex &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;calculate_humidex&lt;/span&gt;(tmpc, dwpc))
summer_values &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; summer_weather &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(station) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(summer_humidex &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mean&lt;/span&gt;(humidex, na.rm &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip; as it was for winter temperatures.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;winter_values &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; winter_weather &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(station) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(winter_tmpc &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mean&lt;/span&gt;(tmpc, na.rm &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;prepare-data-for-plotting&#34;&gt;Prepare data for plotting&lt;/h1&gt;
&lt;p&gt;I first joined winter and summer values&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;climates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(winter_values, summer_values,
                             by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;station&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I re-added city airport names.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;climates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(climates, us_airports,
                             by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;station&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Code&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I only kept the city name.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(climates&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;Name)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Atlanta, GA (Hartsfield-Jackson Atlanta International)&amp;quot;              
## [2] &amp;quot;Austin, TX (Austin - Bergstrom International)&amp;quot;                       
## [3] &amp;quot;Nashville, TN (Nashville International)&amp;quot;                             
## [4] &amp;quot;Boston, MA (Logan International)&amp;quot;                                    
## [5] &amp;quot;Baltimore, MD (Baltimore/Washington International Thurgood Marshall)&amp;quot;
## [6] &amp;quot;Cleveland, OH (Cleveland-Hopkins International)&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;climates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(climates, 
                          city &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(Name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; \\(.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(climates&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;city)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Atlanta, GA&amp;quot;   &amp;quot;Austin, TX&amp;quot;    &amp;quot;Nashville, TN&amp;quot; &amp;quot;Boston, MA&amp;quot;   
## [5] &amp;quot;Baltimore, MD&amp;quot; &amp;quot;Cleveland, OH&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;plotting&#34;&gt;Plotting!&lt;/h1&gt;
&lt;p&gt;When imitating an xkcd graph, one should use the &lt;code&gt;xkcd&lt;/code&gt; package! I had already done that &lt;a href=&#34;https://masalmon.eu/2017/05/14/evergreenreviewgraph/&#34;&gt;in this post&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;xkcd&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;extrafont&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggrepel&amp;#34;&lt;/span&gt;)

xrange &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;range&lt;/span&gt;(climates&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;summer_humidex)
yrange &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;range&lt;/span&gt;(climates&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;winter_tmpc)

&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(climates,
       &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(summer_humidex, winter_tmpc)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_text_repel&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; city),
                   family &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;xkcd&amp;#34;&lt;/span&gt;, 
                   max.iter &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;50000&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Where to live based on your temperature preferences&amp;#34;&lt;/span&gt;,
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Data from airports weather stations, 2016-2017&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Summer heat and humidity via Humidex&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Winter temperature in Celsius degrees&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xkcdaxis&lt;/span&gt;(xrange &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; xrange,
           yrange &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; yrange)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_xkcd&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;, family &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;xkcd&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-11-16-wheretoliveus/unnamed-chunk-10-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-10&#34;&gt;&lt;/p&gt;
&lt;p&gt;So, which city seems attractive to you based on this plot? Or would you use different weather measures, e.g. do you care about rain?&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>You beautiful, naïve, sophisticated newborn series</title>
      <link>https://masalmon.eu/2017/11/05/newborn-serie/</link>
      <pubDate>Sun, 05 Nov 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/11/05/newborn-serie/</guid>
      <description>&lt;p&gt;My husband and I recently started watching the wonderful series &amp;ldquo;Parks and recreation&amp;rdquo; which was recommended to me by my fellow R-Lady Jennifer Thompson in &lt;a href=&#34;https://twitter.com/jent103/status/908162485689122816&#34;&gt;this very convincing thread&lt;/a&gt;. The serie was even endorsed by other R-Ladies. Jennifer told me the first two seasons are not as good as the following ones, but that it was worth it to make it through them. We actually started enjoying the humor and characters right away!&lt;/p&gt;
&lt;p&gt;Then, this week while watching the show, one of the characters did a very basic text analysis that made me feel like imitating him for a blog post &amp;ndash; my husband told me it was very Leslie of me to plan something while doing something else which made me very proud. I &lt;a href=&#34;https://twitter.com/ma_salmon/status/926167897478778880&#34;&gt;tested my idea&lt;/a&gt; on other Leslie fans, and they seemed to think it was a great idea&amp;hellip; and that this post should be the beginning of a series of R-Ladies blog posts about Parks and recreation!&lt;/p&gt;
&lt;p&gt;In this two-short-part blog post, I&amp;rsquo;ll therefore inaugurate this series, what an honor!&lt;/p&gt;
&lt;h1 id=&#34;less-than-stellar-first-seasons&#34;&gt;Less than stellar first seasons?&lt;/h1&gt;
&lt;p&gt;Jennifer told me the first two seasons were not the best ones. My brother who is a cruel man (just kidding) told me this was a very good joke idea: you tell someone a very bad TV series starts getting awesome after a few seasons that you need to watch in order to know the characters&amp;hellip; therefore forcing them to loose their time and sanity in front of the screen, ah! Luckily Jennifer wasn&amp;rsquo;t doing that.&lt;/p&gt;
&lt;p&gt;I said my husband and I were hooked on the series right from the first episode&amp;hellip; what about other people? To answer this question, I downloaded &lt;a href=&#34;http://www.imdb.com/&#34;&gt;IMDB&lt;/a&gt; ratings for the show! I first tried using R packages accessing the &lt;a href=&#34;http://www.omdbapi.com/&#34;&gt;OMDB API&lt;/a&gt;, but &lt;a href=&#34;https://github.com/RMHogervorst/imdb&#34;&gt;this one&lt;/a&gt; was outdated and &lt;a href=&#34;https://github.com/hrbrmstr/omdbapi&#34;&gt;this up-to-date one&lt;/a&gt; was not but taught me the API no longer returns ratings by season&amp;hellip; So I scraped the IMDB website using the &lt;a href=&#34;https://github.com/hadley/rvest&#34;&gt;&lt;code&gt;rvest&lt;/code&gt; package&lt;/a&gt;, after checking I was allowed to do so thanks to the &lt;a href=&#34;https://github.com/ropenscilabs/robotstxt&#34;&gt;&lt;code&gt;robotstxt&lt;/code&gt; package&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;robotstxt&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;paths_allowed&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;http://www.imdb.com/title/tt1266020/eprate&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] TRUE
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rvest&amp;#34;&lt;/span&gt;)
imdb_page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;html&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;http://www.imdb.com/title/tt1266020/eprate&amp;#34;&lt;/span&gt;)
ratings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; imdb_page &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;table&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  .[[1]] &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;html_table&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  .[,&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;]

knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(ratings[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;#&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Episode&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;UserRating&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;UserVotes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;7.13&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;One Last Ride: Part 2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9.7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2,407&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;7.12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;One Last Ride: Part 1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9.6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1,934&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;7.40&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Leslie and Ron&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9.6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1,842&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;6.22&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Moving Up: Part 2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9.4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1,273&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;5.14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Leslie and Ben&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9.3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1,205&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I just had to wrangle this table a little bit.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(ratings)[1] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;number&amp;#34;&lt;/span&gt;
ratings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;separate&lt;/span&gt;(ratings, col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; number,
                           into &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;season&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;episode&amp;#34;&lt;/span&gt;),
                           sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\.&amp;#34;&lt;/span&gt;)
ratings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(ratings, UserVotes &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(UserVotes, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
ratings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(ratings, UserVotes &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(UserVotes))
ratings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(ratings, episode &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(episode))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then I could at last plot the ratings and see whether the two first seasons were not that loved! Before that I quickly assessed whether there was an ok number of votes for all episodes, and that this did not vary widely over seasons, which was the case.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(ratings, &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(episode, UserRating,
                    color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; season)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_smooth&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;()  &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;IMDB rating&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  viridis&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;scale_color_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;,
              axis_title_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-11-05-newborn-serie/unnamed-chunk-3-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-3&#34;&gt;&lt;/p&gt;
&lt;p&gt;Note that for the first season, there are too few points for actually doing a smoothing. Looking at the plot I guess we can say the first season with its only 6 episodes was slightly less enjoyed! I am very thankful that the first season was deemed good enough to continue the series though! Besides I am thankful that it was so simple to answer this crucial question.&lt;/p&gt;
&lt;h1 id=&#34;leslies-wordcloud&#34;&gt;Leslie&amp;rsquo;s wordcloud&lt;/h1&gt;
&lt;p&gt;Warning: the wordcloud produced here might be a spoiler if you have not watched the 4 first seasons!&lt;/p&gt;
&lt;p&gt;In the 10th episode of season 4, Tom produces&lt;a href=&#34;http://ifiwasthelastgirl.tumblr.com/post/77940482792/can-we-talk-about-leslies-word-cloud&#34;&gt; a wordcloud of Leslie&amp;rsquo;s emails and memos&lt;/a&gt;. I cannot really do the same, but was inspired to make a worldcloud of things said in the episodes by downloading all subtitles from the 4 first seasons and using the fantastic &lt;a href=&#34;https://github.com/fkeck/subtools&#34;&gt;&lt;code&gt;subtools&lt;/code&gt; package&lt;/a&gt;. Note that a worldcloud is probably not the coolest thing one can do with all these text data&amp;hellip; but it is a start and I truly hope it inspires more people to use François Keck&amp;rsquo;s package which is really user-friendly since it can read all the subtitles of a serie at once from a folder where each sub-folder is a season. It also supports conversion to formats suitable for text analysis!&lt;/p&gt;
&lt;p&gt;The single problem I experienced when doing this work was that I had to download subtitles from the internet and the websites where you find those are not cute places, they&amp;rsquo;re full of &amp;ldquo;women to date&amp;rdquo;&amp;hellip;&lt;/p&gt;
&lt;p&gt;To make the wordcloud I very simply followed &lt;a href=&#34;http://www.pieceofk.fr/?p=437&#34;&gt;this blog post of François Keck&amp;rsquo;s&lt;/a&gt;. It doesn&amp;rsquo;t get easier than that&amp;hellip; which is great given I have very little time at the moment.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;subtools&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tm&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;SnowballC&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;wordcloud&amp;#34;&lt;/span&gt;)
parks_and_rec &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;read.subtitles.serie&lt;/span&gt;(dir &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;getwd&lt;/span&gt;(), &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;/data/pr/&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Read: 4 seasons, 68 episodes
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;corpus &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tmCorpus&lt;/span&gt;(parks_and_rec)

corpus &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tm_map&lt;/span&gt;(corpus, &lt;span style=&#34;color:#06287e&#34;&gt;content_transformer&lt;/span&gt;(tolower))
corpus &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tm_map&lt;/span&gt;(corpus, removePunctuation)
corpus &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tm_map&lt;/span&gt;(corpus, removeNumbers)
corpus &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tm_map&lt;/span&gt;(corpus, removeWords, &lt;span style=&#34;color:#06287e&#34;&gt;stopwords&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;english&amp;#34;&lt;/span&gt;))
corpus &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tm_map&lt;/span&gt;(corpus, stripWhitespace)

TDM &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;TermDocumentMatrix&lt;/span&gt;(corpus)
TDM &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.matrix&lt;/span&gt;(TDM)
vec.season &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;), &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;24&lt;/span&gt;), &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;), &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;22&lt;/span&gt;))
TDM.season &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;t&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;apply&lt;/span&gt;(TDM, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x) &lt;span style=&#34;color:#06287e&#34;&gt;tapply&lt;/span&gt;(x, vec.season, sum)))
&lt;span style=&#34;color:#06287e&#34;&gt;colnames&lt;/span&gt;(TDM.season) &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;S&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;comparison.cloud&lt;/span&gt;(TDM.season, title.size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, max.words &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;100&lt;/span&gt;, random.order &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; T)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-11-05-newborn-serie/unnamed-chunk-4-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-4&#34;&gt;&lt;/p&gt;
&lt;p&gt;It doesn&amp;rsquo;t look anything like &lt;a href=&#34;http://ifiwasthelastgirl.tumblr.com/post/77940482792/can-we-talk-about-leslies-word-cloud&#34;&gt;Leslie&amp;rsquo;s wordcloud&lt;/a&gt; but it made me happy because I had already forgotten about some words or names from the previous seasons!&lt;/p&gt;
&lt;p&gt;Another thing I did with the subtitles was filtering those starting with &amp;ldquo;Oh Ann&amp;rdquo; in order to have a look at some of the terrific compliments Leslie made to Ann&amp;hellip; And one of them inspired the title of this post, replacing &amp;ldquo;baby&amp;rdquo; by &amp;ldquo;series&amp;rdquo;!&lt;/p&gt;
&lt;h1 id=&#34;the-end-of-this-post-the-beginning-a-series&#34;&gt;The end of this post, the beginning a series!&lt;/h1&gt;
&lt;p&gt;Now that I&amp;rsquo;ve done my homework I&amp;rsquo;m truly looking forward to reading the other posts. I can&amp;rsquo;t wait! Stay tuned by following my fellow bloggers/Leslie fans who came out &lt;a href=&#34;https://twitter.com/ma_salmon/status/926167897478778880&#34;&gt;in this Twitter thread&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>R-Ladies global tour</title>
      <link>https://masalmon.eu/2017/10/06/globalrladiestour/</link>
      <pubDate>Fri, 06 Oct 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/10/06/globalrladiestour/</guid>
      <description>&lt;p&gt;It was recently brought to my attention by &lt;a href=&#34;https://twitter.com/hfcfrick&#34;&gt;Hannah Frick&lt;/a&gt; that there are now sooo many R-Ladies chapters around the world! &lt;a href=&#34;http://rladies.org/&#34;&gt;R-Ladies&lt;/a&gt; is a world-wide organization to promote gender diversity in the R community, and I&amp;rsquo;m very grateful to be part of this community through which I met so many awesome ladies! Since we&amp;rsquo;re all connected, it has now happened quite a few times that R-Ladies gave talks at chapters outside of their hometowns. An R-Lady from Taiwan giving a talk in Madrid while on a trip in Europe and another one doing the same in Lisbon, an R-Lady from San Francisco presenting at the London and Barcelona chapters thanks to a conference on the continent, an R-Lady from Uruguay sharing her experience for the New York City and San Francisco chapters&amp;hellip; It&amp;rsquo;s like rockstars tours!&lt;/p&gt;
&lt;p&gt;Therefore we  R-Ladies often joke about doing an exhaustive global tour. Hannah made me think about this tour again&amp;hellip; If someone were to really visit all of the chapters, what would be the shortest itinerary? And could we do a cool gif with the results? These are the problems we solve here.&lt;/p&gt;
&lt;h1 id=&#34;getting-the-chapters&#34;&gt;Getting the chapters&lt;/h1&gt;
&lt;p&gt;To find all chapters, I&amp;rsquo;ll use Meetup information about meetups whose topics include &amp;ldquo;r-ladies&amp;rdquo;, although it means forgetting a few chapters that maybe haven&amp;rsquo;t updated their topics yet. Thus, I&amp;rsquo;ll scrape &lt;a href=&#34;https://www.meetup.com/topics/r-ladies/all/&#34;&gt;this webpage&lt;/a&gt; because I&amp;rsquo;m too impatient to wait for the cool &lt;a href=&#34;https://github.com/rladies/meetupr/&#34;&gt;&lt;code&gt;meetupr&lt;/code&gt; package&lt;/a&gt; to include the Meetup API topic endpoint and because I&amp;rsquo;m too lazy to include it myself. I did open &lt;a href=&#34;https://github.com/rladies/meetupr/issues/13&#34;&gt;an issue&lt;/a&gt; though. Besides, I was allowed to scrape the page:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;robotstxt&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;paths_allowed&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.meetup.com/topics/&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] TRUE
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Yesss. So let&amp;rsquo;s scrape!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rvest&amp;#34;&lt;/span&gt;)

link &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.meetup.com/topics/r-ladies/all/&amp;#34;&lt;/span&gt;
page_content &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;read_html&lt;/span&gt;(link)
css &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;span[class=&amp;#34;text--secondary text--small chunk&amp;#34;]&amp;#39;&lt;/span&gt;

chapters &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt;  &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(page_content, css) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;html_text&lt;/span&gt;(trim &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
chapters &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(chapters, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.*\\|&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
chapters &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(chapters)
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(chapters)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;London, United Kingdom&amp;quot; &amp;quot;San Francisco, CA&amp;quot;     
## [3] &amp;quot;Istanbul, Turkey&amp;quot;       &amp;quot;Melbourne, Australia&amp;quot;  
## [5] &amp;quot;New York, NY&amp;quot;           &amp;quot;Madrid, Spain&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Montenegro&lt;/span&gt;
chapters[stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(chapters, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Montenegro&amp;#34;&lt;/span&gt;)] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Herceg Novi, Montenegro&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;geolocating-the-chapters&#34;&gt;Geolocating the chapters&lt;/h1&gt;
&lt;p&gt;Here I decided to use a &lt;a href=&#34;https://github.com/ropensci/opencage&#34;&gt;nifty package&lt;/a&gt; to the awesome OpenCage API. Ok, this is my own package. But hey it&amp;rsquo;s really a good geocoding API. And the package was &lt;a href=&#34;https://github.com/ropensci/onboarding/issues/36&#34;&gt;reviewed for rOpenSci by Julia Silge&lt;/a&gt;! In the docs of the package you&amp;rsquo;ll see how to save your API key in order not to have to input it as a function parameter every time.&lt;/p&gt;
&lt;p&gt;Given that there are many chapters but not that many (41 to be exact), I could inspect the results and check them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;geolocate_chapter &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(chapter){
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# query the API&lt;/span&gt;
  results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; opencage&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;opencage_forward&lt;/span&gt;(chapter)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;results
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# deal with Strasbourg&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(chapter &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Strasbourg, France&amp;#34;&lt;/span&gt;){
    results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(results, components.city &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Strasbourg&amp;#34;&lt;/span&gt;)
  }
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get a CITY&lt;/span&gt;
  results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(results, components._type &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;city&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# sort the results by confidence score &lt;/span&gt;
  results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(results, &lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(confidence))
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# choose the first line among those with highest confidence score&lt;/span&gt;
  results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; results[1,]
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# return only long and lat&lt;/span&gt;
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(long &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; results&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;geometry.lng,
                 lat &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; results&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;geometry.lat,
                 chapter &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; chapter, 
                 formatted &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; results&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;formatted)
}

chapters_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(chapters, geolocate_chapter)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# add an index variable&lt;/span&gt;
chapters_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(chapters_df, id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(chapters_df))

knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(chapters_df[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;long&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;lat&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;chapter&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;formatted&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;id&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;-0.1276473&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;51.50732&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;London, United Kingdom&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;London, United Kingdom&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;-122.4192362&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;37.77928&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;San Francisco, CA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;San Francisco, San Francisco City and County, California, United States of America&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;28.9651646&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;41.00963&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Istanbul, Turkey&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Istanbul, Fatih, Turkey&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;144.9631608&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-37.81422&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Melbourne, Australia&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Melbourne VIC 3000, Australia&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;-73.9865811&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;40.73060&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;New York, NY&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;New York City, United States of America&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;-3.7652699&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;40.32819&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Madrid, Spain&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Leganés, Community of Madrid, Spain&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;-77.0366455&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;38.89495&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Washington, DC&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Washington, District of Columbia, United States of America&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;-83.0007064&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;39.96226&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Columbus, OH&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Columbus, Franklin County, Ohio, United States of America&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;-71.0595677&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;42.36048&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Boston, MA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Boston, Suffolk, Massachusetts, United States of America&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;-79.0232050&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;35.85030&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Durham, NC&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Durham, NC, United States of America&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;planning-the-trip&#34;&gt;Planning the trip&lt;/h1&gt;
&lt;p&gt;I wanted to use the &lt;a href=&#34;https://github.com/dirkschumacher/ompr&#34;&gt;&lt;code&gt;ompr&lt;/code&gt; package&lt;/a&gt; inspired by this fantastic use case, &lt;a href=&#34;https://rstudio-pubs-static.s3.amazonaws.com/199542_7f23d4edf6094d89b386e9c875d09a1c.html&#34;&gt;&amp;ldquo;Boris Johnson’s fully global itinerary of apology&amp;rdquo;&lt;/a&gt; &amp;ndash; be careful, the code of this use case is slightly outdated but is up-to-date &lt;a href=&#34;https://dirkschumacher.github.io/ompr/articles/problem-tsp.html&#34;&gt;in the traveling salesperson vignette&lt;/a&gt;. The &lt;code&gt;ompr&lt;/code&gt; package supports modeling and solving &lt;a href=&#34;https://en.wikipedia.org/wiki/Integer_programming&#34;&gt;Mixed Integer Linear Programs&lt;/a&gt;. I got a not so bad notion of what this means by looking &lt;a href=&#34;https://dirkschumacher.github.io/ompr/articles/index.html&#34;&gt;at this collection of use cases&lt;/a&gt;. Sadly, the traveling salesperson problem is a complicated problem and its solving time exponentially increases with the number of stops&amp;hellip; in that case, it became really too long for plain mixed integer linear programming, as in &amp;ldquo;more than 24 hours later not done&amp;rdquo; too long.&lt;/p&gt;
&lt;p&gt;Therefore, I decided to use a &lt;a href=&#34;https://github.com/mhahsler/TSP&#34;&gt;specific R package for traveling salesperson problems &lt;code&gt;TSP&lt;/code&gt;&lt;/a&gt;. Dirk, &lt;code&gt;ompr&lt;/code&gt;&#39;s maintainer, actually used it once as seen &lt;a href=&#34;https://gist.github.com/berlinermorgenpost/027e9c2cd7cd54f36a4033121012252e&#34;&gt;in this gist&lt;/a&gt; and then &lt;a href=&#34;https://interaktiv.morgenpost.de/lange-nacht-der-museen/&#34;&gt;in this newspaper piece&lt;/a&gt; about how to go to all 78 Berlin museums during the night of the museums. Quite cool!&lt;/p&gt;
&lt;p&gt;We first need to compute the distance between chapters. In kilometers and rounded since it&amp;rsquo;s enough precision.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;convert_to_km &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x){
  &lt;span style=&#34;color:#06287e&#34;&gt;round&lt;/span&gt;(x&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1000&lt;/span&gt;)
}

distance &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; geosphere&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;distm&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;as.matrix&lt;/span&gt;(dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(chapters_df, long, lat)), fun &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; geosphere&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;distGeo) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;convert_to_km&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I used methods that do not find the optimal tour. This means that probably my solution isn&amp;rsquo;t the best one, but let&amp;rsquo;s say it&amp;rsquo;s ok for this time. Otherwise, the best thing is to ask Concorde&amp;rsquo;s maintainer if one can use their algorithm which is the best one out there, see &lt;a href=&#34;http://www.tsp.gatech.edu/concorde/&#34;&gt;its terms of use here&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;TSP&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;42&lt;/span&gt;)
result0 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;solve_TSP&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;TSP&lt;/span&gt;(distance), method &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;nearest_insertion&amp;#34;&lt;/span&gt;)
result &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;solve_TSP&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;TSP&lt;/span&gt;(distance), method &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;two_opt&amp;#34;&lt;/span&gt;,
                    control &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(tour &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; result0))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And here is how to link the solution to our initial chapters &lt;code&gt;data.frame&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;paths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; chapters_df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;chapter&lt;span style=&#34;color:#06287e&#34;&gt;[as.integer&lt;/span&gt;(result)],
                        to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; chapters_df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;chapter&lt;span style=&#34;color:#06287e&#34;&gt;[c&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;as.integer&lt;/span&gt;(result)[2&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;41&lt;/span&gt;], &lt;span style=&#34;color:#06287e&#34;&gt;as.integer&lt;/span&gt;(result)[1])], 
                        trip_id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;41&lt;/span&gt;)
paths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;gather&lt;/span&gt;(paths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;property&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;chapter&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;)
paths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(paths, chapters_df, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;chapter&amp;#34;&lt;/span&gt;)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(paths[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;trip_id&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;property&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;chapter&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;long&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;lat&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;formatted&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;id&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;from&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Charlottesville, VA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-78.55676&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;38.08766&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Charlottesville, VA, United States of America&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;38&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;from&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Washington, DC&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-77.03665&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;38.89495&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Washington, District of Columbia, United States of America&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;from&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;New York, NY&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-73.98658&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;40.73060&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;New York City, United States of America&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;plotting-the-tour-boring-version&#34;&gt;Plotting the tour, boring version&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll start by plotting the trips as it is done in the vignette, i.e. in a static way. Note: I used Dirk&amp;rsquo;s code in the Boris Johnson use case for the map, and &lt;a href=&#34;https://github.com/hrbrmstr/ggalt/issues/33&#34;&gt;had to use a particular branch of &lt;code&gt;ggalt&lt;/code&gt;&lt;/a&gt; to get &lt;code&gt;coord_proj&lt;/code&gt; working.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggalt&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggmap&amp;#34;&lt;/span&gt;)
world &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map_data&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(region &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Antarctica&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; paths, &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(long, lat)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_map&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; world, map &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; world, &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(long, lat, map_id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; region), 
           fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;white&amp;#34;&lt;/span&gt;, color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;darkgrey&amp;#34;&lt;/span&gt;, alpha &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.8&lt;/span&gt;, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.2&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_path&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(group &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; trip_id), color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#88398A&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; chapters_df, color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#88398A&amp;#34;&lt;/span&gt;, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.8&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_map&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;coord_proj&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;+proj=robin +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;R-Ladies global tour&amp;#34;&lt;/span&gt;, 
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;tour_length&lt;/span&gt;(result), &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; km&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-10-06-globalrladiestour/unnamed-chunk-8-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;&lt;/p&gt;
&lt;p&gt;Dirk told me the map would look better with great circles instead of straight lines so I googled a bit around, asked for help &lt;a href=&#34;https://twitter.com/ma_salmon/status/915515028702466048&#34;&gt;on Twitter&lt;/a&gt; before finding &lt;a href=&#34;http://strimas.com/spatial/long-flights/&#34;&gt;this post&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;geosphere&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# find points on great circles between chapters&lt;/span&gt;
gc_routes &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gcIntermediate&lt;/span&gt;(paths[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(chapters), &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;long&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lat&amp;#34;&lt;/span&gt;)],
                            paths&lt;span style=&#34;color:#06287e&#34;&gt;[&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(chapters)&lt;span style=&#34;color:#40a070&#34;&gt;+1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(chapters)), &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;long&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lat&amp;#34;&lt;/span&gt;)],
                            n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;360&lt;/span&gt;, addStartEnd &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;, sp &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;, 
                            breakAtDateLine &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
gc_routes &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;SpatialLinesDataFrame&lt;/span&gt;(gc_routes, 
                                   &lt;span style=&#34;color:#06287e&#34;&gt;data.frame&lt;/span&gt;(id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; paths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;id,
                                              stringsAsFactors &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;))
gc_routes_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;fortify&lt;/span&gt;(gc_routes)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_map&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; world, map &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; world, &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(long, lat, map_id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; region), 
           fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;white&amp;#34;&lt;/span&gt;, color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;darkgrey&amp;#34;&lt;/span&gt;, alpha &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.8&lt;/span&gt;, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.2&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_path&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; gc_routes_df, 
            &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(long, lat, group &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; group), alpha &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;, color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#88398A&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; chapters_df, color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#88398A&amp;#34;&lt;/span&gt;, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.8&lt;/span&gt;,
             &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(long, lat)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_map&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;coord_proj&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;+proj=robin +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs&amp;#34;&lt;/span&gt;)

p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;R-Ladies global tour&amp;#34;&lt;/span&gt;, 
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;tour_length&lt;/span&gt;(result), &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; km&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-10-06-globalrladiestour/unnamed-chunk-10-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-10&#34;&gt;&lt;/p&gt;
&lt;p&gt;Ok this is nicer, it was worth the search.&lt;/p&gt;
&lt;h1 id=&#34;plotting-the-tour-magical-version&#34;&gt;Plotting the tour, magical version&lt;/h1&gt;
&lt;p&gt;And now I&amp;rsquo;ll use &lt;code&gt;magick&lt;/code&gt; because I want to add a small star flying around the world. By the way if this global tour were to happen I reckon that one would need to donate a lot of money to rainforest charities or the like, because it&amp;rsquo;d have a huge carbon footprint! Too bad really, I don&amp;rsquo;t want my gif to promote planet destroying behaviours.&lt;/p&gt;
&lt;p&gt;To make the gif I used code similar to the one &lt;a href=&#34;https://masalmon.eu/2017/02/18/complot/&#34;&gt;shared in this post&lt;/a&gt; but in a better version thanks to Jeroen who told me to &lt;a href=&#34;https://cran.r-project.org/web/packages/magick/vignettes/intro.html#animated_graphics&#34;&gt;read the vignette again&lt;/a&gt;. Not saving PNGs saves time!&lt;/p&gt;
&lt;p&gt;I first wanted to really show the emoji flying along the route and even created data for that, with a number of rows between chapters proportional to the distance between them. It&amp;rsquo;d have looked nice and smooth. But making a gif with hundreds of frames ended up being too long for me at the moment. So I came up with another idea, I&amp;rsquo;ll have to hope you like it!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;emojifont&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;load.emojifont&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;OpenSansEmoji.ttf&amp;#39;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magick&amp;#34;&lt;/span&gt;)

plot_one_moment &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(chapter, size, p,
                            chapters_df){
 
&lt;span style=&#34;color:#06287e&#34;&gt;print&lt;/span&gt;(p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;R-Ladies global tour, &amp;#34;&lt;/span&gt;,
                 chapters_df[chapters_df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;chapter &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; chapter,]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;chapter), 
          subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;tour_length&lt;/span&gt;(result), &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; km&amp;#34;&lt;/span&gt;))&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
    &lt;span style=&#34;color:#06287e&#34;&gt;geom_text&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; chapters_df[chapters_df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;chapter &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; chapter,], 
            &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; long, 
                y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lat,
                label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;emoji&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;star2&amp;#34;&lt;/span&gt;)),
            family&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;OpenSansEmoji&amp;#34;&lt;/span&gt;,
                size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; size))


}

img &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;image_graph&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1000&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;800&lt;/span&gt;, res &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;96&lt;/span&gt;)
out &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;walk2&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(chapters&lt;span style=&#34;color:#06287e&#34;&gt;[as.integer&lt;/span&gt;(result)], each &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;),
                   &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;), length &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(chapters)&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;),
                   p &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; p,
     plot_one_moment,
      chapters_df &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; chapters_df) 
&lt;span style=&#34;color:#06287e&#34;&gt;dev.off&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## png 
##   2
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_animate&lt;/span&gt;(img, fps&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rladiesglobal.gif&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/rladiesglobal.gif&#34; alt=&#34;r-ladies global tour&#34; width=&#34;700&#34;&gt;
&lt;p&gt;At least I made a twinkling star. I hope Hannah will be happy with the gif, because now I&amp;rsquo;d like to just dream of potential future trips! Or learn a bit of geography by looking at the gif.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>The Guardian Experience: heavy or light topics?</title>
      <link>https://masalmon.eu/2017/10/02/guardian-experience/</link>
      <pubDate>Mon, 02 Oct 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/10/02/guardian-experience/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve recently been binge-reading The Guardian Experience columns. I&amp;rsquo;m a big fan of The Guardian life and style section regulars: the &lt;a href=&#34;https://www.theguardian.com/lifeandstyle/series/blind-date&#34;&gt;blind dates&lt;/a&gt; to which I dedicated &lt;a href=&#34;https://masalmon.eu/2017/03/07/blinddates/&#34;&gt;a blog post&lt;/a&gt;, Oliver Burkeman&amp;rsquo;s &lt;a href=&#34;https://www.theguardian.com/lifeandstyle/series/thiscolumnwillchangeyourlife&#34;&gt;This column will change your life&lt;/a&gt;, etc. &lt;a href=&#34;https://www.theguardian.com/lifeandstyle/series/experience&#34;&gt;Experience&lt;/a&gt; is another regular that I enjoy a lot. In each of the column, someone tells something remarkable that happened to them. It can really be anything.&lt;/p&gt;
&lt;p&gt;I was thinking of maybe scraping the titles and get a sense of most common topics. The final push was my husband&amp;rsquo;s telling me about &lt;a href=&#34;https://www.thecut.com/2017/09/10-best-guardian-experience-columns.html&#34;&gt;this article&lt;/a&gt; of
Gabriella Paiella&amp;rsquo;s about the best Guardian Experience columns. She wrote &amp;ldquo;the “Experience” column does often touch on heavier topics&amp;rdquo;. Can one know what is the most prevalent &amp;ldquo;weight&amp;rdquo; of Experience columns scraping all their titles?&lt;/p&gt;
&lt;h1 id=&#34;experience-i-downloaded-all-the-titles-of-the-guardian-experience-columns&#34;&gt;Experience: I downloaded all the titles of The Guardian Experience columns&lt;/h1&gt;
&lt;p&gt;I learnt a lot about responsible (and elegant) webscraping from Bob Rudis, and decided to use the tool he mentioned &lt;a href=&#34;https://rud.is/b/2017/09/19/pirating-web-content-responsibly-with-r/&#34;&gt;in this blog post&lt;/a&gt;, the &lt;a href=&#34;https://github.com/ropenscilabs/robotstxt&#34;&gt;&lt;code&gt;robotstxt&lt;/code&gt; package&lt;/a&gt; which &amp;ldquo;makes it easy to check if bots (spiders, crawler, scrapers, &amp;hellip;) are allowed to access specific resources on a domain.&amp;rdquo;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;robotstxt&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;get_robotstxt&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.theguardian.com&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # this is the robots.txt file for theguardian.com
## 
## User-agent: *
## Disallow: /sendarticle/
## Disallow: /Users/
## Disallow: /users/
## Disallow: /*/print$
## Disallow: /email/
## Disallow: /contactus/
## Disallow: /share/
## Disallow: /websearch
## Disallow: /*?commentpage=
## Disallow: /whsmiths/
## Disallow: /external/overture/
## Disallow: /discussion/report-abuse/*
## Disallow: /discussion/report-abuse-ajax/*
## Disallow: /discussion/comment-permalink/*
## Disallow: /discussion/report-abuse/*
## Disallow: /discussion/user-report-abuse/*
## Disallow: /discussion/handlers/*
## Disallow: /discussion/your-profile
## Disallow: /discussion/your-comments
## Disallow: /discussion/edit-profile
## Disallow: /discussion/search/comments
## Disallow: /discussion/*
## Disallow: /search
## Disallow: /music/artist/*
## Disallow: /music/album/*
## Disallow: /books/data/*
## Disallow: /settings/
## Disallow: /embed/
## Disallow: /*styles/js-on.css$
## Disallow: /sport/olympics/2008/events/*
## Disallow: /sport/olympics/2008/medals/*
## Disallow: /f/healthcheck
## Disallow: /sections
## Disallow: /top-stories
## Disallow: /most-read/sport
## Disallow: /articles
## Disallow: /podcasts
## Disallow: /global$
## Disallow: /*/feedarticle/*
## Disallow: /travel/2013/aug/22/been-there-readers-competition?*
## Disallow: /preference/*
## Disallow: /59666047/
## Disallow: /print/
## Disallow: /info/tech-feedback
## Disallow: /production-monitoring/
## 
## User-agent: Mediapartners-Google
## Disallow:
## 
## Sitemap: http://www.theguardian.com/sitemaps/news.xml
## Sitemap: http://www.theguardian.com/sitemaps/video.xml
## 
## User-agent: bingbot
## Crawl-delay: 1
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;robotstxt&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;paths_allowed&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.theguardian.com/lifeandstyle/series/experience&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] TRUE
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If I understand the above correctly, I&amp;rsquo;m allowed to scrape the titles of the columns, great!&lt;/p&gt;
&lt;p&gt;I also noticed the crawl delay at the end of the robots.txt, of 1 second. Since I&amp;rsquo;ve decided to be a really nice scraper and also because I only have 29 pages to scrape in total, I&amp;rsquo;ll use a delay of 2 seconds between requests. In his post Bob says that if there is no indication, you should wait 5 seconds.&lt;/p&gt;
&lt;p&gt;After these checks, I started working on the scraping itself.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rvest&amp;#34;&lt;/span&gt;)

xtract_titles &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(node) {
  css &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;span[class=&amp;#34;js-headline-text&amp;#34;]&amp;#39;&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(node, css) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;html_text&lt;/span&gt;(trim &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
}


get_titles_from_page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(page_number){
  &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;)
  link &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.theguardian.com/lifeandstyle/series/experience?page=&amp;#34;&lt;/span&gt;, page_number)
  page_content &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;read_html&lt;/span&gt;(link)
  &lt;span style=&#34;color:#06287e&#34;&gt;xtract_titles&lt;/span&gt;(page_content)
}

experience_titles &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;29&lt;/span&gt;, get_titles_from_page) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;()
&lt;span style=&#34;color:#06287e&#34;&gt;save&lt;/span&gt;(experience_titles, file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-10-02-guardian-experience.RData&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;sample&lt;/span&gt;(experience_titles, &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;##  [1] &amp;quot;Experience: pregnancy sickness nearly killed me&amp;quot;            
##  [2] &amp;quot;Experience: I was a sperm donor for my friends&amp;quot;             
##  [3] &amp;quot;Experience: I was attacked in my front garden&amp;quot;              
##  [4] &amp;quot;I was brought up in the exclusive brethren&amp;quot;                 
##  [5] &amp;quot;Experience: I am Dancing Man&amp;quot;                               
##  [6] &amp;quot;The boy who missed the mainstream&amp;quot;                          
##  [7] &amp;quot;I still can&#39;t explain what I saw&amp;quot;                           
##  [8] &amp;quot;Experience: My twin rewrote my childhood&amp;quot;                   
##  [9] &amp;quot;Experience: I&#39;ve renewed my wedding vows more than 50 times&amp;quot;
## [10] &amp;quot;Experience: I talk with my eyes&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;See, these are really diverse topics! And I think this sample of 10 titles actually shows many heavy topics.&lt;/p&gt;
&lt;h1 id=&#34;experience-i-computed-the-most-frequent-words&#34;&gt;Experience: I computed the most frequent words&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll first remove the &amp;ldquo;Experience: &amp;quot; part of many titles, since it&amp;rsquo;s not exactly the most interesting word.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;experience_titles &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(experience_titles, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;^Experience: &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then unnested words. Interestingly in order to remember how to do this I went and read &lt;a href=&#34;https://masalmon.eu/2017/03/07/blinddates/&#34;&gt;my Guardian blind dates post&lt;/a&gt; (the &amp;ldquo;So what did they talk about?&amp;rdquo; part).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidytext&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rcorpora&amp;#34;&lt;/span&gt;)

stopwords &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;corpora&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;words/stopwords/en&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;stopWords

words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; experience_titles) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(word, title) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;word &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; stopwords) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(word, sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(words[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;word&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;years&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;fell&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;lost&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saved&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;life&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;man&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;baby&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;killed&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;survived&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;car&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;daughter&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;love&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;father&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;friend&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;husband&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;birth&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;dad&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;married&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;attacked&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;days&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In my opinion this list of the most common words support my feeling topics are often heavy, but I also think it might be because there are many, many different words that can describe a light topic while well death will be primarily described by &amp;ldquo;killed&amp;rdquo;. Could sentiment analysis of the titles help me?&lt;/p&gt;
&lt;h1 id=&#34;experience-i-computed-the-sentiment-of-titles&#34;&gt;Experience: I computed the sentiment of titles&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;afinn &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_sentiments&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;afinn&amp;#34;&lt;/span&gt;)

sentiment &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; experience_titles) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(saved_title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; title) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(word, title) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;inner_join&lt;/span&gt;(afinn) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(saved_title) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(sentiment &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sum&lt;/span&gt;(score)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(sentiment))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(sentiment[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;saved_title&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;sentiment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;‘I stopped a terrorist attack’&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;a coup interrupted our wedding&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A great white shark ate my leg&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;a head injury made me a musical prodigy&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;a ladybird nearly killed me&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A machine keeps me alive&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A six-metre wall collapsed on top of me&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Becoming homeless helped me find love&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Being obese made me feel like a social outcast&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Blind date&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(sentiment) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_bar&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(sentiment)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum_rc&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-10-02-guardian-experience/unnamed-chunk-9-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-9&#34;&gt;&lt;/p&gt;
&lt;p&gt;Honestly, I think sentiment analysis didn&amp;rsquo;t help much here: the titles are too short, and the sample presented above is not very convincing. Moreoever, would the sentiment reveal the dramatic intensity of light vs. heavy, anyway?&lt;/p&gt;
&lt;h1 id=&#34;experience-i-tried-using-machine-learning-to-derive-a-topic-from-the-title&#34;&gt;Experience: I tried using machine learning to derive a topic from the title&lt;/h1&gt;
&lt;p&gt;In the following I&amp;rsquo;ll use &lt;a href=&#34;https://github.com/ropensci/monkeylearn&#34;&gt;my own &lt;code&gt;monkeylearn&lt;/code&gt; package&lt;/a&gt; and in particular &lt;a href=&#34;https://app.monkeylearn.com/main/classifiers/cl_5icAVzKR/&#34;&gt;this topic classifier&lt;/a&gt; without too much hope since I&amp;rsquo;m feeding it a title, not a whole article.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;topics &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; monkeylearn&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;monkeylearn_classify&lt;/span&gt;(experience_titles,
                                            classifier_id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cl_5icAVzKR&amp;#34;&lt;/span&gt;)

titles &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; experience_titles,
                         text_md5 &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(experience_titles, digest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;digest, algo &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;md5&amp;#34;&lt;/span&gt;))

titles &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;inner_join&lt;/span&gt;(titles, topics, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;text_md5&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s a sample of the results after an arbitrary filtering based on probability:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;titles &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(titles, probability &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;sample_n&lt;/span&gt;(titles, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(title, label, probability) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;title&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;label&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;probability&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;my family was attacked by lions&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Land Mammals&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.680&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Muhammad Ali was my mentor&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Religion &amp;amp; Spirituality&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.681&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I&amp;rsquo;m a championship arm-wrestler&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Entertainment &amp;amp; Recreation&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.873&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I lit my father&amp;rsquo;s funeral pyre&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Relationships&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.603&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I have sudden death syndrome&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Health &amp;amp; Medicine&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.816&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;One drink and I&amp;rsquo;m dead&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Food &amp;amp; Drink&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.511&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I was a compulsive gambler&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Mental health&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.805&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I flew the English Channel using a bunch of balloons&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aircraft&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.828&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I crushed my £1m violin&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Humanities&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.625&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I crashed into the North Sea&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Travel&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.549&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I said yes to marriage the first time we met&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Society&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.775&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I can fly&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aircraft&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.930&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;We were told our son has cystic fibrosis – he hasn&amp;rsquo;t&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Special Occasions&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.511&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I found out I&amp;rsquo;m not my son&amp;rsquo;s father&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Society&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.521&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I became a famous artist at the age of 94&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Music&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.673&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I was impaled while pregnant&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Mental health&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.548&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A great white shark ate my leg&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Animals&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.656&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;The holiday capsule wardrobe&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Accommodation&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.761&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I don&amp;rsquo;t wear shoes&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Beauty &amp;amp; Style&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.798&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;I became a famous artist at the age of 94&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Art&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.531&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Note that after this filtering I had at least one topic for 288 titles. I don&amp;rsquo;t think this classification is really useful either but at least it&amp;rsquo;s fun to look at the proposed topic. What are the most frequent ones?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;titles &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(label) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;(),
                   some &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(title[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;])) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;label&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;some&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Transportation&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;45&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I pulled a man from a burning car, I was hit by a car doing 101mph, a car crashed into me in the bath&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Relationships&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;36&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I’m a divorce party planner, a coup interrupted our wedding, my husband didn’t meet our daughter until she was 27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Society&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;32&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;my husband didn’t meet our daughter until she was 27, I first met my mother at a party, I was accused of having a sham marriage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Land Vehicles&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;30&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I pulled a man from a burning car, I was hit by a car doing 101mph, a car crashed into me in the bath&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Special Occasions&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I fell in love through Airbnb, I made peace with my daughter’s killer, I’ve been protesting for more than 60 years&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Animals&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;my dog rescues cats, I accidentally bought a giant pig, I was bitten by a shark&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Parenting&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I had a free birth, I saved a stranger’s life, We found a baby in a manger&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Travel&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a car crashed into me in the bath, I crashed into the North Sea, I saved my school bus from crashing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Land Mammals&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;my dog rescues cats, my cat saved me from a fire, I own the world’s ugliest dog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Health &amp;amp; Medicine&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I have sudden death syndrome, I am afraid of pregnancy, my anti-malaria drugs made me psychotic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;That, in a way, makes me more okay with the classification. I&amp;rsquo;ve always had the impression (you have to believe me) that many of the columns dealt with accidents, which corresponds to the transportation category, and families and relationships, and well animals, the ones &lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2010/oct/16/experience-shark-attack-paralympian&#34;&gt;that try to eat you&lt;/a&gt; or &lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2015/jun/12/experience-my-dog-stole-my-tractor&#34;&gt;that steal your tractor&lt;/a&gt;. But now does it help me judge whether the Experience columns deal with rather light or heavy topics? Hum, no.&lt;/p&gt;
&lt;h1 id=&#34;experience-i-could-not-really-answer-my-initial-question&#34;&gt;Experience: I could not really answer my initial question&lt;/h1&gt;
&lt;p&gt;So, it was fun, but I can&amp;rsquo;t really tell Gabriella Paiella whether she was right or wrong. One thing is sure, these columns are quite varied&amp;hellip; so everyone can find what they&amp;rsquo;re looking for, either a dramatic story or a funny one?&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>The music of Les Mills Body Pump, with Spotify data</title>
      <link>https://masalmon.eu/2017/10/01/bodypump/</link>
      <pubDate>Sun, 01 Oct 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/10/01/bodypump/</guid>
      <description>&lt;p&gt;I am a runner but also a Body Pump enthusiast. Body Pump is a group fitness class of the Les Mills company, in which you train different muscle groups using a weighted bar &amp;ndash; whose total weight you modulate with plates in order to adapt it to your fitness level and to the muscle group. Like R, Body Pump was created in New Zealand, what a wonderful country! Every three months, a new class is released, with new songs and choreographies. What doesn&amp;rsquo;t change is the muscle group trained in each of the 10 songs of each class.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve thought of analysing Body Pump data for a long time now but could never find what I was looking for, which was a dataset of number of &amp;ldquo;reps&amp;rdquo; by song, e.g. how many squats do you do in each squats song. Then I realized I could also play with other data, like a quite comprehensive list of songs used in releases. I decided to cross this information with information about style of the corresponding artist in Spotify. Here is what I came up with!&lt;/p&gt;
&lt;h1 id=&#34;track-1-track-list-cleaning&#34;&gt;Track 1: Track list cleaning&lt;/h1&gt;
&lt;p&gt;This I did listening to pop music, actually using my husband&amp;rsquo;s Deezer account. I downloaded data from &lt;a href=&#34;http://www.blogforumsupport.com/2008/bodypump2008.html&#34;&gt;this page&lt;/a&gt; which is quite exhaustive for many releases but well not formatted in a consistent way over releases, so I needed to be patient. A bit like when in the triceps track one does many half repetitions and feels one&amp;rsquo;s arms are going to fall off.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rvest&amp;#34;&lt;/span&gt;)
pg &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;http://www.blogforumsupport.com/2008/bodypump2008.html&amp;#34;&lt;/span&gt;
pg_content &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;read_html&lt;/span&gt;(pg, encoding &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;latin1&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;save&lt;/span&gt;(pg_content, file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/pg_content.RData&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I extracted the track lists, in a non very elegant way. Sometimes one just wants the job done&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
xtract_nodes &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(node, css) {
  &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(node, css) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;html_text&lt;/span&gt;(trim &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
}
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;xtract_nodes&lt;/span&gt;(pg_content, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;p&amp;#39;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tracks&lt;span style=&#34;color:#06287e&#34;&gt;[grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, tracks) &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;, tracks) &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;9&amp;#34;&lt;/span&gt;, tracks) &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;10&amp;#34;&lt;/span&gt;, tracks)]
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(tracks)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What follows is scripted manual correction of some mistakes in the data, or things that makes later extraction of title vs. artist a bit complicated.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, 
                               &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;04. Campione 2012 - DJ Flow05. 50 Ways to Say Goodbye - Train&amp;#34;&lt;/span&gt;,
                               &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;04. Campione 2012 - DJ Flow \n 05. 50 Ways to Say Goodbye - Train&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, 
                               &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Upion Havoc09. She&amp;#39;s so Mean&amp;#34;&lt;/span&gt;,
                               &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Upion Havoc \n 09. She&amp;#39;s so Mean&amp;#34;&lt;/span&gt;)

tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;07. How Deep Is Your Love -&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;07. How Deep Is Your Love - Calvin Harris&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;08 Bumble Bee -&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;08 Bumble Bee - Zedd &amp;amp; Botnek&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Young &amp;amp; Stupid -&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Young &amp;amp; Stupid - Travis Mills feat. T.I.&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Bpn Jovi&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; - Bon Jovi&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Damn-R&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Damn R&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Re-Dub&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Re Dub&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Boom-Lay Boom-Lay Boom&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Boom Lay Boom Lay Boom&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Hi-Tack&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Hi Tack&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\(Calvin Harris Remix\\) Fatboy Slim&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Fatboy Slim&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;B-Tastic&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;B Tastic&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;E-Nergy&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;E Nergy&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;In the Clear Six60&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;In the Clear - Six60&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Everybody Go! Vice&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Everybody Go! - Vice&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;My Love - feat. T.I. - Justin Timberlake&amp;#34;&lt;/span&gt;,
                               &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;My Love - Justin Timberlake feat. T.I.&amp;#34;&lt;/span&gt;)
 
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Original Release \\(PPCA\\)&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tracks[&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(tracks, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Get ready for what may be our fiercest release yet&amp;#34;&lt;/span&gt;)]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After doing this I lied on the floor drenched in sweat / created a &lt;code&gt;tibble&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(track &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; tracks)
tracks&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;release &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(tracks)&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that the release variable isn&amp;rsquo;t the actual release number, it&amp;rsquo;s more a time variable.&lt;/p&gt;
&lt;p&gt;At this stage I had one string by release, which I split in one string by track.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tracks&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;track &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(tracks&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;track, stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;str_split,
                     pattern &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\\n&amp;#34;&lt;/span&gt;, simplify &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)
tracks&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;track &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(tracks&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;track, unlist)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;unnest&lt;/span&gt;(tracks, track)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The next step was keeping only the 10 first tracks by release, ignoring bonus and alternative tracks listed at the end. It also involved removing useless strings that were not actually songs.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;              02. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;              03. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;              04. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;              05. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;              06. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;              07. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;              08. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;            08. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;              09. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;            09. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;              10. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;            10. &amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;          Calvin Harris&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;          Zedd &amp;amp; Botnek&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;          Travis Mills feat. T.I.&amp;#34;&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(tracks, release)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(tracks, song &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;())
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tracks, song &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;(tracks)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(tracks[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;release&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;track&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;song&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;01. Run Wild - Hardwell feat. Jake Reese&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;02. Go! (Vincent Price Remix) - Wolfpack &amp;amp; Avancada&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;03. Spoken Word - Chase &amp;amp; Status feat. George the Poet&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;04 .LRAD - Knife Party&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;05. Friday - PARRI&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;06. Jungle Youth - Young The Giant&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;07. Ocho Cinco - DJ Snake feat. Yellow Claw&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;08. Feel Your Love - Flux Pavilion &amp;amp; NGHTMRE feat. Jamie Lewis&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;09. Closer - The Chainsmokers feat. Halsey&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;10. Love On The Brain - Rihanna&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;After this I extracted the title and artist of each track. I&amp;rsquo;m not sure why I needed to change the encoding of the string for that, but before trying this solution I was bothered by there being different sorts of dashes and hyphens.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(tracks, track &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_trim&lt;/span&gt;(track))

split_title_artist &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(string, release){
  track &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; string
  &lt;span style=&#34;color:#06287e&#34;&gt;Encoding&lt;/span&gt;(string) &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;latin1&amp;#34;&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# avoid some issues later&lt;/span&gt;
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;â\u0080\u0099&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#39;&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ï¼\u0088&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;(&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;¼\u0089&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;`&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#39;&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;â\u0080¦&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;...&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;DÃ©jÃ&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Déjà&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Bbn Jovi&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;- Bon Jovi&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Marfia&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Mafia&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Diamond Eyes (Boom-Lay Boom-Lay Boom)&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Diamond Eyes (Boom Lay Boom Lay Boom)&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Studio-X&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Studio X&amp;#34;&lt;/span&gt;)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# hyphens/dashes&lt;/span&gt;
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;â\u0080\u0093&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;–&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;)
  string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\u0096&amp;#34;&lt;/span&gt;)
  both &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(string, pattern &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\u0096&amp;#34;&lt;/span&gt;,
                             simplify &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; both[1],
                artist &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; both[2], 
                release &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; release,
                track &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; track)
}

split_a_release &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(strings, release){
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(strings, split_title_artist, release)
}

tracks_si &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map2_df&lt;/span&gt;(tracks&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;track, tracks&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;release, split_a_release)
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(tracks, tracks_si, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;release&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;track&amp;#34;&lt;/span&gt;))
tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(tracks, title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;^[0-1]*[0-9]* *\\.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When the artist was in fact two artists, I kept only the first one which I assumed to be more informative of the style of the song.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;first_artist &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(artist){
  artist &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(artist, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\&amp;amp;.*$&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  first_artist &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(artist, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[fF]eat.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(first_artist, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Colourbox&amp;#34;&lt;/span&gt;)){
    first_artist &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Colourbox&amp;#34;&lt;/span&gt;
  }
  first_artist
}

tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(tracks, first_artist &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;first_artist&lt;/span&gt;(tracks&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;artist))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And I got there:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(tracks[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;release&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;track&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;song&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;title&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;artist&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;first_artist&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;01. Run Wild - Hardwell feat. Jake Reese&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Run Wild&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hardwell feat. Jake Reese&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hardwell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;02. Go! (Vincent Price Remix) - Wolfpack &amp;amp; Avancada&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Go! (Vincent Price Remix)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Wolfpack &amp;amp; Avancada&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Wolfpack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;03. Spoken Word - Chase &amp;amp; Status feat. George the Poet&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Spoken Word&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chase &amp;amp; Status feat. George the Poet&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;04 .LRAD - Knife Party&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LRAD&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Knife Party&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Knife Party&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;05. Friday - PARRI&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Friday&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;PARRI&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;PARRI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;06. Jungle Youth - Young The Giant&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Jungle Youth&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Young The Giant&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Young The Giant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;07. Ocho Cinco - DJ Snake feat. Yellow Claw&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ocho Cinco&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;DJ Snake feat. Yellow Claw&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;DJ Snake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;08. Feel Your Love - Flux Pavilion &amp;amp; NGHTMRE feat. Jamie Lewis&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Feel Your Love&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Flux Pavilion &amp;amp; NGHTMRE feat. Jamie Lewis&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Flux Pavilion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;09. Closer - The Chainsmokers feat. Halsey&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Closer&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;The Chainsmokers feat. Halsey&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;The Chainsmokers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;10. Love On The Brain - Rihanna&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Love On The Brain&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rihanna&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rihanna&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;track-2-spotify-data-downloading&#34;&gt;Track 2: Spotify data downloading&lt;/h1&gt;
&lt;p&gt;I dreamt of a database giving me the beats per minute, style, etc of each song. I didn&amp;rsquo;t get any information about the bpm but thanks to the Spotify API and &lt;a href=&#34;https://github.com/tiagomendesdantas/Rspotify&#34;&gt;this R package&lt;/a&gt; I was able to get information about the artists including their genres and popularity. For songs, the API does not give such information.&lt;/p&gt;
&lt;p&gt;Note: the &lt;code&gt;spotifyOAuth&lt;/code&gt; part of the following lines demands your first getting an Spotify API app client ID and secret as explained in the README of the package. I saved these as environment variables &lt;a href=&#34;http://stat545.com/bit003_api-key-env-var.html&#34;&gt;in my .Renviron&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Rspotify&amp;#34;&lt;/span&gt;)
keys &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;spotifyOAuth&lt;/span&gt;(app_id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;Sys.getenv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;SPOTIFY_APPID&amp;#34;&lt;/span&gt;),
                     client_id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;Sys.getenv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;SPOTIFY_CLIENTID&amp;#34;&lt;/span&gt;),
                     client_secret &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;Sys.getenv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;SPOTIFY_SECRET&amp;#34;&lt;/span&gt;))
get_and_wait &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(artist, keys){
  &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
  info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;searchArtist&lt;/span&gt;(artist, token &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; keys)
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.null&lt;/span&gt;(info)){
    info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; info[1,]
  }
  info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;first_artist &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; artist
  info
}

artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(tracks&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;first_artist), get_and_wait, keys)
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(artists_info, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/artists_info.csv&amp;#34;&lt;/span&gt;)

tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(tracks, artists_info, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;first_artist&amp;#34;&lt;/span&gt;)
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(tracks, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/tracks.csv&amp;#34;&lt;/span&gt;)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(artists_info[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;display_name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;id&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;popularity&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;followers&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;genres&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;type&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;first_artist&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Hardwell&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;6BrvowZBreEkXzJQMpL174&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;78&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1660846&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;big room,deep big room,dutch house,edm,electro house,progressive electro house,progressive house,tropical house&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;artist&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hardwell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Wolfpack&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;74ycentHh1YZrW5x4PLnox&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;54&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8554&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;crust punk,deep big room,sky room&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;artist&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Wolfpack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Chase &amp;amp; Status&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;3jNkaOXasoc7RsxdchvEVq&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;69&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;300912&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;brostep,deep groove house,drum and bass,edm,grime,house,tropical house&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;artist&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Knife Party&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2DuJi13MWHjRHrqRUwk8vH&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;64&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;529738&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;australian dance,big room,brostep,catstep,complextro,edm,electro house,electronic trap,moombahton,zapstep&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;artist&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Knife Party&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;PARRI$&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;17L4AvcA7zS5xdnLhemEMM&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;40&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7264&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;escape room&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;artist&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;PARRI&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I got a genres information for 209 out of 313 artists.&lt;/p&gt;
&lt;h1 id=&#34;track-3-making-sense-of-the-genres-of-artists&#34;&gt;Track 3: making sense of the genres of artists&lt;/h1&gt;
&lt;p&gt;As one sees above, each artist can have several genres and there are a ton of possible genres. When googling a bit about Spotify music genres, I found &lt;a href=&#34;http://everynoise.com/engenremap.html&#34;&gt;this gem of a webpage&lt;/a&gt;. Impressive! In my case, I wanted to have a few groups of musical genres in order to link them to the track, e.g. is there a musical genre more representative of the biceps track as opposed to other tracks?&lt;/p&gt;
&lt;p&gt;I decided to cluster the artists based on the binary variables for each genre. For this I used the &lt;code&gt;klaR::kmodes&lt;/code&gt; function because k-modes is a method for clustering based on categorical variables as opposed to k-means for instance. In work that I don&amp;rsquo;t present here, I played with 1) the number of clusters, looking at the resulting total sum of within-cluster differences and 2) the minimal number of artists that should have a genre for this genre to be included. For instance if a single artist has the style &amp;ldquo;francoton&amp;rdquo;, then I don&amp;rsquo;t want to use it for clustering. In the end, I was quite happy with 6 clusters and keeping only genres that occurred more than 10 times in the data. Doing this there were some artists I couldn&amp;rsquo;t cluster since they had only been described by very rare genres.&lt;/p&gt;
&lt;p&gt;Before clustering I had to transform the data a bit.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/artists_info.csv&amp;#34;&lt;/span&gt;)
artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(artists_info, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(display_name))
artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(artists_info, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; first_artist, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; followers)
artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(artists_info)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# most important word?&lt;/span&gt;
split_the_genres &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(genres){
  genres &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(genres, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;)
  genres
}

artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(artists_info, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(genres))
artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(artists_info, genre &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;split_the_genres&lt;/span&gt;(genres))
artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;unnest&lt;/span&gt;(artists_info, genre)
artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(artists_info, value &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;spread&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(artists_info), genre, value, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# &lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# keep only variables with more than 10 occurrence&lt;/span&gt;
sum_or_not &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x){
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.logical&lt;/span&gt;(x)){
    &lt;span style=&#34;color:#06287e&#34;&gt;sum&lt;/span&gt;(x) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;
  }else{
    &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;
  }
}
variables_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise_all&lt;/span&gt;(artists_info, sum_or_not)
artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; artists_info[,&lt;span style=&#34;color:#06287e&#34;&gt;as.logical&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;t&lt;/span&gt;(variables_info))]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(artists_info[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;display_name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;id&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;popularity&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;genres&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;type&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;alternative metal&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;big room&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;brostep&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;bubblegum dance&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;dance pop&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;deep big room&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;edm&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;electro house&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;eurodance&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;europop&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;modern rock&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;neo mellow&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;nu metal&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;pop&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;pop christmas&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;pop punk&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;pop rap&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;pop rock&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;post-grunge&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;post-teen pop&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;progressive electro house&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;progressive house&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;r&amp;amp;b&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;rock&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;tropical house&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;3 Doors Down&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2RTUTCvo6onsAnheUk3aL9&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;76&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;alternative metal,alternative rock,heavy christmas,nu metal,pop punk,pop rock,post-grunge,rap metal,rock&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;artist&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;3OH!3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;0FWzNDaEu9jdgcYTbcOa4F&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;68&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dance pop,electropowerpop,modern rock,pop,pop punk,pop rap,post-teen pop&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;artist&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Then the clustering happened.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
clustering &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; klaR&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kmodes&lt;/span&gt;(artists_info[, &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ncol&lt;/span&gt;(artists_info)], modes &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;)
clustering&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;size
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## cluster
##  1  2  3  4  5  6 
## 17 13 22 14 21 84
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;artists_info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;cluster &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; clustering&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;cluster
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(artists_info, cluster &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(display_name, genres) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;display_name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;genres&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Armin van Buuren&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;big room,edm,progressive house,progressive trance,trance,tropical house&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Avicii&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;big room,dance pop,edm,pop,tropical house&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Bob Sinclar&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;disco house,edm,filter house,house,tropical house,vocal house&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Calvin Harris&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;edm,electro house,house,pop,progressive house&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Chase &amp;amp; Status&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;brostep,deep groove house,drum and bass,edm,grime,house,tropical house&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;David Guetta&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dance pop,edm,pop,tropical house&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I then tried to characterize each cluster by its most important genre, well one of them. It&amp;rsquo;s as arbitrary as the rest of the clustering but I needed to summarize information anyway. I&amp;rsquo;d be glad to hear about other ideas for categorizing artists!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;get_most_important_genre &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
  counts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;t&lt;/span&gt;(dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize_all&lt;/span&gt;(df[, &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;ncol&lt;/span&gt;(df)&lt;span style=&#34;color:#40a070&#34;&gt;-1&lt;/span&gt;)], sum)))
  &lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(df)[6&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;ncol&lt;/span&gt;(df)&lt;span style=&#34;color:#40a070&#34;&gt;-1&lt;/span&gt;)]&lt;span style=&#34;color:#06287e&#34;&gt;[which&lt;/span&gt;(counts &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;max&lt;/span&gt;(counts))][1]
}

styles &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; artists_info &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;split&lt;/span&gt;(artists_info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;cluster) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(get_most_important_genre)

cluster_music &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(cluster &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;,
                                style &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; styles)

knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(cluster_music)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;cluster&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;style&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;edm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;big room&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dance pop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;alternative metal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;pop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;eurodance&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;track-4-plotting&#34;&gt;Track 4: Plotting&lt;/h1&gt;
&lt;p&gt;Once I had my categories for some artists, I was impatient to look at their proportions depending on the muscle group. I first prepared the data in order to have meaningful names for clusters and tracks.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;artists_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(artists_info, display_name, cluster, id, popularity,
                              genres)

tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(tracks, artists_info,
                           by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;display_name&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;popularity&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;genres&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;theme_set&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;theme_gray&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;18&lt;/span&gt;))
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;viridis&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)

track_muscle &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(song &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,
                               muscle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;warm-up&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;squats&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;chest&amp;#34;&lt;/span&gt;,
                                          &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;back&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;triceps&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;biceps&amp;#34;&lt;/span&gt;,
                                          &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lunges&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;shoulders&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;core&amp;#34;&lt;/span&gt;,
                                          &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cool-down&amp;#34;&lt;/span&gt;))

tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(tracks, track_muscle,
                           by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;song&amp;#34;&lt;/span&gt;)

tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(tracks,
                        muscle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; forcats&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;fct_reorder&lt;/span&gt;(muscle, song))


tracks &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(tracks, cluster_music, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cluster&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I first made a figure of the number of missing values i.e. missing cluster by muscle group. Sadly some muscle groups seem to have more missing values, hopefully the sample I do have for them is representative. Note that in total I have 42 releases.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tracks &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(muscle) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(prop_na &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sum&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(cluster))&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(muscle, prop_na)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Proportion of missing values&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(axis.text.x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;90&lt;/span&gt;, hjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, vjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-10-01-bodypump/unnamed-chunk-19-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-19&#34;&gt;&lt;/p&gt;
&lt;p&gt;And then I looked at the musical genres by muscle group.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tracks &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(cluster)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_bar&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(muscle, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; style),
           position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;fill&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(axis.text.x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;90&lt;/span&gt;, hjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, vjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-10-01-bodypump/unnamed-chunk-20-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-20&#34;&gt;&lt;/p&gt;
&lt;p&gt;So, is this interesting? I&amp;rsquo;m not exactly sure, ah! It seems that the shoulders track is associated with less pop or dance than the other tracks, maybe because overhead presses demand more rythm? Cool down does seem more quite with no electronic music (edm and big room) which makes sense. All in all, I was happy to see this plot but would like to have a better categorization of songs and well less missing values. I&amp;rsquo;m not a good musical analyst yet! Oh and I&amp;rsquo;d love to get data about beats per minute&amp;hellip; Maybe in a next release of this post, by me or one of you dear readers? Oh and if you want music that&amp;rsquo;s more quiet, check out &lt;a href=&#34;https://masalmon.eu/2017/04/30/radioedit/&#34;&gt;this post of mine about Radio Swiss Classic program&lt;/a&gt;!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Is it wine o&#39;clock?</title>
      <link>https://masalmon.eu/2017/08/12/wineoclock/</link>
      <pubDate>Sat, 12 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/08/12/wineoclock/</guid>
      <description>&lt;p&gt;Emojis were again quite &lt;em&gt;en vogue&lt;/em&gt; this week on Twitter with Romain François doing some &lt;a href=&#34;https://twitter.com/romain_francois/status/896364762124234752&#34;&gt;awesome stuff&lt;/a&gt; for the &lt;a href=&#34;https://github.com/hadley/emo&#34;&gt;&lt;code&gt;emo&lt;/code&gt; package&lt;/a&gt;, in particular this &lt;a href=&#34;https://twitter.com/romain_francois/status/896030932356005888&#34;&gt;teeny tiny animated clock&lt;/a&gt;. It reminded me of my own emoji animated clock that I had done a while ago for representing time-use data. Time for me to present its genesis!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m actually not a &lt;a href=&#34;https://en.wikipedia.org/wiki/Quantified_Self&#34;&gt;Quantified Self&lt;/a&gt; person, but at my work time-use data was collected &lt;a href=&#34;http://www.sciencedirect.com/science/article/pii/S1438463917301876&#34;&gt;for an epidemiology project&lt;/a&gt;: information about people activities and locations throughout one day can help unraveling sources of exposure to air pollution. I&amp;rsquo;ve therefore spent some time thinking about how to represent such data. In particular, my colleague &lt;a href=&#34;https://www.researchgate.net/profile/Margaux_Sanchez&#34;&gt;Margaux&lt;/a&gt; directed a &lt;a href=&#34;https://www.youtube.com/watch?v=LztOw_7MVPw&#34;&gt;fantastic video about our project&lt;/a&gt;. We introduced some real data from our project in it, including an animated clock that I made with emoji-coding of indoor-outdoor location. I&amp;rsquo;ll present code and data for producing a similar clock with my own agenda on some Wednesday evenings of last year.&lt;/p&gt;
&lt;h1 id=&#34;loading-the-time-use-data&#34;&gt;Loading the time-use data&lt;/h1&gt;
&lt;p&gt;I logged data from my Wednesday in a rather ok format.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
date &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2016-03-10&amp;#34;&lt;/span&gt;
activities &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv2&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-08-12-wineoclock-timeuse.csv&amp;#34;&lt;/span&gt;,
                               col_types &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ccc&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(start &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd_hms&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(date, start, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;:00&amp;#34;&lt;/span&gt;)),
         end &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd_hms&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(date, end, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;:00&amp;#34;&lt;/span&gt;)))
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(activities)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;start&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;end&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;activity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 07:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;coffee&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 07:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 08:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 08:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 09:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;train&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 09:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 17:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;computer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 17:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 18:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;train&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 18:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 20:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;school&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 20:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 20:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;pizza&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 20:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 22:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dancer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 22:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 22:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;wine_glass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 22:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 23:59:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;When I prepared this visualization &lt;a href=&#34;https://github.com/GuangchuangYu/ggimage&#34;&gt;&lt;code&gt;ggimage&lt;/code&gt;&lt;/a&gt; didn&amp;rsquo;t exist so I knew I&amp;rsquo;d have to use emojis from &lt;a href=&#34;https://github.com/GuangchuangYu/emojifont&#34;&gt;&lt;code&gt;emojifont&lt;/code&gt;&lt;/a&gt; to represent my activities, therefore I directly entered the activities as emojis. My Wednesdays at that time were quite varied, I started the day with breakfast (how original), then some time at the gym, followed by a rather short workday due to my taking a Catalan class at the end of the afternoon. The evening was spent enjoying a quick and cheap pizza dinner with my husband before our salsa class and sometimes treating ourselves to a wine glass at the small and rather shabby-looking bar at the end of our street, whose name really was Small bar.&lt;/p&gt;
&lt;h2 id=&#34;making-the-animated-clock&#34;&gt;Making the animated clock&lt;/h2&gt;
&lt;p&gt;I didn&amp;rsquo;t have to think about how to draw and animated a clock with &lt;code&gt;ggplot2&lt;/code&gt; because somebody already had: I used code &lt;a href=&#34;https://gist.github.com/drewconway/1142938&#34;&gt;from this gist&lt;/a&gt; of &lt;a href=&#34;https://twitter.com/drewconway&#34;&gt;Drew Conway&amp;rsquo;s&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Generate digitial clock face&lt;/span&gt;
first_nine &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;00&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;01&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;02&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;03&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;04&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;05&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;06&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;07&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;08&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;09&amp;#39;&lt;/span&gt;)
hours &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(first_nine, &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;23&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)))
mins &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(first_nine, &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;59&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)))
time_chars_l &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(hours, &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(h) &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(h, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;:&amp;#39;&lt;/span&gt;, mins, sep&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;))
time_chars &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;do.call&lt;/span&gt;(c, time_chars_l)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Generate analog clock face&lt;/span&gt;
hour_pos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;60&lt;/span&gt;))[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;720&lt;/span&gt;]
min_pos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;60&lt;/span&gt;)[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;60&lt;/span&gt;]
hour_pos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(hour_pos, &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;)
all_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tbl_df&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;cbind&lt;/span&gt;(hour_pos, min_pos)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(index &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; time_chars) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(time &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd_hms&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(date, index, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;:00&amp;#34;&lt;/span&gt;))) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then needed to join the &lt;code&gt;all_times&lt;/code&gt; table, containing many snapshots of the time, with my time-use table made of intervals (start and end of each activity). Another package born in the meantime, &lt;a href=&#34;https://github.com/dgrtwo/fuzzyjoin&#34;&gt;&lt;code&gt;fuzzyjoin&lt;/code&gt;&lt;/a&gt;, would have allowed me to write more efficient code, and I was so sad when looking at the old code that I re-wrote it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;all_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(all_times, start &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; time, end &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; time)
all_times  &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; fuzzyjoin&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;interval_left_join&lt;/span&gt;(all_times, activities)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(all_times[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;hour_pos&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;min_pos&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;index&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;time&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;start.x&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;end.x&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;start.y&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;end.y&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;activity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0.0000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:00:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0.0166667&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;00:01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:01:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:01:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:01:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0.0333333&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;00:02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:02:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:02:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:02:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0.0500000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;00:03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:03:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:03:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:03:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0.0666667&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.8&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;00:04&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:04:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:04:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:04:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0.0833333&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;00:05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:05:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:05:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:05:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0.1000000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;00:06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:06:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:06:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:06:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0.1166667&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;00:07&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:07:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:07:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:07:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0.1333333&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;00:08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:08:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:08:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:08:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0.1500000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.8&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;00:09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:09:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:09:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 00:09:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-03-10 06:30:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sleeping&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Then I could continue using the code &lt;a href=&#34;https://gist.github.com/drewconway/1142938&#34;&gt;from the gist&lt;/a&gt;, this step generating stuff for the two clock hands.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;all_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; all_times &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; start.x, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; end.x, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; start.y, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; end.y) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;gather&lt;/span&gt;(name, time.info, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(index) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(hands &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(name &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hour_pos&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I decided to only plot a subset of my exciting day.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;all_times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(all_times, 
                           time &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd_hms&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2016-03-10 15:00:00&amp;#34;&lt;/span&gt;),
                           time &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd_hms&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2016-03-10 23:00:00&amp;#34;&lt;/span&gt;) )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Last but not least, I plotted the clock. Nowadays I&amp;rsquo;d probably stick to &lt;a href=&#34;https://github.com/ropensci/magick&#34;&gt;&lt;code&gt;magick&lt;/code&gt;&lt;/a&gt; for animating the plot but &lt;a href=&#34;https://github.com/dgrtwo/gganimate&#34;&gt;&lt;code&gt;gganimate&lt;/code&gt;&lt;/a&gt; is awesome too anyway.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
emojifont&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;load.emojifont&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;OpenSansEmoji.ttf&amp;#39;&lt;/span&gt;)
clock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(all_times, &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(xmin &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; time.info,
                               xmax &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; time.info &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.03&lt;/span&gt;, 
                               ymin &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,
                               ymax &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; hands,
                              frame &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; index))
clock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; clock &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;geom_rect&lt;/span&gt;()
clock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; clock &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;theme_bw&lt;/span&gt;()
clock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; clock &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;coord_polar&lt;/span&gt;()
clock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; clock &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;scale_x_continuous&lt;/span&gt;(limits &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;), 
                                    breaks &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;11&lt;/span&gt;,
                     labels &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;11&lt;/span&gt;))
clock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; clock &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;scale_y_continuous&lt;/span&gt;(limits&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;1.1&lt;/span&gt;)) 
clock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; clock &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;coord_polar&lt;/span&gt;()
clock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; clock &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;geom_text&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,
                               y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,
                               label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; emojifont&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;emoji&lt;/span&gt;(activity)),
                          family&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;OpenSansEmoji&amp;#34;&lt;/span&gt;, 
                          size&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;)
clock &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; clock &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(legend.position&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;,
                      axis.text.y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_blank&lt;/span&gt;(),
                      axis.ticks.y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_blank&lt;/span&gt;(),
                      axis.title.y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_blank&lt;/span&gt;(),
                      axis.title.x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_blank&lt;/span&gt;(),
                      panel.background &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_blank&lt;/span&gt;(),
                      panel.border &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_blank&lt;/span&gt;(),
                      panel.grid.major &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_blank&lt;/span&gt;(),
                      panel.grid.minor &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_blank&lt;/span&gt;(),
                      plot.background &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_blank&lt;/span&gt;())

animation&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ani.options&lt;/span&gt;(interval &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.025&lt;/span&gt;)
gganimate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;gganimate&lt;/span&gt;(clock, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;clock.gif&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/clock.gif&#34; alt=&#34;clock&#34; width=&#34;700&#34;&gt;
&lt;p&gt;I ended up with a very useful visualization as you can see&amp;hellip; at least, I have no trouble finding out when wine o&amp;rsquo;clock is!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Pets or livestock? Naming your RMarkdown chunks</title>
      <link>https://masalmon.eu/2017/08/08/chunkpets/</link>
      <pubDate>Tue, 08 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/08/08/chunkpets/</guid>
      <description>&lt;p&gt;Today I made a &lt;a href=&#34;https://twitter.com/ma_salmon/status/894877595417948160&#34;&gt;confession on Twitter&lt;/a&gt;: I told the world I had spent my whole career not naming chunks in RMarkdown documents. Even if I had said one should name them when teaching RMarkdown. But it was also a tweet for showing off since I was working on the first manuscript with named chunks and loving it. I got some interesting reactions to my tweet, including &lt;a href=&#34;https://twitter.com/thomasp85/status/894882639303368705&#34;&gt;one that made me feel better about myself&lt;/a&gt; (sorry Thomas), and other ones that made me feel like phrasing why one should name RMarkdown chunks.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/hadleywickham/status/894889893922459648&#34;&gt;Hadley Wickham asked&lt;/a&gt; whether chunks were pets or livestock, as in &lt;a href=&#34;https://twitter.com/mikeksmith/status/857583637465878528&#34;&gt;his analogy for models&lt;/a&gt;. Livestock chunks are identified by numbers, not names, in the case of chunks defined by position. I now think we have good reason to consider them as pets and here&amp;rsquo;s why&amp;hellip;&lt;/p&gt;
&lt;img src=&#34;https://masalmon.eu/figure/source/2017-08-08-chunkpets/running.png&#34; alt=&#34;gestation&#34; width=&#34;600&#34;&gt;
&lt;p&gt;&lt;em&gt;My fur sibling does come if you call him&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Navigating the RMarkdown document. You can yell a dog&amp;rsquo;s name and it&amp;rsquo;ll come to you. Well hopefully&amp;hellip; In any case in RStudio you can actually navigate named chunks fairly easily.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Making your RMarkdown easier to understand. Even if you comment code, having an informative code chunk name will help your collaborators when they read your file. For that, the chunk names should reflect what&amp;rsquo;s being done in them, not your creativity, keep that for your real pets or kids. Naming the chunks has moreover made me divide my code into chunks doing one thing, e.g. preparing the data, then fitting a model. David Robinson &lt;a href=&#34;https://twitter.com/drob/status/738786604731490304&#34;&gt;suggested&lt;/a&gt; naming chunks such as to make dependencies more explicit, and the thread contains some nice tips about automatic dependencies between chunks, something I need to explore more myself (thanks &lt;a href=&#34;https://twitter.com/nj_tierney&#34;&gt;Nick&lt;/a&gt; for providing me with this tweet link!). &lt;a href=&#34;https://yihui.name/knitr/options/#chunk-options&#34;&gt;Don&amp;rsquo;t use spaces or dots in chunk labels&lt;/a&gt;, and Nick even says not to use &amp;ldquo;_&amp;rdquo; but rather &amp;ldquo;-&amp;rdquo; because it makes names navigation easier at least on Mac.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;img src=&#34;https://masalmon.eu/figure/source/2017-08-08-chunkpets/chunkdown.png&#34; alt=&#34;gestation&#34; width=&#34;600&#34;&gt;
&lt;p&gt;&lt;em&gt;Chunk down! Don&amp;rsquo;t worry, Mowgli was just taking a nap.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Reading error reports or progress of knitting. It&amp;rsquo;s much easier to find which chunk exactly is down, or to see how well knitting is going, with chunk names.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Moving chunks around, &lt;a href=&#34;https://twitter.com/robjhyndman/status/894886426885578752&#34;&gt;adding some&lt;/a&gt;. In particular, cache results are saved by chunk name or position, so caching is more efficient with named chunks. With unnamed chunks you might end up unwillingly re-running that long slow chunk!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;img src=&#34;https://masalmon.eu/figure/source/2017-08-08-chunkpets/cool.png&#34; alt=&#34;gestation&#34; width=&#34;600&#34;&gt;
&lt;p&gt;&lt;em&gt;When you&amp;rsquo;re cool and you know it&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/pallavipnt/status/894894067179335681&#34;&gt;Feeling organized&lt;/a&gt; (no shame, Pallavi!) and empowered. And boasting on Twitter.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Truth be told maybe I won&amp;rsquo;t always name my chunks, e.g. in blog posts, but for manuscripts and other bigger projects I think it&amp;rsquo;s the way to go. And now I need to go read more about &lt;code&gt;autodep&lt;/code&gt; in &lt;code&gt;knitr&lt;/code&gt;, at least to distract myself for missing my fur sibling too much!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Who are the Swedish radio P1 summer guests? Answer via Wikidata</title>
      <link>https://masalmon.eu/2017/08/06/p1/</link>
      <pubDate>Sun, 06 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/08/06/p1/</guid>
      <description>&lt;p&gt;This week, a &lt;a href=&#34;https://eric.netlify.com/&#34;&gt;very promising new R blog&lt;/a&gt; was launched, namely the blog of Eric Persson a.k.a as &lt;a href=&#34;https://twitter.com/expersso&#34;&gt;expersso on Twitter&lt;/a&gt;. I had really been looking forward to this because expersso&amp;rsquo;s code screenshots have always been &lt;a href=&#34;https://twitter.com/expersso/status/870661615989002240&#34;&gt;quite cool&lt;/a&gt;, so seeing his no longer being limited to them is awesome! His first articles series is about a game, you should really &lt;a href=&#34;https://eric.netlify.com/2017/08/04/implementing-nim-in-r/&#34;&gt;check it out&lt;/a&gt;. (&lt;em&gt;PSA: if you post screenshots of R code on Twitter, have a look at Sean Kross&amp;rsquo; &lt;a href=&#34;https://github.com/ropenscilabs/codefinch&#34;&gt;&lt;code&gt;codefinch&lt;/code&gt; package&lt;/a&gt;!&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Because I&amp;rsquo;m a nosy person I asked Eric whether he was Swedish, his last name being quite Swedish-looking in my opinion. He is, which made me wonder about Swedish blog topics and actually decided to use one Swedish topic I came up with, the &lt;a href=&#34;http://sverigesradio.se/sida/artikel.aspx?programid=2071&amp;amp;artikel=4833403&#34;&gt;summer guests of the Swedish radio P1&lt;/a&gt;! Every summer since 1959, P1 selects a bunch of famous or interesting people and have them record a bit more than one hour program where they&amp;rsquo;re free to discuss what they want (important events of their life for instance) and to choose the musical breaks (which you don&amp;rsquo;t get to listen entirely to in the online version because of copyright stuff). The program is then broadcasted in the summer, one guest a day from the end of June to the beginning of August. There&amp;rsquo;s even a winter version now but I&amp;rsquo;ll ignore it because it&amp;rsquo;s too hot here in Barcelona to even think about winter.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a very cool radio program in my opinion. I discovered it at the end of my 5-month research stay in Gothenburg in 2010 and decided it&amp;rsquo;d be one way to keep my Swedish skills up to date (my other methods include listening to ABBA in Swedish and reading Camilla Läckberg&amp;rsquo;s novels). I haven&amp;rsquo;t listened to that many guests but I really enjoy it when I do, and I like how diverse the list of guests is. In this post, I&amp;rsquo;ll actually try to have a look at the occupations of the guests via Wikidata!&lt;/p&gt;
&lt;h1 id=&#34;how-to-get-the-data&#34;&gt;How to get the data?&lt;/h1&gt;
&lt;p&gt;In order to answer my question I needed a list of all summer guests, and their occupations. I first thought I&amp;rsquo;d resort to webscraping P1 website, which would have been a good way to provide expersso with an opportunity to give me some &lt;a href=&#34;https://twitter.com/expersso/status/839395958316232704&#34;&gt;constructive&lt;/a&gt; &lt;a href=&#34;https://twitter.com/expersso/status/893530164482756609&#34;&gt;feedback&lt;/a&gt;. However after websurfing a bit to assess my options, I realized I could use Wikipedia data obtained through APIs rather than &lt;a href=&#34;https://masalmon.eu/2017/02/12/wikideaths3_scraping/&#34;&gt;webscraping as in my posts about famous dead people&lt;/a&gt;. Here was my strategy.&lt;/p&gt;
&lt;h2 id=&#34;getting-the-list-of-all-summer-guests-from-1959&#34;&gt;Getting the list of all summer guests from 1959&lt;/h2&gt;
&lt;p&gt;I downloaded the table of all summer guests from 1959 from &lt;a href=&#34;http://sverigesradio.se/sida/artikel.aspx?programid=2071&amp;amp;artikel=4833403&#34;&gt;this page&lt;/a&gt;, which gave me their names and the dates of their episode(s) &amp;ndash; yeah some people are invited back.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# all summer guests&lt;/span&gt;
sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/p1sommar.csv&amp;#34;&lt;/span&gt;, col_names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;, 
                                 locale &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;locale&lt;/span&gt;(encoding &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;latin1&amp;#34;&lt;/span&gt;))
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(sommargaester[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;X1&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;X2&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;X3&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;X4&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;X5&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;X6&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;X7&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Aaro,Lars-Eric&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;110714&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Abdelhadi,Magdi&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;070809&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;120716&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Abdulle,Sherihan &amp;lsquo;Cherrie&amp;rsquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;170706&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Abele,Anton&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;130725&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Abenius,Folke&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;800627&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Abrahamson,Kjell-Albin&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;880809&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Ackebo,Lena&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;970708&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Adami,Zanyar&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;060707&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Adamo,Amelia&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;860806&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;870718&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;080701&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Adams,Maud&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;920703&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;070805&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get their names&lt;/span&gt;
sommargaester_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(sommargaester&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;X1)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# for putting names in the right order for later queries&lt;/span&gt;
transform_name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(name){
  &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;,
                           simplify &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)[2],
        stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;,
                           simplify &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)[1])
}

pretty_sommargaester_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(sommargaester_names, transform_name)
sommargaester_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; pretty_sommargaester_names,
                                      X1 &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; sommargaester_names)
sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(sommargaester, sommargaester_names,
                                  by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;X1&amp;#34;&lt;/span&gt;)

sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(sommargaester, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; X1)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# transform the date&lt;/span&gt;
sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;gather&lt;/span&gt;(sommargaester, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rep&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;date&amp;#34;&lt;/span&gt;, X2&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;X7)
sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(sommargaester, name)
sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(sommargaester, rep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;())
sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;(sommargaester)

sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(sommargaester, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(date))
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# remove winter&lt;/span&gt;
sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(sommargaester, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(date, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;V&amp;#34;&lt;/span&gt;))
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# remove repeat episodes&lt;/span&gt;
sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(sommargaester, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(date, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;R&amp;#34;&lt;/span&gt;))


&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# transform the date to a format with a non ambiguous year&lt;/span&gt;
sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(sommargaester, date &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(date))
sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(sommargaester, date &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(date &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;180000&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;19&amp;#34;&lt;/span&gt;, date),
                                                            &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(date &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;100000&lt;/span&gt;,
                                                                   &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;, date),
                                                                   &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;20&amp;#34;&lt;/span&gt;, date))))
sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(sommargaester, pretty_date &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(date))

knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(sommargaester[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;rep&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;date&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;pretty_date&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars-Eric Aaro&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;20110714&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2011-07-14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Magdi Abdelhadi&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;20070809&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2007-08-09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Sherihan &amp;lsquo;Cherrie&amp;rsquo; Abdulle&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;20170706&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-07-06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Anton Abele&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;20130725&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-07-25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Folke Abenius&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;19800627&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1980-06-27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Kjell-Albin Abrahamson&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;19880809&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1988-08-09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lena Ackebo&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;19970708&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1997-07-08&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Zanyar Adami&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;20060707&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2006-07-07&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Amelia Adamo&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;19860806&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1986-08-06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Maud Adams&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;19920703&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1992-07-03&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;getting-wikidata-about-the-summer-guests&#34;&gt;Getting Wikidata about the summer guests&lt;/h2&gt;
&lt;p&gt;Then I read the &lt;a href=&#34;https://people.wikimedia.org/~bearloga/notes/r-pkgs.html&#34;&gt;list of Wikipedia R packages&lt;/a&gt; put together by &lt;a href=&#34;https://twitter.com/bearloga&#34;&gt;Mikhail Popov&lt;/a&gt;, data scientist at the Wikimedia foundation with whom I exchanged a few messages after my Wikipedia deaths posts. These packages were either created by him or by &lt;a href=&#34;https://twitter.com/awrno&#34;&gt;Oliver Keyes&lt;/a&gt; and really give you access to plenty of structured data so I was happy to at last give the list a try!&lt;/p&gt;
&lt;p&gt;I used &lt;a href=&#34;https://github.com/bearloga/WikidataQueryServiceR&#34;&gt;&lt;code&gt;WikidataQueryServiceR&lt;/code&gt;&lt;/a&gt; to access &lt;a href=&#34;https://www.wikidata.org/wiki/Wikidata:Introduction&#34;&gt;Wikidata&lt;/a&gt; via the query language &lt;code&gt;SPARQL&lt;/code&gt;. Luckily I didn&amp;rsquo;t need to actually learn &lt;code&gt;SPARQL&lt;/code&gt;, I used the first example of the documentation, getting Douglas Adams&amp;rsquo; data and played with &lt;a href=&#34;https://query.wikidata.org/&#34;&gt;this online query tool&lt;/a&gt; to see how I could modify it to 1) obtain data in Swedish because Swedish Wikipedia is probably more complete about Swedish people and 2) obtain data about the summer guests, not Douglas Adams. For that second point I needed the item ID of each summer guests which I queried via another R package, &lt;a href=&#34;https://github.com/Ironholds/WikidataR&#34;&gt;&lt;code&gt;WikidataR&lt;/code&gt;&lt;/a&gt;. I could have modified the &lt;code&gt;SPARQL&lt;/code&gt; even more since I wouldn&amp;rsquo;t be using picture information but I wasn&amp;rsquo;t in a very perfectionist mood.&lt;/p&gt;
&lt;p&gt;Doing all of this I only scraped the surface of the possibilities offered by the Wikipedia-related R packages and can already tell one could do a bunch of exciting analyses with them!&lt;/p&gt;
&lt;p&gt;Note that I used &lt;a href=&#34;https://rud.is/b/2017/04/23/decomposing-composers-with-r/&#34;&gt;Bob Rudis&amp;rsquo; code&lt;/a&gt; as an example of how to insert a progress bar which made me feel quite cool. I also inserted a pause of 1 second between calls to the APIs in order to be a good person. My function name however shows how uninspired I was for naming things.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# function for getting someone&amp;#39;s data&lt;/span&gt;
get_someone_data &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(name, pb &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;){
  &lt;span style=&#34;color:#06287e&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.null&lt;/span&gt;(pb)) pb&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tick&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;print&lt;/span&gt;()
  &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
  item &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; WikidataR&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;find_item&lt;/span&gt;(name, language &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sv&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# sometimes people have no Wikidata entry so I need this condition&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(item) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;){
    entity_code &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; item[[1]]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;id
    query &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt;  &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;PREFIX entity: &amp;lt;http://www.wikidata.org/entity/&amp;gt;
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     #partial results
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     SELECT ?propUrl ?propLabel ?valUrl ?valLabel ?picture
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     WHERE
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     {
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     hint:Query hint:optimizer &amp;#39;None&amp;#39; .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     {	BIND(entity:&amp;#34;&lt;/span&gt;,entity_code,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; AS ?valUrl) .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     BIND(\&amp;#34;N/A\&amp;#34; AS ?propUrl ) .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     BIND(\&amp;#34;identity\&amp;#34;@sv AS ?propLabel ) .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     }
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     UNION
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     {	entity:&amp;#34;&lt;/span&gt;, entity_code,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; ?propUrl ?valUrl .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     ?property ?ref ?propUrl .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     ?property rdf:type wikibase:Property .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     ?property rdfs:label ?propLabel
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     }
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     ?valUrl rdfs:label ?valLabel
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     FILTER (LANG(?valLabel) = &amp;#39;sv&amp;#39;) .
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     OPTIONAL{ ?valUrl wdt:P18 ?picture .}
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     FILTER (lang(?propLabel) = &amp;#39;sv&amp;#39; )
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     }
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     ORDER BY ?propUrl ?valUrl
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                     LIMIT 200&amp;#34;&lt;/span&gt;)
    results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; WikidataQueryServiceR&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;query_wikidata&lt;/span&gt;(query)
    results&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;name&lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; name
    results
  }else{
    &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
  }
   
  }

pb &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;progress_estimated&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(sommargaester&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;name)))
sommargaester_wiki &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(sommargaester&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;name),
                                    get_someone_data, pb&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;pb)

sommargaester &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(sommargaester, sommargaester_wiki, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;)

readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(sommargaester, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/p1_wiki_data.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(sommargaester[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;rep&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;pretty_date&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;propLabel&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;valLabel&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars-Eric Aaro&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2011-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;arbetsgivare&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LKAB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars-Eric Aaro&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2011-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;födelseort&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Vittangi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars-Eric Aaro&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2011-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;kön&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;man&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars-Eric Aaro&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2011-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;nationalitet&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Sverige&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars-Eric Aaro&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2011-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;instans av&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;människa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars-Eric Aaro&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2011-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;alma mater&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Luleå tekniska universitet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars-Eric Aaro&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2011-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;medlem av&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Kungliga Ingenjörsvetenskapsakademien&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars-Eric Aaro&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2011-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;förnamn&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lars&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars-Eric Aaro&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2011-07-14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;identity&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lars-Eric Aaro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Magdi Abdelhadi&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2007-08-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sysselsättning&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;journalist&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I get one line per guest and propriety value, sometimes some propriety labels have more than one value for the same person, e.g. if the person has several occupations (occupation = sysselsättning).&lt;/p&gt;
&lt;h2 id=&#34;translation-the-occupations&#34;&gt;Translation the occupations&lt;/h2&gt;
&lt;p&gt;This is the point at which I realized that maybe doing the search in English in the first place wouldn&amp;rsquo;t have made me get less data? Oh well. In any case for each possible occupation I can get an English translation which is awesome.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;occupation &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(sommargaester, propLabel &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sysselsättning&amp;#34;&lt;/span&gt;)
occupations &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(occupation&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;valLabel)
translate_occupation &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(occupation){
  job &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; WikidataR&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;find_item&lt;/span&gt;(occupation, language &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sv&amp;#34;&lt;/span&gt;)[[1]]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;label
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.null&lt;/span&gt;(job)){
    job &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
  }
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(job)
}
english_occupations &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(occupations, translate_occupation)
translations &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;data.frame&lt;/span&gt;(sysselsaettning &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; occupations,
                           occupation &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; english_occupations)
occupation &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(occupation, translations, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;valLabel&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sysselsaettning&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I guess it&amp;rsquo;s good to know that Wikidata has data in many languages because I can totally see it being useful as a sort of translation service.&lt;/p&gt;
&lt;h1 id=&#34;profiling-the-summer-guests&#34;&gt;Profiling the summer guests&lt;/h1&gt;
&lt;h2 id=&#34;how-much-data&#34;&gt;How much data?&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;withoccupation &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(sommargaester, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(propLabel))
withoccupation &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(withoccupation, name)
withoccupation &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(withoccupation, withoccupation &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;any&lt;/span&gt;(propLabel &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sysselsättning&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are 2192 unique guests in the dataset. We got Wikidata information for 1587 of them which means 72% of them. We got at least one occupation for 1421 guests which is 65% of them. At this point I have no way to know whether the sample is representative. Maybe the people with more Wikidata output are the most famous ones and some occupations probably help getting more famous than other so I tend to think this makes my sample a bit limited.&lt;/p&gt;
&lt;h2 id=&#34;how-often-do-guests-get-invited&#34;&gt;How often do guests get invited&lt;/h2&gt;
&lt;p&gt;As I said earlier some guests were invited several times. I want to look at the distribution of the number of invitations per guest.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;invites &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(sommargaester, name, rep)
invites &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(invites, name)
invites &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(invites, no_invites &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;max&lt;/span&gt;(rep))
invites &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(invites)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
 &lt;span style=&#34;color:#06287e&#34;&gt;theme_set&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;theme_gray&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;18&lt;/span&gt;))
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(invites) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_histogram&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(no_invites)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Number of invitations per P1 summer guest&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-08-06-p1/unnamed-chunk-5-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-5&#34;&gt;&lt;/p&gt;
&lt;p&gt;Some people have been invited &lt;em&gt;a lot&lt;/em&gt;! If you remember my initial tables, it had only a few columns for the episode dates but one guest could have several lines.&lt;/p&gt;
&lt;p&gt;Who are the people that got invited that many times?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;jobs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(occupation, name, occupation) 
jobs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(jobs)
invites &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(invites, occupation, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;)
invites &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(invites, name, no_invites, occupation)
invites &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(invites)
invites &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(invites, name, no_invites)
invites &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(invites, occupation &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(occupation))
invites &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;(invites)
invites &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(invites, &lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(no_invites))
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(invites[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;,])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;no_invites&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;occupation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Torsten Ehrenmark&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;54&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;journalist, translator, writer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Jörgen Cederberg&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;53&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Gösta Knutsson&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;cartoonist, journalist, translator, children&amp;rsquo;s writer, writer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Maud Reuterswärd&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;35&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;writer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Georg Eliasson&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;screenwriter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Pekka Langer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;television presenter, actor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Britt Edwall&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;24&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;writer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Arne Ericsson&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;musician&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Bengt Feldreich&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;journalist, television presenter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Berndt Friberg&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;journalist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Carl-Olof Lång&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;director&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Carl-Uno Sjöblom&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;television presenter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars Ulvenstam&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;journalist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lars Widding&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;journalist, writer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Åke Falck&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;film director, director, television presenter, screenwriter, actor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Barbro Alving&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;journalist, screenwriter, writer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Bo Setterlind&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;writer, poet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Bo Strömstedt&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Elisabeth Söderström&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;singer, opera singer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Fredrik Burgman&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;journalist&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;most-frequent-occupations-by-episode&#34;&gt;Most frequent occupations (by episode)&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;everything &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(occupation, occupation)
everything &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(everything, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;())
everything &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(everything, n &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;50&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
everything &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(n) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(occupation &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;factor&lt;/span&gt;(occupation, ordered &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;, levels &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(occupation))) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_col&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(occupation, n)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(axis.text.x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;90&lt;/span&gt;, hjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Number of episodes by occupation&amp;#34;&lt;/span&gt;,
subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;for occupations represented more than 50 times&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-08-06-p1/unnamed-chunk-7-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-7&#34;&gt;&lt;/p&gt;
&lt;p&gt;So in terms of episodes I&amp;rsquo;d say the media and culture fields are quite well represented. That said it might also be due to the fact that a person doing sports for instance will be classified as either ice skater or sprinter, so there&amp;rsquo;s no chance for sports to appear here. I&amp;rsquo;ll leave the classification of occupations in categories as an exercise for the reader though.&lt;/p&gt;
&lt;h2 id=&#34;most-frequent-occupations-by-unique-guest&#34;&gt;Most frequent occupations (by unique guest)&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;everything &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(occupation, name, occupation)
everything &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(everything)
everything &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(everything, occupation)
everything &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(everything, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;())
everything &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(everything, n &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
everything &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(n) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(occupation &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;factor&lt;/span&gt;(occupation, ordered &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;, levels &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(occupation))) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_col&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(occupation, n)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(axis.text.x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;90&lt;/span&gt;, hjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Number of guests by occupation&amp;#34;&lt;/span&gt;,
subtitle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;for occupations represented more than 20 times&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-08-06-p1/unnamed-chunk-8-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;&lt;/p&gt;
&lt;p&gt;With this figure by guest rather than by episode, a bit more diversity has appeared, e.g. &amp;ldquo;university professor&amp;rdquo; and &amp;ldquo;association football player&amp;rdquo;. Moreover although this was a nice exercise I won&amp;rsquo;t pretend that someone&amp;rsquo;s occupation characterizes them fully! The P1 summer guest programm really presents a variety of episodes, and I&amp;rsquo;d tend to think everyone can find an episode that they appreciate. For instance I remember liking &lt;a href=&#34;http://sverigesradio.se/sida/avsnitt/116698?programid=2071&#34;&gt;the baker Sébastien Boudet&amp;rsquo;s episode&lt;/a&gt; (yep he&amp;rsquo;s French) and &lt;a href=&#34;http://sverigesradio.se/sida/avsnitt/369285?programid=2071&#34;&gt;the one featuring the former high jumper Kajsa Berqvist&lt;/a&gt;. Now all this data munging has left me more than ready to look at the list of episodes again to choose the next ones I&amp;rsquo;ll listen to!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>What&#39;s in our internal chaimagic package at work</title>
      <link>https://masalmon.eu/2017/07/22/chaimagic/</link>
      <pubDate>Sat, 22 Jul 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/07/22/chaimagic/</guid>
      <description>&lt;p&gt;At my day job I&amp;rsquo;m a data manager and statistician for an epidemiology project called &lt;a href=&#34;http://www.chaiproject.org/&#34;&gt;CHAI&lt;/a&gt; lead by &lt;a href=&#34;https://twitter.com/cathryn_tonne&#34;&gt;Cathryn Tonne&lt;/a&gt;. CHAI means &amp;ldquo;Cardio-vascular health effects of air pollution in Telangana, India&amp;rdquo; and you can find more about it in &lt;a href=&#34;http://www.sciencedirect.com/science/article/pii/S1438463917301876&#34;&gt;our recently published protocol paper &lt;/a&gt;. At &lt;a href=&#34;http://www.isglobal.org/&#34;&gt;my institute&lt;/a&gt; you could also find the &lt;a href=&#34;http://www.pastaproject.eu/home/&#34;&gt;PASTA&lt;/a&gt; and &lt;a href=&#34;http://www.tapas-program.org/&#34;&gt;TAPAS&lt;/a&gt; projects so apparently epidemiologists are good at naming things, or obsessed with food&amp;hellip; But back to CHAI! This week Sean Lopp from RStudio wrote an &lt;a href=&#34;https://rviews.rstudio.com/2017/07/19/supporting-corporate-r-user-groups/&#34;&gt;interesting blog post&lt;/a&gt; about internal packages. I liked reading it and feeling good because we do have an internal R package for CHAI! In this blog post, I&amp;rsquo;ll explain what&amp;rsquo;s in there, in the hope of maybe providing inspiration for your own internal package!&lt;/p&gt;
&lt;img src=&#34;https://masalmon.eu/figure/source/2017-07-22-chaimagic/chaiteam_barcelona.jpg&#34; alt=&#34;gestation&#34; width=&#34;700&#34;&gt;
&lt;p&gt;As posted &lt;a href=&#34;https://twitter.com/chaiproject/status/832330667954315264&#34;&gt;in this tweet&lt;/a&gt;, this pic represents the Barcelona contingent of CHAI, a really nice group to work with! We have other colleagues in India obviously, but also in the US.&lt;/p&gt;
&lt;h1 id=&#34;the-birth-of-chaimagic-help-for-data-wrangling&#34;&gt;The birth of &lt;code&gt;chaimagic&lt;/code&gt;: help for data wrangling&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Note: part of this post was submitted as an abstract for the useR! conference in Brussels, for which I received feedback from my whole team, as well as from &lt;a href=&#34;https://twitter.com/fmic_&#34;&gt;François Michonneau&lt;/a&gt;, &lt;a href=&#34;https://twitter.com/dirk_sch&#34;&gt;Dirk Schumacher&lt;/a&gt; and &lt;a href=&#34;https://twitter.com/jent103&#34;&gt;Jennifer Thompson&lt;/a&gt;. Thanks a lot! I got to present a lightning talk about &lt;a href=&#34;https://github.com/ropensci/rtimicropem&#34;&gt;&lt;code&gt;rtimicropem&lt;/code&gt;&lt;/a&gt; instead.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Right from the beginning of my time here in October 2015 I had quite a lot of data to clean, which I started doing in R of course. One task in particular was parsing filenames because those were informative in our project, containing for instance a date and a participant ID. I wrote a function for that, &lt;code&gt;batch_parse_filenames&lt;/code&gt;, which parses all filenames in a vector and returns a list composed of two data.frames: one with the information contained in the filename (e.g. participant ID, date of sampling) and one with possible parsing mistakes (e.g. a nonexistent ID) and an informative message. It was a very useful function, and I packaged it up together with the data containing the participant IDs for instance. This was the beginning of an internal package!&lt;/p&gt;
&lt;p&gt;I decided to call it &lt;code&gt;chaimagic&lt;/code&gt; because it sounded cool, and this despite knowing that there&amp;rsquo;s absolutely no magic in the code I write.&lt;/p&gt;
&lt;h1 id=&#34;the-growth-of-chaimagic-support-for-data-analysis&#34;&gt;The growth of &lt;code&gt;chaimagic&lt;/code&gt;: support for data analysis&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;chaimagic&lt;/code&gt; evolved with helper functions for analysis, e.g. a function returning the season in India from a date (e.g. monsoon, winter), or functions for common operations on variables from our questionnaire data. &lt;code&gt;chaimagic&lt;/code&gt; also got &lt;a href=&#34;https://twitter.com/MilaCarles&#34;&gt;one more contributor&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;chaimagic&lt;/code&gt; also contains a &lt;code&gt;Shiny&lt;/code&gt; dashboard for exploring personal monitoring data that were collected in the project: one selects a participant-day and gets interactive &lt;code&gt;leaflet&lt;/code&gt; and &lt;code&gt;rbokeh&lt;/code&gt; plots of GPS, air quality, and time-activity data from questionnaires and wearable cameras. I told my boss that the dashboard was brought to us by the &lt;a href=&#34;https://en.wikipedia.org/wiki/Biblical_Magi&#34;&gt;biblical Magi&lt;/a&gt; but maybe I helped them, who knows.&lt;/p&gt;
&lt;h1 id=&#34;the-maturity-of-chaimagic-serving-scientific-communication&#34;&gt;The maturity of &lt;code&gt;chaimagic&lt;/code&gt;: serving scientific communication&lt;/h1&gt;
&lt;p&gt;Now, our package also supports scientific communication thanks to an &lt;code&gt;RMarkdown&lt;/code&gt; template for internal reports which fostered reproducibility of analyses by making the use of &lt;code&gt;RMarkdown&lt;/code&gt; even more appealing. Having an &lt;code&gt;RMarkdown&lt;/code&gt; template also supports consistent branding, which is discussed in the RStudio blog post.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;chaimagic&lt;/code&gt; also includes a function returning affiliation information for any possible collaborator we have; and a function returning the agreed-upon acknowledgement sentences to be put in each manuscript. These are pieces of information we can be very happy not to have to go look for in a folder somewhere, we can get them right without leaving R!&lt;/p&gt;
&lt;h1 id=&#34;why-is-chaimagic-a-really-cool-package&#34;&gt;Why is &lt;code&gt;chaimagic&lt;/code&gt; a really cool package?&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;chaimagic&lt;/code&gt; has been a valuable tool for the work of two statisticians/data managers, one GIS technician, one post-doc and one PhD student. Discussing its development and using it was an occasion to share our R joy, thus fostering best practices in scientific computing in our project. Why use Stata or other statistical softwares when you have such a nice internal R package? We found that even if our package served a small team of users, an R package provided a robust infrastructure to ensure that everyone was using the same code and R coding best practices in our team.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-07-22-chaimagic/chaimagic.jpg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;So this is very good&amp;hellip; but we all know from e.g. &lt;a href=&#34;https://twitter.com/i/web/status/855422698230599680&#34;&gt;Airbnb&lt;/a&gt; (see also &lt;a href=&#34;https://medium.com/airbnb-engineering/using-r-packages-and-education-to-scale-data-science-at-airbnb-906faa58e12d&#34;&gt;this post&lt;/a&gt; about Airbnb and R) that &lt;em&gt;stickers&lt;/em&gt; are a very important aspect of an internal R package. I was over the moon when &lt;a href=&#34;https://twitter.com/MilaCarles&#34;&gt;my colleague Carles&lt;/a&gt; handed me these fantastic &lt;code&gt;chaimagic&lt;/code&gt; stickers! He used &lt;a href=&#34;https://github.com/GuangchuangYu/hexSticker&#34;&gt;the &lt;code&gt;hexSticker&lt;/code&gt; package&lt;/a&gt;. I&amp;rsquo;ll leave the team in September after everyone&amp;rsquo;s vacations, and this piece of art was the goodbye present I received at my goodbye lunch. Doesn&amp;rsquo;t it make our internal package completely cool now?&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>How I became a crolute i.e. an user of the crul package</title>
      <link>https://masalmon.eu/2017/06/30/crolute/</link>
      <pubDate>Fri, 30 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/06/30/crolute/</guid>
      <description>&lt;p&gt;A few months ago rOpenSci&amp;rsquo;s Scott Chamberlain asked me for feedback about a new package of his called &lt;a href=&#34;https://github.com/ropensci/crul&#34;&gt;&lt;code&gt;crul&lt;/code&gt;&lt;/a&gt;, an http client like &lt;code&gt;httr&lt;/code&gt;, so basically something you use for e.g. writing a package interfacing an API. He told me that a great thing about &lt;a href=&#34;https://github.com/ropensci/crul&#34;&gt;&lt;code&gt;crul&lt;/code&gt;&lt;/a&gt; was that it supports &lt;em&gt;asynchronous requests&lt;/em&gt;. I felt utterly uncool because I had no idea what this meant although I had already written quite a few API packages (for instance &lt;a href=&#34;https://github.com/ropensci/ropenaq&#34;&gt;&lt;code&gt;ropenaq&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;https://github.com/ropensci/riem&#34;&gt;&lt;code&gt;riem&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/ropensci/opencage&#34;&gt;&lt;code&gt;opencage&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;So I googled the concept, my mind was blown and I decided that I&amp;rsquo;d trust Scott&amp;rsquo;s skills (spoiler: you can always do that) and just replace the &lt;code&gt;httr&lt;/code&gt;
dependency of &lt;code&gt;ropenaq&lt;/code&gt; by &lt;a href=&#34;https://github.com/ropensci/crul&#34;&gt;&lt;code&gt;crul&lt;/code&gt;&lt;/a&gt;. Why? First of all note that Crul is a planet in Star Wars whose male inhabitants are called &lt;em&gt;crolutes&lt;/em&gt; which sound quite cool (there are female ones as well, called &lt;em&gt;gilliands&lt;/em&gt; which doesn&amp;rsquo;t sound like the package name) and which I now use as a synonym for &amp;ldquo;user of the &lt;code&gt;crul&lt;/code&gt; package&amp;rdquo;. But I had other reasons to switch&amp;hellip; that was the subject of my lightning talk today at the French R conference in Anglet. In this blog post I&amp;rsquo;ll tell the story again, with a bit more details, in the hope to make you curious about &lt;a href=&#34;https://github.com/ropensci/crul&#34;&gt;&lt;code&gt;crul&lt;/code&gt;&lt;/a&gt;!&lt;/p&gt;
&lt;img src=&#34;https://masalmon.eu/figure/source/2017-06-30-crolute/title.jpg&#34; alt=&#34;gestation&#34; width=&#34;500&#34;&gt;
&lt;p&gt;Pic by &lt;a href=&#34;https://twitter.com/thinkR_fr/status/880778815148101632&#34;&gt;ThinkR&lt;/a&gt;, thanks Colin/Diane/Vincent!&lt;/p&gt;
&lt;h1 id=&#34;asynchronous-requests-for-dummies-like-me&#34;&gt;Asynchronous requests for dummies like me&lt;/h1&gt;
&lt;p&gt;OpenAQ API, which is a fantastic source of open data about air quality (see my blog post about &lt;code&gt;ropenaq&lt;/code&gt; &lt;a href=&#34;https://ropensci.org/blog/blog/2017/02/21/ropenaq&#34;&gt;on rOpenSci&amp;rsquo;s blog&lt;/a&gt;), has a pagination system. If you want say all ozone measures for one country, the API will produce several pages of results containing 10,000 measurements each, and for each of these pages you&amp;rsquo;ll need to make a request.&lt;/p&gt;
&lt;p&gt;In theory, you can either do all these requests one after the other (&lt;em&gt;synchronous&lt;/em&gt; requests, yes &lt;em&gt;synchronous&lt;/em&gt;) or all of them at once or at least in bunches, which corresponds to &lt;em&gt;asynchronous&lt;/em&gt; requests. The &lt;a href=&#34;https://github.com/ropensci/crul&#34;&gt;&lt;code&gt;crul&lt;/code&gt;&lt;/a&gt; package supports &lt;em&gt;asynchronous&lt;/em&gt; requests while &lt;code&gt;httr&lt;/code&gt; doesn&amp;rsquo;t. As you can imagine, sending several requests at once can increase speed!&lt;/p&gt;
&lt;p&gt;Of course, you can&amp;rsquo;t send too many requests at once to an API, either because it&amp;rsquo;s not allowed anyway, or at least because it&amp;rsquo;s not a really nice thing to do: you might put an API in trouble by asking too many things in one go and you probably don&amp;rsquo;t want to break things. I asked &lt;a href=&#34;https://twitter.com/joseph_flasher&#34;&gt;OpenAQ&amp;rsquo;s co-founder Joe Flasher&lt;/a&gt; whether I could use asynchronous requests, thinking he might say no. That was funny because I actually thought the API was frailer than it is, Joe told me it was fine to do up to 10 requests at once, so I started doing that.&lt;/p&gt;
&lt;h1 id=&#34;a-big-change-for-ropenaq&#34;&gt;A big change for &lt;code&gt;ropenaq&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;So I started removing all calls to &lt;code&gt;httr&lt;/code&gt; functions by calls to &lt;code&gt;crul&lt;/code&gt;, which wasn&amp;rsquo;t too hard really because &lt;code&gt;crul&lt;/code&gt; has two vignettes, in particular one about asynchronous requests. I like the style of the vignettes, I could recognize the style from &lt;a href=&#34;https://rforcats.net/&#34;&gt;R for cats&lt;/a&gt;. Besides, Scott had asked for feedback and I assumed that asking many questions would just help him make the documentation fool-proof. Thanks for your patience Scott!&lt;/p&gt;
&lt;p&gt;You can see the &lt;code&gt;crul&lt;/code&gt; calls of &lt;code&gt;ropenaq&lt;/code&gt; &lt;a href=&#34;https://github.com/ropensci/ropenaq/blob/master/R/utils.R&#34;&gt;here&lt;/a&gt;. I have no ambition to write a step by step but basically what happens now in &lt;code&gt;ropenaq&lt;/code&gt; is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;if the user provides a page argument, then I do a simple request for that page thanks to an &lt;code&gt;crul::HttpRequest&lt;/code&gt; object. In the past as an user of &lt;code&gt;ropenaq&lt;/code&gt; for any data wish you had to first had to make a query to get the count of measurements and then write a loop over all pages. Now you don&amp;rsquo;t, see the following point.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;if the user doesn&amp;rsquo;t provide a page, then I retrieve the number of measurements for the query in total, then count the pages and prepare one query by page, which I group in bunches of 10 queries. Each bunch, which is a list, is then used to create an &lt;code&gt;AsyncVaried&lt;/code&gt; object via &lt;code&gt;crul::AsyncVaried$new(.list = async)&lt;/code&gt;, and then I use methods of that object to retrieve the status and the content.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The only methods I needed to use where &lt;code&gt;new&lt;/code&gt; to create objects, &lt;code&gt;request&lt;/code&gt; to actually make the requests, &lt;code&gt;status_code&lt;/code&gt; to retrieve the request status, &lt;code&gt;get&lt;/code&gt; to extract the content of the request output when it had worked and &lt;code&gt;parse&lt;/code&gt; to well parse the contents. Their names are quite well chosen. For figuring all of that out I read the vignettes, the documentation of the classes and as mentioned previously asked questions to Scott. In particular at the beginning I wasn&amp;rsquo;t too sure how to make the 10 requests for different pages at once but as the async vignette of &lt;code&gt;crul&lt;/code&gt; says,&lt;/p&gt;
&lt;p&gt;&amp;ldquo;There are two interfaces to asynchronous requests in crul:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Simple async: any number of URLs, all treated with the same curl options, headers, etc., and only one HTTP method type at a time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Varied request async: build any type of request and execute all asynchronously.&amp;rdquo;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;and my case was the second one. I was also a bit puzzled as to how to pass my list of requests to the function creating the &lt;code&gt;AsyncVaried&lt;/code&gt; object but it turned out you can just pass a list to the &lt;code&gt;.list&lt;/code&gt; argument.&lt;/p&gt;
&lt;p&gt;Now the CRAN version of &lt;code&gt;ropenaq&lt;/code&gt; is a proud reverse dependency of &lt;code&gt;crul&lt;/code&gt; (yes my packages have feelings), so if you do &lt;code&gt;install.packages(&amp;quot;ropenaq&amp;quot;)&lt;/code&gt; you can take advantage of my hard work. In my talk I had the results of a small &lt;code&gt;microbenchmark&lt;/code&gt; and long story short as you can imagine the total time needed to retrieve data is shorter when you use asynchronous requests.&lt;/p&gt;
&lt;h1 id=&#34;other-arguments-in-favour-of-crul&#34;&gt;Other arguments in favour of &lt;code&gt;crul&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;So asynchronous requests are a big argument in my opinion to use &lt;code&gt;crul&lt;/code&gt; instead of &lt;code&gt;httr&lt;/code&gt; as an API package developer but I&amp;rsquo;ve also listed a few other reasons. Note that I don&amp;rsquo;t get any money for saying any of this, this is my most honest opinion.&lt;/p&gt;
&lt;h2 id=&#34;r6-classes&#34;&gt;R6 classes!&lt;/h2&gt;
&lt;p&gt;You might have noticed I talked about creating objects and then using methods. &lt;code&gt;crul&lt;/code&gt; is based on R6 classes so uses object-oriented programming. You can do things with these objects thanks to the methods. In &lt;code&gt;httr&lt;/code&gt;, everything is supported by &lt;em&gt;functions&lt;/em&gt;. This is an argument for using &lt;code&gt;crul&lt;/code&gt; if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;you like R6 classes or object-oriented programming in general.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;like me you&amp;rsquo;ve not used a lot of object-oriented programming but you&amp;rsquo;re curious to discover them. It was really not scary. Besides I love the fact that once you&amp;rsquo;ve created an object, in RStudio thanks to auto-completion you can start typing &amp;ldquo;$&amp;rdquo;, then press tab and see all the methods of that object.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Furthermore, each time I called an &lt;code&gt;httr&lt;/code&gt; function in my package code I wrote &lt;code&gt;httr::&lt;/code&gt; before the name of the function to specify the import. With &lt;code&gt;crul&lt;/code&gt; you do that only when creating an object, after that when you use the methods of that object you don&amp;rsquo;t need to declare any more import. So now I can be a bit lazier!&lt;/p&gt;
&lt;h2 id=&#34;the-promise-of-mocking-made-easy-quite-soon&#34;&gt;The promise of mocking made easy quite soon!&lt;/h2&gt;
&lt;p&gt;The unit tests of an API package might fail because your code no longer works&amp;hellip; or because the API changed its output or is just down. A solution to differentiate these failure reasons is to have tests calling the API, and tests using fake data, the latter being &lt;em&gt;mocked tests&lt;/em&gt;. This is discussed &lt;a href=&#34;https://discuss.ropensci.org/t/best-practices-for-testing-api-packages/460&#34;&gt;in this very good thread&lt;/a&gt;. Right now &lt;code&gt;crul&lt;/code&gt; supports mocking via &lt;a href=&#34;https://github.com/ropensci/webmockr&#34;&gt;&lt;code&gt;webmockr&lt;/code&gt;&lt;/a&gt;, and if I understood correctly will soon support mocking in an easier way via &lt;a href=&#34;https://github.com/ropensci/vcr&#34;&gt;&lt;code&gt;vcr&lt;/code&gt;&lt;/a&gt;. When it does I&amp;rsquo;ll try to make myself wiser about mocking which I don&amp;rsquo;t use at all currently.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;So overall if you&amp;rsquo;re an API package developper you should consider giving &lt;code&gt;crul&lt;/code&gt; a try! I&amp;rsquo;ll keep using &lt;code&gt;httr&lt;/code&gt; in my webscraping and well it is still a dependency of all my other API packages so I like both packages.&lt;/p&gt;
&lt;img src=&#34;https://masalmon.eu/figure/source/2017-06-30-crolute/end.jpg&#34; alt=&#34;gestation&#34; width=&#34;500&#34;&gt;
&lt;p&gt;Pic by &lt;a href=&#34;https://twitter.com/alinedeschamps/status/880777453752528896&#34;&gt;Aline Deschamps&lt;/a&gt;, on that slide I was merely advertising for &lt;a href=&#34;https://ropensci.org/&#34;&gt;rOpenSci&lt;/a&gt; and in particular its &lt;a href=&#34;https://github.com/ropensci/onboarding&#34;&gt;onboarding process for packages&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At the French R conference I was happy to get to present the reasons why I became a crolute. I also enjoyed meeting new people, some of them I knew from Twitter (&lt;a href=&#34;https://twitter.com/_ColinFay&#34;&gt;Colin Fay&lt;/a&gt; who actually gave a talk about API packages, &lt;a href=&#34;https://twitter.com/DianeBELDAME&#34;&gt;Diane Beldame&lt;/a&gt; who lead a tutorial about the tidyverse, &lt;a href=&#34;https://twitter.com/VincentGuyader&#34;&gt;Vincent Guyader&lt;/a&gt; who made the use of Docker to encapsulate a Shiny app look really easy, all of them from &lt;a href=&#34;https://twitter.com/thinkR_fr&#34;&gt;ThinkR&lt;/a&gt;, &lt;a href=&#34;https://twitter.com/joelgombin&#34;&gt;Joël Gombin&lt;/a&gt; who gave a keynote about data journalism and &lt;a href=&#34;https://twitter.com/alinedeschamps&#34;&gt;Aline Deschamps&lt;/a&gt; from &lt;a href=&#34;https://twitter.com/dacta_fr&#34;&gt;Dacta&lt;/a&gt;), many others I didn&amp;rsquo;t know at all, for instance the real guy behind &lt;a href=&#34;https://twitter.com/R_Graph_Gallery&#34;&gt;The R graph gallery&lt;/a&gt; who made a cool project using tweets about surfing. I even got to see Nick Tierney again, who gave a talk about his awesome &lt;a href=&#34;https://github.com/njtierney/narnia&#34;&gt;&lt;code&gt;narnia&lt;/code&gt; package&lt;/a&gt; for handling missing data. The talks were great, some findings were shared via the &lt;a href=&#34;https://twitter.com/search?q=%23angletr2017&amp;amp;src=tyah&#34;&gt;#angletr2017 hashtag on Twitter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We heard that the next French R conference will be in Rennes which is in Brittany, my beloved home region, so I&amp;rsquo;m already hoping I can go next year, as an human or a crolute or whatever!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Automatic tools for improving R packages</title>
      <link>https://masalmon.eu/2017/06/17/automatictools/</link>
      <pubDate>Sat, 17 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/06/17/automatictools/</guid>
      <description>&lt;p&gt;On Tuesday I gave a talk at a meetup of the R users group of Barcelona. I got to choose the topic of my talk, and decided I&amp;rsquo;d like to expand a bit on &lt;a href=&#34;https://twitter.com/ma_salmon/status/824646744688488450&#34;&gt;a recent tweet of mine&lt;/a&gt;. There are tools that help you improve your R packages, some of them are not famous enough yet in my opinion, so I was happy to help spread the word! I &lt;a href=&#34;http://rpubs.com/masalmon/282469&#34;&gt;published my slides online&lt;/a&gt; but thought that a blog post would be nice as well.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-06-17-automatictools/tweets.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;During my talk at RUG BCN, for each tool I gave a short introduction and then applied it to a small package I had created for the occasion. In that post I&amp;rsquo;ll just shortly present each tool. Most of them are only &lt;em&gt;automatic&lt;/em&gt; because they &lt;em&gt;automatically&lt;/em&gt; provide you with a list of things to fix, but they won&amp;rsquo;t do the work for you, sorry. If you have an R package you develop at hand, I&amp;rsquo;d really advise you to apply them on it and see what you get! I concentrated on tools improving the coding style, the package structure, testing, the documentation, but not features and performance.&lt;/p&gt;
&lt;p&gt;Note: before my talk &lt;a href=&#34;https://twitter.com/lucacerone?lang=es&#34;&gt;Luca Cerone&lt;/a&gt; gave a short introduction to package development with &lt;code&gt;devtools&lt;/code&gt; and &lt;code&gt;roxygen2&lt;/code&gt;. This is how I develop packages now although the first package I contributed to, &lt;a href=&#34;https://cran.r-project.org/web/packages/surveillance/index.html&#34;&gt;&lt;code&gt;surveillance&lt;/code&gt;&lt;/a&gt;, has separate man pages, a NAMESPACE maintained by hand, etc. I gave its maintainer a hard time with all my stupid beginner mistakes! Thankfully Sebastian was always patient and nice. In any case, if you want to start developping packages you should definitely read &lt;a href=&#34;http://r-pkgs.had.co.nz/&#34;&gt;Hadley Wickham&amp;rsquo;s book&lt;/a&gt;, it&amp;rsquo;s a good one! I read it all once I started upping my package game &amp;ndash; this upping being a continuous process of course.&lt;/p&gt;
&lt;h1 id=&#34;the-basics-run-r-cmd-check&#34;&gt;The basics: run R CMD check!&lt;/h1&gt;
&lt;p&gt;In his talk Luca said that when he develops a package he often doesn&amp;rsquo;t have time to check it passes R CMD check, which made me die inside a little bit. I totally understand the lack of time but I think that R CMD check complains about important stuff, and most often unknown NOTE, WARNING or ERROR messages can be googled and solved, and one learns something. So please do run R CMD check!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-06-17-automatictools/runrcmdcheck.jpeg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;The R-Lady that uploaded this picture to the Meetup event told me that this is my &amp;ldquo;Run R CMD check, you fools!&amp;rdquo; face (she actually said &lt;em&gt;Usad el R CMD check, malditos!!!&lt;/em&gt;).&lt;/p&gt;
&lt;h1 id=&#34;lintr-static-code-analysis-for-r&#34;&gt;&lt;code&gt;lintr&lt;/code&gt;, Static Code Analysis for R&lt;/h1&gt;
&lt;p&gt;I then presented Jim Hester&amp;rsquo;s &lt;code&gt;lintr&lt;/code&gt; package which allows you to check some stuff in your code without running it. It will for instance tell you if you used camel case instead of snake case for a variable name, or if you defined a variable without using it afterwards. The README of the &lt;a href=&#34;https://github.com/jimhester/lintr&#34;&gt;Github repository of the package&lt;/a&gt; provides a list of available linters, each linter being one of these annoying, hum useful, checks.&lt;/p&gt;
&lt;p&gt;How does one use &lt;code&gt;lintr&lt;/code&gt;? Just by typing &lt;code&gt;lintr::lint_package()&lt;/code&gt; at the root of the package folder. This week I applied it to a package of mine and spent some time adding white space that made my code prettier. In my opinion using &lt;code&gt;lintr&lt;/code&gt; helps you maintain a code that is nice to read, which is cool because then you, future you or another human can concentrate on important stuff when reading it.&lt;/p&gt;
&lt;p&gt;I mentioned two small tips as well.&lt;/p&gt;
&lt;h2 id=&#34;how-to-customize-the-lintr-linters&#34;&gt;How to customize the &lt;code&gt;lintr&lt;/code&gt; linters?&lt;/h2&gt;
&lt;p&gt;For that one needs to create a .lintr file at the root of the package (and add it to .Rbuildignore). Here is an example of the content of such a file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;linters&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;with_defaults&lt;/span&gt;(camel_case_linter &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;, &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# you prefer camel case &lt;/span&gt;
              snake_case_linter, &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# so flag snake case&lt;/span&gt;
              &lt;span style=&#34;color:#06287e&#34;&gt;line_length_linter&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;120&lt;/span&gt;)) &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# you love long lines&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Refer to &lt;a href=&#34;https://github.com/jimhester/lintr/#project-configuration&#34;&gt;the &amp;ldquo;Project Configuration&amp;rdquo; section of &lt;code&gt;lintr&lt;/code&gt; README&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;how-to-never-ever-ignore-lintr-output&#34;&gt;How to never ever ignore &lt;code&gt;lintr&lt;/code&gt; output&lt;/h2&gt;
&lt;p&gt;Edit on 2019-10-02: &lt;a href=&#34;https://github.com/jimhester/lintr/#continuous-integration&#34;&gt;the &lt;code&gt;lintr&lt;/code&gt;docs recommend using the package in combination with continuoua integration, not to set up an unit test&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can add an unit test for &lt;code&gt;lintr&lt;/code&gt;! Why would one ever want to do that? Well, you might want to force yourself, or contributors to your package, to respect some rules. The test would be:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;requireNamespace&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lintr&amp;#34;&lt;/span&gt;, quietly &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)) {
  &lt;span style=&#34;color:#06287e&#34;&gt;context&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lints&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;test_that&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Package Style&amp;#34;&lt;/span&gt;, {
    lintr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;expect_lint_free&lt;/span&gt;()
  })
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After I published my slides &lt;a href=&#34;https://twitter.com/najkoja/status/874889344888320000&#34;&gt;someone added such a test to one of his packages&lt;/a&gt; which made me very proud.&lt;/p&gt;
&lt;p&gt;One tip I forgot to mention during my talk is how to add exceptions, I was far too strict!&lt;/p&gt;
&lt;h2 id=&#34;how-to-exclude-lines-from-lintr-checks&#34;&gt;How to exclude lines from &lt;code&gt;lintr&lt;/code&gt; checks&lt;/h2&gt;
&lt;p&gt;For that either put &lt;code&gt;# nolint&lt;/code&gt; at the end of the line or &lt;code&gt;# nolint start&lt;/code&gt; and &lt;code&gt;# nolint end&lt;/code&gt; before and after a block of lines you&amp;rsquo;d like to exclude. A good example is for instance a very long line that you can&amp;rsquo;t break because it contains a very long URL.&lt;/p&gt;
&lt;h1 id=&#34;goodpractice-advice-on-r-package-building&#34;&gt;&lt;code&gt;goodpractice&lt;/code&gt;, Advice on R Package Building&lt;/h1&gt;
&lt;p&gt;This package by Gabor Csardi can only be installed &lt;a href=&#34;https://github.com/mangothecat/goodpractice&#34;&gt;from Github&lt;/a&gt;. It integrates a variety of tools, including &lt;code&gt;lintr&lt;/code&gt;, for providing &amp;ldquo;Advice (that) includes functions and syntax to avoid, package structure, code complexity, code formatting, etc.&amp;rdquo;. For instance, &lt;code&gt;goodpractice&lt;/code&gt; uses &lt;a href=&#34;https://github.com/mangothecat/cyclocomp&#34;&gt;&lt;code&gt;cyclocomp&lt;/code&gt;&lt;/a&gt; to check whether any of your functions is too complex. A participant of the meetup told me she got a lot of messages when running &lt;code&gt;goodpractice::gp()&lt;/code&gt; on her first package, which is great because it means &lt;code&gt;goodpractice&lt;/code&gt; will really have provided her with useful guidance. Some things that &lt;code&gt;goodpractice::gp()&lt;/code&gt; will flag might be necessary features of your package, but in general it&amp;rsquo;s a nice list to read. Note: you can only run &lt;code&gt;goodpractice::gp()&lt;/code&gt; once R CMD check passes.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://twitter.com/romain_francois?lang=es&#34;&gt;Romain François&lt;/a&gt; who came to the Meetup from Montpellier (thanks, Romain!) asked me if I had ever run &lt;code&gt;goodpractice::gp()&lt;/code&gt; on famous packages like &lt;code&gt;dplyr&lt;/code&gt;. I haven&amp;rsquo;t but since the default advice of &lt;code&gt;goodpractice&lt;/code&gt; seems quite consistent with the advice in Hadley Wickham&amp;rsquo;s book, I doubt I&amp;rsquo;d find anything interesting.&lt;/p&gt;
&lt;p&gt;At &lt;a href=&#34;https://github.com/ropensci/onboarding&#34;&gt;rOpenSci onboarding&lt;/a&gt;, we run &lt;code&gt;goodpractice::gp()&lt;/code&gt; on every submitted package as part of the editorial checks, which makes me like this tool a bit more every week. It&amp;rsquo;s actually tunable but the defaults are so great that I never needed to tune it!&lt;/p&gt;
&lt;p&gt;I was asked when to run &lt;code&gt;goodpractice::gp()&lt;/code&gt; and I&amp;rsquo;d say once in a while, e.g. before submitting a package to CRAN for the first time, or after creating its first working version.&lt;/p&gt;
&lt;h1 id=&#34;devtoolsspell_check&#34;&gt;&lt;code&gt;devtools::spell_check()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;This function was written by Jeroen Ooms and is supported by his &lt;a href=&#34;https://github.com/ropensci/hunspell&#34;&gt;&lt;code&gt;hunspell&lt;/code&gt; package&lt;/a&gt;. It will look for possible typos in the documentation of a package. In the output, there might be quite a few false positives, e.g. the name of an API, but I strongly believe that its helping you find typos in the documentation compensates the effort of reading the whole list of potential typos.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve noticed that &lt;code&gt;devtools::release()&lt;/code&gt;, which one can use when submitting a package to CRAN, now includes the output of &lt;code&gt;devtools::spell_check()&lt;/code&gt;. It helped me find a typo at the last minute in one of my packages! Typos might not be that bad, but a typo-free documentation looks much better.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-06-17-automatictools/audience.jpeg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;pkgdown-generate-static-html-documentation-for-an-r-package&#34;&gt;&lt;code&gt;pkgdown&lt;/code&gt;, generate static html documentation for an R package&lt;/h2&gt;
&lt;p&gt;This last tool was the only one that&amp;rsquo;s truly automatic. This package was created by Hadley Wickham and is currently only &lt;a href=&#34;https://github.com/hadley/pkgdown&#34;&gt;on Github&lt;/a&gt;. It allows you to create a pretty website for your package without any big effort.&lt;/p&gt;
&lt;p&gt;How does one use it? After installing it, run &lt;code&gt;pkgdown::init()&lt;/code&gt; and &lt;code&gt;pkgdown::build_site()&lt;/code&gt; at the root of your package. This will create a docs/ folder containing the static html documentation, that you can browse locally.&lt;/p&gt;
&lt;p&gt;Now, how do you present it to the world? In theory I guess you could publish it anywhere but the really handy thing is to have it as a Github page, if you develop your package on Github. For this you just need to change the settings of the repository to make master/docs the source for Github pages.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-06-17-automatictools/gh.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Unless you typically redirect all links from your Github account to your domain, your package will live at account_name.github.io/package_name. See for instance &lt;a href=&#34;https://github.com/dirkschumacher/ompr&#34;&gt;this nice package of Dirk Schumacher&amp;rsquo;s&lt;/a&gt; whose website is &lt;a href=&#34;https://dirkschumacher.github.io/ompr/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;how-to-customize-the-website&#34;&gt;How to customize the website?&lt;/h2&gt;
&lt;p&gt;This part is not automatic, and demands creating a &lt;code&gt;_pkgdown.yml&lt;/code&gt; file at the root of your package. I&amp;rsquo;ve only mentioned two aspects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;One can change the style of the website, e.g. &lt;a href=&#34;https://github.com/maelle/rtimicropem/blob/master/_pkgdown.yml&#34;&gt;in this config file&lt;/a&gt; I chose another Boostrap theme than the default one. To choose one Boostrap theme one can browse them online or look at a pkgdown website that one likes and look at how it was created. A participant of the meetup told me that there is an RStudio addin for choosing a theme but I couldn&amp;rsquo;t locate it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;One can change the order of vignettes, or of the functions, and even group them, which might be extremely useful when a package has many functions. Usually the alphabetical order makes little sense. See &lt;a href=&#34;https://github.com/dirkschumacher/ompr/blob/master/_pkgdown.yml&#34;&gt;here&lt;/a&gt; the config file of &lt;a href=&#34;https://dirkschumacher.github.io/ompr/&#34;&gt;this website&lt;/a&gt;, the grouping is really well done.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Since this was a talk, not a long workshop, and also because I don&amp;rsquo;t know everything, I have not mentioned every useful tool in the world. I&amp;rsquo;d be grateful for suggestions in the comments, and in the meantime here are some tools I briefly mentioned at the end of my talk:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Continuous integration, with this &lt;a href=&#34;https://juliasilge.com/blog/beginners-guide-to-travis/&#34;&gt;well written post by Julia Silge&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/r-hub&#34;&gt;R-hub project&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/ropensci/PackageDevelopment&#34;&gt;CRAN task view about package development&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/ropenscilabs/available&#34;&gt;&lt;code&gt;available&lt;/code&gt; package&lt;/a&gt; to check whether the name you want to use for your package is a) available and b) appropriate.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A very important tip I gave was to have your code read by humans. The automatic tools will flag some things, but the feedback of an human about your code and your documentation will be crucial. And when &lt;em&gt;you&lt;/em&gt; review code, you&amp;rsquo;ll learn a lot! If you want to do that, you can volunteer to become a reviewer for rOpenSci, see more info &lt;a href=&#34;https://github.com/ropensci/onboarding#why-review&#34;&gt;here&lt;/a&gt; and fill the short form &lt;a href=&#34;https://ropensci.org/onboarding/&#34;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-06-17-automatictools/tshirt.jpeg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;After my talk I got a nice RMarkdown t-shirt that has the same colour as my face! Thanks a lot to the organizers, in particular Luca Cerone!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Who is talking about the French Open?</title>
      <link>https://masalmon.eu/2017/06/10/rolandgarros/</link>
      <pubDate>Sat, 10 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/06/10/rolandgarros/</guid>
      <description>&lt;p&gt;I don&amp;rsquo;t think rOpenSci&amp;rsquo;s Jeroen Ooms can ever top the coolness of his &lt;a href=&#34;https://github.com/ropensci/magick&#34;&gt;&lt;code&gt;magick&lt;/code&gt; package&lt;/a&gt; but I have to admit other things he&amp;rsquo;s developped are not bad at all. He&amp;rsquo;s recently been working on interfaces to Google compact language detectors 2 and 3 (the latter being more experimental). I saw &lt;a href=&#34;http://marcbeldata.github.io/Language-use-MP-Twitter/&#34;&gt;this cool use case&lt;/a&gt; and started thinking about other possible applications of the packages.&lt;/p&gt;
&lt;p&gt;I was very sad when I realized it was too late to try and download tweets about the Eurovision song context but then I also remembered there&amp;rsquo;s &lt;a href=&#34;https://en.wikipedia.org/wiki/French_Open&#34;&gt;this famous tennis tournament&lt;/a&gt; going on right now, about which people probably tweet in various languages. I don&amp;rsquo;t follow the French Open myself, but it seemed interesting to find out which languages were the most prevalent, and whether the results from the &lt;a href=&#34;https://github.com/ropensci/cld2&#34;&gt;&lt;code&gt;cld2&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/ropensci/cld3&#34;&gt;&lt;code&gt;cld3&lt;/code&gt;&lt;/a&gt; packages are similar and whether they&amp;rsquo;re similar to the language detection results from Twitter itself.&lt;/p&gt;
&lt;h1 id=&#34;getting-the-tweets&#34;&gt;Getting the tweets&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m using my usual &lt;code&gt;rtweet&lt;/code&gt; recipe. I no longer need to open my eyes when downloading tweets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;rg_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rtweet&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;search_tweets&lt;/span&gt;(q &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#RolandGarros2017&amp;#34;&lt;/span&gt;,
                                   include_rts &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;,
                                   n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;18000&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;save&lt;/span&gt;(rg_tweets, file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-06-07-rolandgarros.RData&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I got 18000 tweets.&lt;/p&gt;
&lt;h1 id=&#34;using-the-language-detectors&#34;&gt;Using the language detectors&lt;/h1&gt;
&lt;p&gt;I decided to first clean the tweets a bit, removing hashtags, mentions, and at least part of the links.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;rg_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rg_tweets,
                           text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#.*$&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;),
                           text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https.*$&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;),
                           text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;@.*$&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;),
                           text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#.* &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;),
                           text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https.* &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;),
                           text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;@.* &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Today I&amp;rsquo;m a happy naive user of language detectors, but more technical details can be found in their &lt;a href=&#34;https://github.com/CLD2Owners/cld2&#34;&gt;respective&lt;/a&gt; &lt;a href=&#34;https://github.com/google/cld3#readme&#34;&gt;README&amp;rsquo;s&lt;/a&gt;. It&amp;rsquo;d be difficult to have an easier interface than the two &lt;code&gt;cld2&lt;/code&gt; and &lt;code&gt;cld3&lt;/code&gt; packages. They&amp;rsquo;re also fast, although I haven&amp;rsquo;t timed the following chunk so you&amp;rsquo;ll have to believe me or test the packages yourselves.&lt;/p&gt;
&lt;p&gt;Note that &lt;code&gt;cld2&lt;/code&gt; and &lt;code&gt;cld3&lt;/code&gt; both have functions for outputting several languages instead of one, with the associated reliability, but I won&amp;rsquo;t use them since I want a direct comparison with the Twitter output of one language per tweet.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;rg_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rg_tweets, 
                           cld2_language &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; cld2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;detect_language&lt;/span&gt;(text,
                                                                 lang_code &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;), 
                           cld3_language &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; cld3&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;detect_language&lt;/span&gt;(text))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Before analysing the results, I&amp;rsquo;ll transform the Twitter detected language a bit: it&amp;rsquo;s not NA for undertemined language, it&amp;rsquo;s &amp;ldquo;und&amp;rdquo;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;rg_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rg_tweets, 
                           lang &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(lang &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;und&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;, lang))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;looking-at-detected-languages&#34;&gt;Looking at detected languages&lt;/h1&gt;
&lt;p&gt;Twitter output a language for 96% of the tweets, &lt;code&gt;cld2&lt;/code&gt; for 59% and &lt;code&gt;cld3&lt;/code&gt; for 84% of them.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see a few cases in which Twitter outputs a language whereas the other don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;As a side note, I learnt how to insert a &lt;code&gt;DT::datatable&lt;/code&gt; from Daniela Vázquez after admiring one she had put &lt;a href=&#34;https://d4tagirl.com/2017/05/how-do-you-feel-about-last-week-tonight&#34;&gt;in this cool blog post&lt;/a&gt;. This was an adventure in htmlwidgets hell. I started looking at Daniela&amp;rsquo;s Github blog repo, then talked with her on the R-Ladies slack, and I told her I&amp;rsquo;d do more the next day. I woke up to a PR solving all problems! Thanks a lot Daniela, and also thanks to your husband! Update: Daniela&amp;rsquo;s husband Gervasio came up with &lt;a href=&#34;https://github.com/maelle/maelle.github.io/pull/3&#34;&gt;a fix&lt;/a&gt; not involving custom Jekyll plugins after I realized my site couldn&amp;rsquo;t be built on Github pages&amp;hellip; I am so thankful for their help!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
rg_tweets &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(cld2_language), &lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(cld3_language)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(text, lang, cld2_language,
         cld3_language)&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;50&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  DT&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;datatable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--html_preserve--&gt;&lt;div id=&#34;htmlwidget-63daaefa0d92bf46c034&#34; style=&#34;width:100%;height:auto;&#34; class=&#34;datatables html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;htmlwidget-63daaefa0d92bf46c034&#34;&gt;{&#34;x&#34;:{&#34;filter&#34;:&#34;none&#34;,&#34;data&#34;:[[&#34;1&#34;,&#34;2&#34;,&#34;3&#34;,&#34;4&#34;,&#34;5&#34;,&#34;6&#34;,&#34;7&#34;,&#34;8&#34;,&#34;9&#34;,&#34;10&#34;,&#34;11&#34;,&#34;12&#34;,&#34;13&#34;,&#34;14&#34;,&#34;15&#34;,&#34;16&#34;,&#34;17&#34;,&#34;18&#34;,&#34;19&#34;,&#34;20&#34;,&#34;21&#34;,&#34;22&#34;,&#34;23&#34;,&#34;24&#34;,&#34;25&#34;,&#34;26&#34;,&#34;27&#34;,&#34;28&#34;,&#34;29&#34;,&#34;30&#34;,&#34;31&#34;,&#34;32&#34;,&#34;33&#34;,&#34;34&#34;,&#34;35&#34;,&#34;36&#34;,&#34;37&#34;,&#34;38&#34;,&#34;39&#34;,&#34;40&#34;,&#34;41&#34;,&#34;42&#34;,&#34;43&#34;,&#34;44&#34;,&#34;45&#34;,&#34;46&#34;,&#34;47&#34;,&#34;48&#34;,&#34;49&#34;,&#34;50&#34;],[&#34;Congratulations to &#34;,&#34;Verdasco y Zimonjic se quedan a las puertas de la final de dobles\nhttps://t.co/Mm3nnAhfpo\n\n&#34;,&#34;Next up :\nSimona Halep v Karolina Pliskova\n&#34;,&#34;攼㹤愼㸰戼㹣攼㹤戼㸷戼㸱攼㹤愼㸰戼㹣攼㹤戼㸷戼㹢攼㹤愼㸰戼㹣攼㹤戼㹥戼㹥 Jelena Ostapenko avanzó a su 1er final al vencer 7-6 3-6 6-3 a Timea Bacsinszky &#34;,&#34;Enorme &#34;,&#34;OSTAPENKOOOO BEBEEE 攼㹤愼㸰戼㹤攼㹤戼㸴愼㸵攼㹤愼㸰戼㹤攼㹤戼㸲㤼㸸攼㹤愼㸰戼㹤攼㹤戼㸲㤼㸸 cote a 2,5 qui passe on continue a encaisser la famille !! 攼㹤愼㸰戼㹤攼㹤戼㸲戼㸰攼㹤愼㸰戼㹤攼㹤戼㸲戼㸰 &#34;,&#34;Listen &#34;,&#34;TIMEA 攼㹤愼㸰戼㹤攼㹤戼㸸愼㹤攼㹤愼㸰戼㹤攼㹤戼㸸愼㹤攼㹤愼㸰戼㹤攼㹤戼㸸愼㹤攼㹤愼㸰戼㹤攼㹤戼㸸愼㹤攼㹤愼㸰戼㹤攼㹤戼㸸愼㹤攼㹤愼㸰戼㹤攼㹤戼㸸愼㹤攼㹤愼㸰戼㹤攼㹤戼㸸愼㹤攼㹤愼㸰戼㹤攼㹤戼㸸愼㹤攼㹤愼㸰戼㹤攼㹤戼㸸愼㹤 &#34;,&#34;OsTaPenKo!!!! Fantastika!! 6dien svetki!! Finals!!! &#34;,&#34;Merci &#34;,&#34;YEEEES BRAVO! LA FINALE !!! :D &#34;,&#34;Jelena Ostapenko - French Open Finalist. &#34;,&#34;Bravo &#34;,&#34;Ostapenko WINS !!!!!! &#34;,&#34;Goooo 攼㹤愼㸰戼㹣攼㹤戼㹦㠼㸶攼㹤愼㸰戼㹤攼㹤戼㸴㤼㹤\n\n\n&#34;,&#34;Jelena strong\n&#34;,&#34;ostapenko-bacsinszky muazzam maç oluyor... &#34;,&#34;Congratulations &#34;,&#34;A la final!!! Bien &#34;,&#34;Eyes on &#34;,&#34;[攼㹤愼㸰戼㹣攼㹤戼㹥戼㹥\n1 set partout entre Bacsinszky et Ostapenko ! (6/7 6/3)&#34;,&#34;Belle demie ! &#34;,&#34;Enorme Santyyy &#34;,&#34;Grande &#34;,&#34;A un game de la final! &#34;,&#34;Going 3 &#34;,&#34;Lache pas Ostapenko !!!! &#34;,&#34;played!\n\n\n&#34;,&#34;Congratulations &#34;,&#34;Set González / Young por 7-5. Verdasco y Zimonjic al tercero &#34;,&#34;Unranked Latvian &#34;,&#34;BBCSport: \n\n攼㹤愼㸰戼㹤攼㹤戼㸱㠼㸹 &#34;,&#34;Congratulations to &#34;,&#34;Dominic thiem攼㹤愼㸰戼㹤攼㹤戼㸲愼㹡攼㹤愼㸰戼㹤攼㹤戼㸲愼㹡\n&#34;,&#34;Anyway &#34;,&#34;Merci &#34;,&#34;Rhoooo pas de &#34;,&#34;Alizé Lim 攼㹤愼㸰戼㹤攼㹤戼㸸㠼㹤 &#34;,&#34;攼㹤愼㸰戼㹣攼㹤戼㹥戼㹥 Bet on &#34;,&#34;Congratulations &#34;,&#34;Congratulations 攼㹤愼㸰戼㹣攼㹤戼㹦㠼㸶攼㹤愼㸰戼㹣攼㹤戼㹥戼㹥\n攼㹤愼㸰戼㹣攼㹤戼㸷愼㹥攼㹤愼㸰戼㹣攼㹤戼㸷戼㸳\n\n&#34;,&#34;TENNIS &#34;,&#34;Respect &#34;,&#34;Congratulations &#34;,&#34;Congratulations &#34;,&#34;Robert Farah \n &#34;,&#34;Por favorrrrrr no digan la S en Roland Garros, suena horribleeeeeee!!!! &#34;,&#34;Congratulations &#34;,&#34;Congratulations &#34;,&#34;Congratulations \n\n\n&#34;],[&#34;en&#34;,&#34;es&#34;,&#34;cs&#34;,&#34;ro&#34;,&#34;es&#34;,&#34;fr&#34;,&#34;en&#34;,&#34;en&#34;,&#34;sl&#34;,&#34;fr&#34;,&#34;it&#34;,&#34;eu&#34;,&#34;pt&#34;,&#34;pl&#34;,null,&#34;en&#34;,&#34;tr&#34;,&#34;en&#34;,&#34;es&#34;,&#34;en&#34;,&#34;fi&#34;,&#34;fr&#34;,&#34;en&#34;,&#34;es&#34;,&#34;es&#34;,&#34;en&#34;,&#34;ht&#34;,&#34;en&#34;,&#34;en&#34;,&#34;es&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;fr&#34;,&#34;fr&#34;,&#34;ht&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;is&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;es&#34;,&#34;es&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;],[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null]],&#34;container&#34;:&#34;&lt;table class=\&#34;display\&#34;&gt;\n  &lt;thead&gt;\n    &lt;tr&gt;\n      &lt;th&gt; &lt;\/th&gt;\n      &lt;th&gt;text&lt;\/th&gt;\n      &lt;th&gt;lang&lt;\/th&gt;\n      &lt;th&gt;cld2_language&lt;\/th&gt;\n      &lt;th&gt;cld3_language&lt;\/th&gt;\n    &lt;\/tr&gt;\n  &lt;\/thead&gt;\n&lt;\/table&gt;&#34;,&#34;options&#34;:{&#34;order&#34;:[],&#34;autoWidth&#34;:false,&#34;orderClasses&#34;:false,&#34;columnDefs&#34;:[{&#34;orderable&#34;:false,&#34;targets&#34;:0}]}},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;&lt;!--/html_preserve--&gt;
&lt;p&gt;It seems that the languages with undetermined languages via &lt;code&gt;cld2&lt;/code&gt; and &lt;code&gt;cld3&lt;/code&gt; are quite short. The Twitter language detector might be more focused at short sentences which well given the length of tweets wouldn&amp;rsquo;t be surprising. Moreover, maybe it often inputs a language even when uncertain. If we take the example of the word &amp;ldquo;Merci&amp;rdquo;, it&amp;rsquo;s French but also used in Catalan at least in Barcelona, so to me that seems uncertain. Some other tweets to which Twitter but not the other language detectors associated a language are a mix of languages.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at lines with disagreements when no language information is missing.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;rg_tweets &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(lang),
                &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(cld2_language),
                &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(cld3_language)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(lang, cld2_language,
                              cld3_language))) &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;50&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(text, lang, cld2_language,
         cld3_language)&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  DT&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;datatable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!--html_preserve--&gt;&lt;div id=&#34;htmlwidget-8c3851ccde84819289b8&#34; style=&#34;width:100%;height:auto;&#34; class=&#34;datatables html-widget&#34;&gt;&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;htmlwidget-8c3851ccde84819289b8&#34;&gt;{&#34;x&#34;:{&#34;filter&#34;:&#34;none&#34;,&#34;data&#34;:[[&#34;1&#34;,&#34;2&#34;,&#34;3&#34;,&#34;4&#34;,&#34;5&#34;,&#34;6&#34;,&#34;7&#34;,&#34;8&#34;,&#34;9&#34;,&#34;10&#34;,&#34;11&#34;,&#34;12&#34;,&#34;13&#34;,&#34;14&#34;,&#34;15&#34;,&#34;16&#34;,&#34;17&#34;,&#34;18&#34;,&#34;19&#34;,&#34;20&#34;,&#34;21&#34;,&#34;22&#34;,&#34;23&#34;,&#34;24&#34;,&#34;25&#34;,&#34;26&#34;,&#34;27&#34;,&#34;28&#34;,&#34;29&#34;,&#34;30&#34;,&#34;31&#34;,&#34;32&#34;,&#34;33&#34;,&#34;34&#34;,&#34;35&#34;,&#34;36&#34;,&#34;37&#34;,&#34;38&#34;,&#34;39&#34;,&#34;40&#34;,&#34;41&#34;,&#34;42&#34;,&#34;43&#34;,&#34;44&#34;,&#34;45&#34;,&#34;46&#34;,&#34;47&#34;,&#34;48&#34;,&#34;49&#34;,&#34;50&#34;],[&#34;#RolandGarros2017\nEl mexicano Santiago Gonzales y el estadounidense Donald Young están en la final de dobles &#34;,&#34;Rafael Nadal face à son seul bourreau &#34;,&#34;COME ON SIMONA HALEP !攼㹤愼㸰戼㹣攼㹤戼㸷戼㸹攼㹤愼㸰戼㹣攼㹤戼㸷愼㸹攼㹤愼㸰戼㹣攼㹤戼㸷戼㸹攼㹤愼㸰戼㹣攼㹤戼㸷愼㸹攼㹤愼㸰戼㹣攼㹤戼㸷戼㸹攼㹤愼㸰戼㹣攼㹤戼㸷愼㸹 &#34;,&#34;I&#39;d like to see Simona Halep start winning some slams. &#34;,&#34;Much respect. Congratulations! &#34;,&#34;The latest ))) El Fútbol se Siente! &#34;,&#34;LA aceleración de la pelota de Pliskova. Nada, eso. &#34;,&#34;Break point Halep! &#34;,&#34;Hallelujah!! &#34;,&#34;Timea the Swiss vs. Jelena the Latvian\n\n&#34;,&#34;Timea the Swiss vs. Jelena the Latvian\n\n&#34;,&#34;Timea the Swiss vs. Jelena the Latvian\n\n&#34;,&#34;Timea the Swiss vs. Jelena the Latvian\n\n&#34;,&#34;Ostapenko is a joy to watch. Happy birthday. &#34;,&#34;Timea the Swiss vs. Jelena the Latvian\n\n&#34;,&#34;Timea the Swiss vs. Jelena the Latvian\n\n&#34;,&#34;Aus der Traum: &#34;,&#34;Ostapenko is a beaasstt &#34;,&#34;Jelena Ostapenko s&#39;offre \n&#34;,&#34;Alona Finaalaa! &#34;,&#34;Le sang ostapenko &#34;,&#34;Jelena Ostapienko w finale &#34;,&#34;Happy Birthday Ostapenko 攼㹤愼㸰戼㹤攼㹤戼㸱㠼㹦攼㹤愼㸰戼㹣攼㹤戼㹦戼㹢攼㹤愼㸰戼㹤攼㹤戼㸱㠼㹦攼㹤愼㸰戼㹣攼㹤戼㹦戼㹢攼㹤愼㸰戼㹣攼㹤戼㹥㠼㸹 &#34;,&#34;allez jelena !!! &#34;,&#34;Felicitar ampliamente a &#34;,&#34;On sait maintenant que &#34;,&#34;Pauvre Timea, écouter Ostapenko comme ça... &#34;,&#34;Osta marafakin&#39; penko &#34;,&#34;Felicidades &#34;,&#34;El mexa 攼㹤愼㸰戼㹣攼㹤戼㸷戼㸲攼㹤愼㸰戼㹣攼㹤戼㸷戼㹤 ya está en la final de dobles. &#34;,&#34;Felicidades a Santiago Gonzalez &#34;,&#34;Bresnik nach Champion!\&#34;\n\n&#34;,&#34;Día histórico para el tenis mexicano, &#34;,&#34;Ostapenko se na kurtu chova jako 13 lete rozmazlene decko. Zensky tenis je k smichu. &#34;,&#34;Très belle 1/2 finale : ostapenko vs bacsinzky. 攼㹤愼㸰戼㹣攼㹤戼㹥戼㹥&#34;,&#34;Early break Jelena 3rd set &#34;,&#34;Que lindo que juega Ostapenko &#34;,&#34;Ostapenko j&#39;aime bien ! 攼㹤愼㸰戼㹣攼㹤戼㹥戼㹥&#34;,&#34;Nan ta pas le droit la !! &#34;,&#34;quel match entre ostapenko et bacsinsky!! &#34;,&#34;Jelena Ostapenko 攼㹤愼㸰戼㹤攼㹤戼㸲愼㹡攼㹤愼㸰戼㹣攼㹤戼㹦戼㹢攼㹤愼㸰戼㹤攼㹤戼㸱㠼㹣攼㹤愼㸰戼㹣攼㹤戼㹦戼㹢攼㹤愼㸰戼㹤攼㹤戼㸸㠼㹤 &#34;,&#34;Selain cute, dek Ostapenko ini boleh ya. Agresif! &#34;,&#34;Tocó acostumbrarse a ver perder a &#34;,&#34;1st set to Ostapenko after tiebreak 7-6 (7-4)! &#34;,&#34;elle joue trop bien &#34;,&#34;Is \&#34;JOKER\&#34; grand slam career over? &#34;,&#34;Come on Jelena !!\n&#34;,&#34;Ostapenko..good luck..\n&#34;,&#34;Happy birthday, girls! Ostapenko v bacsinzky &#34;,&#34;Vero Cepede llegó a Paraguay tras su histórico Francia\n\n&#34;],[&#34;es&#34;,&#34;fr&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;es&#34;,&#34;es&#34;,&#34;en&#34;,&#34;in&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;de&#34;,&#34;nl&#34;,&#34;fr&#34;,&#34;fi&#34;,&#34;eu&#34;,&#34;pl&#34;,&#34;en&#34;,&#34;eu&#34;,&#34;es&#34;,&#34;fr&#34;,&#34;fr&#34;,&#34;eu&#34;,&#34;es&#34;,&#34;es&#34;,&#34;es&#34;,&#34;de&#34;,&#34;es&#34;,&#34;cs&#34;,&#34;ht&#34;,&#34;en&#34;,&#34;es&#34;,&#34;fr&#34;,&#34;fr&#34;,&#34;no&#34;,&#34;eu&#34;,&#34;in&#34;,&#34;es&#34;,&#34;no&#34;,&#34;fr&#34;,&#34;en&#34;,&#34;en&#34;,&#34;tl&#34;,&#34;en&#34;,&#34;es&#34;],[&#34;gl&#34;,&#34;fr&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;es&#34;,&#34;en&#34;,&#34;et&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;hmn&#34;,&#34;en&#34;,&#34;sr&#34;,&#34;fi&#34;,&#34;st&#34;,&#34;sr&#34;,&#34;en&#34;,&#34;sr&#34;,&#34;ca&#34;,&#34;en&#34;,&#34;fr&#34;,&#34;fi&#34;,&#34;pt&#34;,&#34;es&#34;,&#34;gl&#34;,&#34;en&#34;,&#34;gl&#34;,&#34;cs&#34;,&#34;fr&#34;,&#34;en&#34;,&#34;es&#34;,&#34;fr&#34;,&#34;fr&#34;,&#34;fr&#34;,&#34;sr&#34;,&#34;ms&#34;,&#34;pt&#34;,&#34;en&#34;,&#34;fr&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;en&#34;,&#34;gl&#34;],[&#34;es&#34;,&#34;co&#34;,&#34;ceb&#34;,&#34;haw&#34;,&#34;lb&#34;,&#34;es&#34;,&#34;eo&#34;,&#34;de&#34;,&#34;nl&#34;,&#34;sq&#34;,&#34;sq&#34;,&#34;sq&#34;,&#34;sq&#34;,&#34;pl&#34;,&#34;sq&#34;,&#34;sq&#34;,&#34;de&#34;,&#34;lb&#34;,&#34;hr&#34;,&#34;so&#34;,&#34;st&#34;,&#34;pl&#34;,&#34;sr&#34;,&#34;sr&#34;,&#34;gl&#34;,&#34;fr&#34;,&#34;ro&#34;,&#34;eu&#34;,&#34;gl&#34;,&#34;ca&#34;,&#34;gl&#34;,&#34;ru-Latn&#34;,&#34;es&#34;,&#34;hr&#34;,&#34;fy&#34;,&#34;fy&#34;,&#34;pt&#34;,&#34;fy&#34;,&#34;ht&#34;,&#34;lb&#34;,&#34;hr&#34;,&#34;ms&#34;,&#34;ca&#34;,&#34;nl&#34;,&#34;af&#34;,&#34;no&#34;,&#34;hr&#34;,&#34;fi&#34;,&#34;ru-Latn&#34;,&#34;es&#34;]],&#34;container&#34;:&#34;&lt;table class=\&#34;display\&#34;&gt;\n  &lt;thead&gt;\n    &lt;tr&gt;\n      &lt;th&gt; &lt;\/th&gt;\n      &lt;th&gt;text&lt;\/th&gt;\n      &lt;th&gt;lang&lt;\/th&gt;\n      &lt;th&gt;cld2_language&lt;\/th&gt;\n      &lt;th&gt;cld3_language&lt;\/th&gt;\n    &lt;\/tr&gt;\n  &lt;\/thead&gt;\n&lt;\/table&gt;&#34;,&#34;options&#34;:{&#34;order&#34;:[],&#34;autoWidth&#34;:false,&#34;orderClasses&#34;:false,&#34;columnDefs&#34;:[{&#34;orderable&#34;:false,&#34;targets&#34;:0}]}},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;&lt;!--/html_preserve--&gt;
&lt;p&gt;Similarly I think these tweets are quite short. Moreover, languages seem to often be different but not &lt;em&gt;that&lt;/em&gt; different, e.g. &amp;ldquo;es&amp;rdquo; (Spanish) and &amp;ldquo;ca&amp;rdquo; (Catalan) or &amp;ldquo;es&amp;rdquo; and &amp;ldquo;gl&amp;rdquo; (Galician). I sometimes make similar mistakes, when I say I&amp;rsquo;ve heard a &amp;ldquo;Nordic language&amp;rdquo;&amp;rdquo; because I couldn&amp;rsquo;t identify it further than &amp;ldquo;not Swedish&amp;rdquo; (which I should be able to recognize).&lt;/p&gt;
&lt;p&gt;I can also look at dissimilarities, computed on tweets with determined language.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(rg_tweets, lang, cld2_language, cld3_language) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate_all&lt;/span&gt;(dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;funs&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;as.factor&lt;/span&gt;(.))) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;t&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;as.data.frame&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
cluster&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;daisy&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Dissimilarities :
##                     lang cld2_language
## cld2_language 0.09870999              
## cld3_language 0.41158430    0.16547982
## 
## Metric :  mixed ;  Types = N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N 
## Number of objects : 3
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Unsurprisingly there&amp;rsquo;s a worse agreement between &lt;code&gt;cld3&lt;/code&gt; results and the other two ones than between &lt;code&gt;cld2&lt;/code&gt; and Twitter. I say I&amp;rsquo;m not surprised because &lt;code&gt;cld3&lt;/code&gt; is a still experimental language detector.&lt;/p&gt;
&lt;h1 id=&#34;representing-languages&#34;&gt;Representing languages&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m going to assume that if Twitter and &lt;code&gt;cld2&lt;/code&gt; agree on the language assigned to a tweet, then it&amp;rsquo;s quite reliable.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;agreed &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(rg_tweets,
                        lang &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; cld2_language)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m therefore only considering 9432 tweets out of the original 18000 tweets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;agreed &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(agreed, lang)
agreed &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(agreed, tweets_count &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;())
agreed &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;(agreed)
agreed &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(agreed, &lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(tweets_count))
agreed &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(agreed, lang &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;factor&lt;/span&gt;(lang, ordered &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;, levels &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(lang))) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s plot the results.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(agreed) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_col&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(lang, tweets_count)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;,
              axis_title_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Detected language&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;No. of tweets in the sample&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-06-10-rolandgarros/unnamed-chunk-11-1.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;The most represented languages, English, French and Spanish are surely a result of who&amp;rsquo;s on Twitter, what are the most spoken languages on Earth, who&amp;rsquo;s interested in tennis (or the tennis players) and who&amp;rsquo;s awake when the tournament happens. One way to control for the timezone of the tournament would be to stream tweets during each of the tournaments of the &lt;a href=&#34;https://en.wikipedia.org/wiki/Grand_Slam_(tennis)&#34;&gt;tennis Grand Slam&lt;/a&gt;. Another extension of this small blog post would be to look for players names in tweets and to then see if one can find an association between the most mentioned players in a language and the nationality of these players. This could even be coupled to a sentiment analysis (you could support one player and criticize the other players). Then again, that&amp;rsquo;s something that&amp;rsquo;d be even more interesting in my opinion if applied to Eurovision contestants instead! Next year maybe&amp;hellip;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Which science is all around? #BillMeetScienceTwitter</title>
      <link>https://masalmon.eu/2017/05/20/billnye/</link>
      <pubDate>Sat, 20 May 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/05/20/billnye/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ll admit I didn&amp;rsquo;t really know who Bill Nye was before yesterday. His name sounds a bit like &lt;a href=&#34;https://en.wikipedia.org/wiki/Bill_Nighy&#34;&gt;Bill Nighy&amp;rsquo;s&lt;/a&gt;, that&amp;rsquo;s all I knew. But well science is all around and quite often scientists on Twitter start interesting campaigns. Remember the #actuallylivingscientists whose animals I dedicated &lt;a href=&#34;https://masalmon.eu/2017/02/05/actuallivingscientists/&#34;&gt;a blog post&lt;/a&gt;? This time, the Twitter campaign is the #BillMeetScienceTwitter hashtag with which scientists introduce themselves to the famous science TV host Bill Nye. &lt;a href=&#34;https://www.theverge.com/tldr/2017/5/19/15663446/bill-nye-neil-degrasse-tyson-meet-scientists-twitter-hashtag&#34;&gt;Here&lt;/a&gt; is a nice article about the movement.&lt;/p&gt;
&lt;p&gt;Since I like surfing on Twitter trends, I decided to download a few of these tweets and to use my own R interface to the Monkeylearn machine learning API, &lt;a href=&#34;https://github.com/ropensci/monkeylearn&#34;&gt;&lt;code&gt;monkeylearn&lt;/code&gt;&lt;/a&gt; (part of the &lt;a href=&#34;https://ropensci.org/&#34;&gt;rOpenSci project&lt;/a&gt;!), to classify the tweets in the hope of finding the most represented science fields. So, which science is all around?&lt;/p&gt;
&lt;h1 id=&#34;getting-the-tweets&#34;&gt;Getting the tweets&lt;/h1&gt;
&lt;p&gt;It might sound a bit like trolling by now, but if you wanna get Twitter data, I recommend using &lt;a href=&#34;https://github.com/mkearney/rtweet/&#34;&gt;&lt;code&gt;rtweet&lt;/code&gt;&lt;/a&gt; because it&amp;rsquo;s a good package and because it&amp;rsquo;s going to replace &lt;code&gt;twitteR&lt;/code&gt; which you might know from other blogs.&lt;/p&gt;
&lt;p&gt;I only keep tweets in English, and moreover original ones, i.e. not retweets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rtweet&amp;#34;&lt;/span&gt;)
billmeet &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;search_tweets&lt;/span&gt;(q &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#BillMeetScienceTwitter&amp;#34;&lt;/span&gt;, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;18000&lt;/span&gt;, type &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;recent&amp;#34;&lt;/span&gt;)
billmeet &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(billmeet)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;billmeet &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(billmeet, lang &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;)
billmeet &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(billmeet, is_retweet &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve ended up with 2491 tweets.&lt;/p&gt;
&lt;h1 id=&#34;classifying-the-tweets&#34;&gt;Classifying the tweets&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve chosen to use this &lt;a href=&#34;https://app.monkeylearn.com/main/classifiers/cl_5icAVzKR/&#34;&gt;taxonomy classifier&lt;/a&gt; which classifies text according to generic topics and had quite a few stars on Monkeylearn website. I don&amp;rsquo;t think it was trained on tweets, and well it wasn&amp;rsquo;t trained to classify science topics in particular, which is not optimal, but it had the merit of being readily available. I&amp;rsquo;ve still not started training my own algorithms, and anyway, if I did I&amp;rsquo;d start by creating a very crucial algorithm for determining animal fluffiness on pictures, not text mining stuff. This was a bit off topic, let&amp;rsquo;s go back to science Twitter!&lt;/p&gt;
&lt;p&gt;When I decided to use my own package I had forgotten it took charge of cutting the request vector into groups of 20 tweets, since the API only accept 20 texts at a time. I thought I&amp;rsquo;d have to do that splitting myself, but no, since I did it once in the code of the package, I&amp;rsquo;ll never need to write that code ever again. Great feeling! Look at how easy the code is after cleaning up the tweets a bit! One just needs to wait a bit before getting all results.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;output &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; monkeylearn&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;monkeylearn_classify&lt;/span&gt;(request &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; billmeet&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text,
                                            classifier_id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cl_5icAVzKR&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;str&lt;/span&gt;(output)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Classes &#39;tbl_df&#39;, &#39;tbl&#39; and &#39;data.frame&#39;:	4466 obs. of  4 variables:
##  $ category_id: int  64638 64640 64686 64696 64686 64687 64689 64692 64648 64600 ...
##  $ probability: num  0.207 0.739 0.292 0.784 0.521 0.565 0.796 0.453 0.301 0.605 ...
##  $ label      : chr  &amp;quot;Computers &amp;amp; Internet&amp;quot; &amp;quot;Internet&amp;quot; &amp;quot;Humanities&amp;quot; &amp;quot;Religion &amp;amp; Spirituality&amp;quot; ...
##  $ text_md5   : chr  &amp;quot;f7b28f45ea379b4ca6f34284ce0dc4b7&amp;quot; &amp;quot;f7b28f45ea379b4ca6f34284ce0dc4b7&amp;quot; &amp;quot;b95429d83df2cabb9cd701a562444f0b&amp;quot; &amp;quot;b95429d83df2cabb9cd701a562444f0b&amp;quot; ...
##  - attr(*, &amp;quot;headers&amp;quot;)=Classes &#39;tbl_df&#39;, &#39;tbl&#39; and &#39;data.frame&#39;:	0 obs. of  0 variables
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In the output, the package creator decided not to put the whole text corresponding to each line but its digested form itself, digested by the &lt;a href=&#34;https://en.wikipedia.org/wiki/MD5&#34;&gt;MD5 algorithm&lt;/a&gt;. So to join the output to the tweets again, I&amp;rsquo;ll have to first digest the tweet, which I do just copying the code from the package. After all I wrote it. Maybe it was the only time I successfully used &lt;code&gt;vapply&lt;/code&gt; in my whole life.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;billmeet &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(billmeet, text_md5 &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;vapply&lt;/span&gt;(X &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; text,
                                                    FUN &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; digest&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;digest,
                                                    FUN.VALUE &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;character&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;),
                                                    USE.NAMES &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;,
                                                    algo &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;md5&amp;#34;&lt;/span&gt;))
billmeet &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(billmeet, text, text_md5)
output &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(output, billmeet, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;text_md5&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Looking at this small sample, some things make sense, other make less sense, either because the classification isn&amp;rsquo;t good or because the tweet looks like spam. Since my own field isn&amp;rsquo;t text analysis, I&amp;rsquo;ll consider myself happy with these results, but I&amp;rsquo;d be of course happy to read any better version of it.&lt;/p&gt;
&lt;p&gt;As in my #first7jobs, I&amp;rsquo;ll make a very arbitrary decision and filter the labels to which a probability higher to 0.5 was attributed.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;output &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(output, probability &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This covers 0.45 of the original tweets sample. I can only hope it&amp;rsquo;s a representative sample.&lt;/p&gt;
&lt;p&gt;How many labels do I have by tweet?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(output) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(nlabels &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(nlabels) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(n_tweets &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;nlabels&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n_tweets&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1415&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Perfect, only one.&lt;/p&gt;
&lt;h1 id=&#34;looking-at-the-results&#34;&gt;Looking at the results&lt;/h1&gt;
&lt;p&gt;I know I suck at finding good section titles&amp;hellip; At least I like the title of the post, which is a reference to the song Bill Nighy, not Bill Nye, sings in &lt;a href=&#34;https://www.youtube.com/watch?v=t_KI-mRyE_0&#34;&gt;Love Actually&lt;/a&gt;. My husband assumed that science Twitter has more biomedical stuff. Now, even if my results were to support this fact, note that this could as well be because it&amp;rsquo;s easier to classify biomedical tweets.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll first show a few examples of tweets for given labels.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(output, label &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Chemistry&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;category_id&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;probability&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;label&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;text_md5&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;text&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;64701&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.530&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chemistry&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;e82fc920b07ea9d08850928218529ca9&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hi @billnye I started off running BLAST for other ppl but now I have all the money I make them do my DNA extractions #BillMeetScienceTwitter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;64701&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.656&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chemistry&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;d21ce4386512aae5458565fc2e36b686&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;.@uw’s biochemistry dept - home to Nobel Laureate Eddy Fischer &amp;amp; ZymoGenetics co founder Earl Davie… https://t.co/0nsZW3b3xu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;64701&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.552&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chemistry&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1d5be9d1e169dfbe2453b6cbe07a4b34&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Yo @BillNye - I&amp;rsquo;m a chemist who plays w lasers &amp;amp; builds &lt;f0&gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+0094&amp;gt;&amp;lt;U+00AC&amp;gt; to study protein interactions w materials #BillMeetScienceTwitter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;64701&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.730&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chemistry&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1b6a25fcb66deebf35246d7eeea34b1f&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Meow @BillNye!  I&amp;rsquo;m Zee and I study quantum physics and working on a Nobel prize. #BillMeetScienceTwitter https://t.co/oxAZO5Y6kI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;64701&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.873&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chemistry&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;701d8c53e3494961ee7f7146b28b9c8c&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hi @BillNye, I&amp;rsquo;m a organic chemist studying how molecules form materials like the liquid crystal shown below.… https://t.co/QNG2hSG8Fw&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(output, label &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Aquatic Mammals&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;category_id&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;probability&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;label&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;text_md5&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;text&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;64609&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.515&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aquatic Mammals&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f070a05b09d2ccc85b4b1650139b6cd0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hi Bill, I am Anusuya. I am a palaeo-biologist working at the University of Cape Town. @BillNye  #BillMeetScienceTwitter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;64609&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.807&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aquatic Mammals&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;bb06d18a1580c28c255e14e15a176a0f&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hi @BillNye! I worked with people at APL to show that California blue whales are nearly recovered #BillMeetScienceTwitter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;64609&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.748&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aquatic Mammals&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1ca07aad8bc1abe54836df8dd1ff1a9d&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hi @BillNye! I&amp;rsquo;m researching marine ecological indicators to improve Arctic marine monitoring and management… https://t.co/pJv8Om4IeI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;64609&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.568&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aquatic Mammals&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;a140320fcf948701cfc9e7b01309ef8b&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;More like as opposed to vaginitis in dolphins or chimpanzees or sharks #BillMeetScienceTwitter https://t.co/gFCQIASty1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;64609&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.520&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aquatic Mammals&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;06d1e8423a7d928ea31fd6db3c5fee05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hi @BillNye I study visual function in ppl born w/o largest connection between brain hemispheres #callosalagenesis… https://t.co/WSz8xsP38R&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(output, label &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Internet&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;category_id&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;probability&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;label&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;text_md5&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;text&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;64640&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.739&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Internet&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;f7b28f45ea379b4ca6f34284ce0dc4b7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;@BillNye #AskBillNye @BillNye join me @AllendaleCFD. More details at https://t.co/nJPwWARSsa&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;#BillMeetScienceTwitter                         |
|       64640|       0.725|Internet |b2b7843dc9fcd9cd959c828beb72182d |@120Stat you could also use #actuallivingscientist #womeninSTEM  or #BillMeetScienceTwitter to spread the word about your survey as well      |
|       64640|       0.542|Internet |a357e1216c5e366d7f9130c7124df316 |Thank you so much for the retweet, @BillNye! &amp;lt;U+263A&amp;gt;&amp;lt;U+FE0F&amp;gt; I&amp;rsquo;m excited for our next generation of science-lovers!… https://t.co/B3iz3KVCOQ |
|       64640|       0.839|Internet |61712f61e877f3873b69fed01486d073 |@ParkerMolloy Hi @BillNye, Im an elem school admin who wants 2 bring in STEM/STEAM initiatives 2 get my students EX… https://t.co/VMLO3WKVRv  |
|       64640|       0.924|Internet |4c7f961acfa2cdd17c9af655c2e81684 |I just filled my twitter-feed with brilliance. #BIllMeetScienceTwitter                                                                        |&lt;/p&gt;
&lt;p&gt;Based on that, and on the huge number of internet-labelled tweets, I decided to remove those.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;viridis&amp;#34;&lt;/span&gt;)

label_counts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; output &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(label &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Internet&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(label) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n))

label_counts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; label_counts &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;others&amp;#34;&lt;/span&gt;, label)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(label) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sum&lt;/span&gt;(n)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n))

label_counts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(label_counts,
                        label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;factor&lt;/span&gt;(label,
                                        ordered &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;,
                                        levels &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(label)))

&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(label_counts) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_bar&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(label, n, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; label), stat &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;identity&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;, option &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;plasma&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(axis.text.x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;90&lt;/span&gt;,
                            hjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;,
                            vjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;),
          text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(size&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;25&lt;/span&gt;),
          legend.position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-05-20-billnye/unnamed-chunk-8-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;&lt;/p&gt;
&lt;p&gt;In the end, I&amp;rsquo;m always skeptical when looking at the results of such classifiers, and well at the quality of my sample to begin with &amp;ndash; but then I doubt there ever was a hashtag that was perfectly used to only answer the question and not spam it and comment it (which is what I&amp;rsquo;m doing). I&amp;rsquo;d say it seems to support my husband&amp;rsquo;s hypothesis about biomedical stuff.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m pretty sure Bill Nye won&amp;rsquo;t have had the time to read all the tweets, but I think he should save them, or at least all the ones he can get via the Twitter API thanks to e.g. &lt;code&gt;rtweet&lt;/code&gt;, in order to be able to look through them next time he needs an expert. And in the random sample of tweets he&amp;rsquo;s read, let&amp;rsquo;s hope he was exposed to a great diversity of science topics (and of scientists), although, hey, the health and life related stuff is the most interesting of course. Just kidding. I liked reading tweets about various scientists, science rocks! And these last words would be labelled with &amp;ldquo;performing arts&amp;rdquo;, perfect way to end this post.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>How not to make an evergreen review graph</title>
      <link>https://masalmon.eu/2017/05/14/evergreenreviewgraph/</link>
      <pubDate>Sun, 14 May 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/05/14/evergreenreviewgraph/</guid>
      <description>&lt;p&gt;In this post I am inspired by two tweets, mainly &lt;a href=&#34;https://twitter.com/noamross/status/843913486266777605&#34;&gt;this one&lt;/a&gt; and also &lt;a href=&#34;https://twitter.com/polesasunder/status/824639612354228225&#34;&gt;this one&lt;/a&gt;. Since the total number of articles every year is increasing, no matter which subject you choose, the curve representing number of articles as a function of year of publication will probably look exponential, so one should not use such graphs to impress readers. At least I&amp;rsquo;m not impressed, I&amp;rsquo;m more amused by such graphs now that there&amp;rsquo;s a hashtag for them.&lt;/p&gt;
&lt;p&gt;I shall use an rOpenSci package for getting some data about number of articles about a query term, and to do a graph that&amp;rsquo;s not an evergreen review graph!&lt;/p&gt;
&lt;h1 id=&#34;getting-some-numbers-of-articles&#34;&gt;Getting some numbers of articles&lt;/h1&gt;
&lt;p&gt;For this I&amp;rsquo;ll use one of the &lt;a href=&#34;https://ropensci.org/packages/#literature&#34;&gt;numerous rOpenSci packages simplifying your programmatic access to scientific literature&lt;/a&gt;, &lt;a href=&#34;https://github.com/ropensci/europepmc&#34;&gt;&lt;code&gt;europepmc&lt;/code&gt;&lt;/a&gt; which is an interface to &lt;a href=&#34;https://europepmc.org/&#34;&gt;Europe PMC&lt;/a&gt;, &amp;ldquo;Search worldwide, life-sciences literature&amp;rdquo;. The package includes a cool function called &lt;code&gt;epmc_profile&lt;/code&gt; that gives you the number of hits for a given query. Perfect!&lt;/p&gt;
&lt;p&gt;Now my goal is to get the number of hits by year for a search term but also the total number of hits in order to put things into perspective. I had no idea how to write a proper Europe PMC query so I went to the &lt;a href=&#34;https://europepmc.org/advancesearch&#34;&gt;advanced search page&lt;/a&gt; and made queries there in order to learn enough words of this language to get what I needed. Indeed, when you create a query by clicking there and then hit search, the URL contains the query as you need it to be written for using the &lt;code&gt;europepmc&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;For each query &lt;code&gt;epmc_profile&lt;/code&gt; returns hits by source and type, but I&amp;rsquo;m interested in all hits, including e.g. books, so that&amp;rsquo;s what I&amp;rsquo;ll use.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s write functions!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;europepmc&amp;#34;&lt;/span&gt;)
find_hits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(query_term){
  years &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1975&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2016&lt;/span&gt;
  results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(years, find_hits_by_year, query_term &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; query_term)
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(results)
}

find_hits_by_year &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(year, query_term){
  queryforall &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;(FIRST_PDATE:[&amp;#39;&lt;/span&gt;, year, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;-01-01+TO+&amp;#39;&lt;/span&gt;, year, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;-12-31])&amp;#39;&lt;/span&gt;)
  all_hits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;epmc_profile&lt;/span&gt;(queryforall)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;pubType[1, &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;])
  
  queryforterm &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;(FIRST_PDATE:[&amp;#39;&lt;/span&gt;, year, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;-01-01+TO+&amp;#39;&lt;/span&gt;, year, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;-12-31]) AND &amp;#34;&amp;#39;&lt;/span&gt;, query_term, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;&amp;#34;&amp;#39;&lt;/span&gt;)
  
  term_hits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;epmc_profile&lt;/span&gt;(queryforterm)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;pubType[1, &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;])
  
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(year &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; year, all_hits &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; all_hits, term_hits &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; term_hits))
  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now let&amp;rsquo;s apply the function to one term. I&amp;rsquo;ll choose Malaria because it&amp;rsquo;s the term used in one of &lt;code&gt;europepmc&lt;/code&gt; examples.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;malaria_fame &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;find_hits&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;malaria&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(malaria_fame) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;year&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;all_hits&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;term_hits&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1975&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;252386&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;394&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1976&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;259044&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;425&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1977&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;266538&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;432&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1978&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;279160&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;475&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1979&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;294491&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;516&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1980&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;295471&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;443&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Obviously in a review about malaria research one might have a more precise query, and one might want to compare the number of hits for that query to other precise queries, but in this simple example I&amp;rsquo;m just comparing the number of hits of one term to the number of all hits, Note that one could also make no graph about number of hits over time, shocking I now! I&amp;rsquo;ll most certainly won&amp;rsquo;t do no graph here though, now that I collected the data.&lt;/p&gt;
&lt;h1 id=&#34;making-nice-plots&#34;&gt;Making nice plots&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll do as Lucy in &lt;a href=&#34;http://livefreeordichotomize.com/2017/03/04/xkcd-thank-you-note/&#34;&gt;this blog post&lt;/a&gt; and use the &lt;code&gt;xkcd&lt;/code&gt; package. As noted by Lucy, &lt;a href=&#34;https://cran.r-project.org/web/packages/xkcd/vignettes/xkcd-intro.pdf&#34;&gt;its vignette&lt;/a&gt; is great. I might have done something wrong but after downloading the file with the xkcd font I had to copy-paste it myself in the fonts folder of Windows. The syntax of the xkcdman is a bit long but following the examples I could get what I wanted.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;xkcd&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;extrafont&amp;#34;&lt;/span&gt;)
xrange &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;range&lt;/span&gt;(malaria_fame&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;year)
yrange &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;range&lt;/span&gt;(malaria_fame&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;term_hits)
ratioxy &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;diff&lt;/span&gt;(xrange)&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;diff&lt;/span&gt;(yrange)
mapping &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;x,
               y&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;y,
               scale&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;scale,
               ratioxy&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;ratioxy,
               angleofspine &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; angleofspine,
               anglerighthumerus &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; anglerighthumerus,
               anglelefthumerus &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; anglelefthumerus,
               anglerightradius &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; anglerightradius,
               angleleftradius &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; angleleftradius,
               anglerightleg &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;  anglerightleg,
               angleleftleg &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; angleleftleg,
               angleofneck &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; angleofneck)
dataman &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;data.frame&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1985&lt;/span&gt;, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4000&lt;/span&gt;,
                  scale &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1000&lt;/span&gt;,
                  ratioxy &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; ratioxy,
                  angleofspine &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;  &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;,
                  anglerighthumerus &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;,
                  anglelefthumerus &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;,
                  anglerightradius &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;,
                  angleleftradius &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;,
                  angleleftleg &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;  &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt; ,
                  anglerightleg &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;  &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;,
                  angleofneck &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;  &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(malaria_fame) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(year, term_hits)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Time in years&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Number of hits for Malaria&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xkcdaxis&lt;/span&gt;(xrange &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; xrange,
           yrange &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; yrange) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;, family &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;xkcd&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xkcdman&lt;/span&gt;(mapping,dataman) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;annotate&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;, family &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;xkcd&amp;#34;&lt;/span&gt;, x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1985&lt;/span&gt;, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4800&lt;/span&gt;, 
           label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Oops!\n I made an evergreen review graph!&amp;#34;&lt;/span&gt;, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-05-14-evergreenreviewgraph/unnamed-chunk-3-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-3&#34;&gt;&lt;/p&gt;
&lt;p&gt;Ok that one is not really the one I&amp;rsquo;d advise you to submit to any journal. Let&amp;rsquo;s do better.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;malaria_fame &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(malaria_fame, 
                              prop &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; term_hits&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;all_hits)
xrange &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;range&lt;/span&gt;(malaria_fame&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;year)
yrange &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;range&lt;/span&gt;(malaria_fame&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;prop)
ratioxy &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;diff&lt;/span&gt;(xrange)&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;diff&lt;/span&gt;(yrange)

dataman &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;data.frame&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1985&lt;/span&gt;, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.005&lt;/span&gt;,
                  scale &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.001&lt;/span&gt;,
                  ratioxy &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; ratioxy,
                  angleofspine &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;  &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;,
                  anglerighthumerus &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;,
                  anglelefthumerus &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;,
                  anglerightradius &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,
                  angleleftradius &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,
                  angleleftleg &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;  &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt; ,
                  anglerightleg &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;  &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;,
                  angleofneck &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;  &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pi&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(malaria_fame) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(year, prop)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Time in years&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;No. of hits for Malaria divided by total no. of hits&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xkcdaxis&lt;/span&gt;(xrange &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; xrange,
           yrange &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; yrange) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;, family &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;xkcd&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xkcdman&lt;/span&gt;(mapping,dataman) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;annotate&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;, family &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;xkcd&amp;#34;&lt;/span&gt;, x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1985&lt;/span&gt;, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.006&lt;/span&gt;, 
           label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Now that&amp;#39;s more interesting!&amp;#34;&lt;/span&gt;, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-05-14-evergreenreviewgraph/unnamed-chunk-4-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-4&#34;&gt;&lt;/p&gt;
&lt;p&gt;Okay friends so that one is a bit more interesting, and I&amp;rsquo;m more convinced my its shape. I&amp;rsquo;d like to know whether there really was a malaria research peak, but only waiting for a few years will bring me the answer! It&amp;rsquo;d also be interesting to compare the fate of other diseases, and to put that in context with some domain knowledge. But that&amp;rsquo;d be a subject for another study, now at least you know how to not make an evergreen review graph!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>A tribute to Lucy D&#39;Agostino McGowan&#39;s git commit emoji game</title>
      <link>https://masalmon.eu/2017/05/03/lucysemojis/</link>
      <pubDate>Wed, 03 May 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/05/03/lucysemojis/</guid>
      <description>&lt;p&gt;Do you know &lt;a href=&#34;https://twitter.com/LucyStats&#34;&gt;Lucy&lt;/a&gt;? She is a very talented biostatistics PhD candidate that I had the chance to e-meet thanks to R-Ladies. One maybe superficial reason to admire her, on top of her other achievements, is her emoji game in git commits. Looking at Lucy&amp;rsquo;s git history (find &lt;a href=&#34;https://github.com/LucyMcGowan&#34;&gt;her on Github&lt;/a&gt;), one wants to start using version control because she makes it look fun!&lt;/p&gt;
&lt;p&gt;In this post, I will download many git commit messages of Lucy&amp;rsquo;s from Github&amp;rsquo;s API via the &lt;code&gt;gh&lt;/code&gt; package, and have a look at the emojis she uses the most frequently.&lt;/p&gt;
&lt;h1 id=&#34;getting-the-commit-messages&#34;&gt;Getting the commit messages&lt;/h1&gt;
&lt;p&gt;As I said I&amp;rsquo;ll use the &lt;code&gt;gh&lt;/code&gt; package as in my post about &lt;a href=&#34;https://masalmon.eu/2017/02/21/firstcommit/&#34;&gt;first commits&lt;/a&gt; and as in the one about &lt;a href=&#34;https://masalmon.eu/2017/04/12/seeds/&#34;&gt;random seeds&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The first step is to get the names of Lucy&amp;rsquo;s repositories. I get all her public repositories, and also a few of the repositories of the LFOD organization &lt;a href=&#34;http://livefreeordichotomize.com/&#34;&gt;where she blogs&lt;/a&gt;, that I selected by hand for not getting forks from the public repositories I already had. Hopefully her commit messages in these repositories, obviously excluding her private repositories, is representative of her typical emoji use.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;gh&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
lucy_repos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gh&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;/users/:username/repos&amp;#34;&lt;/span&gt;, 
                 type &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;public&amp;#34;&lt;/span&gt;, 
                 username &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;LucyMcGowan&amp;#34;&lt;/span&gt;)
lucy_repos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;vapply&lt;/span&gt;(lucy_repos, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;)
lucy_repos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(repos &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lucy_repos,
                             who &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;LucyMcGowan&amp;#34;&lt;/span&gt;)
lucy_repos_org &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(repos &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;LFOD.github.io&amp;#34;&lt;/span&gt;,
                                           &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;blog&amp;#34;&lt;/span&gt;,
                                           &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;real-blog&amp;#34;&lt;/span&gt;),
                                 who &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;LFOD&amp;#34;&lt;/span&gt;)

lucy_repos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(lucy_repos,
                               lucy_repos_org)

&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(lucy_repos) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;repos&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;who&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18_hackathon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;branchingExample&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;comps-survival-guide&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;contributr&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;cowsay&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;datasauRus&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Then I got the commit messages, but also their authors in order to filter commits by Lucy herself, and the time and date at which they were made because Lucy told me she started using emojis last October. &lt;code&gt;gh&lt;/code&gt; is a minimal package so it outputs lists of lists, so each time I use it I have a look at their structure to find how to extract exactly what I need, see below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;get_all_lucy_commits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(repo, who){
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Since I don&amp;#39;t know the number of pages&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# I grow the vectors of messages, dates and authors&lt;/span&gt;
  messages &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
  authors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
  dates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
  
  page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
  is_still_ok &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# loop while page still full of content&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;while&lt;/span&gt;(is_still_ok[1]){
    commits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;gh&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;/repos/:owner/:repo/commits&amp;#34;&lt;/span&gt;,
                      owner &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; who,
                      repo &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; repo,
                      page &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; page))
    
    &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;class&lt;/span&gt;(commits)[1] &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;try-error&amp;#34;&lt;/span&gt;){
      is_still_ok &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; commits &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
    }else{
      is_still_ok &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;
    }
    
    &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(is_still_ok[1]){
      &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get information about commits&lt;/span&gt;
      commit_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(commits, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;commit&amp;#34;&lt;/span&gt;)
      
      &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# commit messages&lt;/span&gt;
      now_messages &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(commit_info, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;)
      messages &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(messages, &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(now_messages))
      
      &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# date (and time)&lt;/span&gt;
      committer &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(commit_info, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;committer&amp;#34;&lt;/span&gt;)
      now_dates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(committer, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;date&amp;#34;&lt;/span&gt;)
      dates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(dates, &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(now_dates))
      
      &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# who committed&lt;/span&gt;
      now_authors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(commit_info, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;author&amp;#34;&lt;/span&gt;)
      now_authors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(now_authors, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;)
      authors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(authors, &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(now_authors))
      
      page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; page &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
    }
  }
  
  results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(commit &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; messages,
                           repo &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; repo,
                           owner &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; who,
                           author &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; authors,
                           datetime &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; dates)
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# I only want commits from Lucy herself&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter_&lt;/span&gt;(results, 
                 lazyeval&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(author, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[Ll]ucy&amp;#34;&lt;/span&gt;)))
}

commits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map2&lt;/span&gt;(lucy_repos&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;repos,
                       lucy_repos&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;who, 
                       get_all_lucy_commits)
commits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(commits)
commits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(commits, 
                         encoding &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;Encoding&lt;/span&gt;(commit))

commits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(commits, 
                         datetime &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd_hms&lt;/span&gt;(datetime))


&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(commits) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;commit&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;repo&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;owner&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;author&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;datetime&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;encoding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Rename park_dat_json.JSON to park_dat_json.json&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18_hackathon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lucy D&amp;rsquo;Agostino McGowan&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18 19:59:44&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;update json&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18_hackathon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lucy&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18 19:59:00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;update json&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18_hackathon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lucy&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18 19:57:29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;update json&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18_hackathon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lucy&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18 19:57:16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;fix json&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18_hackathon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lucy&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18 19:31:56&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;unknown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;first commit &lt;f0&gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+00A4&amp;gt;&amp;lt;U+00A1&amp;gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18_hackathon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;LucyMcGowan&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lucy&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-03-18 19:23:06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;UTF-8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;looking-at-emojis&#34;&gt;Looking at emojis&lt;/h1&gt;
&lt;p&gt;I used this &lt;a href=&#34;https://github.com/today-is-a-good-day/emojis/blob/master/emDict.csv&#34;&gt;awesome emoji dictionary&lt;/a&gt; created and presented in &lt;a href=&#34;http://opiateforthemass.es/articles/emoticons-in-R/&#34;&gt;this blog&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dico &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv2&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://raw.githubusercontent.com/today-is-a-good-day/emojis/master/emDict.csv&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(dico) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;Description&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Native&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Bytes&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;R-encoding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;AERIAL TRAMWAY&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;f0&gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+009A&amp;gt;&amp;lt;U+00A1&amp;gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;\xF0\x9F\x9A\xA1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;ed&gt;&lt;a0&gt;&lt;bd&gt;&lt;ed&gt;&lt;ba&gt;&lt;a1&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;AIRPLANE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&amp;lt;U+2708&amp;gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;\xE2\x9C\x88&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;e2&gt;&amp;lt;9c&amp;gt;&amp;lt;88&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ALARM CLOCK&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&amp;lt;U+23F0&amp;gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;\xE2\x8F\xB0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;e2&gt;&amp;lt;8f&amp;gt;&lt;b0&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ALIEN MONSTER&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;f0&gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+0091&amp;gt;&amp;lt;U+00BE&amp;gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;\xF0\x9F\x91\xBE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;ed&gt;&lt;a0&gt;&lt;bd&gt;&lt;ed&gt;&lt;b1&gt;&lt;be&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;AMBULANCE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;f0&gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+009A&amp;gt;&amp;lt;U+0091&amp;gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;\xF0\x9F\x9A\x91&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;ed&gt;&lt;a0&gt;&lt;bd&gt;&lt;ed&gt;&lt;ba&gt;&amp;lt;91&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;AMERICAN FOOTBALL&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;f0&gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+008F&amp;gt;&amp;lt;U+0088&amp;gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;\xF0\x9F\x8F\x88&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;ed&gt;&lt;a0&gt;&lt;bc&gt;&lt;ed&gt;&lt;bf&gt;&amp;lt;88&amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As the Github username of the person who created, today is a good day! Like in &lt;a href=&#34;https://masalmon.eu/2017/04/30/radioedit/&#34;&gt;my last post&lt;/a&gt; I&amp;rsquo;ll use &lt;code&gt;fuzzyjoin&lt;/code&gt; to identify emojis.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;fuzzyjoin&amp;#34;&lt;/span&gt;)

commits_decoded &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;regex_inner_join&lt;/span&gt;(commits, dico,
                            by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(commit &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Native&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yes! Doing this, I got 63 emojis!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;table&lt;/span&gt;(commits_decoded&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;Description) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  broom&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tidy&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(Freq)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;Var1&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Freq&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;SEE-NO-EVIL MONKEY&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ROOSTER&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;BUG&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;FACE WITH OK GESTURE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;NAIL POLISH&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;PARTY POPPER&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;FACE SCREAMING IN FEAR&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;INFORMATION DESK PERSON&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;RUNNER&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;SUNFLOWER&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Seeing the frequency of the &amp;ldquo;see no evil&amp;rdquo; emoji&amp;hellip; Is Lucy ashamed of her commits? Why, Lucy? Then, rooster is a chicken, and Lucy is trying &lt;a href=&#34;https://twitter.com/LucyStats/status/829905505862709249&#34;&gt;to make the &amp;ldquo;#RChickenLadies&amp;rdquo; hashtag happen&lt;/a&gt; (note to self: Lucy probably has puns in her commit messages). One important point though, on top of these cool most frequent emojis, is the diversity of emojis, 33 unique emojis for 63 emojis in total. It&amp;rsquo;s a real language! I can&amp;rsquo;t wait for Lucy to commit and push more in her public repositories to try and decode this language! And also to see the awesome work behind each commit, of course.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Radio edit: an improved scraping of and look at Radio Swiss classic program</title>
      <link>https://masalmon.eu/2017/04/30/radioedit/</link>
      <pubDate>Sun, 30 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/04/30/radioedit/</guid>
      <description>&lt;p&gt;Last week I published a post about &lt;a href=&#34;https://masalmon.eu/2017/04/23/radioswissclassic/&#34;&gt;scraping Radio Swiss Classic program&lt;/a&gt;. After that, Bob Rudis wrote &lt;a href=&#34;https://rud.is/b/2017/04/23/decomposing-composers-with-r/&#34;&gt;an extremely useful post&lt;/a&gt; improving my code a lot and teaching me cool stuff. I don&amp;rsquo;t know why I forgot to add pauses between requests&amp;hellip; Really bad behaviour! I will use his code today for re-scraping the data.&lt;/p&gt;
&lt;p&gt;Why re-scrape the data? I mentioned broken links in my post. In fact, each time I hit a broken page, Radio Swiss Classic webmaster received an email. That person received &lt;em&gt;a lot&lt;/em&gt; of emails because of me. They repaired the bug explaining these broken pages and contacted me because someone had turned me in (I feel super famous or spied on now), very kindly mentioning they had fixed all pages, and not holding any grudge against me. So let&amp;rsquo;s scrape everything again!&lt;/p&gt;
&lt;h1 id=&#34;scraping-the-program&#34;&gt;Scraping the program&lt;/h1&gt;
&lt;p&gt;So this is mostly Bob Rudis&amp;rsquo; code with my clumsy comments alongside his comments. His are always in-line. I really recommend you to read &lt;a href=&#34;https://rud.is/b/2017/04/23/decomposing-composers-with-r/&#34;&gt;his post&lt;/a&gt;!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rvest&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purrr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;stringi&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lubridate&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidyverse&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# using purrr::safely is cool because if the page &lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# is broken you get NULL as an output&lt;/span&gt;
s_read_html &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;safely&lt;/span&gt;(read_html)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# helper for brevity&lt;/span&gt;
xtract_nodes &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(node, css) {
  &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(node, css) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;html_text&lt;/span&gt;(trim &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
}

get_one_day_program &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(date&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;Sys.Date&lt;/span&gt;(),
                                base_url&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;http://www.radioswissclassic.ch/en/music-programme/search/%s&amp;#34;&lt;/span&gt;,
                                pb&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;) {
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# progress bar magic!&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.null&lt;/span&gt;(pb)) pb&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tick&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;print&lt;/span&gt;()

  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# that&amp;#39;s the part where you&amp;#39;re nice towards the website&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;sample&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;0.25&lt;/span&gt;), &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# ideally, make this sample(5,1)&lt;/span&gt;

  date &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(date) &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# handles case where input is character ISO date&lt;/span&gt;

  pg &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;s_read_html&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;sprintf&lt;/span&gt;(base_url, &lt;span style=&#34;color:#06287e&#34;&gt;format&lt;/span&gt;(date, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;%Y%m%d&amp;#34;&lt;/span&gt;)))

  &lt;span style=&#34;color:#06287e&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.null&lt;/span&gt;(pg&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;result)) {
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# go read Bob Rudis&amp;#39; post, in particular to read about&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# the extra selector for &amp;#34;playlist&amp;#34;&lt;/span&gt;
    dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;data_frame&lt;/span&gt;(

      date &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; date,
      time &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;xtract_nodes&lt;/span&gt;(pg&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;result, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;div[class=&amp;#34;playlist&amp;#34;] *
&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;                                            span[class=&amp;#34;time hidden-xs&amp;#34;]&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;hm&lt;/span&gt;(),
      datetime &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;update&lt;/span&gt;(date, hour &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;hour&lt;/span&gt;(time), minute &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;minute&lt;/span&gt;(time)),
      artist &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;xtract_nodes&lt;/span&gt;(pg&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;result, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;div[class=&amp;#34;playlist&amp;#34;] * span[class=&amp;#34;titletag&amp;#34;]&amp;#39;&lt;/span&gt;),
      title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;xtract_nodes&lt;/span&gt;(pg&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;result, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;div[class=&amp;#34;playlist&amp;#34;] * span[class=&amp;#34;artist&amp;#34;]&amp;#39;&lt;/span&gt;)

    )

  } else {
    &lt;span style=&#34;color:#06287e&#34;&gt;closeAllConnections&lt;/span&gt;()
    &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
  }

}

search_dates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2008-09-01&amp;#34;&lt;/span&gt;), to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-04-22&amp;#34;&lt;/span&gt;), by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;1 day&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# how you can make the progress bar work,&lt;/span&gt;
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# estimate the time necessary for 5 requests&lt;/span&gt;
pb &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;progress_estimated&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(search_dates))
programs_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map_df&lt;/span&gt;(search_dates, get_one_day_program, pb&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;pb)
programs_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; programs_df &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
   dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; time) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
   dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(datetime &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;force_tz&lt;/span&gt;(datetime, tz &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Europe/Zurich&amp;#34;&lt;/span&gt;))
programs_df

&lt;span style=&#34;color:#06287e&#34;&gt;save&lt;/span&gt;(programs_df, file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/radioswissclassic_programs_radioedit.RData&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;load&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/radioswissclassic_programs_radioedit.RData&amp;#34;&lt;/span&gt;)
search_dates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2008-09-01&amp;#34;&lt;/span&gt;), to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-04-22&amp;#34;&lt;/span&gt;), by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;1 day&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This time I got 100% of programs!&lt;/p&gt;
&lt;p&gt;Now I can improve my analysis of the data: My &lt;a href=&#34;https://twitter.com/MilaCarles&#34;&gt;colleague Carles&lt;/a&gt; (who miiight have been receiving the link to each of my posts because I feel he needs to know about all of them&amp;hellip; poor Carles) left a comment on my last post with two nice suggestions.&lt;/p&gt;
&lt;h1 id=&#34;applying-quantile-regression-to-the-duration-of-pieces&#34;&gt;Applying quantile regression to the duration of pieces&lt;/h1&gt;
&lt;p&gt;What Carles said: &amp;ldquo;Regarding differences throughout the day, I agree that there are no major differences on the mean, but there are in the upper quantiles. I&amp;rsquo;d suggest quantile regression or quantile smoothing in case you want to try ;)&amp;rdquo;. Let&amp;rsquo;s not comment on the absence of nose of this smiley, my colleague is a nice guy so I&amp;rsquo;ll try to not freak out and to concentrate on the statistics.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
programs_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(programs_df, datetime)
programs_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(programs_df,
                          duration &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;difftime&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;lead&lt;/span&gt;(datetime, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;),
                                       datetime,
                                       units &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;min&amp;#34;&lt;/span&gt;))

programs_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(programs_df,
                          duration &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(duration &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;60&lt;/span&gt;,
                                            &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;, duration))
programs_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(programs_df,
                          hour &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.factor&lt;/span&gt;(lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;hour&lt;/span&gt;(datetime)))

programs_df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(programs_df,
                             night &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; (lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;hour&lt;/span&gt;(datetime) &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;hour&lt;/span&gt;(datetime) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;))


quantiles &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x){
  probs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;, to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.95&lt;/span&gt;, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.05&lt;/span&gt;)
  quantiles_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;q&amp;#34;&lt;/span&gt;, probs&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;100&lt;/span&gt;)
  quantiles &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_dbl&lt;/span&gt;(probs, &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(p, v &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; x){
    &lt;span style=&#34;color:#06287e&#34;&gt;quantile&lt;/span&gt;(v, probs &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; p, na.rm &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  })
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;as.tibble&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;t&lt;/span&gt;(quantiles))
  &lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(df) &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; quantiles_names
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(df)
}

programs_df &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(night) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(duration_q &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;quantiles&lt;/span&gt;(duration))) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;unnest&lt;/span&gt;(duration_q) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;night&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;q50&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;q55&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;q60&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;q65&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;q70&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;q75&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;q80&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;q85&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;q90&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;q95&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;13&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;26&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Looking at this table above, it&amp;rsquo;s true that the upper quantiles of piece duration seem to be longet at night.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(programs_df) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_histogram&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(duration)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;facet_grid&lt;/span&gt;(night &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; .) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Duration (minutes)&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-04-30-radioedit/unnamed-chunk-4-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-4&#34;&gt;&lt;/p&gt;
&lt;p&gt;And I think these histograms are actually clearer than the boxplots of last post.&lt;/p&gt;
&lt;p&gt;So now let&amp;rsquo;s try quantile regression, which I admit I had never used. The &lt;a href=&#34;https://cran.r-project.org/web/packages/quantreg/vignettes/rq.pdf&#34;&gt;vignette of the &lt;code&gt;quantreg&lt;/code&gt; package&lt;/a&gt; is really nice, it feels a bit old school with a real introduction and a section called &amp;ldquo;What is a vignette?&amp;rdquo;. The vignette starts with this sentence &amp;ldquo;Beran’s (2003) provocative definition of statistics as &amp;lsquo;the study of algorithms for
data analysis&amp;rsquo; elevates computational considerations to the forefront of the field.&amp;rdquo;. &lt;a href=&#34;https://en.wikipedia.org/wiki/Roger_Koenker&#34;&gt;Roger Koenker&lt;/a&gt; also writes &amp;quot; Although there is now some functionality for quantile regression in most of the major commercial statistical packages, I have a natural predilection for the R environment and the software that I have developed for R.&amp;rdquo; which made me smile. Last nice point about the vignette I noticed, it encourages a contributor mindset by saying &amp;ldquo;When such modifications appear to be of general applicability,
it is desirable to communicate them to the package author, so they could be shared with the larger community.&amp;rdquo; Ok a real last point about that package, the list of authors includes Brian D Ripley with this note from Roger Koenker &amp;ldquo;Initial (2001) R port from S (to my everlasting shame &amp;ndash; how could I have been so slow to adopt R!&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;In the following I will just look at the effect of night on the duration for various quantiles, nothing fancy.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;quantreg&amp;#34;&lt;/span&gt;)

model &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rq&lt;/span&gt;(duration &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; night, 
            tau &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;, to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.95&lt;/span&gt;, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.05&lt;/span&gt;), 
           data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; programs_df,
           method &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pfn&amp;#34;&lt;/span&gt;)
summaries &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;summary&lt;/span&gt;(model, se &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ker&amp;#34;&lt;/span&gt;)

transform_summary &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(summ){
  coeffs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;as.tibble&lt;/span&gt;(summ&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;coefficients)
  coeffs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(coeffs, tau &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;summ&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;tau)
  coeffs[2,]
}

purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(summaries, transform_summary) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;Value&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Std. Error&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;t value&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Pr(&amp;gt;|t|)&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;tau&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0082075&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;121.83907&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0082689&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.00000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.55&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0094450&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;105.87571&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0093682&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.00000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.65&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0106465&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;93.92756&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.70&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0122657&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;81.52811&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0216791&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;138.38211&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0298266&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;167.63566&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0428316&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;163.43057&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.90&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0605325&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;165.20043&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.95&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This seems to support the idea that upper quantiles of duration are bigger at night. This shift of the distribution of duration at night compared to its distribution during daytime means that there are more long pieces at night&amp;hellip; which is what the website claims, so we&amp;rsquo;re good. Just for info, we are looking at 171668 pieces played at night and 355487 pieces played during the day, that is to say a lot.&lt;/p&gt;
&lt;h1 id=&#34;using-keywords-to-identify-the-speed-of-pieces&#34;&gt;Using keywords to identify the speed of pieces&lt;/h1&gt;
&lt;p&gt;Carles said: &amp;ldquo;For romantic music the type of composition &amp;ldquo;Scherzo&amp;rdquo;/&amp;ldquo;Waltz&amp;rdquo;/&amp;ldquo;Nocturne&amp;rdquo; may tell you something about the mood of the composition&amp;rdquo;. Okay, time to analyse some text data then! Instead of looking at the mood of the music as suggested by Carles, I&amp;rsquo;ll look at the tempo of the pieces instead (from &lt;a href=&#34;https://en.wikipedia.org/wiki/Tempo&#34;&gt;Wikipedia page&lt;/a&gt;, see &amp;ldquo;Italian tempo markings&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;To identify the tempo of each piece indicating one, I shall use &lt;a href=&#34;https://github.com/dgrtwo/fuzzyjoin&#34;&gt;&lt;code&gt;fuzzyjoin&lt;/code&gt;&lt;/a&gt;, a very handy package for joining tables based on say, close geographical coordinates or regular expressions.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tempos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tolower&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Larghissimo&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Grave&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Largo&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Lento&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Larghetto&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Adagio&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Adagietto&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Andante&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Andantino&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Marcia moderato&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Andante moderato&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Moderato&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Allegretto&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Allegro moderato&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Allegro&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Vivace&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Vivacissimo&amp;#34;&lt;/span&gt;,
    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Allegrissimo&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Presto&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Prestissimo&amp;#34;&lt;/span&gt;))
tempos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(tempo &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; tempos,
                         speed &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(tempos))

programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(programs_df,
                          title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tolower&lt;/span&gt;(title))

&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;fuzzyjoin&amp;#34;&lt;/span&gt;)
programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;regex_inner_join&lt;/span&gt;(programs, tempos,
                            by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tempo&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now I have to take care of pieces that got several tempos, for instance because their title is &amp;ldquo;grave and allegro blabla&amp;rdquo; or &amp;ldquo;something moderato&amp;rdquo; thus yielding &amp;ldquo;something&amp;rdquo; and &amp;ldquo;something moderato&amp;rdquo; as tempos. For the first case I&amp;rsquo;ll randomly sample one of the tempos, for the second case I&amp;rsquo;ll keep the most precise tempo.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(programs)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] 120052
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;split&lt;/span&gt;(programs, programs&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;datetime)

clean_tempos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(df) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;){
    &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;any&lt;/span&gt;(stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;tempo, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; moderato&amp;#34;&lt;/span&gt;))){
      df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter_&lt;/span&gt;(df, lazyeval&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;tempo, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; moderato&amp;#34;&lt;/span&gt;)))
    }else{
      df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;sample_n&lt;/span&gt;(df, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
    }
    
  }
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(df)
  
}

programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(programs, clean_tempos)
programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(programs)
&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(programs)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] 102439
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now that we have 102439 pieces with a known speed out of 527168, let&amp;rsquo;s look at speed distribution depending on the hour of the day.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;programs &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(night) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(mean_speed &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mean&lt;/span&gt;(speed),
            median_speed &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;median&lt;/span&gt;(speed)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;night&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mean_speed&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;median_speed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10.453073&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;TRUE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9.888101&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(programs, speed &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.factor&lt;/span&gt;(speed))

&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;viridis&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(programs) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_bar&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(hour, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; speed),
           position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;fill&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-04-30-radioedit/unnamed-chunk-8-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(programs) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_bar&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(night, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; speed),
           position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;fill&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-04-30-radioedit/unnamed-chunk-8-2.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;&lt;/p&gt;
&lt;p&gt;Honestly, I don&amp;rsquo;t really see a change of speed at night, or only a really small one, so my method was probably not a very good way of estimating the liveliness of pieces.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;d like to say thanks again to Bob Rudis, to Radio Swiss Classic webmaster and to &lt;a href=&#34;https://twitter.com/MilaCarles&#34;&gt;my colleague Carles&lt;/a&gt;. I was also surprised and happy to receive an email from a university music theory teacher, who told me he could use such data in class to look at popular music pieces. I really like how this blogging thing makes me discover new fields!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>A classical analysis (Radio Swiss classic program)</title>
      <link>https://masalmon.eu/2017/04/23/radioswissclassic/</link>
      <pubDate>Sun, 23 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/04/23/radioswissclassic/</guid>
      <description>&lt;p&gt;I am not a classical music expert at all, but I happen to have friends who are, and am even married to someone who plays the cello (and the ukulele!). I appreciate listening to such music from time to time, in particular Baroque music. A friend made me discover &lt;a href=&#34;http://www.radioswissclassic.ch/en&#34;&gt;Radio Swiss classic&lt;/a&gt;, an online radio playing classical music all day and all night long, with a quite nice variety, and very little speaking between pieces, with no ads (thank you, funders of the radio!). Besides, the voices telling me which piece has just been played are really soothing, so Radio Swiss classic is a good one in my opinion.&lt;/p&gt;
&lt;p&gt;Today, instead of anxiously waiting for the results of the French presidential elections, I decided to download the program of the radio in the last years and have a quick look at it, since after all, the website says that the radio aims at relaxing people.&lt;/p&gt;
&lt;h1 id=&#34;scraping-the-program&#34;&gt;Scraping the program&lt;/h1&gt;
&lt;p&gt;My webscraping became a bit more elegant because I followed &lt;a href=&#34;https://twitter.com/expersso/status/839395958316232704&#34;&gt;the advice of EP alias expersso&lt;/a&gt;, who by the way should really start blogging. I started downloading programs since September 2008 because that&amp;rsquo;s when I met the friend who told me about Radio Swiss Classic.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2008-09-01&amp;#34;&lt;/span&gt;),
             to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-04-22&amp;#34;&lt;/span&gt;),
             by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;1 day&amp;#34;&lt;/span&gt;)


base_url &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;http://www.radioswissclassic.ch/en/music-programme/search/&amp;#34;&lt;/span&gt;

get_one_day_program &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(date, base_url){
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# in order to see progress&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;message&lt;/span&gt;(date)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# build URL&lt;/span&gt;
  date_as_string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(date)
  date_as_string &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(date_as_string, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  url &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(base_url, date_as_string)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# read page&lt;/span&gt;
  page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_html&lt;/span&gt;(url),
              silent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is&lt;/span&gt;(page, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;try-error&amp;#34;&lt;/span&gt;)){
    &lt;span style=&#34;color:#06287e&#34;&gt;message&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;horribly wrong&amp;#34;&lt;/span&gt;)

    &lt;span style=&#34;color:#06287e&#34;&gt;closeAllConnections&lt;/span&gt;()
    &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;)
  }else{
    
    &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# find all times, artists and pieces&lt;/span&gt;
    times &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_text&lt;/span&gt;(xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(page, 
                                               xpath&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;//span[@class=&amp;#39;time hidden-xs&amp;#39;]//text()&amp;#34;&lt;/span&gt;))
    artists &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_text&lt;/span&gt;(xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(page, 
                                                 xpath&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;//span[@class=&amp;#39;titletag&amp;#39;]//text()&amp;#34;&lt;/span&gt;))
    pieces &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_text&lt;/span&gt;(xml2&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xml_find_all&lt;/span&gt;(page, 
                                                xpath&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;//span[@class=&amp;#39;artist&amp;#39;]//text()&amp;#34;&lt;/span&gt;))
    &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# the last artist and piece are the current ones&lt;/span&gt;
    artists &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; artists[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(artists) &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)]
    pieces &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pieces[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(pieces) &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)]
    
    &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get a timedate from each time&lt;/span&gt;
    timedates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(date), times)
    timedates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd_hm&lt;/span&gt;(timedates)
    timedates &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;force_tz&lt;/span&gt;(timedates, tz &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Europe/Zurich&amp;#34;&lt;/span&gt;)
    
    &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# format the output&lt;/span&gt;
    program &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(time &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; timedates,
                              artist &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; artists,
                              piece &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; pieces)
    
    &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(program)
  }
  
}

programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(dates, get_one_day_program, 
                       base_url &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; base_url)

programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(programs)

&lt;span style=&#34;color:#06287e&#34;&gt;save&lt;/span&gt;(programs, file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/radioswissclassic_programs.RData&amp;#34;&lt;/span&gt;)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There were some days without any program on the website, for which the website said something was horribly wrong with the server.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;load&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/radioswissclassic_programs.RData&amp;#34;&lt;/span&gt;)
wegot &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;as_date&lt;/span&gt;(programs&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;time)))
wewanted &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2008-09-01&amp;#34;&lt;/span&gt;),
                       to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-04-22&amp;#34;&lt;/span&gt;),
                       by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;1 day&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, I got a program for approximately 0.96 of the days.&lt;/p&gt;
&lt;h1 id=&#34;who-are-the-most-popular-composers&#34;&gt;Who are the most popular composers?&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;table&lt;/span&gt;(programs&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;artist) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  broom&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tidy&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(Freq)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;Var1&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Freq&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Wolfgang Amadeus Mozart&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;37823&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Ludwig van Beethoven&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20936&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Joseph Haydn&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18140&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Franz Schubert&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15596&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Antonio Vivaldi&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14947&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Johann Sebastian Bach&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12003&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Felix Mendelssohn-Bartholdy&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11541&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Antonin Dvorak&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10265&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Gioachino Rossini&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9591&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Frédéric Chopin&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8470&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Piotr Iljitsch Tchaikowsky&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8092&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Georg Friedrich Händel&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7935&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Tomaso Albinoni&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6175&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Gaetano Donizetti&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5945&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Giuseppe Verdi&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5639&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Johannes Brahms&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5526&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Johann Nepomuk Hummel&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5439&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Camille Saint-Saëns&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5395&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Luigi Boccherini&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5130&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Johann Christian Bach&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4976&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I&amp;rsquo;ll have to admit that I don&amp;rsquo;t even know all the composers in this table but they&amp;rsquo;re actually all famous according to my live-in classical music expert. Radio Swiss classic allows listeners to rate pieces, so the most popular ones are programmed more often, and well I guess the person making the programs also tend to program famous composers quite often.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;table&lt;/span&gt;(programs&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;artist) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  broom&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tidy&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_histogram&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(Freq)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_x_log10&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;14&lt;/span&gt;) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-04-23-radioswissclassic/unnamed-chunk-3-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-3&#34;&gt;&lt;/p&gt;
&lt;p&gt;Interestingly, but not that surprisingly I guess given the popularity of, say, Mozart, the distribution of occurrences by composers seems to be log-normally distributed.&lt;/p&gt;
&lt;h1 id=&#34;how-long-are-pieces&#34;&gt;How long are pieces?&lt;/h1&gt;
&lt;p&gt;On the website of Radio Swiss classic it is stated that pieces are longer in the evening than during the day, which I wanted to try and see. Because the program of the radio was not corrected for time changes (i.e. on 25 hour-days there are only 24 hours of music according to the online program), I shall only look at pieces whose duration is smaller than 60 minutes, which solves the issue of missing days at the same time.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(programs, time)
programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(programs,
                          duration &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;difftime&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;lead&lt;/span&gt;(time, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;),
                                       time,
                                       units &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;min&amp;#34;&lt;/span&gt;))

programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(programs,
                          duration &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(duration &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;60&lt;/span&gt;,
                                            &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;, duration))
programs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(programs,
                          hour &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.factor&lt;/span&gt;(lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;hour&lt;/span&gt;(time)))

programs &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_boxplot&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(hour, duration))&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;14&lt;/span&gt;) 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-04-23-radioswissclassic/unnamed-chunk-4-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-4&#34;&gt;&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t find the difference between day and night that striking, maybe I could try to define day and night to have a prettier figure (but I won&amp;rsquo;t do any test, I soon need to go watch TV).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;programs &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(night &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; (lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;hour&lt;/span&gt;(time) &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;hour&lt;/span&gt;(time) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_boxplot&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(night, duration))&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;(base_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;14&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-04-23-radioswissclassic/unnamed-chunk-5-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-5&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The website also states that the pieces are more lively in the morning, but I have no data to which to match the titles of the pieces to investigate that claim. Well I have not even looked for such data. Another extension that I would find interesting would be to match each composer&amp;rsquo;s name to a style and then see how often each style is played. Now I&amp;rsquo;ll stop relaxing and go stuff my face with food in front of the election results!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Sow the seeds, know the seeds</title>
      <link>https://masalmon.eu/2017/04/12/seeds/</link>
      <pubDate>Wed, 12 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/04/12/seeds/</guid>
      <description>&lt;p&gt;When you do simulations, for instance in R, e.g. drawing samples from a distribution, it&amp;rsquo;s best to set a random seed via the function &lt;code&gt;set.seed&lt;/code&gt; in order to have reproducible results. The function has no default value. I think I mostly use &lt;code&gt;set.seed(1)&lt;/code&gt;. Last week I received an R script from a colleague in which he used a weird number in &lt;code&gt;set.seed&lt;/code&gt; (maybe a phone number? or maybe he let his fingers type randomly?), which made me curious about the usual seed values. As in my blog post &lt;a href=&#34;https://masalmon.eu/2017/02/21/firstcommit/&#34;&gt;about initial commit messages&lt;/a&gt; I used the Github API via the &lt;a href=&#34;https://github.com/r-pkgs/gh&#34;&gt;&lt;code&gt;gh&lt;/code&gt; package&lt;/a&gt; to get a very rough answer (an answer seedling from the question seed?).&lt;/p&gt;
&lt;p&gt;From Github API search endpoint you can get up to 1,000 results corresponding to a query which in the case of &lt;code&gt;set.seed&lt;/code&gt; occurrences in R code isn&amp;rsquo;t the whole picture but hopefully a good sample. I wrote a function to treat the output of a query to the API where I take advantage of the &lt;a href=&#34;https://github.com/tidyverse/stringr&#34;&gt;&lt;code&gt;stringr&lt;/code&gt; package&lt;/a&gt;. I just want the thing inside &lt;code&gt;set.seed()&lt;/code&gt; from the text matches returned by the API.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;get_seeds_from_matches &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(item){
  url &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; item&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;html_url
  matches &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; item&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text_matches
  matches &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(matches, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;fragment&amp;#34;&lt;/span&gt;))
  matches &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(matches, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\\n&amp;#34;&lt;/span&gt;, simplify &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  matches &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_extract&lt;/span&gt;(matches, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;set\\.seed\\(.*\\)&amp;#34;&lt;/span&gt;)
  matches &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(matches, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;set\\.seed\\(&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  seeds &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(matches, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\).*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  seeds &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; seeds[&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(seeds)]
  tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(seed &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; seeds,
             url &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(url, &lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(seeds)))
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After that I made the queries themselves, pausing every 30 pages because of the rate limiting, and adding a &lt;code&gt;try&lt;/code&gt; around the call in order to stop as soon as I reached the 1,000 results. Not a very elegant solution but I wasn&amp;rsquo;t in a perfectionnist mood.&lt;/p&gt;
&lt;p&gt;Note that the header &lt;code&gt;&amp;quot;Accept&amp;quot; = &#39;application/vnd.github.v3.text-match+json&#39;&lt;/code&gt; is very important, without it you wouldn&amp;rsquo;t get the text fragments in the results.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;gh&amp;#34;&lt;/span&gt;)
seeds &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;

ok &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;
page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;while&lt;/span&gt;(ok){
  matches &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;gh&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;/search/code&amp;#34;&lt;/span&gt;, q &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;set.seed&amp;amp;language:r&amp;#34;&lt;/span&gt;,
                    .token &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;Sys.getenv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;GITHUB_PAT&amp;#34;&lt;/span&gt;),
                    .send_headers &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Accept&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;application/vnd.github.v3.text-match+json&amp;#39;&lt;/span&gt;),
                    page &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; page), silent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  ok &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is&lt;/span&gt;(matches, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;try-error&amp;#34;&lt;/span&gt;)
 
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(ok){
    seeds &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(seeds, &lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(matches&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;items, 
                                               get_seeds_from_matches)))
  }

  page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; page &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# wait 2 minutes every 30 pages&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(page &lt;span style=&#34;color:#666&#34;&gt;%%&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;30&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt; page &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;){
    &lt;span style=&#34;color:#06287e&#34;&gt;Sys.sleep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;120&lt;/span&gt;)
  }
  
}

&lt;span style=&#34;color:#06287e&#34;&gt;save&lt;/span&gt;(seeds, file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-04-12-seeds.RData.RData&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magrittr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;load&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-04-12-seeds.RData&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(seeds) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;seed&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;url&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/berndbischl/ParamHelpers/blob/9d374430701d94639cc78db84f91a0c595927189/tests/testthat/helper_zzz.R&#34;&gt;https://github.com/berndbischl/ParamHelpers/blob/9d374430701d94639cc78db84f91a0c595927189/tests/testthat/helper_zzz.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/TypeFox/R-Examples/blob/d0917dbaf698cb8bc0789db0c3ab07453016eab9/ParamHelpers/tests/testthat/helper_zzz.R&#34;&gt;https://github.com/TypeFox/R-Examples/blob/d0917dbaf698cb8bc0789db0c3ab07453016eab9/ParamHelpers/tests/testthat/helper_zzz.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/cran/ParamHelpers/blob/92a49db23e69d32c8ae52585303df2875d740706/tests/testthat/helper_zzz.R&#34;&gt;https://github.com/cran/ParamHelpers/blob/92a49db23e69d32c8ae52585303df2875d740706/tests/testthat/helper_zzz.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;4.0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/ACP-KR/AsanAdvR/blob/0517e88efce94266997d680e8b5a7c2a97c9277d/R-Object-Oriented-Programming-master/chapter4/chapter_4_ex11.R&#34;&gt;https://github.com/ACP-KR/AsanAdvR/blob/0517e88efce94266997d680e8b5a7c2a97c9277d/R-Object-Oriented-Programming-master/chapter4/chapter_4_ex11.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;4.0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/ACP-KR/AsanAdvR/blob/0517e88efce94266997d680e8b5a7c2a97c9277d/R-Object-Oriented-Programming-master/chapter4/chapter_4_ex11.R&#34;&gt;https://github.com/ACP-KR/AsanAdvR/blob/0517e88efce94266997d680e8b5a7c2a97c9277d/R-Object-Oriented-Programming-master/chapter4/chapter_4_ex11.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;4.0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/KellyBlack/R-Object-Oriented-Programming/blob/efbb0b81063baa30dd9d56d5d74b3f73b12b4926/chapter4/chapter_4_ex11.R&#34;&gt;https://github.com/KellyBlack/R-Object-Oriented-Programming/blob/efbb0b81063baa30dd9d56d5d74b3f73b12b4926/chapter4/chapter_4_ex11.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I got 984 entries, not 1,000 so maybe I lost some seeds in the process or the results weren&amp;rsquo;t perfect. The reason why I also added the URL of the script to the results was to be able to go and look at the code around surprising seeds.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at the most frequent seeds in the sample.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;table&lt;/span&gt;(seeds&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;seed) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  broom&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tidy&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(Freq)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;Var1&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Freq&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;seed&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;312&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;134&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;123&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;iseed&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;48&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;13121098&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ss&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;20&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;1234&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;42&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;123456&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;So the most prevalent seed is a mystery because I&amp;rsquo;m not motivated enough to go scrape the code to find if the seed gets assigned a value before, like &lt;a href=&#34;https://twitter.com/millerdl/status/852152963502149638&#34;&gt;in that tweet I saw today&lt;/a&gt;. I was happy that 1 was so popular, maybe it means I belong?&lt;/p&gt;
&lt;p&gt;I was surprised by two values. First, 13121098.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(seeds, seed &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;13121098&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;seed&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;url&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;13121098&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/DJRumble/Swirl-Course/blob/4e2771141e579904eb6dd32bce51ff6e0d840d44/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&#34;&gt;https://github.com/DJRumble/Swirl-Course/blob/4e2771141e579904eb6dd32bce51ff6e0d840d44/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;13121098&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/swirldev/swirl_courses/blob/b3d432bfdf480c865af1c409ee0ee927c1fdbda0/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&#34;&gt;https://github.com/swirldev/swirl_courses/blob/b3d432bfdf480c865af1c409ee0ee927c1fdbda0/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;13121098&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/1vbutkus/swirl/blob/310874100536e1e7c66861eced9ecb52939a3e0a/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&#34;&gt;https://github.com/1vbutkus/swirl/blob/310874100536e1e7c66861eced9ecb52939a3e0a/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;13121098&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/gotitsingh13/swirldev/blob/b7369b974ba76716fbcf6101bcbdc2db2f774d18/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&#34;&gt;https://github.com/gotitsingh13/swirldev/blob/b7369b974ba76716fbcf6101bcbdc2db2f774d18/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;13121098&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/pauloramazza/swirl_courses/blob/4e2771141e579904eb6dd32bce51ff6e0d840d44/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&#34;&gt;https://github.com/pauloramazza/swirl_courses/blob/4e2771141e579904eb6dd32bce51ff6e0d840d44/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;13121098&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/ildesoft/Swirl_Courses/blob/3e7f43cecbeb41e92e4f5972658f9b293e0e4b84/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&#34;&gt;https://github.com/ildesoft/Swirl_Courses/blob/3e7f43cecbeb41e92e4f5972658f9b293e0e4b84/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;13121098&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/hrdg/Regression_Models/blob/22f47ecf2ae62f553aa132d3d948cc6b4e1599cc/Residuals_Diagnostics_and_Variation/initLesson.R&#34;&gt;https://github.com/hrdg/Regression_Models/blob/22f47ecf2ae62f553aa132d3d948cc6b4e1599cc/Residuals_Diagnostics_and_Variation/initLesson.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;13121098&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/Rizwanabro/Swirl-Course/blob/3e7f43cecbeb41e92e4f5972658f9b293e0e4b84/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&#34;&gt;https://github.com/Rizwanabro/Swirl-Course/blob/3e7f43cecbeb41e92e4f5972658f9b293e0e4b84/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;13121098&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/mkgiitr/Data-Analytics/blob/1d659db1e9137b1fe595a6ef3356887de431b1be/win-library/3.1/swirl/Courses/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&#34;&gt;https://github.com/mkgiitr/Data-Analytics/blob/1d659db1e9137b1fe595a6ef3356887de431b1be/win-library/3.1/swirl/Courses/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;13121098&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://github.com/Jutair/R-programming-Coursera/blob/4faeed6ca780ee7f14b224c293cae77293146f37/Swirl/Rsubversion/branches/Writing_swirl_Courses/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&#34;&gt;https://github.com/Jutair/R-programming-Coursera/blob/4faeed6ca780ee7f14b224c293cae77293146f37/Swirl/Rsubversion/branches/Writing_swirl_Courses/Regression_Models/Residuals_Diagnostics_and_Variation/initLesson.R&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I went and had a look and it seems most repositories correspond to code learnt in a &lt;a href=&#34;https://es.coursera.org/learn/data-cleaning&#34;&gt;Coursera course&lt;/a&gt;. I have taken a few courses from that specialization and loved it but I don&amp;rsquo;t remember learning about the special seed, too bad. Well I guess everyone used it to reproduce results but what does this number mean in the first place? Who typed it? A cat walking on the keyboard?&lt;/p&gt;
&lt;p&gt;The other number that surprised me was 42 but then I remembered it is the &lt;a href=&#34;https://simple.wikipedia.org/wiki/42_(answer)&#34;&gt;&amp;ldquo;Answer to the Ultimate Question of Life, the Universe, and Everything&amp;rdquo; &lt;/a&gt;. I&amp;rsquo;d therefore say that this might be the coolest random seed. Now I can&amp;rsquo;t tell you whether it produces better results. Maybe it helps when your code actually tries to answer the Ultimate Question of Life, the Universe, and Everything?&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Mapping waxwings annual migration without Twitter</title>
      <link>https://masalmon.eu/2017/04/08/spocc/</link>
      <pubDate>Sat, 08 Apr 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/04/08/spocc/</guid>
      <description>&lt;p&gt;Recently a reader left a comment on this blog mentioning &lt;a href=&#34;https://robbriers.github.io/post/2017-03-14-mapping-the-spread-of-a-migratory-bird-using-twitter/&#34;&gt;his cool blog post&lt;/a&gt; in which he mapped the spread of a migratory bird using Twitter. His data source was &lt;a href=&#34;https://twitter.com/WaxwingsUK&#34;&gt;the Waxwings UK account&lt;/a&gt; which reports sightings of Bohemian waxwings in the UK. I decided to try reproducing and extending his work using &lt;a href=&#34;https://github.com/ropensci/spocc&#34;&gt;the rOpenSci &lt;code&gt;spocc&lt;/code&gt; package&lt;/a&gt; that interfaces different sources of species occurrence data.&lt;/p&gt;
&lt;h1 id=&#34;getting-the-occurrence-data&#34;&gt;Getting the occurrence data&lt;/h1&gt;
&lt;p&gt;As mentioned above I got the data via &lt;code&gt;spocc&lt;/code&gt;. I read the README of the Github repo and learnt that it&amp;rsquo;s called &lt;code&gt;spocc&lt;/code&gt; like &lt;em&gt;sp&lt;/em&gt;ecies &lt;em&gt;occ&lt;/em&gt;urrence data. So now I should never forget how many &amp;ldquo;c&amp;rdquo; there are in the word &lt;em&gt;occurrence&lt;/em&gt;. Now please send help for my remembering it has two &amp;ldquo;r&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;spocc&lt;/code&gt; package interacts with so many data sources that I felt a bit overwhelmed. I guess ecologists are not often blessed with so much data. Note that I don&amp;rsquo;t limit my query to the UK. Indeed, since seeing &lt;a href=&#34;https://en.wikipedia.org/wiki/Bohemian_waxwing#/media/File:Bombycillagarrulusmap2.png&#34;&gt;this map&lt;/a&gt; my interest for the Bohemian waxwing became global. I even decided to get data for the two other species of waxwings, although it only worked for the Bohemian and Cedar waxwings in the end.&lt;/p&gt;
&lt;p&gt;I decided to use only data from &lt;a href=&#34;http://www.gbif.org/&#34;&gt;GBIF&lt;/a&gt;. You&amp;rsquo;ll find more information about GBIF for instance, and other data sources for species occurrences, in this &lt;a href=&#34;https://ropensci.org/blog/2014/03/17/spocc/&#34;&gt;blog post from rOpenSci blog&lt;/a&gt;. Since I wanted to get data for different years and all 3 species of waxwings, which meant a lot of data so for getting it I sliced the Earth (I like how evil this sentence makes me sound, ah!). Note that I used overlapping slices because otherwise I didn&amp;rsquo;t get data at the limits between slices. I guess I could have made my slices slightly less overlapping though.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;spocc&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purrr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;scrubr&amp;#34;&lt;/span&gt;)
get_slice &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(longitude, year){
  &lt;span style=&#34;color:#06287e&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(year, longitude))
  gbifopts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(limit &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;200000&lt;/span&gt;,
                   year &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; year)
  waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;occ&lt;/span&gt;(query &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Bombycilla&amp;#34;&lt;/span&gt;,
                  from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;gbif&amp;#39;&lt;/span&gt;), 
                  gbifopts &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; gbifopts,
                  geometry &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(longitude &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;90&lt;/span&gt;, 
                               longitude &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;90&lt;/span&gt;))
  waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;occ2df&lt;/span&gt;(waxwings)
}
longitudes &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;( &lt;span style=&#34;color:#40a070&#34;&gt;-180&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;179&lt;/span&gt;, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;)
years &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;2011&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2016&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(lo ngitudes))
longitudes &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(longitudes,  &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;)
waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map2&lt;/span&gt;(longitudes, years, get_slice)
&lt;span style=&#34;color:#06287e&#34;&gt;for &lt;/span&gt;(i in &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(waxwings)){
  waxwings[[i]]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;latitude &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(waxwings[[i]]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;latitude)
  waxwings[[i]]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;longitude &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(waxwings[[i]]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;longitude)
}

waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(waxwings)
waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(waxwings)

waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(waxwings, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(name))
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(waxwings, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;uncleaned_waxwings.csv&amp;#34;&lt;/span&gt;)


&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;cleaning-the-occurrence-data&#34;&gt;Cleaning the occurrence data&lt;/h1&gt;
&lt;p&gt;Now because my MSc of ecology is far behind me (but still close to my heart!) I have no idea how to assess the quality of species occurrence data. And even if I did I would have been delighted by the discovery of another rOpenSci package, &lt;a href=&#34;https://github.com/ropensci/scrubr&#34;&gt;&lt;code&gt;scrubr&lt;/code&gt;&lt;/a&gt;, whose aim is to clean species occurrence records. Because I had so much data, I cleaned each day separately, otherwise it was just too long and hard on my poor computer. Don&amp;rsquo;t start thinking &lt;code&gt;scrubr&lt;/code&gt; is slow, it isn&amp;rsquo;t and it&amp;rsquo;s getting faster by the minute &lt;a href=&#34;https://github.com/ropensci/scrubr/issues/26&#34;&gt;thanks to work by its maintainer&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;cleanup &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
  &lt;span style=&#34;color:#06287e&#34;&gt;print&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;date[1])
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; df &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;coord_impossible&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;coord_incomplete&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;coord_unlikely&lt;/span&gt;() 

    &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(df) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;){
    
      df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;dedup&lt;/span&gt;(df)
    }
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; df &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;date_standardize&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;%Y-%m-%d&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;date_missing&lt;/span&gt;()
    &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(df)
} 
waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;uncleaned_waxwings.csv&amp;#34;&lt;/span&gt;)


waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;split&lt;/span&gt;(waxwings, 
                  waxwings&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;date)

waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(waxwings, cleanup)

waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(waxwings)
waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(waxwings)
waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(waxwings, name &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Bombycilla japonica&amp;#34;&lt;/span&gt;,
                   longitude &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;50&lt;/span&gt;)
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(waxwings, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;waxwings.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I removed the records with impossible, incomplete or unlikely coordinates (unlikely being e.g. a political centroid, impossible coordinates with a too high longitude), I also removed duplicate records and records without a data. This was so easy! I&amp;rsquo;d like the &lt;code&gt;scrubr&lt;/code&gt; package to come clean my flat, as a team with the &lt;a href=&#34;https://github.com/sfirke/janitor&#34;&gt;&lt;code&gt;janitor&lt;/code&gt; package&lt;/a&gt;. Now, in real life, I&amp;rsquo;d probably be even stricter with data cleaning but for the scope of this blog post, using that package without any additionnal check was enough.&lt;/p&gt;
&lt;p&gt;I also removed occurrences of the Japanese waxwing because they were too few of them, and occurrences with a longitude higher than 50 because it seemed weird to have non Japanese waxwings in Asia. After all this glorious data cleaning, I had 1015603 records.&lt;/p&gt;
&lt;h1 id=&#34;exploring-the-data&#34;&gt;Exploring the data&lt;/h1&gt;
&lt;p&gt;Let the fun begin!&lt;/p&gt;
&lt;h2 id=&#34;number-of-occurrences-by-species-over-time&#34;&gt;Number of occurrences by species over time&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lubridate&amp;#34;&lt;/span&gt;)
waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(waxwings,
                   week &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;update&lt;/span&gt;(date, wday &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;))
waxwings &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(week, name) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(week, n)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;facet_grid&lt;/span&gt;(name &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; ., scales &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;free_y&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
   &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(strip.text.y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Time (weeks)&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;No. of occurrences&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-04-08-spocc/unnamed-chunk-2-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-2&#34;&gt;&lt;/p&gt;
&lt;p&gt;I have no idea why I have no data in 2016 for one of the two species. I decided to not investigate it further since I had enough birds for my primary goal which was mapping migration. The number of occurrences of Cedar waxwing increases over time before 2016, maybe because of more birders reporting sightings? For both species there is a clear seasonality, probably because these birds tend to breed in places where less people can observe them as we&amp;rsquo;ll see later in the post.&lt;/p&gt;
&lt;h2 id=&#34;day-of-the-week-effects&#34;&gt;Day-of-the-week effects&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(waxwings, 
                   wday &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;wday&lt;/span&gt;(date, label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;))
waxwings &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;update&lt;/span&gt;(date, wday &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;), wday) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_boxplot&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(wday, n))&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;labs&lt;/span&gt;(x&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Day of the week&amp;#34;&lt;/span&gt;, y&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;No. of reported occurrences&amp;#34;&lt;/span&gt;,
       title&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;No. of occurrences of waxwings by day-of-the week&amp;#34;&lt;/span&gt;,
       caption&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Data from GBIF accessed via rOpenSci package spocc&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-04-08-spocc/unnamed-chunk-3-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-3&#34;&gt;&lt;/p&gt;
&lt;p&gt;So, more birds are reported on week-ends than on weekdays which I assume is due to a difference in human rather than bird behaviour (but who knows?). Note that for finer characterization of days where more people are birding, I could have used the &lt;a href=&#34;https://github.com/wilsonfreitas/R-bizdays&#34;&gt;&lt;code&gt;bizdays&lt;/code&gt; package&lt;/a&gt;, but then I&amp;rsquo;d have limited my observations for one country only, because mixing holidays from different countries doesn&amp;rsquo;t sound like fun. Another thing that might influence sightings, beside people having the day off, might be the weather. For getting weather data in R I can recommend &lt;a href=&#34;http://ropensci.org/blog/blog/2017/04/04/gsodr&#34;&gt;a&lt;/a&gt; &lt;a href=&#34;https://github.com/ropensci/rnoaa&#34;&gt;few&lt;/a&gt; &lt;a href=&#34;https://github.com/ropensci/riem&#34;&gt;packages&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;mapping-the-migrations&#34;&gt;Mapping the migrations!&lt;/h1&gt;
&lt;p&gt;I first decided to plot the occurrences themselves on maps, by month, and to make a gif out of it. I then had to choose the colour and shape of the points used to represent the birds. Shape? Bird emojis of course! Regarding the colour, I was quite glad when someone I follow on Twitter posted about the birdcolourbot account created by &lt;a href=&#34;https://twitter.com/millerdl/status/846713149323726848&#34;&gt;David Lawrence Miller&lt;/a&gt;, because I looked and found &lt;a href=&#34;https://twitter.com/birdcolourbot/status/847706299936587776&#34;&gt;this tweet&lt;/a&gt; with colours for the Bohemian waxwing, Bombycilla garrulus, the one present in both America and Europe. For the Cedar waxwing I had to create a palette myself, which I&amp;rsquo;d never thought of doing if I hadn&amp;rsquo;t seen the birdcolourbot account, I&amp;rsquo;m not a colour artist and often stick to &lt;a href=&#34;https://cran.r-project.org/web/packages/viridis/vignettes/intro-to-viridis.html&#34;&gt;&lt;code&gt;viridis&lt;/code&gt;&lt;/a&gt;. I used &lt;a href=&#34;https://www.allaboutbirds.org/guide/Cedar_Waxwing/id&#34;&gt;a pretty pic&lt;/a&gt; from the internet. In both cases, I uploaded images &lt;a href=&#34;http://imagecolourpicker.com/es&#34;&gt;on this website&lt;/a&gt; to get colour codes. A bit of copy-paste work but much easier than having to mix paint colours for real.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;bohemian_palette &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#1A1A1A&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#878787&amp;#34;&lt;/span&gt;,
                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#B15929&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#E21A1C&amp;#34;&lt;/span&gt;,
                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#FEFF99&amp;#34;&lt;/span&gt;)

cedar_palette &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#050608&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#5D5C7A&amp;#34;&lt;/span&gt;,
                   &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#AF5F2A&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#8E2F49&amp;#34;&lt;/span&gt;,
                   &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#F3DD31&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To me both species look quite similar so I didn&amp;rsquo;t expect the palettes to be reallt different. I decided the colours would all have the same probability, instead of weighing them according them to their presence in the usual patterns of each species.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(waxwings,
                   colour &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;factor&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;sample&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(waxwings), replace &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)))
waxwings &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(waxwings,
                   month &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;month&lt;/span&gt;(date),
                   month_name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;month&lt;/span&gt;(date, label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;, abbr &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;))
bohemian &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(waxwings,
                   name &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Bombycilla garrulus&amp;#34;&lt;/span&gt;)


cedar &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(waxwings,
                   name &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Bombycilla cedrorum&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After this preparation of the two data.frames I created a function for plotting a month of data for one species. A point I&amp;rsquo;d like to work on in the future for not being so ashamed of each of my maps are projections.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggalt&amp;#34;&lt;/span&gt;) 
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magick&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggmap&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;emojifont&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;load.emojifont&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;OpenSansEmoji.ttf&amp;#39;&lt;/span&gt;)
wax_map &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map_data&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;)
wax_map &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; wax_map[wax_map&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;region &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Antarctica&amp;#34;&lt;/span&gt;,]

plot_month_species &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df, species,
                               name, palette){
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;()
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;geom_map&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; wax_map,
                    map &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; wax_map,
                    &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; long, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lat, map_id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; region),
                    color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;white&amp;#34;&lt;/span&gt;, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#7f7f7f&amp;#34;&lt;/span&gt;,
                    size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.05&lt;/span&gt;, alpha &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;)
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;theme_map&lt;/span&gt;() 
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;geom_text&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(longitude, latitude,
                col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colour),
                label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;emoji&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bird&amp;#34;&lt;/span&gt;),
                      data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; df,
            family&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;OpenSansEmoji&amp;#34;&lt;/span&gt;, 
                      size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;)
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;scale_colour_manual&lt;/span&gt;(values &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; palette)
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ylim&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(species&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;latitude), 
                &lt;span style=&#34;color:#06287e&#34;&gt;max&lt;/span&gt;(species&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;latitude))
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;xlim&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(species&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;longitude), 
                &lt;span style=&#34;color:#06287e&#34;&gt;max&lt;/span&gt;(species&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;longitude))
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(legend.position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;)
  outfil &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;fig_waxwings/&amp;#34;&lt;/span&gt;, name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;_&amp;#34;&lt;/span&gt;, df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;month[1], &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;ggsave&lt;/span&gt;(outfil, p, width&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;, height&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(outfil) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;image_annotate&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;month_name[1]),
                   size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;100&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(outfil)
  outfil
  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I chose to annotate the graph after creating it in order not to have to use the emoji font for the month name.&lt;/p&gt;
&lt;p&gt;I first applied the function to the Bohemian waxwings.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;bohemian_l &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;split&lt;/span&gt;(bohemian, bohemian&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;month)


bohemian_l &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(plot_month_species, species &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; bohemian, name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bohemian&amp;#34;&lt;/span&gt;, palette &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; bohemian_palette) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(image_read) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_join&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_animate&lt;/span&gt;(fps&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bohemian.gif&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/bohemian.gif&#34; alt=&#34;bohemian&#34; width=&#34;700&#34;&gt;
&lt;p&gt;First observation: I think the colours are pretty, but I also think I&amp;rsquo;ve just invented the concept of a confetti map and I&amp;rsquo;m not sure I&amp;rsquo;m proud of that. Then, regarding the underlying bird movements, Bohemian waxwings breed in the spring in regions farther up North than the regions where they winter and this can be seen on the map. There seem to be less sightings in the breeding season, probably because less people live up there, and apparently Santa&amp;rsquo;s helpers don&amp;rsquo;t even help.&lt;/p&gt;
&lt;p&gt;Then it was the turn of the Cedar waxwing for which I had many more observations (871310 vs. 144293). Brace yourself for many confetti!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;cedar_l &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;split&lt;/span&gt;(cedar, cedar&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;month)


cedar_l &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(plot_month_species, species &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; cedar, name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cedar&amp;#34;&lt;/span&gt;, palette &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; cedar_palette) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(image_read) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_join&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_animate&lt;/span&gt;(fps&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cedar.gif&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/cedar.gif&#34; alt=&#34;cedar&#34; width=&#34;700&#34;&gt;
&lt;p&gt;I&amp;rsquo;ve had a lot of fun making my confetti gifs. I could extend the analysis by using spatial smoothing to draw the zone where waxwings are mostly seen each month. I think the general pattern is clear enough now, but there are some outliers like one Bohemian waxwing in Spain. If there really is a Bohemian waxwing in Spain I&amp;rsquo;d appreciate its visiting me because I&amp;rsquo;ve never seen a waxwing!&lt;/p&gt;
&lt;h1 id=&#34;concluding&#34;&gt;Concluding&lt;/h1&gt;
&lt;p&gt;I was impressed by rOpenSci tools for getting and cleaning occurrence data, and quite thankful for the species occurrence data provided by GBIF. I liked plotting migration thanks to species occurrence, although I guess the best method for knowing migration patterns is tracking birds. But then I&amp;rsquo;ll let professionals do this and keep my bird migration confetti map making as a nice hobby.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Faces of #rstats Twitter</title>
      <link>https://masalmon.eu/2017/03/19/facesofr/</link>
      <pubDate>Sun, 19 Mar 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/03/19/facesofr/</guid>
      <description>&lt;p&gt;This week I was impressed by &lt;a href=&#34;https://twitter.com/DEJPett/status/842330248549158913&#34;&gt;this tweet&lt;/a&gt; where Daniel Pett, Digital Humanities Lead at the British Museum, presented a collage of Twitter profile pics of all his colleagues. He made this piece of art using R (for collecting the usernames) and Python. I&amp;rsquo;m a bit of an R fanatic (or a Python dummy&amp;hellip;) so I decided to write a code in R only to make a collage of profile pics of Twitter #rstats users.&lt;/p&gt;
&lt;p&gt;Note: if you&amp;rsquo;re interested in Daniel Pett&amp;rsquo;s code, the data gathering is &lt;a href=&#34;https://github.com/BritishMuseumDH/BMTwitter&#34;&gt;here&lt;/a&gt; and the montage code is &lt;a href=&#34;https://github.com/BritishMuseumDH/scripts/blob/master/imageDownloadFromCSV.py&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;getting-the-users&#34;&gt;Getting the users&lt;/h1&gt;
&lt;p&gt;Once again I&amp;rsquo;ll use &lt;code&gt;rtweet&lt;/code&gt;! In case you&amp;rsquo;ve been using &lt;code&gt;twitteR&lt;/code&gt;, note that &lt;code&gt;twitteR&lt;/code&gt; maintainer is currently passing the torch to &lt;code&gt;rtweet&lt;/code&gt; so you&amp;rsquo;d better switch packages.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rtweet&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magick&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;httr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;stringr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purrr&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;search_users&lt;/span&gt;(q&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;#rstats&amp;#39;&lt;/span&gt;,
                      n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1000&lt;/span&gt;,
                      parse &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(users)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I &lt;em&gt;think&lt;/em&gt; that doing this I got only profiles whose description includes &amp;ldquo;rstats&amp;rdquo; or &amp;ldquo;#rstats&amp;rdquo;. Moreover, although I got 1,000 results, many of them were duplicates, so in the end I had about 450 #rstats Twitter users.&lt;/p&gt;
&lt;h1 id=&#34;gathering-profile-pics&#34;&gt;Gathering profile pics&lt;/h1&gt;
&lt;p&gt;This is the part where I felt slightly creepy downloading pictures of so many people.&lt;/p&gt;
&lt;p&gt;I first had to create the link to each person&amp;rsquo;s profile page.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(users,
                where &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://twitter.com/&amp;#34;&lt;/span&gt;,
                               screen_name))
                               
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I wrote a function for getting the profile pic for each user. I worked for everyone except 1) eggs and 2) a person whose profile pic had no extension, so I was quite satisfied with the result.&lt;/p&gt;
&lt;p&gt;Update: Daniel Pett told me I could have used the column &amp;ldquo;profile_image_url&amp;rdquo; of the data.frame obtained from &lt;code&gt;rtweet::search_users&lt;/code&gt;&amp;hellip; I had completely missed that column! Thanks a lot!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;get_piclink &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
  content &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;GET&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;where)
  content &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; httr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;content&lt;/span&gt;(content, as &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;)
  image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_extract&lt;/span&gt;(content,
                       &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;class=\&amp;#34;ProfileAvatar-image \&amp;#34; src=\&amp;#34;https://pbs.twimg.com/profile_images/.*\\..*\&amp;#34; alt&amp;#34;&lt;/span&gt;)
  image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(image, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;class=\&amp;#34;ProfileAvatar-image \&amp;#34; src=\&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(image, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;..alt&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(image)
}

users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;by_row&lt;/span&gt;(users, get_piclink,
                .to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;piclink&amp;#34;&lt;/span&gt;, .collate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols&amp;#34;&lt;/span&gt;)

readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(users, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;users.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After getting the links I could start saving the pictures, in a small 50px x 50px format. At that point I started using the &lt;a href=&#34;https://github.com/ropensci/magick&#34;&gt;&lt;code&gt;magick&lt;/code&gt; package&lt;/a&gt;, a real game changer for image manipulation in R!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;save_image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
  image &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;piclink), silent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;class&lt;/span&gt;(image)[1] &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;try-error&amp;#34;&lt;/span&gt;){
    image &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
      &lt;span style=&#34;color:#06287e&#34;&gt;image_scale&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;50x50&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
      &lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-03-19-facesofr_users_images/&amp;#34;&lt;/span&gt;, df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;screen_name,&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.jpg&amp;#34;&lt;/span&gt;))
  }
  
}

users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(users, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(piclink))
users &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;split&lt;/span&gt;(users, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(users))
&lt;span style=&#34;color:#06287e&#34;&gt;walk&lt;/span&gt;(users, save_image)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I got 448 images.&lt;/p&gt;
&lt;h1 id=&#34;preparing-the-collage-itself&#34;&gt;Preparing the collage itself&lt;/h1&gt;
&lt;p&gt;I want to take a minute thinking about myself in elementary school. I am left-handed and I had scissors for right-handed people that I used with my left hand because no one in my family or school knew any better. I was therefore very bad at collages because of the cutting part. Had I known that I&amp;rsquo;d do collages with a computer as a grown-up, I would have been less sad to have to skip the break to keep on slowly cutting pieces of paper! (Note: I actually had a very happy childhood.)&lt;/p&gt;
&lt;p&gt;Back to R talk now! For doing the collage I had to know how many columns and rows I wanted. For this I factorized the number of pics I had. Note that I also re-sampled the images, because I didn&amp;rsquo;t want all the R-Ladies chapters and their beautiful purple logo to end up near each other in the collage.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;files &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;dir&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-03-19-facesofr_users_images/&amp;#34;&lt;/span&gt;, full.names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
files &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sample&lt;/span&gt;(files, &lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(files))
gmp&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;factorize&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(files))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Big Integer (&#39;bigz&#39;) object of length 7:
## [1] 2 2 2 2 2 2 7
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Based on this I chose this format:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;no_rows &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;28&lt;/span&gt;
no_cols &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In &lt;code&gt;magick&lt;/code&gt; there&amp;rsquo;s a function for appending images, &lt;code&gt;image_append&lt;/code&gt;, from which you get either a row or a column depending on the &lt;code&gt;stack&lt;/code&gt; argument. I first created all columns.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;make_column &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(i, files, no_rows){
  &lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(files&lt;span style=&#34;color:#06287e&#34;&gt;[&lt;/span&gt;(i&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;no_rows&lt;span style=&#34;color:#40a070&#34;&gt;+1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;((i&lt;span style=&#34;color:#40a070&#34;&gt;+1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;no_rows)]) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_append&lt;/span&gt;(stack &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols/&amp;#34;&lt;/span&gt;, i, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.jpg&amp;#34;&lt;/span&gt;))
}

&lt;span style=&#34;color:#06287e&#34;&gt;walk&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(no_cols&lt;span style=&#34;color:#40a070&#34;&gt;-1&lt;/span&gt;), make_column, files &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; files,
    no_rows &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; no_rows)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally, I appended the columns!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;image_read&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;dir&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols/&amp;#34;&lt;/span&gt;, full.names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;image_append&lt;/span&gt;(stack &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2017-03-19-facesofr.jpg&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;the-end&#34;&gt;The end&lt;/h1&gt;
&lt;p&gt;Here is the result, where many, many R users are most certainly missing. Besides, can we talk about these accounts with the old R logo? They make me feel old, while the R-Ladies logo make me happy. Too bad &lt;a href=&#34;https://twitter.com/R_Forwards&#34;&gt;Forwards&lt;/a&gt; wasn&amp;rsquo;t included, because their logo is really pretty.&lt;/p&gt;
&lt;img src=&#34;https://masalmon.eu/figure/2017-03-19-facesofr.jpg&#34; alt=&#34;facesofr&#34;&gt;
&lt;p&gt;Now you can try doing the same with your followers, the people you follow, or making a doormat with base plot advocates.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Hundreds of Guardian blind dates</title>
      <link>https://masalmon.eu/2017/03/07/blinddates/</link>
      <pubDate>Tue, 07 Mar 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/03/07/blinddates/</guid>
      <description>&lt;p&gt;One of my more or less guilty pleasures is reading &lt;a href=&#34;https://www.theguardian.com/lifeandstyle/series/blind-date&#34;&gt;The Guardian blind date&lt;/a&gt; each week. I think I started doing this when living in Cambridge, England for five months. I would buy &lt;a href=&#34;https://en.wikipedia.org/wiki/I_(newspaper)&#34;&gt;i&lt;/a&gt; every weekday and The Guardian week-end every week-end. I wasn&amp;rsquo;t even dating at the time I discovered The Guardian blind dates but I&amp;rsquo;ve always liked their format.&lt;/p&gt;
&lt;p&gt;I get so much into each date report that seeing both participants say they want to meet again makes me ridiculously happy. I like wondering how matches were made, but today I just want to look into the contents of post-date interviews.&lt;/p&gt;
&lt;h1 id=&#34;scraping-the-data&#34;&gt;Scraping the data&lt;/h1&gt;
&lt;p&gt;The first step was scraping the data from The Guardian&amp;rsquo;s website. Webscraping has gotten quite boring at this point on my blog I guess, but I see no alternative.&lt;/p&gt;
&lt;h2 id=&#34;getting-links-to-all-articles&#34;&gt;Getting links to all articles&lt;/h2&gt;
&lt;p&gt;The structure of a link to a blind date was quite unpredictable so I scraped all links from the 13 pages like &lt;a href=&#34;%22https://www.theguardian.com/lifeandstyle/series/blind-date?page=1%22&#34;&gt;this one&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rvest&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;stringr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purrr&amp;#34;&lt;/span&gt;)
get_link &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(link){
    link &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;a href=.&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, link)
    link &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\&amp;#34;.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, link)
    link
  }
get_page_links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(page_number){
  url &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.theguardian.com/lifeandstyle/series/blind-date?page=&amp;#34;&lt;/span&gt;, page_number)
  page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;read_html&lt;/span&gt;(url)
  
  links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(page, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt;) 
  
  text &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;html_text&lt;/span&gt;(links)
  links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; links&lt;span style=&#34;color:#06287e&#34;&gt;[which&lt;/span&gt;(stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(text, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Blind date&amp;#34;&lt;/span&gt;))]
  
  links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(links, get_link)
  links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(links)
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(links)
}

all_links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; purrr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;13&lt;/span&gt;, get_page_links)
all_links &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(all_links)

&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(all_links)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;https://www.theguardian.com/lifeandstyle/2017/apr/01/blind-date-id-planned-my-escape-dan-jack&amp;quot;           
## [2] &amp;quot;https://www.theguardian.com/lifeandstyle/2017/mar/25/blind-date-bex-fashion-pr-meets-henry-civil-servant&amp;quot;
## [3] &amp;quot;https://www.theguardian.com/lifeandstyle/2017/mar/18/blind-date-i-mistook-a-waiter-for-my-date&amp;quot;          
## [4] &amp;quot;https://www.theguardian.com/lifeandstyle/2017/mar/11/blind-date-we-talked-about-having-children&amp;quot;         
## [5] &amp;quot;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&amp;quot;                            
## [6] &amp;quot;https://www.theguardian.com/lifeandstyle/2017/feb/25/blind-date-david-mary&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Doing this I found 434 links. How exciting!&lt;/p&gt;
&lt;h2 id=&#34;extract-content-from-each-article&#34;&gt;Extract content from each article&lt;/h2&gt;
&lt;p&gt;Then for each article I tried to extract answers to 8 questions. I&amp;rsquo;ve seen at least &lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2016/dec/10/blind-date-elise-oliver&#34;&gt;one example&lt;/a&gt; with not exactly these questions which was a shock although the question &amp;ldquo;Would you follow them on social media?&amp;rdquo; is great.&lt;/p&gt;
&lt;p&gt;I first wrote down all the classical questions.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;questions &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(number &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;8&lt;/span&gt;,
                        question &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;First impressions&amp;#34;&lt;/span&gt;,
                                     &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;What did you talk about\\?&amp;#34;&lt;/span&gt;,
                                     &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Any awkward moments\\?&amp;#34;&lt;/span&gt;,
                                     &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Good table manners\\?&amp;#34;&lt;/span&gt;,
                                     &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Best thing about&amp;#34;&lt;/span&gt;,
                                     &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Did you go on somewhere\\?&amp;#34;&lt;/span&gt;,
                                     &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Marks out of 10\\?&amp;#34;&lt;/span&gt;,
                                     &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Would you meet again\\?&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I defined the function for getting answers to one question, taking into account the fact that this question was maybe not asked. The function is used in a function for scraping pages.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;for_one_question &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(question, content, link){
  answer &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; content&lt;span style=&#34;color:#06287e&#34;&gt;[which&lt;/span&gt;(stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(content, question))]
  answer &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(answer, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.*&amp;lt;br\\/&amp;gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  answer &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(answer, question, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  answer &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(answer, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;\\/p&amp;gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  answer &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(answer, question, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  answer &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(answer, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  answer &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(answer, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;\\/strong&amp;gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  answer &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(answer)
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(answer) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;){
    &lt;span style=&#34;color:#06287e&#34;&gt;data.frame&lt;/span&gt;(question &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(question, &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;),
               answer &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; answer, which &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;,
               link &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(link, &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;))
  }else{
    &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
  }
  
} 

scrape_page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(link){
  &lt;span style=&#34;color:#06287e&#34;&gt;print&lt;/span&gt;(link)
  content &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;read_html&lt;/span&gt;(link)&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
    &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;p&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;()
  
  answers &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(questions&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;question, for_one_question,
                 content &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; content,
                 link &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; link)
  answers &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;suppressWarnings&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(answers))
  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And at last I could scrape all the data, that I gitignored for not making public something I&amp;rsquo;m not sure I can.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;results &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(all_links, scrape_page) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;()

readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(results, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-03-07-blinddates_allanswers.csv&amp;#34;&lt;/span&gt;)

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;question&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;answer&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;which&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;link&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;First impressions&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Cool, comfortable, cultured.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&#34;&gt;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;First impressions&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;He was very warm, friendly and dynamic.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&#34;&gt;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;What did you talk about?&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Our families, travelling, religion, how much we both like &lt;a href=&#34;https://www.theguardian.com/music/2011/apr/17/jamiroquai-review&#34; data-link-name=&#34;in body link&#34; class=&#34;u-underline&#34;&gt;Jamiroquai&lt;/a&gt;, and what it would be like living on Mars. Or a desert island. Or a desert island on Mars. Who would win: giant spider v giant octopus? The usual.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&#34;&gt;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;What did you talk about?&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Life’s zigzags, comedy, Mars.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&#34;&gt;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Any awkward moments?&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;When the manager raced out of the restaurant as we were saying goodbye. We thought he was going to slap us with a crazy bill. He was just coming to say goodbye.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&#34;&gt;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Any awkward moments?&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;We were seated at different tables at the beginning.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&#34;&gt;https://www.theguardian.com/lifeandstyle/2017/mar/04/blind-date-damola-karen&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For a Guardian blind date fan like myself, getting all this data was really cool.&lt;/p&gt;
&lt;h1 id=&#34;analysing-blind-dates&#34;&gt;Analysing blind dates&lt;/h1&gt;
&lt;p&gt;This is a quite wrong section title since I won&amp;rsquo;t do any fancy analysis. I want to look at only part of the classical questions.&lt;/p&gt;
&lt;h2 id=&#34;so-what-did-they-talk-about&#34;&gt;So what did they talk about?&lt;/h2&gt;
&lt;p&gt;For knowing what people talked about in all these dates, I&amp;rsquo;ll look for the most common words. Note that I&amp;rsquo;m not looking at the consistency between date participants answers (in theory you should have talked about the same things as the other person on your date, but human memory isn&amp;rsquo;t perfect), and I&amp;rsquo;ll use all answers together. I remove stopwords and words related to html formatting or links in the answers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidytext&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rcorpora&amp;#34;&lt;/span&gt;)
what &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(results, question &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;What did you talk about\\?&amp;#34;&lt;/span&gt;)

stopwords &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;corpora&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;words/stopwords/en&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;stopWords

what_words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; what &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(word, answer) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(word, sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;word &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; stopwords) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;word &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;href&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;http&amp;#34;&lt;/span&gt;,
                      &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;strong&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;link&amp;#34;&lt;/span&gt;,
                      &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;,
                      &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt;,
                      &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;class&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;underline&amp;#34;&lt;/span&gt;))
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(what_words, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;word&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;work&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;98&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;music&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;90&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;food&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;88&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;travel&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;london&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;84&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;meet&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;82&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;family&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;74&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;jobs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;66&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;friends&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;55&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;travelling&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;50&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Remember we&amp;rsquo;re looking at 434 blind dates and in particular 828 answers. So these unsurprising common themes are not that common, but then people might have used synonyms.&lt;/p&gt;
&lt;h2 id=&#34;what-grade-did-they-give-each-other&#34;&gt;What grade did they give each other?&lt;/h2&gt;
&lt;p&gt;I agree that giving a grade out of 10 to your date can be a bit cruel, especially when this grade will be published in a famous newspaper, but then people get free food and often a nice evening and know about it so I guess it&amp;rsquo;s ok? In any case, I decided to extract the grades they gave each other. For this I had to use regular expressions because some people don&amp;rsquo;t only give a number, they explain their choice.&lt;/p&gt;
&lt;p&gt;I keep only dates with two answers to the question, and for each answer I want to have only one possible grade and it has to be between 0 and 10.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;grades &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(results, question &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Marks out of 10\\?&amp;#34;&lt;/span&gt;)
grades &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(grades, answer &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(answer, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\/10&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
grades &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(grades, answer &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(answer, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;out of 10&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
get_grade &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
  grade &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;str_match_all&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;answer, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[:digit:][\\.]?[:digit:]?&amp;#34;&lt;/span&gt;)))
  grade &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; grade[&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(grade)]
  grade &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; grade[grade &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;]
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(grade) &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;){
    &lt;span style=&#34;color:#40a070&#34;&gt;999&lt;/span&gt;
  }else{
    grade
  }
}
grades &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;by_row&lt;/span&gt;(grades, get_grade,
                 .to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;grade&amp;#34;&lt;/span&gt;, .collate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols&amp;#34;&lt;/span&gt;)

grades &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(grades, grade &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;999&lt;/span&gt;)
grades &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(grades, link)
grades &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(grades, &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;)
grades &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;(grades)
&lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(grades, answer, grade) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;answer&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;grade&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;8.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;7.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A strong 7 for a great evening of conversation and laughs.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;8.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;7.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;10.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Now I can see which grades were given and most importantly how different both grades are.&lt;/p&gt;
&lt;p&gt;I have 522 grades which means grades for 261 dates out of 434 dates which is a bit disappointing but hopefully still a representative sample. Also I&amp;rsquo;m not sure the problem is my code, sometimes people just don&amp;rsquo;t want to give a grade so they give several or write some sort of explanation with &lt;em&gt;words&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hrbrthemes&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(grades) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_histogram&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(grade)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum_rc&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;labs&lt;/span&gt;(title&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Grades given by Guardian blind dates participants&amp;#34;&lt;/span&gt;,
       subtitle&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;See how I use Bob Rudis&amp;#39; nice theme&amp;#34;&lt;/span&gt;,
       caption&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Thank God for webscraping and regex&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-03-07-blinddates/unnamed-chunk-7-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-7&#34;&gt;&lt;/p&gt;
&lt;p&gt;Ok now we all want to know what date was catastrophic enough for someone to get a small grade.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(grades, grade &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(grade)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; .$link
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;https://www.theguardian.com/lifeandstyle/2012/jun/29/blind-date&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So now please all stop being sad, the actual answer was &amp;ldquo;Would it be cheeky to say the same as her and add 1?&amp;rdquo;! Which shows the limits of my code and how nice people seem to be to each other in this small sample (although maybe they&amp;rsquo;re just nice because they want the other one to be nice as well)? And to answer the participant&amp;rsquo;s question, I&amp;rsquo;d say it&amp;rsquo;s not cheeky but not analysis-friendly.&lt;/p&gt;
&lt;p&gt;Now, did people give each other close grades?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;grades &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(grades, link)
grades &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(grades, diff &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;abs&lt;/span&gt;(grade[1] &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; grade[2]))
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(grades) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_histogram&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(diff)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum_rc&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;labs&lt;/span&gt;(title&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Difference between grades&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-03-07-blinddates/unnamed-chunk-9-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-9&#34;&gt;&lt;/p&gt;
&lt;p&gt;To me it seems grades are pretty close, but more than an agreement it might indicate most people choose some sort of common grade no matter the date because they&amp;rsquo;re not keen on giving grades?&lt;/p&gt;
&lt;h2 id=&#34;did-they-want-to-meet-again&#34;&gt;Did they want to meet again?&lt;/h2&gt;
&lt;p&gt;For finding out whether people would like to meet again, I decided to use sentiment analysis because I had no other better idea and I think it makes this post quite well-rounded with term frequency, number extraction and sentiment analysis. So please give me a good grade!&lt;/p&gt;
&lt;p&gt;I used code from one &lt;a href=&#34;https://cran.r-project.org/web/packages/tidytext/vignettes/tidytext.html&#34;&gt;&lt;code&gt;tidytext&lt;/code&gt; vignette&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;meet &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(results, question &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Would you meet again\\?&amp;#34;&lt;/span&gt;)
bing &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_sentiments&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bing&amp;#34;&lt;/span&gt;)

meetsentiment &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; meet  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(savedanswer &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; answer) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(word, answer)&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;inner_join&lt;/span&gt;(bing) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(link, which, savedanswer, sentiment) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;spread&lt;/span&gt;(sentiment, n, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(sentiment &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; positive &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; negative) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(sentiment))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So how often did one of them want to meet the other again?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(meetsentiment) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_bar&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(sentiment)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_ipsum_rc&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-03-07-blinddates/unnamed-chunk-11-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-11&#34;&gt;&lt;/p&gt;
&lt;p&gt;To get an idea of how good my sentiment analysis is working &amp;ndash; probably not well, let&amp;rsquo;s look at the extremes.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(meetsentiment, sentiment &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;link&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;which&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;savedanswer&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;negative&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;positive&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;sentiment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2009/apr/11/blind-date-cash-coryton&#34;&gt;https://www.theguardian.com/lifeandstyle/2009/apr/11/blind-date-cash-coryton&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I don&amp;rsquo;t think we&amp;rsquo;ll arrange anything, but Brighton is a small place and we&amp;rsquo;d stop to chat if we bumped into each other.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2009/aug/01/blind-date&#34;&gt;https://www.theguardian.com/lifeandstyle/2009/aug/01/blind-date&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I&amp;rsquo;m sure we will – it would be a shame not to.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2009/feb/28/blind-date-relationships&#34;&gt;https://www.theguardian.com/lifeandstyle/2009/feb/28/blind-date-relationships&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;We swapped numbers, but I don&amp;rsquo;t think there will be any romance, sadly.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2009/feb/28/blind-date-relationships&#34;&gt;https://www.theguardian.com/lifeandstyle/2009/feb/28/blind-date-relationships&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;She didn&amp;rsquo;t seem that interested, so I doubt it.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2009/may/02/ian-winterton-jane-thomas&#34;&gt;https://www.theguardian.com/lifeandstyle/2009/may/02/ian-winterton-jane-thomas&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I would but she lives in the Wirral, so it&amp;rsquo;s unlikely to happen that often.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2009/oct/24/blind-date&#34;&gt;https://www.theguardian.com/lifeandstyle/2009/oct/24/blind-date&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;We did the number swap thing, so it would be a shame not to.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;So actually it&amp;rsquo;s not too bad on this small subset although &amp;ldquo;a shame not to&amp;rdquo; shouldn&amp;rsquo;t be sorted in this category.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(meetsentiment, sentiment &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;link&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;which&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;savedanswer&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;negative&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;positive&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;sentiment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2010/aug/07/blind-date&#34;&gt;https://www.theguardian.com/lifeandstyle/2010/aug/07/blind-date&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;strong&gt; It was fun and Ali was very nice, but could I ever love a woman who doesn&amp;rsquo;t like Morrissey? That was a deal breaker, I&amp;rsquo;m afraid.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2010/aug/14/blind-date&#34;&gt;https://www.theguardian.com/lifeandstyle/2010/aug/14/blind-date&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;strong&gt; Only as friends. I wasn&amp;rsquo;t physically attracted to Matt, but found him to be a warm, charming and very nice bloke.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2010/aug/21/blind-date&#34;&gt;https://www.theguardian.com/lifeandstyle/2010/aug/21/blind-date&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;strong&gt; I enjoyed the night and thought we got on really well, but I&amp;rsquo;m not sure if we&amp;rsquo;ll arrange to meet up again. We&amp;rsquo;re both going to the same music festival in September, so it would be great to run into her and catch up then.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2010/dec/11/blind-date&#34;&gt;https://www.theguardian.com/lifeandstyle/2010/dec/11/blind-date&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;strong&gt; Definitely for drinks as friends. We&amp;rsquo;ve already said we&amp;rsquo;ll meet up soon – Mal has promised to show me how to dance properly to jungle music, although I may be better than him as it stands.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2010/nov/06/blind-date&#34;&gt;https://www.theguardian.com/lifeandstyle/2010/nov/06/blind-date&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;No – we had very little in common. But it&amp;rsquo;s a mark of what good company she is that I still managed to have a lovely evening!&lt;strong&gt; &lt;/strong&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.theguardian.com/lifeandstyle/2010/oct/30/blind-date&#34;&gt;https://www.theguardian.com/lifeandstyle/2010/oct/30/blind-date&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;strong&gt; She&amp;rsquo;s great fun, so it&amp;rsquo;d be good to see her again sometime.&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Mmmh so here it works much less well. I should maybe weight by length of the sentence because apparently &amp;ldquo;just as friends&amp;rdquo; sometimes needs many compliments to make it less hurtful. But then given the efforts I invested in automatically sorting the answers (close to zero), I can&amp;rsquo;t complain and will leave this as is.&lt;/p&gt;
&lt;h1 id=&#34;last-words&#34;&gt;Last words&lt;/h1&gt;
&lt;p&gt;I could have done more with this dataset! Ideas I have include also extracting age and profession of the participants, and find which industries are the most represented/compatible using my R &lt;a href=&#34;https://github.com/ropensci/monkeylearn&#34;&gt;&lt;code&gt;monkeylearn&lt;/code&gt; package&lt;/a&gt; as I did in my &lt;a href=&#34;https://masalmon.eu/2016/10/02/first7jobs-repost/&#34;&gt;#first7jobs analysis&lt;/a&gt;. I have also noticed the address of the restaurant where people had dinner is written at the end of each post, which makes me want to geocode them all with  &lt;a href=&#34;https://github.com/ropensci/opencage&#34;&gt;&lt;code&gt;opencage&lt;/code&gt;&lt;/a&gt;. But what would motivate me even more would be to use &lt;a href=&#34;https://github.com/ropenscilabs/charlatan&#34;&gt;Scott Chamberlain&amp;rsquo;s &lt;code&gt;charlatan&lt;/code&gt; package&lt;/a&gt; to create false names and jobs of dates, and then &lt;code&gt;rcorpora&lt;/code&gt; to generate their false interviews. If I did that I could read one &amp;ldquo;Guardian&amp;rdquo; blind date per day instead of one per week!&lt;/p&gt;
&lt;p&gt;To end on a more serious note, Guardian journalists report on other important stuff such as politics and the environment, so if you can please consider &lt;a href=&#34;https://membership.theguardian.com/int/supporter?INTCMP=DOTCOM_HEADER_BECOMEMEMBER_INT&#34;&gt;becoming a Guardian Supporter&lt;/a&gt;. My husband and I did and we&amp;rsquo;re quite happy we did!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>A glance at R-bloggers Twitter feed</title>
      <link>https://masalmon.eu/2017/02/28/rbloggerstweets/</link>
      <pubDate>Tue, 28 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/02/28/rbloggerstweets/</guid>
      <description>&lt;p&gt;It&amp;rsquo;s the second time I write a post about the blog aggregator R-bloggers, probably because I&amp;rsquo;m all about R blogs now that I have one. My husband says my posts are so meta. My first post was about &lt;a href=&#34;https://masalmon.eu/2017/01/29/rbloggersnames/&#34;&gt;R blogs names&lt;/a&gt;, in this one I shall focus on the last 1,000 tweets from R-bloggers.&lt;/p&gt;
&lt;h1 id=&#34;getting-the-tweets&#34;&gt;Getting the tweets&lt;/h1&gt;
&lt;p&gt;Thanks to &lt;a href=&#34;https://github.com/mkearney/rtweet&#34;&gt;&lt;code&gt;rtweet&lt;/code&gt;&lt;/a&gt;, this is fairly easy. I get rid of empty columns using &lt;a href=&#34;https://github.com/sfirke/janitor&#34;&gt;&lt;code&gt;janitor&lt;/code&gt;&lt;/a&gt;, which is a package you should really check out if you ever have to clean data.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rtweet&amp;#34;&lt;/span&gt;)             
rbloggers &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_timeline&lt;/span&gt;(user &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Rbloggers&amp;#34;&lt;/span&gt;,
                          n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1000&lt;/span&gt;)

rbloggers &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; janitor&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;remove_empty_cols&lt;/span&gt;(rbloggers)

readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(rbloggers, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-02-28-rbloggerstweets.csv&amp;#34;&lt;/span&gt;)

knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(rbloggers))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;created_at&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;status_id&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;text&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;source&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;is_quote_status&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;retweet_count&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;favorite_count&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;lang&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;user_id&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;screen_name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;mentions_user_id&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;mentions_screen_name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;hashtags&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;urls&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;is_retweet&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-28 20:00:42&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;836667465333673984&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;How to annotate a plot in ggplot2 https://t.co/78h18Plc5e #rstats #DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://wp.me/pMm6L-Crh&#34;&gt;https://wp.me/pMm6L-Crh&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-28 17:00:40&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;836622157295857665&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;How to create correlation network plots with corrr and ggraph (and which countries drink like https://t.co/K8g1OkvWMs #rstats #DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;55&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://wp.me/pMm6L-Cre&#34;&gt;https://wp.me/pMm6L-Cre&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-28 16:11:45&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;836609848276037636&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;forecast 8.0 https://t.co/XATCVdeoJ8 #rstats #DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;15&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;38&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://wp.me/pMm6L-Crc&#34;&gt;https://wp.me/pMm6L-Crc&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-28 15:18:28&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;836596435307081729&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;New R job: Applied Research Statistician/Methodologist https://t.co/Hfkanf74aM #rstats #DataScience #jobs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience,jobs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://www.r-users.com/jobs/applied-research-statisticianmethodologist/&#34;&gt;https://www.r-users.com/jobs/applied-research-statisticianmethodologist/&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-28 13:12:59&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;836564859647033344&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[WEBINAR] Trading in Live Markets using R https://t.co/nNGyQOqUmw #rstats #DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://wp.me/pMm6L-Cra&#34;&gt;https://wp.me/pMm6L-Cra&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-28 00:40:34&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;836375506945716226&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Video Introduction to Bayesian Data Analysis, Part 2: Why use Bayes? https://t.co/fmHtKr99kw #rstats #DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;101&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://wp.me/pMm6L-CqZ&#34;&gt;https://wp.me/pMm6L-CqZ&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Now that I have the data, I&amp;rsquo;ll have a look at the content of the tweet, at their temporal patterns and at their popularity.&lt;/p&gt;
&lt;h1 id=&#34;what-are-the-most-frequent-words&#34;&gt;What are the most frequent words?&lt;/h1&gt;
&lt;p&gt;For finding the most frequent words in the tweets I use what has now become my usual workflow with &lt;code&gt;tidytext&lt;/code&gt;. I remove 4 words that correspond to the hashtags used in every tweet (#rstats and #datascience) and to links (https and t.co)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;rbloggers &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-02-28-rbloggerstweets.csv&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidytext&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rcorpora&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lubridate&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;viridis&amp;#34;&lt;/span&gt;)
stopwords &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;corpora&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;words/stopwords/en&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;stopWords

rbloggers_words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rbloggers &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(word, text) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(word, sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;word &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; stopwords) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;word &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rstats&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;datascience&amp;#34;&lt;/span&gt;,
                      &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;t.co&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https&amp;#34;&lt;/span&gt;))
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(rbloggers_words, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;word&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;data&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;171&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;analysis&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;62&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;jobs&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;48&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;package&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;job&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;41&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;36&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;shiny&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;science&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;regression&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;learning&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;scientist&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;app&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;map&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ggplot2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;interactive&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;rstudio&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;statistics&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;17&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;model&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I&amp;rsquo;m not surprised by the trendy words, I guess you could mix a few of them up and get a pretty cool title, e.g. &amp;ldquo;How to make an app in RStudio with an interactive map in it&amp;rdquo; or &amp;ldquo;let&amp;rsquo;s analyse data with a regression and plot everything with ggplot2&amp;rdquo;. I think I&amp;rsquo;m more surprised that in 1,000 tweets, no word is that predominant.&lt;/p&gt;
&lt;h1 id=&#34;when-are-blog-posts-published&#34;&gt;When are blog posts published?&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll start with a warning, R-bloggers tweets appear a bit after the actual blog posts are published, about a few hours I&amp;rsquo;d say. I actually need a second warning, regarding time of day we have to keep in mind R blogs can be written from everywhere on the planet so in theory R-bloggers is an account that never sleeps.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;rbloggers &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rbloggers, wday &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.factor&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;wday&lt;/span&gt;(created_at, label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)))
rbloggers &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rbloggers, hour &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.factor&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;hour&lt;/span&gt;(created_at)))
rbloggers &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rbloggers, week &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;week&lt;/span&gt;(created_at))
rbloggers &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rbloggers, day &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.Date&lt;/span&gt;(created_at))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that the reason I can use &lt;code&gt;week&lt;/code&gt; is that there are no tweets from more than one year ago in my data.&lt;/p&gt;
&lt;p&gt;Here I&amp;rsquo;ll show the number of tweets by day of the week.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;weekday_dat &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; rbloggers &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(week, wday) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;(), created_at &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; created_at[1]) 

&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(weekday_dat, &lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;week&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;wday&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;created_at&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Sun&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;98&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-22 23:50:19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Mon&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;82&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-23 23:10:18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Sat&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;65&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-21 23:52:03&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Wed&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;34&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-25 22:10:27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Fri&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-27 23:40:37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tues&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-07 23:50:44&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There are a few days with a lot of tweets, which I guess is due to one blog being added and all its posts being shared at once? In any case, I&amp;rsquo;ll remove these days from the figure by not showing outliers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(weekday_dat) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_boxplot&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(wday, n),
               outlier.shape &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_y_continuous&lt;/span&gt;(limits &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;  &lt;span style=&#34;color:#06287e&#34;&gt;quantile&lt;/span&gt;(weekday_dat&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;n, &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0.9&lt;/span&gt;)))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-28-rbloggerstweets/unnamed-chunk-5-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-5&#34;&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not too sure what to conclude as regards a possible day-of-the-week pattern. Maybe I&amp;rsquo;d need more data, since I don&amp;rsquo;t even have a full year of data:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(rbloggers&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;created_at)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;2016-12-14 19:06:23 UTC&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;max&lt;/span&gt;(rbloggers&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;created_at)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;2017-02-28 20:00:42 UTC&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With more data maybe I could say whether R-bloggers, who I think are often not blogging for work, post more on the week-ends. Thinking of programming, week-ends and weekdays makes me think of &lt;a href=&#34;https://stackoverflow.blog/2017/02/07/what-programming-languages-weekends/&#34;&gt;this very good post of Julia Silge&amp;rsquo;s&lt;/a&gt;.
Similarly for hour of the day (results not shown) I&amp;rsquo;m a victim, I think, of the size of my dataset. Moreover, even with a bigger sample, I&amp;rsquo;d still have trouble finding a circadian rythm since it&amp;rsquo;d mix tweets from several timezones, without any information about the location of the blog author. Too bad! And with years of data I could even look at seasonality!&lt;/p&gt;
&lt;h1 id=&#34;how-popular-are-r-bloggers-tweets&#34;&gt;How popular are R-bloggers tweets?&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ll be honest, this is the primary reason why I got interested into R-bloggers&amp;rsquo; feed. I wondered how famous it made my poor young blog. Well if I have to be honest I also wondered how visible an error of mine would be.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(rbloggers) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_histogram&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(favorite_count))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-28-rbloggerstweets/unnamed-chunk-7-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-7&#34;&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(rbloggers) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_histogram&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(retweet_count))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-28-rbloggerstweets/unnamed-chunk-7-2.png&#34; alt=&#34;plot of chunk unnamed-chunk-7&#34;&gt;&lt;/p&gt;
&lt;p&gt;Both look like negative binomial distributions, right? But I don&amp;rsquo;t want to model them, I&amp;rsquo;m in a minimalistic mood. Note that the median number of retweet is 8 and the median number of favorites is  19. Let&amp;rsquo;s see which were the most popular tweets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(rbloggers, &lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(retweet_count)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;created_at&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;status_id&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;text&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;source&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;is_quote_status&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;retweet_count&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;favorite_count&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;lang&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;user_id&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;screen_name&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;mentions_user_id&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;mentions_screen_name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;hashtags&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;urls&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;is_retweet&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;wday&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;hour&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;week&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;day&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2016-12-29 08:02:09&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.143810e+17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;7 Visualizations You Should Learn in R https://t.co/p7aww3ueiU #rstats #DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;119&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;214&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://wp.me/pMm6L-BEP&#34;&gt;https://wp.me/pMm6L-BEP&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Thurs&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;52&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-12-29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-03 17:42:14&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.163389e+17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Why R is the best data science language to learn today https://t.co/Bp5XouKIZ9 #rstats #DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;101&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;129&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://wp.me/pMm6L-BGQ&#34;&gt;https://wp.me/pMm6L-BGQ&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tues&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;17&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-03&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-25 03:10:20&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.240920e+17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Free guide to text mining with R https://t.co/o8pkSA3Rke #rstats #DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;99&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;191&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://wp.me/pMm6L-C1p&#34;&gt;https://wp.me/pMm6L-C1p&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Wed&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-24 10:50:47&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.350795e+17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Announcing ggraph: A grammar of graphics for relational data https://t.co/5jKGoK6Dsu #rstats #DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;94&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;141&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://wp.me/pMm6L-Cpx&#34;&gt;https://wp.me/pMm6L-Cpx&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Fri&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;10&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-07 03:50:39&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.288132e+17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Deep Learning in R https://t.co/HTHKDy7mnN #rstats #DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;92&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;189&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://wp.me/pMm6L-Cer&#34;&gt;https://wp.me/pMm6L-Cer&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tues&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-02-07&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-28 12:10:33&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.253151e+17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;The “Ten Simple Rules for Reproducible Computational Research” are easy to reach for R users https://t.co/9hsKE2FgHt #rstats #DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r-bloggers.com&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;91&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;122&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;en&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;144592995&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Rbloggers&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;rstats,DataScience&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://wp.me/pMm6L-C6O&#34;&gt;https://wp.me/pMm6L-C6O&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;FALSE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Sat&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;12&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2017-01-28&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I&amp;rsquo;m happy to report I&amp;rsquo;d heard of most of these posts. I feel so well informed.&lt;/p&gt;
&lt;p&gt;Now I guessed that the number of retweets and favorites were correlated, so I decided to draw a scatterplot which according to one of the posts above is a visualization you should learn.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(rbloggers) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(retweet_count, favorite_count))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-28-rbloggerstweets/unnamed-chunk-9-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-9&#34;&gt;&lt;/p&gt;
&lt;p&gt;Wow! I was so surprised by this plot that I decided to make the same for another R content aggregator account, &lt;a href=&#34;https://twitter.com/rweekly_org&#34;&gt;R Weekly&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;rweekly_org &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_timeline&lt;/span&gt;(user &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rweekly_org&amp;#34;&lt;/span&gt;,
                          n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1000&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(rweekly_org) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(retweet_count, favorite_count)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rweekly_org&amp;#39;s timeline&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-28-rbloggerstweets/unnamed-chunk-10-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-10&#34;&gt;&lt;/p&gt;
&lt;p&gt;Well here we have far less tweets sadly. I still think there might be a golden ratio of some sort hidden here, so I&amp;rsquo;ll fit linear models to both datasets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;model &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lm&lt;/span&gt;(favorite_count &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; retweet_count, data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; rbloggers)
broom&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tidy&lt;/span&gt;(model) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;term&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;estimate&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;std.error&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;statistic&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;p.value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;(Intercept)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.945224&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.4105901&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;12.04419&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;retweet_count&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.779315&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0223167&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;79.73038&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;model2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lm&lt;/span&gt;(favorite_count &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; retweet_count, data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; rweekly_org)
broom&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tidy&lt;/span&gt;(model2) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;term&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;estimate&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;std.error&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;statistic&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;p.value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;(Intercept)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.118446&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.7470733&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.7711648&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.4434471&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;retweet_count&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.382438&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.1783162&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.7527315&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.0000000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Now I just hope that if we collected more data for both accounts, the second coefficient estimate would be close to &lt;a href=&#34;https://en.wikipedia.org/wiki/Golden_ratio&#34;&gt;the golden ratio&lt;/a&gt;, about 1.618. Or I could let social media specialists explain me why retweets and favorites have this correlation. Or where the mistake in my post is, which I&amp;rsquo;d like to know before it gets sort of viral thanks to R-bloggers.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>First commit or initial commit?</title>
      <link>https://masalmon.eu/2017/02/21/firstcommit/</link>
      <pubDate>Tue, 21 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/02/21/firstcommit/</guid>
      <description>&lt;p&gt;When I create a new .git repository, my first commit message tends to be &amp;ldquo;1st commit&amp;rdquo;. I&amp;rsquo;ve been wondering what other people use as initial commit message. Today I used the &lt;a href=&#34;https://github.com/r-pkgs/gh&#34;&gt;&lt;code&gt;gh&lt;/code&gt; package&lt;/a&gt; to get first commits of all repositories of the &lt;a href=&#34;https://github.com/ropensci&#34;&gt;ropensci&lt;/a&gt; and &lt;a href=&#34;https://github.com/ropenscilabs&#34;&gt;ropenscilabs&lt;/a&gt; organizations.&lt;/p&gt;
&lt;p&gt;The sample might seem a bit small, but I just wanted to start exploring my question. I agree that it means my answer won&amp;rsquo;t be very conclusive.&lt;/p&gt;
&lt;h1 id=&#34;getting-all-repos-for-an-organization&#34;&gt;Getting all repos for an organization&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve come up with a quite inelegant solution to paging, I just continue querying the API until it returns me nothing.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;gh&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purrr&amp;#34;&lt;/span&gt;)
get_repos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(org){
  ropensci_repos_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
geht &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;while&lt;/span&gt;(geht){
  ropensci_repos &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;gh&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;/orgs/:org/repos&amp;#34;&lt;/span&gt;,
                  org &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; org,
                  page &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; page))
  
  geht &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ropensci_repos &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
  
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(geht){
    ropensci_repos_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(ropensci_repos_names,
                              &lt;span style=&#34;color:#06287e&#34;&gt;vapply&lt;/span&gt;(ropensci_repos, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;))
    page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; page &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
  }
}
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(ropensci_repos_names)
}

&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;get_repos&lt;/span&gt;(org &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropenscilabs&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;webmockr&amp;quot;      &amp;quot;vcr&amp;quot;           &amp;quot;seasl&amp;quot;         &amp;quot;plater&amp;quot;       
## [5] &amp;quot;rnaturalearth&amp;quot; &amp;quot;convertr&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;get-first-commit-for-a-repository&#34;&gt;Get first commit for a repository&lt;/h1&gt;
&lt;p&gt;Here I&amp;rsquo;m doing something quite inefficient. Since the API returns the most recent commits first I get all commits. I could have used the creation date of the repository instead to only query commits created shortly after that.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;first_commit &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(repo, org){
  messages &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
  
  page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
  geht &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;while&lt;/span&gt;(geht){
    commits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;try&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;gh&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;/repos/:owner/:repo/commits&amp;#34;&lt;/span&gt;,
                            owner &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; org,
                            repo &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; repo,
                            page &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; page))
    
    &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;class&lt;/span&gt;(commits)[1] &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;try-error&amp;#34;&lt;/span&gt;){
      geht &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; commits &lt;span style=&#34;color:#666&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
    }else{
      geht &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;
    }
    
    &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(geht){
      now &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(commits, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;commit&amp;#34;&lt;/span&gt;)
      now &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(now, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[[&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;)
      messages &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(messages, &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(now))
      page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; page &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
    }
  }
  
  messages&lt;span style=&#34;color:#06287e&#34;&gt;[length&lt;/span&gt;(messages)]
}
&lt;span style=&#34;color:#06287e&#34;&gt;first_commit&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropenaq&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropensci&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Everything&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&amp;rsquo;m a bit surprised I chose &amp;ldquo;Everything&amp;rdquo; as first commit for my &lt;code&gt;ropenaq&lt;/code&gt; package, actually. Not because I expect my commit history to be particularly smart either, just because it&amp;rsquo;s not a &amp;ldquo;1st commit&amp;rdquo;.&lt;/p&gt;
&lt;h1 id=&#34;get-all-the-first-commits&#34;&gt;Get all the first commits&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;first_commits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_repos&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropenscilabs&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(first_commit, org &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropenscilabs&amp;#34;&lt;/span&gt;) 
&lt;span style=&#34;color:#06287e&#34;&gt;save&lt;/span&gt;(first_commits, file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-02-21_ropenscilabs_first_commits.RData&amp;#34;&lt;/span&gt;)
first_commits &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_repos&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropensci&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(first_commit, org &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ropensci&amp;#34;&lt;/span&gt;) 
&lt;span style=&#34;color:#06287e&#34;&gt;save&lt;/span&gt;(first_commits, file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-02-21_ropensci_first_commits.RData&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;what-are-the-most-frequent-first-commits&#34;&gt;What are the most frequent first commits?&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;load&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-02-21_ropenscilabs_first_commits.RData&amp;#34;&lt;/span&gt;)
ropenscilabs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; first_commits
&lt;span style=&#34;color:#06287e&#34;&gt;load&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-02-21_ropensci_first_commits.RData&amp;#34;&lt;/span&gt;)
ropensci &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; first_commits

all &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(ropenscilabs),
         &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(ropensci))
firstc &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(commit &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; all)
firstc &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(firstc, commit &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tolower&lt;/span&gt;(commit))
firstc &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(commit) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;15&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;commit&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;first commit&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;117&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;initial commit&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;76&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;added readme&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;added files&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;1st commit&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;create readme.md&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;init&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;added readme file&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;code extracted from mikabr/devtools&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;first comit&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;first commit, added files&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;initial&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;initial import&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;package infrastructure&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;rstudio new package project&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Out of the 362 repositories, 76 used &amp;ldquo;initial commit&amp;rdquo; as a first commit message and  117 used &amp;ldquo;first commit&amp;rdquo; instead. In total 0.53 of all repos used either one of these two messages, which isn&amp;rsquo;t as much as I expected. But maybe rOpenSci repositories are unusual as regards first commit originality? And you, what is your favourite initial commit message if you have one?&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Bar bar plots but not Babar plots</title>
      <link>https://masalmon.eu/2017/02/19/babarplot/</link>
      <pubDate>Sun, 19 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/02/19/babarplot/</guid>
      <description>&lt;p&gt;You might have heard of the &lt;a href=&#34;https://twitter.com/search?q=%23barbarplots&amp;amp;src=typd&#34;&gt;&amp;ldquo;bar bar plots&amp;rdquo; movement&lt;/a&gt; whose goal is to prevent using (let&amp;rsquo;s use &lt;code&gt;ggplot2&lt;/code&gt; language shall we) &lt;code&gt;geom_bar&lt;/code&gt; when you could have used e.g. &lt;code&gt;geom_boxplot&lt;/code&gt; or &lt;code&gt;geom_histogram&lt;/code&gt; because the bar plot hides the variability of the distributions you say you&amp;rsquo;re comparing, even if you add some sort of error bar. I whole-heartedly agree with this movement but in this post I&amp;rsquo;d like to present some ok bar plots, that represent counts of individuals in different categories. You might know them as &lt;code&gt;geom_bar(blabla, stat = &amp;quot;identity&amp;quot;)&lt;/code&gt; or &lt;code&gt;geom_col&lt;/code&gt;. They&amp;rsquo;re still bar plots and they&amp;rsquo;re great, in particular when you make puns out of them which is what I did with &lt;a href=&#34;https://twitter.com/MilesMcBain&#34;&gt;Miles McBain&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The reason I mentioned bar plots to Miles was my wanting to recycle some old code of mine (again) for a blog post. It was code from my &amp;ldquo;let&amp;rsquo;s test all the kitsch R plots have to offer&amp;rdquo; period, when I had started using &lt;a href=&#34;https://github.com/leeper/colourlovers&#34;&gt;Thomas Leeper&amp;rsquo;s &lt;code&gt;colourlovers&lt;/code&gt; package&lt;/a&gt; for adding patterns on bars.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;colourlovers&lt;/code&gt; is a great package for getting trendy colour palettes, although I&amp;rsquo;ll admit I&amp;rsquo;m a &lt;code&gt;viridis&lt;/code&gt; person. But &lt;code&gt;colourlovers&lt;/code&gt; also has patterns, about which the package documentation states &amp;ldquo;Patterns are images created on COLOURlovers using a specified palette of colors. They serve as examples of how to use the palette in practice.&amp;rdquo;. At the time I read those sentences I got really excited because I was convinced one could do &lt;em&gt;more&lt;/em&gt; with patterns, like filling bar plots with them. In this post, I&amp;rsquo;ll prove you can, with my non-generalizable worflow.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;httr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;grid&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;colourlovers&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;general-comments-on-using-patterns&#34;&gt;General comments on using patterns&lt;/h1&gt;
&lt;p&gt;A pattern is a square image that I convert to a raster. This raster is a matrix with 200 rows and 200 columns. In this matrix $x_{i,j}$ represents the hex code of the colour of a pixel. Below I show how to get a pattern figure and how to plot it on its own.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get pattern&lt;/span&gt;
catsBlue &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;clpattern&lt;/span&gt;(id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;3363032&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get the URL of the picture corresponding to the pattern&lt;/span&gt;
imageURL &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; catsBlue&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;imageUrl
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get the picture&lt;/span&gt;
 picture &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt;  &lt;span style=&#34;color:#06287e&#34;&gt;content&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;GET&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(imageURL)))
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# convert it to a raster&lt;/span&gt;
img &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.raster&lt;/span&gt;(picture)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# plot it!&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;plot&lt;/span&gt;(img)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-19-babarplot/unnamed-chunk-2-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-2&#34;&gt;&lt;/p&gt;
&lt;p&gt;This pattern can also be seen as a puzzle piece: one can copy the pattern several times and put each copy side by side and/or pile them up and get something that looks homogeneous with no problem at the border of each piece.&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;ggplot2&lt;/code&gt;, I&amp;rsquo;ll add the patterns with &lt;code&gt;geom_point&lt;/code&gt;. The main issue will be to re-size puzzle pieces (how big should be a single puzzle piece for the graph to look nice?), to paste pieces together (now many puzzle pieces?), and to crop the puzzle (the puzzle should not be bigger than the bar it covers, for instance).&lt;/p&gt;
&lt;h1 id=&#34;writing-code-for-decorating-a-bar-plot&#34;&gt;Writing code for decorating a bar plot&lt;/h1&gt;
&lt;p&gt;Here is the original bar plot I aim to make fancier.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Normal plot&lt;/span&gt;
c &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(mtcars, &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;factor&lt;/span&gt;(cyl)))
c &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; c &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;geom_bar&lt;/span&gt;(width &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;.5&lt;/span&gt;,
                  &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;factor&lt;/span&gt;(cyl)))&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(size&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;))
c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-19-babarplot/unnamed-chunk-3-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-3&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now, since my puzzle pieces are squares, I want the plot to have a x/y ratio such that the distance between two major grid lines on the x axis is the same as the distance as the distance between two major grid lines on the y axis.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;plotInfo &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ggplot_build&lt;/span&gt;(c)
extentX &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;diff&lt;/span&gt;(plotInfo&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;layout&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;panel_ranges[[1]]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;x.major_source)[1]
extentY &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;diff&lt;/span&gt;(plotInfo&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;layout&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;panel_ranges[[1]]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;y.major_source)[1]
c &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; c &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;coord_fixed&lt;/span&gt;(ratio &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; extentX&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;extentY)
c
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-19-babarplot/unnamed-chunk-4-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-4&#34;&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll reckon once again that since writing the code and publishing it I&amp;rsquo;ve slept many times and thus forgotten how I came up with the solution. Today I had to change the code for getting &lt;code&gt;extentY&lt;/code&gt; and &lt;code&gt;extentX&lt;/code&gt; a bit since &lt;code&gt;ggplot_build()&lt;/code&gt; gives a slightly different output since &lt;code&gt;ggplot2&lt;/code&gt; newest version was released.&lt;/p&gt;
&lt;p&gt;I shall now get three patterns from colourlovers. I went on the website of colourlovers itself to find three patterns using the same template with different colours so I know their IDs.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get the patterns&lt;/span&gt;
get_patterns &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(id_blue, id_red, id_green){
  blue &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;clpattern&lt;/span&gt;(id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; id_blue)
  red &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;clpattern&lt;/span&gt;(id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; id_red)
  green &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;clpattern&lt;/span&gt;(id &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; id_green)
  &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(red, green, blue)
}

patterns &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_patterns&lt;/span&gt;(id_blue &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4348319&lt;/span&gt;,
                         id_red &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4376078&lt;/span&gt;,
                         id_green &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4360659&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I shall first get one colour from each pattern and re-do the figure with these colours. I do this to have a legend later. I don&amp;rsquo;t want to try and reproduce parts of the patterns to get them in the legend.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purrr&amp;#34;&lt;/span&gt;)
get_colors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(pattern){
  pattern&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;colors[3]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;hex
}
addhash &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(color){
  &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#&amp;#34;&lt;/span&gt;, color)
}

colors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(patterns, get_colors) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(addhash) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;()

c2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; c &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_manual&lt;/span&gt;(values &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colors)
c2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-19-babarplot/unnamed-chunk-6-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-6&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s add the patterns to the graph! It&amp;rsquo;s quite inelegant since I use a loop for adding things successively to the graph.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;add_patterns &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(plot, patterns, colors){
  &lt;span style=&#34;color:#06287e&#34;&gt;for &lt;/span&gt;(i in &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;levels&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;factor&lt;/span&gt;(mtcars&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;cyl)))){
  imageURL &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; patterns[[i]]&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;imageUrl
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get pattern&lt;/span&gt;
  picture &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt;  &lt;span style=&#34;color:#06287e&#34;&gt;content&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;GET&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(imageURL)))
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# picture is a 4 dimensional array&lt;/span&gt;
  img &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.raster&lt;/span&gt;(picture)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# we have to repeat the data.frame/pattern&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# I repeat it so that one extentY = one square&lt;/span&gt;
  xmax &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
  ymax &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sum&lt;/span&gt;(mtcars&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;cyl &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;levels&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;factor&lt;/span&gt;(mtcars&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;cyl))[i])
  
  size &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ceiling&lt;/span&gt;(ymax&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;extentY)
  
  img2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;apply&lt;/span&gt;(img,MARGIN&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;,&lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x) &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(x,size))
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# from matrix to data.frame&lt;/span&gt;
  img2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tbl_df&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;as.data.frame&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;as.matrix&lt;/span&gt;(img2)))
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# I change the column names so that they correspond to x coordinates &lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(img2) &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(i &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.25&lt;/span&gt;, to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; i &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.25&lt;/span&gt;, length &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ncol&lt;/span&gt;(img2))
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# I transform the img2 so that I have one line = 1 x, 1 y and 1 colour&lt;/span&gt;
  dataPlot &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; img2 &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
    &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;seq&lt;/span&gt;(from &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; size&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;extentY, to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, length &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(img2)))&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
    &lt;span style=&#34;color:#06287e&#34;&gt;gather&lt;/span&gt;(x, value, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ncol&lt;/span&gt;(img2)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# filter part of the pattern that doesn&amp;#39;t fit in the original bar&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(y &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;=&lt;/span&gt; ymax)  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(x))
  
  
  plot &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; plot &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; dataPlot, &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x, y), col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; dataPlot&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;value)
}
plot
}

&lt;span style=&#34;color:#06287e&#34;&gt;add_patterns&lt;/span&gt;(plot &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; c2, patterns &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; patterns, colors &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colors) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Babar bar plot&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-19-babarplot/unnamed-chunk-7-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-7&#34;&gt;&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve just made a Babar bar plot! Thanks Miles for this pun. Now let&amp;rsquo;s apply the same principles again and by principles I mean applying the &lt;code&gt;colourlover&lt;/code&gt; code I&amp;rsquo;ve just presented, and using puns developped with Miles. A recipe for success!&lt;/p&gt;
&lt;h1 id=&#34;other-punny-plots&#34;&gt;Other punny plots&lt;/h1&gt;
&lt;h2 id=&#34;barber-plot&#34;&gt;Barber plot&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;patterns &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_patterns&lt;/span&gt;(id_blue &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3490878&lt;/span&gt;,
                         id_red &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3277163&lt;/span&gt;,
                         id_green &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;4038034&lt;/span&gt;)
colors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(patterns, get_colors) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(addhash) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;()
c2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; c &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_manual&lt;/span&gt;(values &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colors)

&lt;span style=&#34;color:#06287e&#34;&gt;add_patterns&lt;/span&gt;(plot &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; c2, patterns &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; patterns, colors &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colors) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Barber bar plot&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-19-babarplot/unnamed-chunk-8-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;
This is one plot decoration you could use to illustrate something about Occam&amp;rsquo;s razor.&lt;/p&gt;
&lt;h2 id=&#34;bark-plot&#34;&gt;Bark plot&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;patterns &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_patterns&lt;/span&gt;(id_blue &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1816764&lt;/span&gt;,
                         id_red &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1825775&lt;/span&gt;,
                         id_green &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1815897&lt;/span&gt;)

colors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(patterns, get_colors) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(addhash) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;()
c2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; c &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_manual&lt;/span&gt;(values &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colors)

&lt;span style=&#34;color:#06287e&#34;&gt;add_patterns&lt;/span&gt;(plot &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; c2, patterns &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; patterns, colors &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colors) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Bark bar plot&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-19-babarplot/unnamed-chunk-9-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-9&#34;&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m less convinced by this one, maybe it&amp;rsquo;d have looked better with barking dogs?&lt;/p&gt;
&lt;h2 id=&#34;bart-plot&#34;&gt;BART plot&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;patterns &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_patterns&lt;/span&gt;(id_blue &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1902711&lt;/span&gt;,
                         id_red &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1916712&lt;/span&gt;,
                         id_green &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1930435&lt;/span&gt;)
colors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(patterns, get_colors) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(addhash) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;()
c2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; c &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_manual&lt;/span&gt;(values &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colors)

&lt;span style=&#34;color:#06287e&#34;&gt;add_patterns&lt;/span&gt;(plot &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; c2, patterns &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; patterns, colors &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colors) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;BART bar plot&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-19-babarplot/unnamed-chunk-10-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-10&#34;&gt;&lt;/p&gt;
&lt;p&gt;This one is the loudest bar plot you&amp;rsquo;ll ever make since it was inspired by San Francisco BART. I might have come up with this idea after not finding a Bart Simpson pattern.&lt;/p&gt;
&lt;p&gt;I told Miles I&amp;rsquo;d stop once I&amp;rsquo;d only think of a barf plot which I don&amp;rsquo;t want to draw ever. As I had said the first time I made a bar plot with patterns, I&amp;rsquo;m not sure how useful it is, but you never know when you&amp;rsquo;re gonna need a fancy plot to get someone&amp;rsquo;s attention, right?&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>A plot against the CatterPlots complot</title>
      <link>https://masalmon.eu/2017/02/18/complot/</link>
      <pubDate>Sat, 18 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/02/18/complot/</guid>
      <description>&lt;p&gt;In these terrible times, we R people have more important subjects to debate/care about than &lt;code&gt;ggplot2&lt;/code&gt; vs. base R graphics (isn&amp;rsquo;t even worth discussing anyway, &lt;code&gt;ggplot2&lt;/code&gt; is clearly the best alternative). Or so I thought until I saw &lt;a href=&#34;https://github.com/Gibbsdavidl/CatterPlots&#34;&gt;&lt;code&gt;CatterPlots&lt;/code&gt;&lt;/a&gt; trending on Twitter this week and even being featured on &lt;a href=&#34;http://blog.revolutionanalytics.com/2017/02/catterplots-plots-with-cats.html&#34;&gt;&lt;strong&gt;Revolutions&lt;/strong&gt; blog&lt;/a&gt;. It was cool because plots with cats are cool, but looking more closely at the syntax of &lt;code&gt;CatterPlots&lt;/code&gt;, I couldn&amp;rsquo;t but realize it was probably a complot to make us all like base R graphics syntax again! So let me show you how to make a cute plot with the awesome &lt;code&gt;ggplot2&lt;/code&gt; extension &lt;a href=&#34;https://github.com/GuangchuangYu/emojifont&#34;&gt;&lt;code&gt;emojifont&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The plot I&amp;rsquo;m going to re-make in this post is an old one already that I designed for celebrating &lt;a href=&#34;https://edoc.ub.uni-muenchen.de/19877/&#34;&gt;my PhD thesis&lt;/a&gt; submission in March last year. I decided to compare the gestation time of my thesis, 1246 days, to the gestation time of some common mammals.&lt;/p&gt;
&lt;h1 id=&#34;getting-data&#34;&gt;Getting data&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;m a bit ashamed because I forgot to write down where I took my data from but I&amp;rsquo;m pretty sure it was from reading Wikipedia pages and taking a more or less random numbers in the gestation time range indicated for each animals. I also chose animals I could find an emoji for. As you can imagine, it was quite an agreeable data collection. Here is what I end up with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;forcats&amp;#34;&lt;/span&gt;)
gestation &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv2&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-02-18-complot.csv&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(gestation) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(animal &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;fct_rev&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;fct_inorder&lt;/span&gt;(animal)))
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(gestation)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;animal&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;gestation&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;label&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;color&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;mouse&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;19&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mouse&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;dog&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;61&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dog&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;cat&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;64&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;cat&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;wolf&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;68&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;wolf&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;tiger&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;105&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;tiger&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;pig&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;112&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;pig&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sheep&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;144&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sheep&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;bear&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;220&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;bear&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;human&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;280&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;baby&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;whale&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;590&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;whale&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;elephant&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;617&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;elephant&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;my thesis&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1246&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;closed_book&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;gold&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;levels&lt;/span&gt;(gestation&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;animal)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;##  [1] &amp;quot;my thesis&amp;quot; &amp;quot;elephant&amp;quot;  &amp;quot;whale&amp;quot;     &amp;quot;human&amp;quot;     &amp;quot;bear&amp;quot;     
##  [6] &amp;quot;sheep&amp;quot;     &amp;quot;pig&amp;quot;       &amp;quot;tiger&amp;quot;     &amp;quot;wolf&amp;quot;      &amp;quot;cat&amp;quot;      
## [11] &amp;quot;dog&amp;quot;       &amp;quot;mouse&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I used &lt;code&gt;forcats::fct_inorder&lt;/code&gt; and &lt;code&gt;forcats::fct_rev&lt;/code&gt; because in such a post not using &lt;code&gt;forcats&lt;/code&gt; would probably have been a deadly sin (and I don&amp;rsquo;t have 7 lives), but also because I needed the levels to be ordered from longest to shortest gestation time, otherwise the plot would have looked ugly.&lt;/p&gt;
&lt;h1 id=&#34;making-the-plot&#34;&gt;Making the plot&lt;/h1&gt;
&lt;p&gt;At the time I used &lt;code&gt;gganimate&lt;/code&gt; which I still love, but in the meantime I also fell in love with &lt;code&gt;magick&lt;/code&gt; in particular since reading &lt;a href=&#34;https://rud.is/b/2016/07/27/u-s-drought-animations-with-the-witchs-brew-purrr-broom-magick/&#34;&gt;Bob&amp;rsquo;s post&lt;/a&gt;. So I decided to re-write my code with &lt;code&gt;magick&lt;/code&gt;. On this blog I already published &lt;a href=&#34;https://masalmon.eu/2017/01/27/catan/&#34;&gt;an article featuring both &lt;code&gt;emojifont&lt;/code&gt; and &lt;code&gt;gganimate&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;emojifont&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;load.emojifont&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;OpenSansEmoji.ttf&amp;#39;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;magick&amp;#34;&lt;/span&gt;)
plot_one_gestation &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(gestation_time, gestation){
  now_data &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter_&lt;/span&gt;(gestation, &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; gestation &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;=&lt;/span&gt; gestation_time)
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(now_data) 
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;geom_col&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; animal,
               y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; gestation,
               fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; color))
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_manual&lt;/span&gt;(values &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;grey&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;grey30&amp;#34;&lt;/span&gt;,
                               &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;gold&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;darkgoldenrod1&amp;#34;&lt;/span&gt;)) 
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;geom_text&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; animal, 
                y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; gestation &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;45&lt;/span&gt;,
                label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;emoji&lt;/span&gt;(label)),
            family&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;OpenSansEmoji&amp;#34;&lt;/span&gt;, size&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;30&lt;/span&gt;) 
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(axis.text.y&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;element_blank&lt;/span&gt;(),
        axis.ticks&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;element_blank&lt;/span&gt;(),
        text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(size&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;40&lt;/span&gt;),
        legend.position&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;)
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(gestation_time)
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;scale_x_discrete&lt;/span&gt;(limits &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;levels&lt;/span&gt;(gestation&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;animal))
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ylim&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;max&lt;/span&gt;(gestation&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;gestation) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;50&lt;/span&gt;)) 
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;  &lt;span style=&#34;color:#06287e&#34;&gt;coord_flip&lt;/span&gt;() 
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Animal&amp;#34;&lt;/span&gt;) 
  p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Gestation in days&amp;#34;&lt;/span&gt;) 
  
  outfil &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;figs/animals_&amp;#34;&lt;/span&gt;, gestation_time, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.png&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;ggsave&lt;/span&gt;(outfil, p, width&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;, height&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;)

  outfil
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I wanted the last image to be repeated 4 times so that everyone might have time to ponder over my accomplishment. I was celebrating &lt;em&gt;and&lt;/em&gt; boasting with this graph.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purrr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(gestation&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;gestation),
  &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;max&lt;/span&gt;(gestation&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;gestation), &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;))&lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(plot_one_gestation, gestation &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; gestation) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(image_read) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_join&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_animate&lt;/span&gt;(fps&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;image_write&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;gestation.gif&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;img src=&#34;https://masalmon.eu/figure/gestation.gif&#34; alt=&#34;gestation&#34; width=&#34;700&#34;&gt;
&lt;p&gt;Aren&amp;rsquo;t these animal emojis adorable? At least as adorable as &lt;code&gt;CatterPlots&lt;/code&gt;cats? You can also bring emojis to &lt;code&gt;ggplot2&lt;/code&gt; with &lt;a href=&#34;https://github.com/dill/emoGG&#34;&gt;&lt;code&gt;emoGG&lt;/code&gt;&lt;/a&gt; (check out &lt;a href=&#34;http://livefreeordichotomize.com/2017/02/09/the-prevalence-of-drunk-podcasts/&#34;&gt;Lucy&amp;rsquo;s recent post&lt;/a&gt;) so you don&amp;rsquo;t need to ever leave the comfort of &lt;code&gt;ggplot2&lt;/code&gt; for the sake of &amp;ldquo;c[au]t[e]?ness&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Disclaimer: I actually starred &lt;code&gt;CatterPlots&lt;/code&gt; on Github because I&amp;rsquo;m an open-minded cat person (married to a cat allergic person!).&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Extracting notable deaths from Wikipedia</title>
      <link>https://masalmon.eu/2017/02/12/wikideaths3_scraping/</link>
      <pubDate>Sun, 12 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/02/12/wikideaths3_scraping/</guid>
      <description>&lt;p&gt;I like Wikipedia. My husband likes it even more, he included it in his PhD thesis acknowledgements! I appreciate the efforts done for sharing knowledge, and also the apparently random stuff you can find on the website. In particular, I&amp;rsquo;ve been intrigued by the monthly lists of notable deaths such as &lt;a href=&#34;https://en.wikipedia.org/wiki/Deaths_in_September_2011&#34;&gt;this one&lt;/a&gt;. Who are people (or dogs, yes, dogs) whose life was deemed notable enough to be listed there? Also, using the numbers of such deaths, can I judge whether 2016 was really worse than previous years? The first step in answering these questions was to scrape the data. I&amp;rsquo;ll describe the process in this post. &lt;a href=&#34;https://masalmon.eu/2017/02/12/wikideaths2_population/&#34;&gt;In another post&lt;/a&gt; I&amp;rsquo;ll have a look at my study population and &lt;a href=&#34;https://masalmon.eu/2017/02/12/wikideaths1_ts/&#34;&gt;in a third post&lt;/a&gt; I&amp;rsquo;ll analyse the time series of death counts.&lt;/p&gt;
&lt;p&gt;I have extracted all deaths listed in Wikipedia from 2004 to 2016 from monthly pages. For most deaths, I extracted the Wikipedia link, the name of the person, their age and the first part of their presentation, which most often includes a nationality and reason for being famous, e.g. &amp;ldquo;Italian astrophysicist&amp;rdquo;. I chose not to get the rest of the line if it was longer, because the length of the reason for being famous was quite variable and cause of death was not consistently indicated.&lt;/p&gt;
&lt;p&gt;Note that there are list of notable deaths for deaths occurred before 2004 but they are in a different format so let&amp;rsquo;s say it&amp;rsquo;s a challenge for another day (or another person, like you, dear reader?).&lt;/p&gt;
&lt;h2 id=&#34;downloading-the-lists-of-deaths&#34;&gt;Downloading the lists of deaths&lt;/h2&gt;
&lt;p&gt;I started by downloading the content of all monthly lists of deaths from 2004 to 2016.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rvest&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purrr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lazyeval&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tibble&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;fuzzyjoin&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;stringr&amp;#34;&lt;/span&gt;)
months &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;January&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;February&amp;#34;&lt;/span&gt;,
            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;March&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;April&amp;#34;&lt;/span&gt;,
            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;May&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;June&amp;#34;&lt;/span&gt;,
            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;July&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;August&amp;#34;&lt;/span&gt;,
            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;September&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;October&amp;#34;&lt;/span&gt;,
            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;November&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;December&amp;#34;&lt;/span&gt;)
years &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2004&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2016&lt;/span&gt;
pages_content &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(months, paste, years, sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;_&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# read page with monthly deaths&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x){
    &lt;span style=&#34;color:#06287e&#34;&gt;read_html&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://en.wikipedia.org/wiki/Deaths_in_&amp;#34;&lt;/span&gt;, x))})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;transforming-the-content-of-the-lists-into-a-table&#34;&gt;Transforming the content of the lists into a table&lt;/h2&gt;
&lt;p&gt;I actually did all this stuff months ago. At that time apparently I was patient enough to figure out how to extract information from the list. I was surprised to see my code still worked, for getting all of 2016 I just needed to change 2015 into 2016. Note that I use the name list, it&amp;rsquo;s a list on the webpage, not a table, which means I couldn&amp;rsquo;t just rely on &lt;code&gt;rvest&lt;/code&gt; and take a nap. My main goal was to be able to get something nice for &lt;em&gt;typical entries&lt;/em&gt; and just forget about the non-typical entries, hoping there wouldn&amp;rsquo;t be many. Here are the two functions I defined. I use &lt;code&gt;stringr&lt;/code&gt;, not &lt;code&gt;stringi&lt;/code&gt;, because it&amp;rsquo;s an old code where this was enough but since reading &lt;a href=&#34;https://rud.is/b/2017/02/06/strung-out-on-string-ops-a-brief-comparison-of-stringi-and-stringr/&#34;&gt;Bob Rudis&amp;rsquo; post&lt;/a&gt; I am more curious about &lt;code&gt;stringi&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;transform_day &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(day_deaths, day_in_month){
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# filter only those that have the format of lines presenting deaths&lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(day_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;days, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(day_deaths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;li&amp;gt;&amp;#34;&lt;/span&gt;, simplify &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; day_deaths[&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(day_deaths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Death&amp;#34;&lt;/span&gt;)]
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; day_deaths[&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(day_deaths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Category&amp;#34;&lt;/span&gt;)]
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Erases the end of each line&lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(day_deaths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\(&amp;lt;i&amp;gt;.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Create a table&lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tibble_&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(line &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;day_deaths))
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Variable for grouping by row &lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, row &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(day_deaths)))
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;group_by_&lt;/span&gt;(day_deaths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;row&amp;#34;&lt;/span&gt;)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# separate by the word &amp;#34;title&amp;#34;, first part is a link, second part description&lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, line &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(line, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;)))
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, wiki_link &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(line[[1]][1], &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;a href=\\\&amp;#34;/wiki/&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)))
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get Wikipedia link or better said the thing to paste to Wikipedia address&lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, 
                        wiki_link &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(wiki_link, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\\\&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)))
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, 
                        wiki_link &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(wiki_link, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)))
  
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# now transform the description into several columns&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# the format of the end of the description is variable so&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# I only keep the beginning of the reason for notoriety i.e. country of origin&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# and a role&lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# anyway cause of death is not written for all and I don&amp;#39;t want to use many details&lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, content &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;line[[1]][2]))
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths,
                        content &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(content, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;&amp;lt;a.*a&amp;gt;&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)))
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;separate_&lt;/span&gt;(day_deaths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt;, 
                          into &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;age&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;country_role&amp;#34;&lt;/span&gt;),
                          sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# when no age&lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, country_role &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(country_role),
                                                                  age,
                                                                  country_role)))
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, age &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.numeric&lt;/span&gt;(age)))
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# improves the name&lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, 
                        name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\&amp;#34;&amp;gt;.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)))
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, 
                        name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;=\&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)))
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# improves the country_role&lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, 
                        country_role &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(country_role, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;/li&amp;gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)))
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(day_deaths, 
                        country_role &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all
&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;                                              &lt;/span&gt;(country_role, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;/ul&amp;gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)))
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get rid of original line&lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;select_&lt;/span&gt;(day_deaths, &lt;span style=&#34;color:#06287e&#34;&gt;quote&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; line))
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get rid of grouping&lt;/span&gt;
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;(day_deaths)
  day_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;select_&lt;/span&gt;(day_deaths, &lt;span style=&#34;color:#06287e&#34;&gt;quote&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; row))
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(day_deaths)
}

parse_month_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(month_deaths){
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# remember month and year&lt;/span&gt;
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; stringr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_extract&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(month_deaths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;)), 
                                &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Deaths in .* -&amp;#34;&lt;/span&gt;)
  
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Deaths in &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; -&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;January&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;01&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;February&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;02&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;March&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;03&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;April&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;04&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;May&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;05&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;June&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;06&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;July&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;07&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;August&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;08&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;September&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;09&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;October&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;10&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;November&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;11&amp;#34;&lt;/span&gt;)
  title &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(title, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;December&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;12&amp;#34;&lt;/span&gt;)
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# find days with deaths&lt;/span&gt;
  content &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(month_deaths)
  content &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(content, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;, simplify &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  days &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;which&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(content, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;h3&amp;#34;&lt;/span&gt;))
  
  paragraphs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;which&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(content, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;ul&amp;gt;&amp;#34;&lt;/span&gt;))
  
  last_good &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;max&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;which&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(month_deaths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;h3&amp;#34;&lt;/span&gt;), 
                                             toString)),
                               pattern &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;title=Deaths_in_.*_..&amp;#34;&lt;/span&gt;)))
  
  possible_days &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;last_good
  
  possible_days &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; possible_days&lt;span style=&#34;color:#06287e&#34;&gt;[diff&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(days[possible_days], &lt;span style=&#34;color:#40a070&#34;&gt;999999&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;]
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# read only lines&lt;/span&gt;
  month_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(month_deaths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ul&amp;#34;&lt;/span&gt;)
  first_not_good &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;max&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;which&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(month_deaths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Template&amp;#34;&lt;/span&gt;)))
  first_good &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;which&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(month_deaths, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;wiki&amp;#34;&lt;/span&gt;)))
  paragraphs &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; paragraphs[first_good&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(first_not_good &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)]
  
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(paragraphs) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(possible_days)){
    jours &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NULL&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;for&lt;/span&gt;(paragraph in paragraphs){
      x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; days[days &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;&lt;/span&gt; paragraph]
      jours &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(jours,
                 possible_days&lt;span style=&#34;color:#06287e&#34;&gt;[which&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;abs&lt;/span&gt;(x&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;paragraph)&lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;min&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;abs&lt;/span&gt;(x&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;paragraph)))])
    }
    possible_days &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; jours
  }
  
  month_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; month_deaths[first_good&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;(first_not_good &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)]
  month_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unlist&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(month_deaths, toString))
  
  
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# transform for getting the different columns&lt;/span&gt;
  month_deaths_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;data.frame&lt;/span&gt;(days &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; month_deaths,
                                   day_in_month &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; possible_days,
                                   title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; title) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;by_row&lt;/span&gt;(transform_day, .to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;all_deaths&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;unnest_&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;all_deaths&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;group_by_&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;wiki_link&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(index &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;filter_&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;index &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;select_&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;quote&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;index)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;group_by_&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;days&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(date &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; lubridate&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;dmy&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(day_in_month, title)))) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;select_&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;quote&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; day_in_month)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;select_&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;quote&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; title)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;select_&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;quote&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; days)) 
  
  month_deaths_table
  
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once the functions were written (and tested on a few pages) I simply mapped them to all the pages.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;deaths_2004_2016 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pages_content &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;  
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(parse_month_deaths) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  dplyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;()
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(deaths_2004_2016))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;wiki_link&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;age&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;country_role&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;date&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Harold_Henning&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Harold Henning&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;69&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;South African golfer.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Elma_Lewis&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Elma Lewis&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;82&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American arts leader.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Manuel_F%C3%A9lix_L%C3%B3pez&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Manuel Félix López&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;66&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ecuadorian politician.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Frederick_Redlich&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Frederick Redlich&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;93&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Austrian-born American dean of the &amp;lt;a href=&amp;rdquo;/wiki/Yale_University&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Etta_Moten_Barnett&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Etta Moten Barnett&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;102&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American actress.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lynn_Cartwright&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lynn Cartwright&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;76&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;U.S. actress.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-02&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I was already quite happy to get this table, but I wanted to add a country to most rows, and separate the role of the person from the adjectival.&lt;/p&gt;
&lt;h2 id=&#34;get-the-demonyms-table-from-wikipedia&#34;&gt;Get the demonyms table from Wikipedia&lt;/h2&gt;
&lt;p&gt;I discovered Wikipedia has a &lt;a href=&#34;https://en.m.wikipedia.org/wiki/List_of_adjectival_and_demonymic_forms_for_countries_and_nations&#34;&gt;table&lt;/a&gt; (a table! a table!) of adjectivals for many countries and nations. The only thing I changed was getting one line by adjectivals when there were several ones by country or nation. I also calculated the number of words in this adjectival in order to be able to easily remove it from the &lt;code&gt;&amp;quot;country_role&amp;quot;&lt;/code&gt; column and thus get the role on its own.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;demonyms_page &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;read_html&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://en.m.wikipedia.org/wiki/List_of_adjectival_and_demonymic_forms_for_countries_and_nations&amp;#34;&lt;/span&gt;)

demonyms_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(demonyms_page, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;table&amp;#34;&lt;/span&gt;)[1]
demonyms_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;html_table&lt;/span&gt;(demonyms_table, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)[[1]]
&lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(demonyms_table) &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;country&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;adjectivals&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;demonyms&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;colloquial_demonyms&amp;#34;&lt;/span&gt;)
demonyms_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;as_tibble&lt;/span&gt;(demonyms_table)
demonyms_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;by_row&lt;/span&gt;(demonyms_table,
                         &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
                           adjectivals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tibble_&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(goodadjectivals &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;adjectivals, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; or &amp;#34;&lt;/span&gt;))))
                           }, .collate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;list&amp;#34;&lt;/span&gt;, .to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;good_adjectivals&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unnest_&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;good_adjectivals&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unnest_&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;goodadjectivals&amp;#34;&lt;/span&gt;)
demonyms_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;select_&lt;/span&gt;(demonyms_table, &lt;span style=&#34;color:#06287e&#34;&gt;quote&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; adjectivals))
demonyms_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rename_&lt;/span&gt;(demonyms_table, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;adjectivals&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;goodadjectivals&amp;#34;&lt;/span&gt; )
demonyms_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;by_row&lt;/span&gt;(demonyms_table,
                         &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
                           adjectivals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tibble_&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(goodadjectivals &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;interp&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;adjectivals, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;))))
                         }, .collate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;list&amp;#34;&lt;/span&gt;, .to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;good_adjectivals&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unnest_&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;good_adjectivals&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unnest_&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;goodadjectivals&amp;#34;&lt;/span&gt;)

demonyms_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;select_&lt;/span&gt;(demonyms_table, &lt;span style=&#34;color:#06287e&#34;&gt;quote&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; adjectivals))
demonyms_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rename_&lt;/span&gt;(demonyms_table, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;adjectivals&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;goodadjectivals&amp;#34;&lt;/span&gt; )

demonyms_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(demonyms_table, adjectivals &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(adjectivals ))
demonyms_table &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;by_row&lt;/span&gt;(demonyms_table,
                         &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
                           &lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;adjectivals, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;)[[1]])},
                         .to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;adj_length&amp;#34;&lt;/span&gt;, .collate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;using-adjectivals-to-split-deaths-country-and-role&#34;&gt;Using adjectivals to split deaths&amp;rsquo; country and role&lt;/h2&gt;
&lt;p&gt;For finding which country/nation to add to a line I used &lt;code&gt;fuzzyjoin::regex_left_join()&lt;/code&gt; which worked well but a bit slowly given the number of lines.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; deaths_2004_2016
demonyms &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; demonyms_table
deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(deaths, country_role &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(country_role,
                                                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))

demonyms &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(demonyms, adjectivals &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(adjectivals, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;))
demonyms &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unnest&lt;/span&gt;(demonyms, adjectivals)
demonyms &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(demonyms, 
                   adjectivals &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(adjectivals, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; .*&amp;#34;&lt;/span&gt;))
deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;regex_left_join&lt;/span&gt;(deaths, 
                          demonyms, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;country_role&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;adjectivals&amp;#34;&lt;/span&gt;))

deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(deaths,
                 country &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;str_detect&lt;/span&gt;(country_role, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;American&amp;#34;&lt;/span&gt;),
                                  &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;United States&amp;#34;&lt;/span&gt;,
                                  country))

deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(deaths,
                 adjectivals &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(country &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;United States&amp;#34;&lt;/span&gt;,
                                       &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;American&amp;#34;&lt;/span&gt;, adjectivals))
deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(deaths,
                 adj_length &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(country &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;United States&amp;#34;&lt;/span&gt;,
                                      &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, adj_length))
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# keep one country only&lt;/span&gt;
deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(deaths, wiki_link) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(index &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(index &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;by_row&lt;/span&gt;(deaths,
                 &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
                   &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;adj_length)) {
                     country_role &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;country_role)
                     splitted &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(country_role, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;)[[1]]
                     role &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(splitted&lt;span style=&#34;color:#06287e&#34;&gt;[&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;adj_length &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(splitted)])
                     &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(role, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
                     }else{
                     df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;country_role
                   }
                   
                 }, .to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;occupation&amp;#34;&lt;/span&gt;, .collate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols&amp;#34;&lt;/span&gt;)

deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(deaths, 
                 occupation &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(occupation, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\r&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(deaths, 
                 occupation &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(occupation, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(deaths, 
                 occupation &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(occupation, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\.&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))

deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(deaths, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; demonyms, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; colloquial_demonyms,
                   &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; index)
readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(deaths, path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/deaths_with_demonyms.csv&amp;#34;&lt;/span&gt;)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(deaths))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;wiki_link&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;age&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;country_role&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;date&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;country&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;adj_length&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;adjectivals&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;occupation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Harold_Henning&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Harold Henning&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;69&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;South African golfer.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;South Africa&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;South African .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;golfer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Elma_Lewis&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Elma Lewis&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;82&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American arts leader.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;arts leader&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Manuel_F%C3%A9lix_L%C3%B3pez&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Manuel Félix López&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;66&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ecuadorian politician.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ecuador&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ecuadorian .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;politician&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Frederick_Redlich&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Frederick Redlich&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;93&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Austrian-born American dean of the&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American dean of the&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Etta_Moten_Barnett&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Etta Moten Barnett&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;102&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American actress.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;actress&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lynn_Cartwright&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lynn Cartwright&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;76&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;U.S. actress.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2004-01-02&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States[20]&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;U.S. .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;actress&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In the table I have information about 56303 notable deaths. I know the age of 97% of them, a country or nation for 96.2% of them. Not too bad I think! It was then time to stop scraping webpages and to start digging into the data&amp;hellip; &lt;a href=&#34;https://masalmon.eu/2017/02/12/wikideaths2_population/&#34;&gt;Who were these people?&lt;/a&gt; and &lt;a href=&#34;https://masalmon.eu/2017/02/12/wikideaths1_ts/&#34;&gt;How bad was 2016?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to end this post with a note from my husband, who thinks having a blog makes me an influencer. If you too like Wikipedia, consider &lt;a href=&#34;https://wikimediafoundation.org/wiki/Ways_to_Give&#34;&gt;donating to the Wikimedia foundation&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Were there more notable deaths than expected in 2016?</title>
      <link>https://masalmon.eu/2017/02/12/wikideaths1_ts/</link>
      <pubDate>Sun, 12 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/02/12/wikideaths1_ts/</guid>
      <description>&lt;p&gt;After exploring my &lt;a href=&#34;https://masalmon.eu/2017/02/12/wikideaths2_population/&#34;&gt;study population&lt;/a&gt; of Wikipedia deaths, I want to analyse the time series of monthly counts of notable deaths. This is not a random interest of mine, &lt;a href=&#34;https://edoc.ub.uni-muenchen.de/19877/&#34;&gt;my PhD thesis&lt;/a&gt; was about monitoring time series of count, the application being weekly number of reported cases of various diseases.&lt;/p&gt;
&lt;h1 id=&#34;number-of-deaths-reported-over-time&#34;&gt;Number of deaths reported over time&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;viridis&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lubridate&amp;#34;&lt;/span&gt;)
deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/deaths_with_demonyms.csv&amp;#34;&lt;/span&gt;)
deaths &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(date) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n_deaths &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; date, xend &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; date,
             y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, yend &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; n_deaths)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_segment&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Time (days)&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Number of reported deaths&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-12-wikideaths1_ts/unnamed-chunk-1-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-1&#34;&gt;&lt;/p&gt;
&lt;p&gt;I have two remarks about this figure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;There is an increase in the number of reported deaths over time, which is not surprising given the growth of Wikipedia.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There are three major peaks. They are due to the &lt;a href=&#34;https://en.wikipedia.org/wiki/2010_Haiti_earthquake&#34;&gt;2010 Haiti earthquake&lt;/a&gt; of the 12th of January; the &lt;a href=&#34;https://en.wikipedia.org/wiki/2010_Polish_Air_Force_Tu-154_crash&#34;&gt;2010 Polish Air Force Tu-154 crash&lt;/a&gt; on the 10th of April of 2010; and the &lt;a href=&#34;https://en.wikipedia.org/wiki/2011_Lokomotiv_Yaroslavl_air_disaster&#34;&gt;2011 Lokomotiv Yaroslavl air disaster&lt;/a&gt; on the 7th of September 2011. In the following, I will remove the fatalities from these events.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;modeling-the-time-series&#34;&gt;Modeling the time series&lt;/h1&gt;
&lt;p&gt;When I think of modeling time series of count in R, I either think of &lt;a href=&#34;https://www.jstatsoft.org/article/view/v070i10&#34;&gt;&lt;code&gt;surveillance&lt;/code&gt;&lt;/a&gt;, which was the implementational repository of my methodological developments &lt;a href=&#34;http://staff.math.su.se/hoehle/blog/2016/12/12/hackinthedark.html&#34;&gt;as Michael would say&lt;/a&gt;; or of &lt;a href=&#34;https://cran.r-project.org/web/packages/tscount/vignettes/tsglm.pdf&#34;&gt;&lt;code&gt;tscount&lt;/code&gt;&lt;/a&gt;, which was the package of my PhD writing buddy Tobias Liboschik (after meeting at a conference we exchanged feedback on our thesis chapters which was awesome). If you have an interest in prospectively detecting outbreaks and a time series with seasonality, like the time series of number of cases of Salmonella, then &lt;code&gt;surveillance&lt;/code&gt; is the best choice. Now in the case of Wikipedia deaths, I felt more inclined towards using &lt;code&gt;tscount&lt;/code&gt;. I had never properly used it apart from a comparison section in my thesis so it was also more exciting. So &lt;code&gt;tscount&lt;/code&gt; it was!&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;tscount&lt;/code&gt;, you have &lt;code&gt;tsglm&lt;/code&gt; models which take into account both the count nature of the data and its time series nature, i.e. you can treat auto-correlation. The &lt;a href=&#34;https://cran.r-project.org/web/packages/tscount/vignettes/tsglm.pdf&#34;&gt;vignette of &lt;code&gt;tscount&lt;/code&gt;&lt;/a&gt; is a really great manuscript.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll use the time series of monthly counts of deaths in the rest of the post.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tscount&amp;#34;&lt;/span&gt;)
monthly_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; deaths &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(wiki_link) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(month &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;update&lt;/span&gt;(date, day &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(month) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) 

haiti_earthquake &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;update&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2010-01-12&amp;#34;&lt;/span&gt;), day &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
aircrash1 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;update&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2010-01-12&amp;#34;&lt;/span&gt;), day &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
aircrash2 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;update&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;ymd&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;2011-09-07&amp;#34;&lt;/span&gt;), day &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)

monthly_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(monthly_deaths, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(month &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; haiti_earthquake, n &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;, n))
monthly_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(monthly_deaths, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(month &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; aircrash1, n &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;96&lt;/span&gt;, n))
monthly_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(monthly_deaths, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(month &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; aircrash2, n &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;44&lt;/span&gt;, n))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(monthly_deaths) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_segment&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; month, xend &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; month,
             y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, yend &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; n)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Number of reported deaths&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Time (months)&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-12-wikideaths1_ts/unnamed-chunk-3-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-3&#34;&gt;&lt;/p&gt;
&lt;p&gt;We still see the upward trend, and I have a feeling we&amp;rsquo;re also dealing with overdispersion. First step before doing any modeling: getting a ts object. I hold off the last 12 months which are 2016 months.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;ts_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xts&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xts&lt;/span&gt;(monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;n[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;144&lt;/span&gt;], monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;month[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;144&lt;/span&gt;])

ts_deaths &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ts&lt;/span&gt;(ts_deaths, freq&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, start&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;2004&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;))
&lt;span style=&#34;color:#06287e&#34;&gt;plot&lt;/span&gt;(ts_deaths)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-12-wikideaths1_ts/unnamed-chunk-4-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-4&#34;&gt;&lt;/p&gt;
&lt;p&gt;Then I use a model with regression on the past observation, on the mean from one year ago, and with a temporal trend. I log-transform time because the regression model uses a log link and I don&amp;rsquo;t expect the time trend to be exponential on the response scale. I&amp;rsquo;ll fit a Poisson and a negative binomial models in order to compare them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;time &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;log&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(monthly_deaths))
fit_pois &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tsglm&lt;/span&gt;(ts_deaths[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;144&lt;/span&gt;], model &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(past_obs &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, past_mean &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;13&lt;/span&gt;), xreg &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; time[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;144&lt;/span&gt;], distr &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;poisson&amp;#34;&lt;/span&gt;)
fit_nb &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tsglm&lt;/span&gt;(ts_deaths[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;144&lt;/span&gt;], model &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(past_obs &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, past_mean &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;13&lt;/span&gt;), xreg &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; time[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;144&lt;/span&gt;], distr &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;nbinom&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For choosing between the two models I&amp;rsquo;ll use scoring rules.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;rbind&lt;/span&gt;(Poisson &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;scoring&lt;/span&gt;(fit_pois), NegBin &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;scoring&lt;/span&gt;(fit_nb))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;##         logarithmic    quadratic  spherical rankprob    dawseb     normsq
## Poisson    10.23428  0.003338134 -0.0495852 40.83497 17.633417 11.8105665
## NegBin      5.68638 -0.004157600 -0.0655695 35.61633  9.417219  0.9722222
##          sqerror
## Poisson 3835.296
## NegBin  3835.296
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The smaller the scoring rule the better, so we should use the negative binomial model which I&amp;rsquo;m happy about since I had assumed we&amp;rsquo;d be dealing with overdispersion. Note that I used scoring rules whose values were computed on the part of the data I used for fitting the model, which is what Tobias Liboschik did in his manuscript for the Campylobacter example.&lt;/p&gt;
&lt;h1 id=&#34;predicting-2016-values&#34;&gt;Predicting 2016 values&lt;/h1&gt;
&lt;p&gt;I realized there&amp;rsquo;s no &lt;code&gt;broom&lt;/code&gt; &amp;ldquo;adapter&amp;rdquo; for &lt;code&gt;tsglm&lt;/code&gt; so I&amp;rsquo;ll write untidy code and hope you&amp;rsquo;ll all forgive me.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
pred2016 &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;predict&lt;/span&gt;(fit_nb, n.ahead &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, level &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.9&lt;/span&gt;, global &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;, B &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3000&lt;/span&gt;, newxreg &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; time[145&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;156&lt;/span&gt;])
monthly_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(monthly_deaths, lower &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;,
                         upper &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;, pred &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;)
monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;lower[145&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;156&lt;/span&gt;] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pred2016&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;interval[,&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;]
monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;upper[145&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;156&lt;/span&gt;] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pred2016&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;interval[,&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;]
monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;pred[145&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;156&lt;/span&gt;] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pred2016&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;pred
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s plot the result.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(monthly_deaths) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_segment&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; month, xend &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; month,
             y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, yend &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; n)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Number of reported deaths&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Time (months)&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_line&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; month, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; pred), col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;blue&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_ribbon&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; month, ymin &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lower, ymax &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; upper),
              alpha &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-12-wikideaths1_ts/unnamed-chunk-8-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;
SEE THE UPDATE BELOW! 2017-02-14&lt;/p&gt;
&lt;p&gt;After discussing the model above with several people (including in the comments of the post, thanks Michael, and by email, thanks Tobias) and realizing I hadn&amp;rsquo;t checked the residual auto-correlation properly (shame on me!) I decided to re-do the model with an offset. Now &lt;code&gt;tscount&lt;/code&gt; doesn&amp;rsquo;t support offsets yet so I resorted to &lt;code&gt;glarma&lt;/code&gt;. I used the number of articles on Wikipedia as an offset and data from 2009 only because after 2009 the ratio of the number of notable deaths per month divided by the number of articles seemed more or less constant. I got the data on the number of articles from &lt;a href=&#34;https://en.wikipedia.org/wiki/Wikipedia:Size_of_Wikipedia&#34;&gt;this really cool Wikipedia article&lt;/a&gt;. I quite lazily used the latest non missing number of Wikipedia articles as number of articles for each day and made an average for the month.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# not really a table so I copy pasted it&lt;/span&gt;
wikisize &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-02-14_wikisize.csv&amp;#34;&lt;/span&gt;,
                            col_names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;date&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;articles_count&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;comment&amp;#34;&lt;/span&gt;))
deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; deaths &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(date) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n_deaths &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) 

deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(deaths, wikisize, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;date&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# latest number of 2003&lt;/span&gt;
deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;articles_count[1] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;188538&lt;/span&gt;
deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(deaths, 
                 articles_count &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; zoo&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;na.locf&lt;/span&gt;(articles_count))

monthly_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; deaths  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(date) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(month &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;update&lt;/span&gt;(date, day &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(month) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sum&lt;/span&gt;(n_deaths),
            articles &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mean&lt;/span&gt;(articles_count))

&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(monthly_deaths) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(month, n&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;articles))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-12-wikideaths1_ts/unnamed-chunk-9-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-9&#34;&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;glarma&amp;#34;&lt;/span&gt;)
monthly_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(monthly_deaths,
                         &lt;span style=&#34;color:#06287e&#34;&gt;year&lt;/span&gt;(month) &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2008&lt;/span&gt;)
ts_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; xts&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;xts&lt;/span&gt;(monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;n[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;84&lt;/span&gt;],
                      monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;month[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;84&lt;/span&gt;])

ts_deaths &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ts&lt;/span&gt;(ts_deaths, freq&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, start&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;2009&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I then use a new model. For upper and lower bounds I used quantiles from the negative binomial distribution.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;glarmamodOffset &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;glarma&lt;/span&gt;(ts_deaths,
                          X &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.matrix&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;84&lt;/span&gt;)),
                          offset &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;log&lt;/span&gt;(monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;articles[1&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;84&lt;/span&gt;]&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;100000&lt;/span&gt;),
                          phiLags &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;),
                          type &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;NegBin&amp;#34;&lt;/span&gt;, method &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;FS&amp;#34;&lt;/span&gt;,
                          residuals &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Pearson&amp;#34;&lt;/span&gt;, maxit &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;100&lt;/span&gt;, grad &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1e-6&lt;/span&gt;)

pred &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;forecast&lt;/span&gt;(glarmamodOffset, n.ahead &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, 
                   newdata &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.matrix&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;)), 
                   newoffset &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;log&lt;/span&gt;(monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;articles[85&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;96&lt;/span&gt;]&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;100000&lt;/span&gt;))

monthly_deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(monthly_deaths,
                         pred &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;, lower &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;, upper &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;)
monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;pred[85&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;96&lt;/span&gt;] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; pred&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;Y
monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;upper[85&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;96&lt;/span&gt;] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;qnbinom&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0.975&lt;/span&gt;, mu &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; pred&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;Y, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; glarmamodOffset&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;delta[4])
monthly_deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;lower[85&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;96&lt;/span&gt;] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;qnbinom&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;0.125&lt;/span&gt;, mu &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; pred&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;Y, size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; glarmamodOffset&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;delta[4])
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(monthly_deaths) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_segment&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; month, xend &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; month,
                   y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, yend &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; n)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ylab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Number of reported deaths&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;xlab&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Time (months)&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_line&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; month, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; pred), col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;blue&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_ribbon&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; month, ymin &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; lower, ymax &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; upper),
              alpha &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.5&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-12-wikideaths1_ts/unnamed-chunk-10-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-10&#34;&gt;&lt;/p&gt;
&lt;p&gt;So what? First I&amp;rsquo;d say it&amp;rsquo;s important to check your model really well, maybe this one isn&amp;rsquo;t the best one but it&amp;rsquo;s already better than the previous one, and I&amp;rsquo;ll keep thinking about how to improve it but I already wanted to post a mea culpa! Now regarding my initial question, nearly all number of deaths of 2016 are below the 95% quantile of the negative binomial distribution (disregarding estimation uncertainty) which means that maybe 2016 wasn&amp;rsquo;t a bad year for notable deaths &lt;em&gt;in general&lt;/em&gt;, but then one should make the same analysis on a subset of the data like notable dead from the arts by filtering them according to their role, or notable dead whose Wikipedia pages consistently had more than X% of total Wikipedia daily page views before their deaths. I&amp;rsquo;m actually planning on doing more with page views, but in the meantime, it was nice to play with time series of counts again!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to end this post with a note from my husband, who thinks having a blog makes me an influencer. If you too like Wikipedia, consider &lt;a href=&#34;https://wikimediafoundation.org/wiki/Ways_to_Give&#34;&gt;donating to the Wikimedia foundation&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Who were the notable dead of Wikipedia?</title>
      <link>https://masalmon.eu/2017/02/12/wikideaths2_population/</link>
      <pubDate>Sun, 12 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/02/12/wikideaths2_population/</guid>
      <description>&lt;p&gt;As described &lt;a href=&#34;https://masalmon.eu/2017/02/12/wikideaths3_scraping/&#34;&gt;in my last post&lt;/a&gt;, I extracted all notable deaths from Wikipedia over the 2004-2016 period. In this post I want to explore this study population. Who were the notable dead?&lt;/p&gt;
&lt;h1 id=&#34;how-old-were-notable-dead&#34;&gt;How old were notable dead?&lt;/h1&gt;
&lt;p&gt;Let me assume here most entries of the table are humans. I won&amp;rsquo;t make the effort to remove dogs or horses from the list yet, which introduces a small mistake.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;viridis&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;broom&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lubridate&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidytext&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rcorpora&amp;#34;&lt;/span&gt;)
deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/deaths_with_demonyms.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As a reminder, in case you didn&amp;rsquo;t learn the figures from my last post (shame on you), the table contains information about 56303 notable deaths. I could extract the age of 97% of them.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(deaths) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_histogram&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(age)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Age at death of Wikipedia notable dead&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-12-wikideaths2_population/unnamed-chunk-2-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-2&#34;&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s be honest, I expected a bimodal distribution with a first peak at 27.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tidy&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;summary&lt;/span&gt;(deaths&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;age))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;##   minimum q1 median  mean q3 maximum   na
## 1       1 68     80 75.94 88     176 1677
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Wow this is a really high maximal age.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(deaths, &lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(age)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;wiki_link&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;age&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;country_role&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;date&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;country&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;adj_length&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;adjectivals&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;occupation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Harriet_(tortoise)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Harriet (tortoise)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;176&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2006-06-23&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Eisenhower_Tree&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Eisenhower Tree&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;125&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-02-16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA American&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;J%C3%B3zef_Piotrowski_(organist)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Józef Piotrowski (organist)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;118&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Polish organist and longevity claimant.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2005-09-08&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Poland&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Polish .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;organist and longevity claimant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Misao_Okawa&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Misao Okawa&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;117&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Japanese supercentenarian&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-04-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Japan&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Japanese .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;supercentenarian&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Pawe%C5%82_Parniak&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Pawel Parniak&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;116&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Polish supercentenarian&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2006-03-27&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Poland&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Polish .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;supercentenarian&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Gertrude_Weaver&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Gertrude Weaver&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;116&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-04-06&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA American&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Jai_Gurudev&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Jai Gurudev&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;116&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Indian religious leader.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2012-05-18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;India&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Indian .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;religious leader&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Susannah_Mushatt_Jones&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Susannah Mushatt Jones&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;116&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2016-05-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA American&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Jiroemon_Kimura&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Jiroemon Kimura&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;116&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Japanese&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2013-06-12&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Japan&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Japanese .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA Japanese&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Jeralean_Talley&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Jeralean Talley&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;116&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American supercentenarian&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2015-06-17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;supercentenarian&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Ok, so the oldest beings in this table were a tortoise and a tree, which we might want to remove from the rest of the analysis.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(deaths, age &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;125&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What about the deaths at the youngest ages?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(deaths, age) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;wiki_link&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;age&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;country_role&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;date&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;country&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;adj_length&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;adjectivals&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;occupation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Manar_Maged class=mw-redirect&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Manar Maged&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Egyptian girl born with two heads&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2006-03-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Egypt&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Egyptian .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;girl born with two heads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Ayelet_Galena&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ayelet Galena&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American child&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2012-01-31&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;child&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Colonel_Meow&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Colonel Meow&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American Himalayan-Persian cat&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-01-29&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Himalayan-Persian cat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Ben_Bowen&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ben Bowen&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American child cancer victim&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2005-02-25&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;child cancer victim&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Marius_(giraffe)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Marius (giraffe)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Danish giraffe&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-02-09&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Denmark&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Danish .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;giraffe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Disappearance_of_Aisling_Symes class=mw-redirect&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Disappearance of Aisling Symes&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;New Zealand child whose disappearance initiated major search&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2009-10-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;New Zealand&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;New Zealand .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;child whose disappearance initiated major search&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Paul_the_Octopus&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Paul the Octopus&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;British-born&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2010-10-26&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;British-born&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Chriselliam&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Chriselliam&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Irish-bred British-trained Thoroughbred racehorse&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2014-02-07&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Irish-bred British-trained Thoroughbred racehorse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Eight_Belles&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Eight Belles&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American racehorse&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2008-05-03&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;American&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;racehorse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Sybil_(cat)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Sybil (cat)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;British Downing Street cat&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2009-07-27&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;England&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;British .*&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Downing Street cat&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As one could have expected, the deaths at youngest ages are some sad stories, about humans but also animals.&lt;/p&gt;
&lt;p&gt;Did the age distribution change over time?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;deaths &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(deaths, death_year &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.factor&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;year&lt;/span&gt;(date)))
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(deaths) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_boxplot&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(death_year, age, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; death_year)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(legend.position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-12-wikideaths2_population/unnamed-chunk-7-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-7&#34;&gt;&lt;/p&gt;
&lt;p&gt;Well &lt;em&gt;maybe&lt;/em&gt; there is an increasing trend? I wouldn&amp;rsquo;t be surprised if it were the case, since life expectancy tends to increase. I first wrote I wouldn&amp;rsquo;t take the time to test the trend and then I had a very interesting discussion with &lt;a href=&#34;https://twitter.com/milesmcbain&#34;&gt;Miles McBain&lt;/a&gt; and &lt;a href=&#34;http://www.njtierney.com/&#34;&gt;Nick Tierney&lt;/a&gt;. I had first thought of a linear model, then of a survival analysis but I only have positive events. While using a linear model or a GLM the residuals were never normally distributed. Then Miles mentioned non-parametric tests which is something I never think about. Googling a bit around I fount the Mann-Kendall test!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m quite lucky I want to see if age at death monotically increases over &lt;em&gt;time&lt;/em&gt; because that seems to be the usual use case for it. I choose to use the time series of weekly median age, which I&amp;rsquo;m not too sure is the best choice. I could have chosen monthly average age, etc.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;trend&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;lubridate&amp;#34;&lt;/span&gt;)
weekly_median_age &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; deaths &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(age)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(wiki_link) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(week &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;year&lt;/span&gt;(date), &lt;span style=&#34;color:#06287e&#34;&gt;week&lt;/span&gt;(date))) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(week) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(age &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;median&lt;/span&gt;(age)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; .$age
weekly_median_age &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.ts&lt;/span&gt;(weekly_median_age)
&lt;span style=&#34;color:#06287e&#34;&gt;plot&lt;/span&gt;(weekly_median_age)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-12-wikideaths2_population/unnamed-chunk-8-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;res &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mk.test&lt;/span&gt;(weekly_median_age)
&lt;span style=&#34;color:#06287e&#34;&gt;summary.trend.test&lt;/span&gt;(res)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Mann-Kendall Test
##  
## two-sided homogeinity test
## H0: S = 0 (no trend)
## HA: S != 0 (monotonic trend)
##  
## Statistics for total series
##       S     varS    Z   tau     pvalue
## 1 79925 36111378 13.3 0.337 &amp;lt; 2.22e-16
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Using this test I have now more support for the existence of a trend, but not for its direction. The same package has an implementation of Sen&amp;rsquo;s method to compute the slope.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;sens &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sens.slope&lt;/span&gt;(weekly_median_age, level &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.95&lt;/span&gt;)
sens
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;##  
## Sen&#39;s slope and intercept
##  
##  
## slope:  0.0065
## 95 percent confidence intervall for slope
## 0.0074 0.0056
##  
## intercept: 77.1831
## nr. of observations: 689
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With such a slope in one year one gains 0.34 years. Will we soon have humans as old as Harriet the tortoise?&lt;/p&gt;
&lt;h1 id=&#34;where-did-notable-dead-come-from&#34;&gt;Where did notable dead come from?&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;deaths &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(country) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;country&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;United States&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20220&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;England&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6163&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Canada&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2183&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Australia&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1783&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;India&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1604&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;France&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1277&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Germany&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1277&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Italy&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1141&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Russia[15]&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;884&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;857&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Unsurprisingly given what I imagine to be the countries of Wikipedia contributors in English, mostly from developped countries, and then India is a huge English-speaking country. It&amp;rsquo;d probably be interesting to repeat the same data extraction for all languages and see how we rather know celebrities speaking our own language or sharing our culture.&lt;/p&gt;
&lt;h2 id=&#34;what-were-the-reasons-of-notability&#34;&gt;What were the reasons of notability?&lt;/h2&gt;
&lt;p&gt;I first played with the idea of using my &lt;code&gt;monkeylearn&lt;/code&gt; package to associated an industry to each occupation/reason for being notable, but I soon realized the description was too short for the extractor. I also soon saw I wouldn&amp;rsquo;t be able to find a good list of jobs, so I resorted to simply look for the most present terms using &lt;code&gt;tidytext&lt;/code&gt;. For removing the stop-words I used &lt;code&gt;rcorpora&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;stopwords &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;corpora&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;words/stopwords/en&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;stopWords

deaths_words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; deaths &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(word, occupation) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;count&lt;/span&gt;(word, sort &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;word &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; stopwords)


&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(deaths_words, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;word&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;politician&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6285&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;player&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4251&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;actor&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2807&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;footballer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2022&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;football&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1899&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;actress&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1693&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;singer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1593&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;writer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1526&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;american&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1476&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;olympic&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1396&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;From these 10 most prevalent terms we could assume being a politician, some sort of athlete (player could also be a football player) or artist can make you notable. It&amp;rsquo;s interesting to see there are far more actors than actresses. In case you didn&amp;rsquo;t get the message, in the table there are 756 businessmen, 44 businesswomen, 4 business persons.&lt;/p&gt;
&lt;p&gt;I also noticed that there are 147 murderers and  41 serial killers vs. 232 chemists and 46 statisticians. Since the term &amp;ldquo;data scientist&amp;rdquo; is quite young, there is none in my table, and I sure wish you&amp;rsquo;ll all stay healthy, my friends! &lt;a href=&#34;https://masalmon.eu/2017/02/12/wikideaths3_ts/&#34;&gt;In the next post&lt;/a&gt; I&amp;rsquo;ll present the analysis of the time series of monthly count of deaths.&lt;/p&gt;
&lt;p&gt;If you liked learning more about notable dead, you can have a look at the analysis Hazel Kavili started doing of &lt;a href=&#34;https://github.com/UniversalTourist/celebrityDeaths&#34;&gt;celebrity deaths in 2016&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to end this post with a note from my husband, who thinks having a blog makes me an influencer. If you too like Wikipedia, consider &lt;a href=&#34;https://wikimediafoundation.org/wiki/Ways_to_Give&#34;&gt;donating to the Wikimedia foundation&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>The animals of #actuallivingscientists</title>
      <link>https://masalmon.eu/2017/02/05/actuallivingscientists/</link>
      <pubDate>Sun, 05 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/02/05/actuallivingscientists/</guid>
      <description>&lt;p&gt;These last days a trending Twitter hashtag was &amp;ldquo;#actuallivingscientist&amp;rdquo;, whose origin can be find in &lt;a href=&#34;https://twitter.com/darthmom7/status/827268431799922688?ref_src=twsrc%5Etfw&#34;&gt;this convo&lt;/a&gt; and whose original goal was to allow scientists to present themselves to everyone, a sort of #scicomm action. A great initiative, because we need science and we need everyone to know how it&amp;rsquo;s done, by actual human beings.&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t tweet with the hashtag, but I consider myself a scientist with more or less experience &lt;a href=&#34;https://masalmon.eu/bio/&#34;&gt;in different fields&lt;/a&gt; &amp;ndash; and &lt;a href=&#34;https://masalmon.eu/2017/02/03/chemist/&#34;&gt;my last post&lt;/a&gt; was about the scientist I married. In my timeline thanks to &lt;a href=&#34;https://twitter.com/RallidaeRule&#34;&gt;Auriel Fournier&lt;/a&gt; there were many tweets of ecologists studying animals. I&amp;rsquo;d like to say &lt;em&gt;cute&lt;/em&gt; animals but some were carcasses&amp;hellip; But still, it made me want to quantify which animals were the most present in the tweets. Any bet?&lt;/p&gt;
&lt;h1 id=&#34;getting-tweets&#34;&gt;Getting tweets&lt;/h1&gt;
&lt;p&gt;I got tweets thanks to Mike Kearney&amp;rsquo;s &lt;a href=&#34;https://github.com/mkearney/rtweet&#34;&gt;&lt;code&gt;rtweet&lt;/code&gt; package&lt;/a&gt;. I&amp;rsquo;ve done something similar in the past for &lt;a href=&#34;https://masalmon.eu/2016/10/02/first7jobs-repost/&#34;&gt;#firstsevenjobs tweets&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rtweet&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
actual &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;search_tweets&lt;/span&gt;(q &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#actuallivingscientist&amp;#34;&lt;/span&gt;,
                        include_rts &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;,
                        n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;18000&lt;/span&gt;, type &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;recent&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# no need for coordinates which are often missing&lt;/span&gt;
actual &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(actual, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; coordinates)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# only English&lt;/span&gt;
actual &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(actual, lang &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# no answers&lt;/span&gt;
actual &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(actual, &lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(in_reply_to_user_id))

&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# save&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;save&lt;/span&gt;(actual, file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-02-05-actuallivingscientists.RData&amp;#34;&lt;/span&gt;)

actual
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 6 × 22
##            created_at          status_id
##                &amp;lt;dttm&amp;gt;              &amp;lt;chr&amp;gt;
## 1 2017-02-05 08:14:53 828154916959088640
## 2 2017-02-05 08:11:17 828154013656952832
## 3 2017-02-05 08:11:04 828153957797261312
## 4 2017-02-05 08:06:18 828152756112351233
## 5 2017-02-05 08:04:27 828152292532695040
## 6 2017-02-05 08:02:55 828151908531568640
## # ... with 20 more variables: text &amp;lt;chr&amp;gt;, source &amp;lt;chr&amp;gt;,
## #   in_reply_to_status_id &amp;lt;chr&amp;gt;, in_reply_to_user_id &amp;lt;chr&amp;gt;,
## #   in_reply_to_screen_name &amp;lt;chr&amp;gt;, is_quote_status &amp;lt;lgl&amp;gt;,
## #   retweet_count &amp;lt;int&amp;gt;, favorite_count &amp;lt;int&amp;gt;, lang &amp;lt;chr&amp;gt;,
## #   quoted_status_id &amp;lt;chr&amp;gt;, user_id &amp;lt;chr&amp;gt;, screen_name &amp;lt;chr&amp;gt;,
## #   mentions_user_id &amp;lt;chr&amp;gt;, mentions_screen_name &amp;lt;chr&amp;gt;, hashtags &amp;lt;chr&amp;gt;,
## #   urls &amp;lt;chr&amp;gt;, is_retweet &amp;lt;lgl&amp;gt;, retweet_status_id &amp;lt;lgl&amp;gt;,
## #   place_name &amp;lt;chr&amp;gt;, country &amp;lt;chr&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Doing this I obtained 9611 tweets. Now let&amp;rsquo;s look for animals in them!&lt;/p&gt;
&lt;h1 id=&#34;looking-for-animals&#34;&gt;Looking for animals&lt;/h1&gt;
&lt;p&gt;Note: if Monkeylearn had an &amp;ldquo;animal extractor&amp;rdquo; module, I&amp;rsquo;d have tested a different approach with &lt;a href=&#34;https://github.com/ropensci/monkeylearn&#34;&gt;my own package&lt;/a&gt; but it would have been really close to my &lt;a href=&#34;https://masalmon.eu/2016/10/02/first7jobs-repost/&#34;&gt;#firstsevenjobs post&lt;/a&gt; a.k.a. as boring for you!&lt;/p&gt;
&lt;p&gt;I have to confess I had never used Julia Silge&amp;rsquo;s and David Robinson&amp;rsquo;s &lt;a href=&#34;https://github.com/juliasilge/tidytext&#34;&gt;&lt;code&gt;tidytext&lt;/code&gt; package&lt;/a&gt; before. I read Julia blog (you should do that too!) though so I knew about &lt;a href=&#34;http://juliasilge.com/blog/Song-Lyrics-Across/&#34;&gt;the post&lt;/a&gt; where she looked for the names of states in songs using &lt;code&gt;tidytext&lt;/code&gt;, in particular a function calling Lincoln Mullen&amp;rsquo;s &lt;a href=&#34;https://github.com/ropensci/tokenizers&#34;&gt;&lt;code&gt;tokenizers&lt;/code&gt; package&lt;/a&gt; to split each song into words and bigrams (combinations of two words). I wanted to reproduce the approach, for this I only needed a list of animals and remembered &lt;a href=&#34;https://github.com/gaborcsardi/rcorpora&#34;&gt;Gabor Csardi&amp;rsquo;s &lt;code&gt;rcorpora&lt;/code&gt; package&lt;/a&gt;, which contains all datasets from &lt;a href=&#34;https://github.com/dariusk/corpora&#34;&gt;these corpora&lt;/a&gt;. Including a list of animals, y&amp;rsquo;all!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rcorpora&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;corpora&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;animals/common&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;animals)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;aardvark&amp;quot;  &amp;quot;alligator&amp;quot; &amp;quot;alpaca&amp;quot;    &amp;quot;antelope&amp;quot;  &amp;quot;ape&amp;quot;       &amp;quot;armadillo&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A few animals are bigrams, for instance &amp;ldquo;grizzly bear&amp;rdquo; so I&amp;rsquo;ll really use the exact same approach and code as Julia in her songs post. In case you think I often end up copy-pasting R code from other people in my blog posts, please know that I often end up copy-pasting R code from other people &lt;em&gt;in general&lt;/em&gt; when I do something for the first time.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidytext&amp;#34;&lt;/span&gt;)
actual &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;as_tibble&lt;/span&gt;(actual)
tidy_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(actual &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
                           &lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(animal_for_detect, text),
                         actual &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
                           &lt;span style=&#34;color:#06287e&#34;&gt;unnest_tokens&lt;/span&gt;(animal_for_detect, text, 
                                         token &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ngrams&amp;#34;&lt;/span&gt;, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;))

tidy_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(tidy_tweets, animal_for_detect, &lt;span style=&#34;color:#06287e&#34;&gt;everything&lt;/span&gt;())
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(tidy_tweets)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 6 × 22
##       animal_for_detect          created_at          status_id
##                   &amp;lt;chr&amp;gt;              &amp;lt;dttm&amp;gt;              &amp;lt;chr&amp;gt;
## 1                    hi 2017-02-05 08:14:53 828154916959088640
## 2                   i&#39;m 2017-02-05 08:14:53 828154916959088640
## 3                 masha 2017-02-05 08:14:53 828154916959088640
## 4                   i&#39;m 2017-02-05 08:14:53 828154916959088640
## 5 actuallivingscientist 2017-02-05 08:14:53 828154916959088640
## 6              studying 2017-02-05 08:14:53 828154916959088640
## # ... with 19 more variables: source &amp;lt;chr&amp;gt;, in_reply_to_status_id &amp;lt;chr&amp;gt;,
## #   in_reply_to_user_id &amp;lt;chr&amp;gt;, in_reply_to_screen_name &amp;lt;chr&amp;gt;,
## #   is_quote_status &amp;lt;lgl&amp;gt;, retweet_count &amp;lt;int&amp;gt;, favorite_count &amp;lt;int&amp;gt;,
## #   lang &amp;lt;chr&amp;gt;, quoted_status_id &amp;lt;chr&amp;gt;, user_id &amp;lt;chr&amp;gt;, screen_name &amp;lt;chr&amp;gt;,
## #   mentions_user_id &amp;lt;chr&amp;gt;, mentions_screen_name &amp;lt;chr&amp;gt;, hashtags &amp;lt;chr&amp;gt;,
## #   urls &amp;lt;chr&amp;gt;, is_retweet &amp;lt;lgl&amp;gt;, retweet_status_id &amp;lt;lgl&amp;gt;,
## #   place_name &amp;lt;chr&amp;gt;, country &amp;lt;chr&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now for the animals &lt;code&gt;data.frame&lt;/code&gt; I need names of animals in singular and plural form because tweets might contain animals in both forms. I first decided to just paste an &amp;ldquo;s&amp;rdquo; to the names since it&amp;rsquo;d work most of the time but then I realized Bob Rudis has a package for pluralizing and singularizing any English word, &lt;a href=&#34;https://github.com/hrbrmstr/pluralize&#34;&gt;&lt;code&gt;pluralizer&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;pluralize&amp;#34;&lt;/span&gt;)
animals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(animal_for_detect &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;corpora&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;animals/common&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;animals)
animals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(animals, animal &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; animal_for_detect)
animals &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(animals, animal_for_detect &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;pluralize&lt;/span&gt;(animal_for_detect)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(animals)
animals
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 268 × 2
##    animal_for_detect    animal
##                &amp;lt;chr&amp;gt;     &amp;lt;chr&amp;gt;
## 1          aardvarks  aardvark
## 2         alligators alligator
## 3            alpacas    alpaca
## 4          antelopes  antelope
## 5               apes       ape
## 6         armadillos armadillo
## 7            baboons    baboon
## 8            badgers    badger
## 9               bats       bat
## 10             bears      bear
## # ... with 258 more rows
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Much more elegant than my &amp;ldquo;let&amp;rsquo;s paste s&amp;rdquo; approach and I learnt that the plural of buffalo is buffalo! Also &amp;ldquo;mouses&amp;rdquo; wouldn&amp;rsquo;t be as useful as &amp;ldquo;mice&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Now I can join the two tables and like Julia in her post I&amp;rsquo;ll only keep one occurence of an animal per tweet.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;tidy_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;inner_join&lt;/span&gt;(tidy_tweets, animals,
                          by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;animal_for_detect&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;distinct&lt;/span&gt;(status_id, animal, .keep_all &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
tidy_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(tidy_tweets, animal_for_detect, animal, &lt;span style=&#34;color:#06287e&#34;&gt;everything&lt;/span&gt;())

tidy_tweets
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 560 × 23
##    animal_for_detect   animal          created_at          status_id
##                &amp;lt;chr&amp;gt;    &amp;lt;chr&amp;gt;              &amp;lt;dttm&amp;gt;              &amp;lt;chr&amp;gt;
## 1               rats      rat 2017-02-05 07:53:28 828149527987171328
## 2            leopard  leopard 2017-02-05 07:52:33 828149297208233985
## 3                cat      cat 2017-02-05 06:57:34 828135460237094919
## 4               fish     fish 2017-02-05 06:26:14 828127576996487168
## 5            turtles   turtle 2017-02-05 06:22:58 828126753805783044
## 6           squirrel squirrel 2017-02-05 06:12:04 828124011431342080
## 7              snake    snake 2017-02-05 06:07:47 828122933390225409
## 8           gorillas  gorilla 2017-02-05 05:49:30 828118330473140224
## 9              sheep    sheep 2017-02-05 05:39:01 828115691572125696
## 10           parrots   parrot 2017-02-05 05:34:55 828114661027504129
## # ... with 550 more rows, and 19 more variables: source &amp;lt;chr&amp;gt;,
## #   in_reply_to_status_id &amp;lt;chr&amp;gt;, in_reply_to_user_id &amp;lt;chr&amp;gt;,
## #   in_reply_to_screen_name &amp;lt;chr&amp;gt;, is_quote_status &amp;lt;lgl&amp;gt;,
## #   retweet_count &amp;lt;int&amp;gt;, favorite_count &amp;lt;int&amp;gt;, lang &amp;lt;chr&amp;gt;,
## #   quoted_status_id &amp;lt;chr&amp;gt;, user_id &amp;lt;chr&amp;gt;, screen_name &amp;lt;chr&amp;gt;,
## #   mentions_user_id &amp;lt;chr&amp;gt;, mentions_screen_name &amp;lt;chr&amp;gt;, hashtags &amp;lt;chr&amp;gt;,
## #   urls &amp;lt;chr&amp;gt;, is_retweet &amp;lt;lgl&amp;gt;, retweet_status_id &amp;lt;lgl&amp;gt;,
## #   place_name &amp;lt;chr&amp;gt;, country &amp;lt;chr&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;so-what-are-the-animals-of-actual-living-scientists&#34;&gt;So, what are the animals of actual living scientists?&lt;/h1&gt;
&lt;p&gt;After doing this, I can at last have a look the frequency of animals in the tweets!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;animal_counts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tidy_tweets &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(animal) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;summarise&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n))

animal_counts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 75 × 2
##     animal     n
##      &amp;lt;chr&amp;gt; &amp;lt;int&amp;gt;
## 1     fish    77
## 2      bat    42
## 3      dog    35
## 4  reptile    33
## 5      cat    28
## 6     frog    27
## 7   turtle    23
## 8    snake    22
## 9   parrot    21
## 10  lizard    17
## # ... with 65 more rows
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;ldquo;cat&amp;rdquo; and &amp;ldquo;dog&amp;rdquo; get good rankings but they also are pets and I&amp;rsquo;ve even seen a tweet saying &lt;a href=&#34;https://twitter.com/pooter03/status/827650864240275459&#34;&gt;&amp;ldquo;I&amp;rsquo;m not an #actuallivingscientist but I have cute cats&amp;rdquo;&lt;/a&gt;. This is still relevant for the hashtag because on the internet cats are always relevant, but it means we should be careful when interpreting these rankings. Also note that Cat can be someone&amp;rsquo;s first name (like Salmon can be someone&amp;rsquo;s last name). In honour of the cover of the &lt;a href=&#34;http://tidytextmining.com/&#34;&gt;&lt;code&gt;tidytext&lt;/code&gt; book&lt;/a&gt;, let&amp;rsquo;s look at rabbit tweets.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;rabbit_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tidy_tweets, animal &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rabbit&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;status_id
&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(actual, status_id &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; rabbit_tweets)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;This #actuallivingscientist hashtag is pretty great. Excuse me while I fall down the rabbit hole... https://t.co/hZFWOTLDlR&amp;quot;                 
## [2] &amp;quot;Hi! I&#39;m an #actuallivingscientist studying the smallest rabbit that only occurs in the sagebrush-steppe of the west https://t.co/9vzi8bOeQF&amp;quot;
## [3] &amp;quot;#DressLikeAWoman #actuallivingscientist are the rabbit hole you need today. https://t.co/fR0ai0kSvn&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Mmmh so only one real occurence of a rabbit studying person in the tweets I collected. What about turtles?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;turtle_tweets &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(tidy_tweets, animal &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;turtle&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;status_id
&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(actual, status_id &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; turtle_tweets)&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;text &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;Hi, I&#39;m Katie and I&#39;m an #ActualLivingScientist. I study sea turtles and conservation in Brazil! &amp;lt;f0&amp;gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+0098&amp;gt;&amp;lt;U+008A&amp;gt;&amp;lt;f0&amp;gt;&amp;lt;U+009F&amp;gt;&amp;lt;U+0090&amp;gt;&amp;lt;U+00A2&amp;gt; #DressLikeAWoman https://t.co/nTn5v5sctx&amp;quot;
## [2] &amp;quot;#actuallivingscientist #DressLikeAWoman getting our community group to sea turtle conservation meeting in Sinaloa M https://t.co/IAEMB6X10f&amp;quot;                                     
## [3] &amp;quot;https://t.co/pM09T2lB9Y\nHelping to save Australia&#39;s turtles #actuallivingscientist&amp;quot;                                                                                              
## [4] &amp;quot;I&#39;m an evolutionary biologist who likes turtles (and ants). #DressLikeAWoman #actuallivingscientist https://t.co/x3tE3Drv7v&amp;quot;                                                      
## [5] &amp;quot;My name is J. I&#39;m an #actuallivingscientist studying oceans, migration, conservation &amp;amp;amp; human emotion. I like turtle https://t.co/WBMyoAplki&amp;quot;                                 
## [6] &amp;quot;I&#39;m Sara. I&#39;m an #ActualLivingScientist studying sea turtles in Georgia, USA! @sweaverflies: snap/insta, during sum https://t.co/rY5DIj8j77&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Although I recognize the limitations of my approach, I&amp;rsquo;ll now make a bar plot of the frequencies of the animals for animals with more than 5 occurences.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;viridis&amp;#34;&lt;/span&gt;)
animal_counts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; animal_counts &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(animal &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;others&amp;#34;&lt;/span&gt;, animal)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(animal) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sum&lt;/span&gt;(n)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n))
animal_counts &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(animal_counts,
                        animal &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;factor&lt;/span&gt;(animal,
                                        ordered &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;,
                                        levels &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(animal)))

&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;(animal_counts) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_bar&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(animal, n, fill &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; animal), stat &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;identity&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_fill_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;, option &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;plasma&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(axis.text.x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(angle &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;45&lt;/span&gt;,
                            hjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;,
                            vjust &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;),
          text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(size&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;15&lt;/span&gt;),
          legend.position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-02-05-actuallivingscientists/unnamed-chunk-9-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-9&#34;&gt;&lt;/p&gt;
&lt;p&gt;I was amazed at the diversity of animals of the tweets, many of them being research subjects. I like my current research field a lot, but how cool is ecology or biology of animals? Keep up the good work folks!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>A visual CV for a chemist</title>
      <link>https://masalmon.eu/2017/02/03/chemist/</link>
      <pubDate>Fri, 03 Feb 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/02/03/chemist/</guid>
      <description>&lt;p&gt;This week at work I started using &lt;a href=&#34;https://hafen.github.io/rbokeh/&#34;&gt;&lt;code&gt;rbokeh&lt;/code&gt;&lt;/a&gt;, the R interface to Bokeh. The package allows to create web-based interactive plots. I was mostly excited about the zooming tools that a local R-Lady mentioned to me. They made data exploration so much easier, thanks a bunch Elena!&lt;/p&gt;
&lt;p&gt;When checking out the doc, I saw an example called &amp;ldquo;Periodic table of the elements with additional info on hover&amp;rdquo;. While this was useless at work where I only made time series plots, I could set aside this application for my leisure time. I made an interactive CV for my husband, Damien, who is a chemist!&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll find the original periodic table example in &lt;a href=&#34;https://hafen.github.io/rbokeh/#preview&#34;&gt;&lt;code&gt;rbokeh&lt;/code&gt;&#39;s preview&lt;/a&gt;. My code is very similar to the one there!&lt;/p&gt;
&lt;h1 id=&#34;getting-data&#34;&gt;Getting data&lt;/h1&gt;
&lt;h2 id=&#34;elements&#34;&gt;Elements&lt;/h2&gt;
&lt;p&gt;One gets the elements data from the package itself.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rbokeh&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;data&lt;/span&gt;(elements)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(elements))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;atomic.number&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;symbol&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;atomic.mass&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;CPK&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;electronic.configuration&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;electronegativity&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;atomic.radius&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;ion.radius&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;van.der.Waals.radius&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;IE.1&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;EA&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;standard.state&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;bonding.type&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;melting.point&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;boiling.point&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;density&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;metal&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;year.discovered&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;group&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;period&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;color&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;type&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;symx&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;numbery&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;massy&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;namey&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;H&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hydrogen&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1.00794&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#FFFFFF&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1s1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.20&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;37&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;120&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1312&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-73&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;gas&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;diatomic&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;14&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;8.99e-05&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;nonmetal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1766&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#baa2a6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;nonmetal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1:0.1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1:0.8&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1:0.15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1:0.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;He&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Helium&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;4.002602&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#D9FFFF&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1s2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;32&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;140&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2372&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;gas&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;atomic&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.00e+00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;noble gas&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1868&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#bbbb88&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;noble gas&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;18:0.1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1:0.8&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1:0.15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1:0.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Li&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lithium&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;6.941&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#CC80FF&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[He] 2s1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.98&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;134&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;76 (+1)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;182&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;520&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-60&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;solid&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;metallic&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;454&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1615&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5.40e-01&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;alkali metal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1817&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#a6cee3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;alkali metal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1:0.1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.8&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Be&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Beryllium&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;9.012182&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#C2FF00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[He] 2s2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.57&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;90&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;45 (+2)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;900&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;solid&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;metallic&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1560&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2743&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1.85e+00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;alkaline earth metal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1798&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#1f78b4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;alkaline earth metal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.8&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;B&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Boron&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;10.811&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#FFB5B5&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[He] 2s2 2p1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.04&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;82&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;27 (+3)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;801&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-27&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;solid&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;covalent network&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2348&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4273&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.46e+00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;metalloid&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1807&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;13&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#33a02c&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;metalloid&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;13:0.1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.8&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;C&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Carbon&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;12.0107&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#909090&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[He] 2s2 2p2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.55&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;77&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;16 (+4)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;170&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1087&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-154&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;solid&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;covalent network&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3823&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4300&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.26e+00&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;nonmetal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ancient&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#baa2a6&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;nonmetal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;14:0.1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.8&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;2:0.3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;It looks fine but some elements recently got &lt;a href=&#34;https://iupac.org/iupac-announces-the-names-of-the-elements-113-115-117-and-118/&#34;&gt;new names&lt;/a&gt;. I wouldn&amp;rsquo;t know about it from my own readings, but well my husband did, and he can recommend &lt;a href=&#34;https://www.franceculture.fr/emissions/la-methode-scientifique/mendeleiev-un-tableau-enfin-complet&#34;&gt;a radio show in French&lt;/a&gt; about it because one of his favourite tweeps is the interviewee. He obviously thinks I can drive traffic to any website I want with this blog. I couldn&amp;rsquo;t find how to update the table of the package so opened an issue at &lt;code&gt;rbokeh&lt;/code&gt; and will selfishly solve the issue for myself here.&lt;/p&gt;
&lt;p&gt;The ones that got new names compared to the table of the package are 113, 114, 115, 116, 117, and 118. Actually 118 wasn&amp;rsquo;t even in the &lt;code&gt;rbokeh&lt;/code&gt; table so we&amp;rsquo;ll add it. I&amp;rsquo;m adding the atomic masses too but I was told that an atomic mass superior to 82 doesn&amp;rsquo;t have much interest anyway because of the unstability of the elements.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(elements, &lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;atomic.number &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;113&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;114&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;115&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;116&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;117&lt;/span&gt;))

renamed_elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;data.frame&lt;/span&gt;(atomic.number &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;113&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;114&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;115&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;116&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;117&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;118&lt;/span&gt;),
                                   symbol &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Nh&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Fl&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Mc&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Lv&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Ts&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Og&amp;#34;&lt;/span&gt;),
                                   name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Nihonium&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Flerovium&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Moscovium&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Livermorium&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Tennessine&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Oganesson&amp;#34;&lt;/span&gt;),
                                   atomic.mass &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[284]&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[289]&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[288]&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[293]&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[294]&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;[294]&amp;#34;&lt;/span&gt;),
                               group &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;13&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;14&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;15&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;16&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;17&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;18&amp;#34;&lt;/span&gt;),
                               period &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;rep&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;7&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;))

elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;(elements, renamed_elements)

knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;tail&lt;/span&gt;(elements))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;atomic.number&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;symbol&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;atomic.mass&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;CPK&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;electronic.configuration&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;electronegativity&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;atomic.radius&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;ion.radius&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;van.der.Waals.radius&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;IE.1&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;EA&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;standard.state&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;bonding.type&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;melting.point&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;boiling.point&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;density&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;metal&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;year.discovered&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;group&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;period&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;color&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;type&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;symx&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;numbery&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;massy&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;namey&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;85&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;113&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nh&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Nihonium&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[284]&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;13&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;86&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;114&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Fl&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Flerovium&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[289]&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;14&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;87&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;115&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Mc&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Moscovium&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[288]&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;15&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;88&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;116&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Lv&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Livermorium&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[293]&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;16&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;89&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;117&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ts&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Tennessine&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[294]&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;17&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;90&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;118&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Og&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Oganesson&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;[294]&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;18&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;7&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;NA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Okay now the table looks like a 2017 table of elements.&lt;/p&gt;
&lt;h2 id=&#34;experience&#34;&gt;Experience&lt;/h2&gt;
&lt;p&gt;I didn&amp;rsquo;t want to have additional information about the elements but rather pieces of experience of my husband who was actually thrilled to fill a table with stuff he&amp;rsquo;s done with elements. Here is what he sent me.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;damien &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv2&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-02-03-chemist_Elements.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Parsed with column specification:
## cols(
##   Element = col_character(),
##   `Why did I use it?` = col_character(),
##   Place = col_character()
## )
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(damien))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;Element&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Why did I use it?&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Place&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;H&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I am currently working on the hydrogenation of alkenes. And, well, H is everywhere!&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hangzhou, Paris, Berlin, Tarragona&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;He&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;It is not possible to cool large superconducting coils without liquid He.&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Berlin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Li&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Butyl lithium is a very powerful base!&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hangzhou&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;C&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I am currently working on the vibrations between carbon monoxide and metallic surfaces. And, well, C is everywhere!&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hangzhou, Paris, Berlin, Tarragona&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;N&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Infrared spectrometer works much better in liquid nitrogen&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Paris, Berlin, Tarragona&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;O&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;I am currently working on the vibrations between carbon monoxide and metallic surfaces. And, well, O is everywhere!&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hangzhou, Paris, Berlin, Tarragona&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I think it&amp;rsquo;s funny to print Damien&amp;rsquo;s head. I was less amused by the second column name because of the spaces, so I renamed it before joining it to the original elements table. I also replaced the missing values of the elements table, corresponding to elements my husband had nothing to say about, with empty strings.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(damien)[2] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;desc&amp;#34;&lt;/span&gt;
elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(elements, damien, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;symbol&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Element&amp;#34;&lt;/span&gt;))
elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(elements, Place &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(Place), &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, Place))
elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(elements, desc &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;is.na&lt;/span&gt;(desc), &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, desc))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;drawing-the-table&#34;&gt;Drawing the table&lt;/h1&gt;
&lt;h2 id=&#34;preparing-the-colours-and-coordinates&#34;&gt;Preparing the colours and coordinates&lt;/h2&gt;
&lt;p&gt;Nothing new here, I&amp;rsquo;m pretty much doing the same as in the doc, &lt;code&gt;dplyr&lt;/code&gt; style.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;places &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(elements&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;Place)
colors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#a6cee3&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#1f78b4&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#fdbf6f&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;white&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#b2df8a&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#33a02c&amp;#34;&lt;/span&gt;,
            &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#bbbb88&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#baa2a6&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;#e08e79&amp;#34;&lt;/span&gt;)
colors &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;data.frame&lt;/span&gt;(Place &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; places, color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; colors)
elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(elements, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; color)
elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(elements, colors, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Place&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is the part where the tutorial indicates how to create coordinates for putting every text in its place.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(elements, symx &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(group, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;:0.1&amp;#34;&lt;/span&gt;))
elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(elements, numbery &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(period, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;:0.8&amp;#34;&lt;/span&gt;, sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(elements, massy &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(period, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;:0.15&amp;#34;&lt;/span&gt;, sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
elements &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(elements, namey &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;paste&lt;/span&gt;(period, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;:0.3&amp;#34;&lt;/span&gt;, sep &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;plotting-itself&#34;&gt;Plotting itself&lt;/h2&gt;
&lt;p&gt;I haven&amp;rsquo;t got a ton of experience with &lt;code&gt;rbokeh&lt;/code&gt;, the main syntax differences I noted compared to &lt;code&gt;ggplot2&lt;/code&gt; was the piping and the fact that you need to specify data for each layer. You&amp;rsquo;ll find a better comparison &lt;a href=&#34;https://rud.is/b/2015/05/26/a-quick-incomplete-comparison-of-ggplot2-rbokeh-plotting-idioms/&#34;&gt;on Bob Rudis&amp;rsquo; blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But in the case of the period table I only really needed to copy paste code, thanks a lot to Ryan Hafen for his awesome package and for the cool example. The part of the code I changed is &lt;code&gt;hover = list(name, desc, place)&lt;/code&gt; which is the part where I choose to show the experience my husband associates with each element. In the original example the hover tool showed more info about elements. Note that Damien doesn&amp;rsquo;t even associates something really interesting with gold like, you know, a wedding ring. Bummer.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# See you create a table like this and add a serious title&lt;/span&gt;
p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;figure&lt;/span&gt;(title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Periodic Table of Damien Cornu&amp;#39;s experience&amp;#34;&lt;/span&gt;, tools &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;resize&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hover&amp;#34;&lt;/span&gt;),
            ylim &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;7&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)), xlim &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;as.character&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;18&lt;/span&gt;),
            xgrid &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;, ygrid &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;, xlab &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, ylab &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;,
            height &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;445&lt;/span&gt;, width &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;800&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# Here the rectangles are created, &lt;/span&gt;
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# without experience rectangles get a while fill&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ly_crect&lt;/span&gt;(group, period, data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; elements, &lt;span style=&#34;color:#40a070&#34;&gt;0.9&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0.9&lt;/span&gt;,
           fill_color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; color,
           line_color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;grey&amp;#34;&lt;/span&gt;, fill_alpha &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.6&lt;/span&gt;,
           hover &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(name, desc, Place)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# add symbol text&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ly_text&lt;/span&gt;(symx, period, text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; symbol, data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; elements,
          font_style &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bold&amp;#34;&lt;/span&gt;, font_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;10pt&amp;#34;&lt;/span&gt;,
          align &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;left&amp;#34;&lt;/span&gt;, baseline &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;middle&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# add atomic number text&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ly_text&lt;/span&gt;(symx, numbery, text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; atomic.number, data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; elements,
          font_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;6pt&amp;#34;&lt;/span&gt;, align &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;left&amp;#34;&lt;/span&gt;, baseline &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;middle&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# add name text&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ly_text&lt;/span&gt;(symx, namey, text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; name, data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; elements,
          font_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;4pt&amp;#34;&lt;/span&gt;, align &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;left&amp;#34;&lt;/span&gt;, baseline &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;middle&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# add atomic mass text&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ly_text&lt;/span&gt;(symx, massy, text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; atomic.mass, data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; elements,
          font_size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;4pt&amp;#34;&lt;/span&gt;, align &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;left&amp;#34;&lt;/span&gt;, baseline &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;middle&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;displaying-the-cv&#34;&gt;Displaying the CV&lt;/h1&gt;
&lt;p&gt;Maybe the way I display the &lt;code&gt;rbokeh&lt;/code&gt; plot on this page is a dirty hack. Using the &lt;code&gt;htmlwidget&lt;/code&gt; package I saved the widget,&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;htmlwidgets&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;saveWidget&lt;/span&gt;(p, file &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;damien.html&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then I simply included the html file thus created. If you knit a html, not a html via a .md as is the case with a Jekyll website, you don&amp;rsquo;t need these two steps to display a widget. At work I made a &lt;a href=&#34;http://rmarkdown.rstudio.com/flexdashboard/&#34;&gt;flexdashboard&lt;/a&gt; with &lt;code&gt;rbokeh&lt;/code&gt; and it couldn&amp;rsquo;t have been easier.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;htmltools&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;includeHTML&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://raw.githubusercontent.com/masalmon/masalmon.github.io/master/_source/damien.html&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;script src=&#34;data:application/x-javascript;base64,KGZ1bmN0aW9uKCkgewogIC8vIElmIHdpbmRvdy5IVE1MV2lkZ2V0cyBpcyBhbHJlYWR5IGRlZmluZWQsIHRoZW4gdXNlIGl0OyBvdGhlcndpc2UgY3JlYXRlIGEKICAvLyBuZXcgb2JqZWN0LiBUaGlzIGFsbG93cyBwcmVjZWRpbmcgY29kZSB0byBzZXQgb3B0aW9ucyB0aGF0IGFmZmVjdCB0aGUKICAvLyBpbml0aWFsaXphdGlvbiBwcm9jZXNzICh0aG91Z2ggbm9uZSBjdXJyZW50bHkgZXhpc3QpLgogIHdpbmRvdy5IVE1MV2lkZ2V0cyA9IHdpbmRvdy5IVE1MV2lkZ2V0cyB8fCB7fTsKCiAgLy8gU2VlIGlmIHdlJ3JlIHJ1bm5pbmcgaW4gYSB2aWV3ZXIgcGFuZS4gSWYgbm90LCB3ZSdyZSBpbiBhIHdlYiBicm93c2VyLgogIHZhciB2aWV3ZXJNb2RlID0gd2luZG93LkhUTUxXaWRnZXRzLnZpZXdlck1vZGUgPQogICAgICAvXGJ2aWV3ZXJfcGFuZT0xXGIvLnRlc3Qod2luZG93LmxvY2F0aW9uKTsKCiAgLy8gU2VlIGlmIHdlJ3JlIHJ1bm5pbmcgaW4gU2hpbnkgbW9kZS4gSWYgbm90LCBpdCdzIGEgc3RhdGljIGRvY3VtZW50LgogIC8vIE5vdGUgdGhhdCBzdGF0aWMgd2lkZ2V0cyBjYW4gYXBwZWFyIGluIGJvdGggU2hpbnkgYW5kIHN0YXRpYyBtb2RlcywgYnV0CiAgLy8gb2J2aW91c2x5LCBTaGlueSB3aWRnZXRzIGNhbiBvbmx5IGFwcGVhciBpbiBTaGlueSBhcHBzL2RvY3VtZW50cy4KICB2YXIgc2hpbnlNb2RlID0gd2luZG93LkhUTUxXaWRnZXRzLnNoaW55TW9kZSA9CiAgICAgIHR5cGVvZih3aW5kb3cuU2hpbnkpICE9PSAidW5kZWZpbmVkIiAmJiAhIXdpbmRvdy5TaGlueS5vdXRwdXRCaW5kaW5nczsKCiAgLy8gV2UgY2FuJ3QgY291bnQgb24galF1ZXJ5IGJlaW5nIGF2YWlsYWJsZSwgc28gd2UgaW1wbGVtZW50IG91ciBvd24KICAvLyB2ZXJzaW9uIGlmIG5lY2Vzc2FyeS4KICBmdW5jdGlvbiBxdWVyeVNlbGVjdG9yQWxsKHNjb3BlLCBzZWxlY3RvcikgewogICAgaWYgKHR5cGVvZihqUXVlcnkpICE9PSAidW5kZWZpbmVkIiAmJiBzY29wZSBpbnN0YW5jZW9mIGpRdWVyeSkgewogICAgICByZXR1cm4gc2NvcGUuZmluZChzZWxlY3Rvcik7CiAgICB9CiAgICBpZiAoc2NvcGUucXVlcnlTZWxlY3RvckFsbCkgewogICAgICByZXR1cm4gc2NvcGUucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBhc0FycmF5KHZhbHVlKSB7CiAgICBpZiAodmFsdWUgPT09IG51bGwpCiAgICAgIHJldHVybiBbXTsKICAgIGlmICgkLmlzQXJyYXkodmFsdWUpKQogICAgICByZXR1cm4gdmFsdWU7CiAgICByZXR1cm4gW3ZhbHVlXTsKICB9CgogIC8vIEltcGxlbWVudCBqUXVlcnkncyBleHRlbmQKICBmdW5jdGlvbiBleHRlbmQodGFyZ2V0IC8qLCAuLi4gKi8pIHsKICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09IDEpIHsKICAgICAgcmV0dXJuIHRhcmdldDsKICAgIH0KICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07CiAgICAgIGZvciAodmFyIHByb3AgaW4gc291cmNlKSB7CiAgICAgICAgaWYgKHNvdXJjZS5oYXNPd25Qcm9wZXJ0eShwcm9wKSkgewogICAgICAgICAgdGFyZ2V0W3Byb3BdID0gc291cmNlW3Byb3BdOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHRhcmdldDsKICB9CgogIC8vIElFOCBkb2Vzbid0IHN1cHBvcnQgQXJyYXkuZm9yRWFjaC4KICBmdW5jdGlvbiBmb3JFYWNoKHZhbHVlcywgY2FsbGJhY2ssIHRoaXNBcmcpIHsKICAgIGlmICh2YWx1ZXMuZm9yRWFjaCkgewogICAgICB2YWx1ZXMuZm9yRWFjaChjYWxsYmFjaywgdGhpc0FyZyk7CiAgICB9IGVsc2UgewogICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHZhbHVlcy5sZW5ndGg7IGkrKykgewogICAgICAgIGNhbGxiYWNrLmNhbGwodGhpc0FyZywgdmFsdWVzW2ldLCBpLCB2YWx1ZXMpOwogICAgICB9CiAgICB9CiAgfQoKICAvLyBSZXBsYWNlcyB0aGUgc3BlY2lmaWVkIG1ldGhvZCB3aXRoIHRoZSByZXR1cm4gdmFsdWUgb2YgZnVuY1NvdXJjZS4KICAvLwogIC8vIE5vdGUgdGhhdCBmdW5jU291cmNlIHNob3VsZCBub3QgQkUgdGhlIG5ldyBtZXRob2QsIGl0IHNob3VsZCBiZSBhIGZ1bmN0aW9uCiAgLy8gdGhhdCBSRVRVUk5TIHRoZSBuZXcgbWV0aG9kLiBmdW5jU291cmNlIHJlY2VpdmVzIGEgc2luZ2xlIGFyZ3VtZW50IHRoYXQgaXMKICAvLyB0aGUgb3ZlcnJpZGRlbiBtZXRob2QsIGl0IGNhbiBiZSBjYWxsZWQgZnJvbSB0aGUgbmV3IG1ldGhvZC4gVGhlIG92ZXJyaWRkZW4KICAvLyBtZXRob2QgY2FuIGJlIGNhbGxlZCBsaWtlIGEgcmVndWxhciBmdW5jdGlvbiwgaXQgaGFzIHRoZSB0YXJnZXQgcGVybWFuZW50bHkKICAvLyBib3VuZCB0byBpdCBzbyAidGhpcyIgd2lsbCB3b3JrIGNvcnJlY3RseS4KICBmdW5jdGlvbiBvdmVycmlkZU1ldGhvZCh0YXJnZXQsIG1ldGhvZE5hbWUsIGZ1bmNTb3VyY2UpIHsKICAgIHZhciBzdXBlckZ1bmMgPSB0YXJnZXRbbWV0aG9kTmFtZV0gfHwgZnVuY3Rpb24oKSB7fTsKICAgIHZhciBzdXBlckZ1bmNCb3VuZCA9IGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gc3VwZXJGdW5jLmFwcGx5KHRhcmdldCwgYXJndW1lbnRzKTsKICAgIH07CiAgICB0YXJnZXRbbWV0aG9kTmFtZV0gPSBmdW5jU291cmNlKHN1cGVyRnVuY0JvdW5kKTsKICB9CgogIC8vIEFkZCBhIG1ldGhvZCB0byBkZWxlZ2F0b3IgdGhhdCwgd2hlbiBpbnZva2VkLCBjYWxscwogIC8vIGRlbGVnYXRlZS5tZXRob2ROYW1lLiBJZiB0aGVyZSBpcyBubyBzdWNoIG1ldGhvZCBvbgogIC8vIHRoZSBkZWxlZ2F0ZWUsIGJ1dCB0aGVyZSB3YXMgb25lIG9uIGRlbGVnYXRvciBiZWZvcmUKICAvLyBkZWxlZ2F0ZU1ldGhvZCB3YXMgY2FsbGVkLCB0aGVuIHRoZSBvcmlnaW5hbCB2ZXJzaW9uCiAgLy8gaXMgaW52b2tlZCBpbnN0ZWFkLgogIC8vIEZvciBleGFtcGxlOgogIC8vCiAgLy8gdmFyIGEgPSB7CiAgLy8gICBtZXRob2QxOiBmdW5jdGlvbigpIHsgY29uc29sZS5sb2coJ2ExJyk7IH0KICAvLyAgIG1ldGhvZDI6IGZ1bmN0aW9uKCkgeyBjb25zb2xlLmxvZygnYTInKTsgfQogIC8vIH07CiAgLy8gdmFyIGIgPSB7CiAgLy8gICBtZXRob2QxOiBmdW5jdGlvbigpIHsgY29uc29sZS5sb2coJ2IxJyk7IH0KICAvLyB9OwogIC8vIGRlbGVnYXRlTWV0aG9kKGEsIGIsICJtZXRob2QxIik7CiAgLy8gZGVsZWdhdGVNZXRob2QoYSwgYiwgIm1ldGhvZDIiKTsKICAvLyBhLm1ldGhvZDEoKTsKICAvLyBhLm1ldGhvZDIoKTsKICAvLwogIC8vIFRoZSBvdXRwdXQgd291bGQgYmUgImIxIiwgImEyIi4KICBmdW5jdGlvbiBkZWxlZ2F0ZU1ldGhvZChkZWxlZ2F0b3IsIGRlbGVnYXRlZSwgbWV0aG9kTmFtZSkgewogICAgdmFyIGluaGVyaXRlZCA9IGRlbGVnYXRvclttZXRob2ROYW1lXTsKICAgIGRlbGVnYXRvclttZXRob2ROYW1lXSA9IGZ1bmN0aW9uKCkgewogICAgICB2YXIgdGFyZ2V0ID0gZGVsZWdhdGVlOwogICAgICB2YXIgbWV0aG9kID0gZGVsZWdhdGVlW21ldGhvZE5hbWVdOwoKICAgICAgLy8gVGhlIG1ldGhvZCBkb2Vzbid0IGV4aXN0IG9uIHRoZSBkZWxlZ2F0ZWUuIEluc3RlYWQsCiAgICAgIC8vIGNhbGwgdGhlIG1ldGhvZCBvbiB0aGUgZGVsZWdhdG9yLCBpZiBpdCBleGlzdHMuCiAgICAgIGlmICghbWV0aG9kKSB7CiAgICAgICAgdGFyZ2V0ID0gZGVsZWdhdG9yOwogICAgICAgIG1ldGhvZCA9IGluaGVyaXRlZDsKICAgICAgfQoKICAgICAgaWYgKG1ldGhvZCkgewogICAgICAgIHJldHVybiBtZXRob2QuYXBwbHkodGFyZ2V0LCBhcmd1bWVudHMpOwogICAgICB9CiAgICB9OwogIH0KCiAgLy8gSW1wbGVtZW50IGEgdmFndWUgZmFjc2ltaWxpZSBvZiBqUXVlcnkncyBkYXRhIG1ldGhvZAogIGZ1bmN0aW9uIGVsZW1lbnREYXRhKGVsLCBuYW1lLCB2YWx1ZSkgewogICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT0gMikgewogICAgICByZXR1cm4gZWxbImh0bWx3aWRnZXRfZGF0YV8iICsgbmFtZV07CiAgICB9IGVsc2UgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT0gMykgewogICAgICBlbFsiaHRtbHdpZGdldF9kYXRhXyIgKyBuYW1lXSA9IHZhbHVlOwogICAgICByZXR1cm4gZWw7CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIldyb25nIG51bWJlciBvZiBhcmd1bWVudHMgZm9yIGVsZW1lbnREYXRhOiAiICsKICAgICAgICBhcmd1bWVudHMubGVuZ3RoKTsKICAgIH0KICB9CgogIC8vIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzQ0NjE3MC9lc2NhcGUtc3RyaW5nLWZvci11c2UtaW4tamF2YXNjcmlwdC1yZWdleAogIGZ1bmN0aW9uIGVzY2FwZVJlZ0V4cChzdHIpIHsKICAgIHJldHVybiBzdHIucmVwbGFjZSgvW1wtXFtcXVwvXHtcfVwoXClcKlwrXD9cLlxcXF5cJFx8XS9nLCAiXFwkJiIpOwogIH0KCiAgZnVuY3Rpb24gaGFzQ2xhc3MoZWwsIGNsYXNzTmFtZSkgewogICAgdmFyIHJlID0gbmV3IFJlZ0V4cCgiXFxiIiArIGVzY2FwZVJlZ0V4cChjbGFzc05hbWUpICsgIlxcYiIpOwogICAgcmV0dXJuIHJlLnRlc3QoZWwuY2xhc3NOYW1lKTsKICB9CgogIC8vIGVsZW1lbnRzIC0gYXJyYXkgKG9yIGFycmF5LWxpa2Ugb2JqZWN0KSBvZiBIVE1MIGVsZW1lbnRzCiAgLy8gY2xhc3NOYW1lIC0gY2xhc3MgbmFtZSB0byB0ZXN0IGZvcgogIC8vIGluY2x1ZGUgLSBpZiB0cnVlLCBvbmx5IHJldHVybiBlbGVtZW50cyB3aXRoIGdpdmVuIGNsYXNzTmFtZTsKICAvLyAgIGlmIGZhbHNlLCBvbmx5IHJldHVybiBlbGVtZW50cyAqd2l0aG91dCogZ2l2ZW4gY2xhc3NOYW1lCiAgZnVuY3Rpb24gZmlsdGVyQnlDbGFzcyhlbGVtZW50cywgY2xhc3NOYW1lLCBpbmNsdWRlKSB7CiAgICB2YXIgcmVzdWx0cyA9IFtdOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBlbGVtZW50cy5sZW5ndGg7IGkrKykgewogICAgICBpZiAoaGFzQ2xhc3MoZWxlbWVudHNbaV0sIGNsYXNzTmFtZSkgPT0gaW5jbHVkZSkKICAgICAgICByZXN1bHRzLnB1c2goZWxlbWVudHNbaV0pOwogICAgfQogICAgcmV0dXJuIHJlc3VsdHM7CiAgfQoKICBmdW5jdGlvbiBvbihvYmosIGV2ZW50TmFtZSwgZnVuYykgewogICAgaWYgKG9iai5hZGRFdmVudExpc3RlbmVyKSB7CiAgICAgIG9iai5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgZnVuYywgZmFsc2UpOwogICAgfSBlbHNlIGlmIChvYmouYXR0YWNoRXZlbnQpIHsKICAgICAgb2JqLmF0dGFjaEV2ZW50KGV2ZW50TmFtZSwgZnVuYyk7CiAgICB9CiAgfQoKICBmdW5jdGlvbiBvZmYob2JqLCBldmVudE5hbWUsIGZ1bmMpIHsKICAgIGlmIChvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcikKICAgICAgb2JqLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBmdW5jLCBmYWxzZSk7CiAgICBlbHNlIGlmIChvYmouZGV0YWNoRXZlbnQpIHsKICAgICAgb2JqLmRldGFjaEV2ZW50KGV2ZW50TmFtZSwgZnVuYyk7CiAgICB9CiAgfQoKICAvLyBUcmFuc2xhdGUgYXJyYXkgb2YgdmFsdWVzIHRvIHRvcC9yaWdodC9ib3R0b20vbGVmdCwgYXMgdXN1YWwgd2l0aAogIC8vIHRoZSAicGFkZGluZyIgQ1NTIHByb3BlcnR5CiAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQ1NTL3BhZGRpbmcKICBmdW5jdGlvbiB1bnBhY2tQYWRkaW5nKHZhbHVlKSB7CiAgICBpZiAodHlwZW9mKHZhbHVlKSA9PT0gIm51bWJlciIpCiAgICAgIHZhbHVlID0gW3ZhbHVlXTsKICAgIGlmICh2YWx1ZS5sZW5ndGggPT09IDEpIHsKICAgICAgcmV0dXJuIHt0b3A6IHZhbHVlWzBdLCByaWdodDogdmFsdWVbMF0sIGJvdHRvbTogdmFsdWVbMF0sIGxlZnQ6IHZhbHVlWzBdfTsKICAgIH0KICAgIGlmICh2YWx1ZS5sZW5ndGggPT09IDIpIHsKICAgICAgcmV0dXJuIHt0b3A6IHZhbHVlWzBdLCByaWdodDogdmFsdWVbMV0sIGJvdHRvbTogdmFsdWVbMF0sIGxlZnQ6IHZhbHVlWzFdfTsKICAgIH0KICAgIGlmICh2YWx1ZS5sZW5ndGggPT09IDMpIHsKICAgICAgcmV0dXJuIHt0b3A6IHZhbHVlWzBdLCByaWdodDogdmFsdWVbMV0sIGJvdHRvbTogdmFsdWVbMl0sIGxlZnQ6IHZhbHVlWzFdfTsKICAgIH0KICAgIGlmICh2YWx1ZS5sZW5ndGggPT09IDQpIHsKICAgICAgcmV0dXJuIHt0b3A6IHZhbHVlWzBdLCByaWdodDogdmFsdWVbMV0sIGJvdHRvbTogdmFsdWVbMl0sIGxlZnQ6IHZhbHVlWzNdfTsKICAgIH0KICB9CgogIC8vIENvbnZlcnQgYW4gdW5wYWNrZWQgcGFkZGluZyBvYmplY3QgdG8gYSBDU1MgdmFsdWUKICBmdW5jdGlvbiBwYWRkaW5nVG9Dc3MocGFkZGluZ09iaikgewogICAgcmV0dXJuIHBhZGRpbmdPYmoudG9wICsgInB4ICIgKyBwYWRkaW5nT2JqLnJpZ2h0ICsgInB4ICIgKyBwYWRkaW5nT2JqLmJvdHRvbSArICJweCAiICsgcGFkZGluZ09iai5sZWZ0ICsgInB4IjsKICB9CgogIC8vIE1ha2VzIGEgbnVtYmVyIHN1aXRhYmxlIGZvciBDU1MKICBmdW5jdGlvbiBweCh4KSB7CiAgICBpZiAodHlwZW9mKHgpID09PSAibnVtYmVyIikKICAgICAgcmV0dXJuIHggKyAicHgiOwogICAgZWxzZQogICAgICByZXR1cm4geDsKICB9CgogIC8vIFJldHJpZXZlcyBydW50aW1lIHdpZGdldCBzaXppbmcgaW5mb3JtYXRpb24gZm9yIGFuIGVsZW1lbnQuCiAgLy8gVGhlIHJldHVybiB2YWx1ZSBpcyBlaXRoZXIgbnVsbCwgb3IgYW4gb2JqZWN0IHdpdGggZmlsbCwgcGFkZGluZywKICAvLyBkZWZhdWx0V2lkdGgsIGRlZmF1bHRIZWlnaHQgZmllbGRzLgogIGZ1bmN0aW9uIHNpemluZ1BvbGljeShlbCkgewogICAgdmFyIHNpemluZ0VsID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcigic2NyaXB0W2RhdGEtZm9yPSciICsgZWwuaWQgKyAiJ11bdHlwZT0nYXBwbGljYXRpb24vaHRtbHdpZGdldC1zaXppbmcnXSIpOwogICAgaWYgKCFzaXppbmdFbCkKICAgICAgcmV0dXJuIG51bGw7CiAgICB2YXIgc3AgPSBKU09OLnBhcnNlKHNpemluZ0VsLnRleHRDb250ZW50IHx8IHNpemluZ0VsLnRleHQgfHwgInt9Iik7CiAgICBpZiAodmlld2VyTW9kZSkgewogICAgICByZXR1cm4gc3Audmlld2VyOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIHNwLmJyb3dzZXI7CiAgICB9CiAgfQoKICAvLyBAcGFyYW0gdGFza3MgQXJyYXkgb2Ygc3RyaW5ncyAob3IgZmFsc3kgdmFsdWUsIGluIHdoaWNoIGNhc2Ugbm8tb3ApLgogIC8vICAgRWFjaCBlbGVtZW50IG11c3QgYmUgYSB2YWxpZCBKYXZhU2NyaXB0IGV4cHJlc3Npb24gdGhhdCB5aWVsZHMgYQogIC8vICAgZnVuY3Rpb24uIE9yLCBjYW4gYmUgYW4gYXJyYXkgb2Ygb2JqZWN0cyB3aXRoICJjb2RlIiBhbmQgImRhdGEiCiAgLy8gICBwcm9wZXJ0aWVzOyBpbiB0aGlzIGNhc2UsIHRoZSAiY29kZSIgcHJvcGVydHkgc2hvdWxkIGJlIGEgc3RyaW5nCiAgLy8gICBvZiBKUyB0aGF0J3MgYW4gZXhwciB0aGF0IHlpZWxkcyBhIGZ1bmN0aW9uLCBhbmQgImRhdGEiIHNob3VsZCBiZQogIC8vICAgYW4gb2JqZWN0IHRoYXQgd2lsbCBiZSBhZGRlZCBhcyBhbiBhZGRpdGlvbmFsIGFyZ3VtZW50IHdoZW4gdGhhdAogIC8vICAgZnVuY3Rpb24gaXMgY2FsbGVkLgogIC8vIEBwYXJhbSB0YXJnZXQgVGhlIG9iamVjdCB0aGF0IHdpbGwgYmUgInRoaXMiIGZvciBlYWNoIGZ1bmN0aW9uCiAgLy8gICBleGVjdXRpb24uCiAgLy8gQHBhcmFtIGFyZ3MgQXJyYXkgb2YgYXJndW1lbnRzIHRvIGJlIHBhc3NlZCB0byB0aGUgZnVuY3Rpb25zLiAoVGhlCiAgLy8gICBzYW1lIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCB0byBhbGwgZnVuY3Rpb25zLikKICBmdW5jdGlvbiBldmFsQW5kUnVuKHRhc2tzLCB0YXJnZXQsIGFyZ3MpIHsKICAgIGlmICh0YXNrcykgewogICAgICBmb3JFYWNoKHRhc2tzLCBmdW5jdGlvbih0YXNrKSB7CiAgICAgICAgdmFyIHRoZXNlQXJncyA9IGFyZ3M7CiAgICAgICAgaWYgKHR5cGVvZih0YXNrKSA9PT0gIm9iamVjdCIpIHsKICAgICAgICAgIHRoZXNlQXJncyA9IHRoZXNlQXJncy5jb25jYXQoW3Rhc2suZGF0YV0pOwogICAgICAgICAgdGFzayA9IHRhc2suY29kZTsKICAgICAgICB9CiAgICAgICAgdmFyIHRhc2tGdW5jID0gZXZhbCgiKCIgKyB0YXNrICsgIikiKTsKICAgICAgICBpZiAodHlwZW9mKHRhc2tGdW5jKSAhPT0gImZ1bmN0aW9uIikgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJUYXNrIG11c3QgYmUgYSBmdW5jdGlvbiEgU291cmNlOlxuIiArIHRhc2spOwogICAgICAgIH0KICAgICAgICB0YXNrRnVuYy5hcHBseSh0YXJnZXQsIHRoZXNlQXJncyk7CiAgICAgIH0pOwogICAgfQogIH0KCiAgZnVuY3Rpb24gaW5pdFNpemluZyhlbCkgewogICAgdmFyIHNpemluZyA9IHNpemluZ1BvbGljeShlbCk7CiAgICBpZiAoIXNpemluZykKICAgICAgcmV0dXJuOwoKICAgIHZhciBjZWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgiaHRtbHdpZGdldF9jb250YWluZXIiKTsKICAgIGlmICghY2VsKQogICAgICByZXR1cm47CgogICAgaWYgKHR5cGVvZihzaXppbmcucGFkZGluZykgIT09ICJ1bmRlZmluZWQiKSB7CiAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUubWFyZ2luID0gIjAiOwogICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLnBhZGRpbmcgPSBwYWRkaW5nVG9Dc3ModW5wYWNrUGFkZGluZyhzaXppbmcucGFkZGluZykpOwogICAgfQoKICAgIGlmIChzaXppbmcuZmlsbCkgewogICAgICBkb2N1bWVudC5ib2R5LnN0eWxlLm92ZXJmbG93ID0gImhpZGRlbiI7CiAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUud2lkdGggPSAiMTAwJSI7CiAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUuaGVpZ2h0ID0gIjEwMCUiOwogICAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUud2lkdGggPSAiMTAwJSI7CiAgICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5oZWlnaHQgPSAiMTAwJSI7CiAgICAgIGlmIChjZWwpIHsKICAgICAgICBjZWwuc3R5bGUucG9zaXRpb24gPSAiYWJzb2x1dGUiOwogICAgICAgIHZhciBwYWQgPSB1bnBhY2tQYWRkaW5nKHNpemluZy5wYWRkaW5nKTsKICAgICAgICBjZWwuc3R5bGUudG9wID0gcGFkLnRvcCArICJweCI7CiAgICAgICAgY2VsLnN0eWxlLnJpZ2h0ID0gcGFkLnJpZ2h0ICsgInB4IjsKICAgICAgICBjZWwuc3R5bGUuYm90dG9tID0gcGFkLmJvdHRvbSArICJweCI7CiAgICAgICAgY2VsLnN0eWxlLmxlZnQgPSBwYWQubGVmdCArICJweCI7CiAgICAgICAgZWwuc3R5bGUud2lkdGggPSAiMTAwJSI7CiAgICAgICAgZWwuc3R5bGUuaGVpZ2h0ID0gIjEwMCUiOwogICAgICB9CgogICAgICByZXR1cm4gewogICAgICAgIGdldFdpZHRoOiBmdW5jdGlvbigpIHsgcmV0dXJuIGNlbC5vZmZzZXRXaWR0aDsgfSwKICAgICAgICBnZXRIZWlnaHQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gY2VsLm9mZnNldEhlaWdodDsgfQogICAgICB9OwoKICAgIH0gZWxzZSB7CiAgICAgIGVsLnN0eWxlLndpZHRoID0gcHgoc2l6aW5nLndpZHRoKTsKICAgICAgZWwuc3R5bGUuaGVpZ2h0ID0gcHgoc2l6aW5nLmhlaWdodCk7CgogICAgICByZXR1cm4gewogICAgICAgIGdldFdpZHRoOiBmdW5jdGlvbigpIHsgcmV0dXJuIGVsLm9mZnNldFdpZHRoOyB9LAogICAgICAgIGdldEhlaWdodDogZnVuY3Rpb24oKSB7IHJldHVybiBlbC5vZmZzZXRIZWlnaHQ7IH0KICAgICAgfTsKICAgIH0KICB9CgogIC8vIERlZmF1bHQgaW1wbGVtZW50YXRpb25zIGZvciBtZXRob2RzCiAgdmFyIGRlZmF1bHRzID0gewogICAgZmluZDogZnVuY3Rpb24oc2NvcGUpIHsKICAgICAgcmV0dXJuIHF1ZXJ5U2VsZWN0b3JBbGwoc2NvcGUsICIuIiArIHRoaXMubmFtZSk7CiAgICB9LAogICAgcmVuZGVyRXJyb3I6IGZ1bmN0aW9uKGVsLCBlcnIpIHsKICAgICAgdmFyICRlbCA9ICQoZWwpOwoKICAgICAgdGhpcy5jbGVhckVycm9yKGVsKTsKCiAgICAgIC8vIEFkZCBhbGwgdGhlc2UgZXJyb3IgY2xhc3NlcywgYXMgU2hpbnkgZG9lcwogICAgICB2YXIgZXJyQ2xhc3MgPSAic2hpbnktb3V0cHV0LWVycm9yIjsKICAgICAgaWYgKGVyci50eXBlICE9PSBudWxsKSB7CiAgICAgICAgLy8gdXNlIHRoZSBjbGFzc2VzIG9mIHRoZSBlcnJvciBjb25kaXRpb24gYXMgQ1NTIGNsYXNzIG5hbWVzCiAgICAgICAgZXJyQ2xhc3MgPSBlcnJDbGFzcyArICIgIiArICQubWFwKGFzQXJyYXkoZXJyLnR5cGUpLCBmdW5jdGlvbih0eXBlKSB7CiAgICAgICAgICByZXR1cm4gZXJyQ2xhc3MgKyAiLSIgKyB0eXBlOwogICAgICAgIH0pLmpvaW4oIiAiKTsKICAgICAgfQogICAgICBlcnJDbGFzcyA9IGVyckNsYXNzICsgIiBodG1sd2lkZ2V0cy1lcnJvciI7CgogICAgICAvLyBJcyBlbCBpbmxpbmUgb3IgYmxvY2s/IElmIGlubGluZSBvciBpbmxpbmUtYmxvY2ssIGp1c3QgZGlzcGxheTpub25lIGl0CiAgICAgIC8vIGFuZCBhZGQgYW4gaW5saW5lIGVycm9yLgogICAgICB2YXIgZGlzcGxheSA9ICRlbC5jc3MoImRpc3BsYXkiKTsKICAgICAgJGVsLmRhdGEoInJlc3RvcmUtZGlzcGxheS1tb2RlIiwgZGlzcGxheSk7CgogICAgICBpZiAoZGlzcGxheSA9PT0gImlubGluZSIgfHwgZGlzcGxheSA9PT0gImlubGluZS1ibG9jayIpIHsKICAgICAgICAkZWwuaGlkZSgpOwogICAgICAgIGlmIChlcnIubWVzc2FnZSAhPT0gIiIpIHsKICAgICAgICAgIHZhciBlcnJvclNwYW4gPSAkKCI8c3Bhbj4iKS5hZGRDbGFzcyhlcnJDbGFzcyk7CiAgICAgICAgICBlcnJvclNwYW4udGV4dChlcnIubWVzc2FnZSk7CiAgICAgICAgICAkZWwuYWZ0ZXIoZXJyb3JTcGFuKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoZGlzcGxheSA9PT0gImJsb2NrIikgewogICAgICAgIC8vIElmIGJsb2NrLCBhZGQgYW4gZXJyb3IganVzdCBhZnRlciB0aGUgZWwsIHNldCB2aXNpYmlsaXR5Om5vbmUgb24gdGhlCiAgICAgICAgLy8gZWwsIGFuZCBwb3NpdGlvbiB0aGUgZXJyb3IgdG8gYmUgb24gdG9wIG9mIHRoZSBlbC4KICAgICAgICAvLyBNYXJrIGl0IHdpdGggYSB1bmlxdWUgSUQgYW5kIENTUyBjbGFzcyBzbyB3ZSBjYW4gcmVtb3ZlIGl0IGxhdGVyLgogICAgICAgICRlbC5jc3MoInZpc2liaWxpdHkiLCAiaGlkZGVuIik7CiAgICAgICAgaWYgKGVyci5tZXNzYWdlICE9PSAiIikgewogICAgICAgICAgdmFyIGVycm9yRGl2ID0gJCgiPGRpdj4iKS5hZGRDbGFzcyhlcnJDbGFzcykuY3NzKCJwb3NpdGlvbiIsICJhYnNvbHV0ZSIpCiAgICAgICAgICAgIC5jc3MoInRvcCIsIGVsLm9mZnNldFRvcCkKICAgICAgICAgICAgLmNzcygibGVmdCIsIGVsLm9mZnNldExlZnQpCiAgICAgICAgICAgIC8vIHNldHRpbmcgd2lkdGggY2FuIHB1c2ggb3V0IHRoZSBwYWdlIHNpemUsIGZvcmNpbmcgb3RoZXJ3aXNlCiAgICAgICAgICAgIC8vIHVubmVjZXNzYXJ5IHNjcm9sbGJhcnMgdG8gYXBwZWFyIGFuZCBtYWtpbmcgaXQgaW1wb3NzaWJsZSBmb3IKICAgICAgICAgICAgLy8gdGhlIGVsZW1lbnQgdG8gc2hyaW5rOyBzbyB1c2UgbWF4LXdpZHRoIGluc3RlYWQKICAgICAgICAgICAgLmNzcygibWF4V2lkdGgiLCBlbC5vZmZzZXRXaWR0aCkKICAgICAgICAgICAgLmNzcygiaGVpZ2h0IiwgZWwub2Zmc2V0SGVpZ2h0KTsKICAgICAgICAgIGVycm9yRGl2LnRleHQoZXJyLm1lc3NhZ2UpOwogICAgICAgICAgJGVsLmFmdGVyKGVycm9yRGl2KTsKCiAgICAgICAgICAvLyBSZWFsbHkgZHVtYiB3YXkgdG8ga2VlcCB0aGUgc2l6ZS9wb3NpdGlvbiBvZiB0aGUgZXJyb3IgaW4gc3luYyB3aXRoCiAgICAgICAgICAvLyB0aGUgcGFyZW50IGVsZW1lbnQgYXMgdGhlIHdpbmRvdyBpcyByZXNpemVkIG9yIHdoYXRldmVyLgogICAgICAgICAgdmFyIGludElkID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgIGlmICghZXJyb3JEaXZbMF0ucGFyZW50RWxlbWVudCkgewogICAgICAgICAgICAgIGNsZWFySW50ZXJ2YWwoaW50SWQpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBlcnJvckRpdgogICAgICAgICAgICAgIC5jc3MoInRvcCIsIGVsLm9mZnNldFRvcCkKICAgICAgICAgICAgICAuY3NzKCJsZWZ0IiwgZWwub2Zmc2V0TGVmdCkKICAgICAgICAgICAgICAuY3NzKCJtYXhXaWR0aCIsIGVsLm9mZnNldFdpZHRoKQogICAgICAgICAgICAgIC5jc3MoImhlaWdodCIsIGVsLm9mZnNldEhlaWdodCk7CiAgICAgICAgICB9LCA1MDApOwogICAgICAgIH0KICAgICAgfQogICAgfSwKICAgIGNsZWFyRXJyb3I6IGZ1bmN0aW9uKGVsKSB7CiAgICAgIHZhciAkZWwgPSAkKGVsKTsKICAgICAgdmFyIGRpc3BsYXkgPSAkZWwuZGF0YSgicmVzdG9yZS1kaXNwbGF5LW1vZGUiKTsKICAgICAgJGVsLmRhdGEoInJlc3RvcmUtZGlzcGxheS1tb2RlIiwgbnVsbCk7CgogICAgICBpZiAoZGlzcGxheSA9PT0gImlubGluZSIgfHwgZGlzcGxheSA9PT0gImlubGluZS1ibG9jayIpIHsKICAgICAgICBpZiAoZGlzcGxheSkKICAgICAgICAgICRlbC5jc3MoImRpc3BsYXkiLCBkaXNwbGF5KTsKICAgICAgICAkKGVsLm5leHRTaWJsaW5nKS5maWx0ZXIoIi5odG1sd2lkZ2V0cy1lcnJvciIpLnJlbW92ZSgpOwogICAgICB9IGVsc2UgaWYgKGRpc3BsYXkgPT09ICJibG9jayIpewogICAgICAgICRlbC5jc3MoInZpc2liaWxpdHkiLCAiaW5oZXJpdCIpOwogICAgICAgICQoZWwubmV4dFNpYmxpbmcpLmZpbHRlcigiLmh0bWx3aWRnZXRzLWVycm9yIikucmVtb3ZlKCk7CiAgICAgIH0KICAgIH0sCiAgICBzaXppbmc6IHt9CiAgfTsKCiAgLy8gQ2FsbGVkIGJ5IHdpZGdldCBiaW5kaW5ncyB0byByZWdpc3RlciBhIG5ldyB0eXBlIG9mIHdpZGdldC4gVGhlIGRlZmluaXRpb24KICAvLyBvYmplY3QgY2FuIGNvbnRhaW4gdGhlIGZvbGxvd2luZyBwcm9wZXJ0aWVzOgogIC8vIC0gbmFtZSAocmVxdWlyZWQpIC0gQSBzdHJpbmcgaW5kaWNhdGluZyB0aGUgYmluZGluZyBuYW1lLCB3aGljaCB3aWxsIGJlCiAgLy8gICB1c2VkIGJ5IGRlZmF1bHQgYXMgdGhlIENTUyBjbGFzc25hbWUgdG8gbG9vayBmb3IuCiAgLy8gLSBpbml0aWFsaXplIChvcHRpb25hbCkgLSBBIGZ1bmN0aW9uKGVsKSB0aGF0IHdpbGwgYmUgY2FsbGVkIG9uY2UgcGVyCiAgLy8gICB3aWRnZXQgZWxlbWVudDsgaWYgYSB2YWx1ZSBpcyByZXR1cm5lZCwgaXQgd2lsbCBiZSBwYXNzZWQgYXMgdGhlIHRoaXJkCiAgLy8gICB2YWx1ZSB0byByZW5kZXJWYWx1ZS4KICAvLyAtIHJlbmRlclZhbHVlIChyZXF1aXJlZCkgLSBBIGZ1bmN0aW9uKGVsLCBkYXRhLCBpbml0VmFsdWUpIHRoYXQgd2lsbCBiZQogIC8vICAgY2FsbGVkIHdpdGggZGF0YS4gU3RhdGljIGNvbnRleHRzIHdpbGwgY2F1c2UgdGhpcyB0byBiZSBjYWxsZWQgb25jZSBwZXIKICAvLyAgIGVsZW1lbnQ7IFNoaW55IGFwcHMgd2lsbCBjYXVzZSB0aGlzIHRvIGJlIGNhbGxlZCBtdWx0aXBsZSB0aW1lcyBwZXIKICAvLyAgIGVsZW1lbnQsIGFzIHRoZSBkYXRhIGNoYW5nZXMuCiAgd2luZG93LkhUTUxXaWRnZXRzLndpZGdldCA9IGZ1bmN0aW9uKGRlZmluaXRpb24pIHsKICAgIGlmICghZGVmaW5pdGlvbi5uYW1lKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiV2lkZ2V0IG11c3QgaGF2ZSBhIG5hbWUiKTsKICAgIH0KICAgIGlmICghZGVmaW5pdGlvbi50eXBlKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiV2lkZ2V0IG11c3QgaGF2ZSBhIHR5cGUiKTsKICAgIH0KICAgIC8vIEN1cnJlbnRseSB3ZSBvbmx5IHN1cHBvcnQgb3V0cHV0IHdpZGdldHMKICAgIGlmIChkZWZpbml0aW9uLnR5cGUgIT09ICJvdXRwdXQiKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiVW5yZWNvZ25pemVkIHdpZGdldCB0eXBlICciICsgZGVmaW5pdGlvbi50eXBlICsgIiciKTsKICAgIH0KICAgIC8vIFRPRE86IFZlcmlmeSB0aGF0IC5uYW1lIGlzIGEgdmFsaWQgQ1NTIGNsYXNzbmFtZQoKICAgIC8vIFN1cHBvcnQgbmV3LXN0eWxlIGluc3RhbmNlLWJvdW5kIGRlZmluaXRpb25zLiBPbGQtc3R5bGUgY2xhc3MtYm91bmQKICAgIC8vIGRlZmluaXRpb25zIGhhdmUgb25lIHdpZGdldCAib2JqZWN0IiBwZXIgd2lkZ2V0IHBlciB0eXBlL2NsYXNzIG9mCiAgICAvLyB3aWRnZXQ7IHRoZSByZW5kZXJWYWx1ZSBhbmQgcmVzaXplIG1ldGhvZHMgb24gc3VjaCB3aWRnZXQgb2JqZWN0cwogICAgLy8gdGFrZSBlbCBhbmQgaW5zdGFuY2UgYXJndW1lbnRzLCBiZWNhdXNlIHRoZSB3aWRnZXQgb2JqZWN0IGNhbid0CiAgICAvLyBzdG9yZSB0aGVtLiBOZXctc3R5bGUgaW5zdGFuY2UtYm91bmQgZGVmaW5pdGlvbnMgaGF2ZSBvbmUgd2lkZ2V0CiAgICAvLyBvYmplY3QgcGVyIHdpZGdldCBpbnN0YW5jZTsgdGhlIGRlZmluaXRpb24gdGhhdCdzIHBhc3NlZCBpbiBkb2Vzbid0CiAgICAvLyBwcm92aWRlIHJlbmRlclZhbHVlIG9yIHJlc2l6ZSBtZXRob2RzIGF0IGFsbCwganVzdCB0aGUgc2luZ2xlIG1ldGhvZAogICAgLy8gICBmYWN0b3J5KGVsLCB3aWR0aCwgaGVpZ2h0KQogICAgLy8gd2hpY2ggcmV0dXJucyBhbiBvYmplY3QgdGhhdCBoYXMgcmVuZGVyVmFsdWUoeCkgYW5kIHJlc2l6ZSh3LCBoKS4KICAgIC8vIFRoaXMgZW5hYmxlcyBhIGZhciBtb3JlIG5hdHVyYWwgcHJvZ3JhbW1pbmcgc3R5bGUgZm9yIHRoZSB3aWRnZXQKICAgIC8vIGF1dGhvciwgd2hvIGNhbiBzdG9yZSBwZXItaW5zdGFuY2Ugc3RhdGUgdXNpbmcgZWl0aGVyIE9PLXN0eWxlCiAgICAvLyBpbnN0YW5jZSBmaWVsZHMgb3IgZnVuY3Rpb25hbC1zdHlsZSBjbG9zdXJlIHZhcmlhYmxlcyAoSSBndWVzcyB0aGlzCiAgICAvLyBpcyBpbiBjb250cmFzdCB0byB3aGF0IGNhbiBvbmx5IGJlIGNhbGxlZCBDLXN0eWxlIHBzZXVkby1PTyB3aGljaCBpcwogICAgLy8gd2hhdCB3ZSByZXF1aXJlZCBiZWZvcmUpLgogICAgaWYgKGRlZmluaXRpb24uZmFjdG9yeSkgewogICAgICBkZWZpbml0aW9uID0gY3JlYXRlTGVnYWN5RGVmaW5pdGlvbkFkYXB0ZXIoZGVmaW5pdGlvbik7CiAgICB9CgogICAgaWYgKCFkZWZpbml0aW9uLnJlbmRlclZhbHVlKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiV2lkZ2V0IG11c3QgaGF2ZSBhIHJlbmRlclZhbHVlIGZ1bmN0aW9uIik7CiAgICB9CgogICAgLy8gRm9yIHN0YXRpYyByZW5kZXJpbmcgKG5vbi1TaGlueSksIHVzZSBhIHNpbXBsZSB3aWRnZXQgcmVnaXN0cmF0aW9uCiAgICAvLyBzY2hlbWUuIFdlIGFsc28gdXNlIHRoaXMgc2NoZW1lIGZvciBTaGlueSBhcHBzL2RvY3VtZW50cyB0aGF0IGFsc28KICAgIC8vIGNvbnRhaW4gc3RhdGljIHdpZGdldHMuCiAgICB3aW5kb3cuSFRNTFdpZGdldHMud2lkZ2V0cyA9IHdpbmRvdy5IVE1MV2lkZ2V0cy53aWRnZXRzIHx8IFtdOwogICAgLy8gTWVyZ2UgZGVmYXVsdHMgaW50byB0aGUgZGVmaW5pdGlvbjsgZG9uJ3QgbXV0YXRlIHRoZSBvcmlnaW5hbCBkZWZpbml0aW9uLgogICAgdmFyIHN0YXRpY0JpbmRpbmcgPSBleHRlbmQoe30sIGRlZmF1bHRzLCBkZWZpbml0aW9uKTsKICAgIG92ZXJyaWRlTWV0aG9kKHN0YXRpY0JpbmRpbmcsICJmaW5kIiwgZnVuY3Rpb24oc3VwZXJmdW5jKSB7CiAgICAgIHJldHVybiBmdW5jdGlvbihzY29wZSkgewogICAgICAgIHZhciByZXN1bHRzID0gc3VwZXJmdW5jKHNjb3BlKTsKICAgICAgICAvLyBGaWx0ZXIgb3V0IFNoaW55IG91dHB1dHMsIHdlIG9ubHkgd2FudCB0aGUgc3RhdGljIGtpbmQKICAgICAgICByZXR1cm4gZmlsdGVyQnlDbGFzcyhyZXN1bHRzLCAiaHRtbC13aWRnZXQtb3V0cHV0IiwgZmFsc2UpOwogICAgICB9OwogICAgfSk7CiAgICB3aW5kb3cuSFRNTFdpZGdldHMud2lkZ2V0cy5wdXNoKHN0YXRpY0JpbmRpbmcpOwoKICAgIGlmIChzaGlueU1vZGUpIHsKICAgICAgLy8gU2hpbnkgaXMgcnVubmluZy4gUmVnaXN0ZXIgdGhlIGRlZmluaXRpb24gd2l0aCBhbiBvdXRwdXQgYmluZGluZy4KICAgICAgLy8gVGhlIGRlZmluaXRpb24gaXRzZWxmIHdpbGwgbm90IGJlIHRoZSBvdXRwdXQgYmluZGluZywgaW5zdGVhZAogICAgICAvLyB3ZSB3aWxsIG1ha2UgYW4gb3V0cHV0IGJpbmRpbmcgb2JqZWN0IHRoYXQgZGVsZWdhdGVzIHRvIHRoZQogICAgICAvLyBkZWZpbml0aW9uLiBUaGlzIGlzIGJlY2F1c2Ugd2UgZm9vbGlzaGx5IHVzZWQgdGhlIHNhbWUgbWV0aG9kCiAgICAgIC8vIG5hbWUgKHJlbmRlclZhbHVlKSBmb3IgaHRtbHdpZGdldHMgZGVmaW5pdGlvbiBhbmQgU2hpbnkgYmluZGluZ3MKICAgICAgLy8gYnV0IHRoZXkgYWN0dWFsbHkgaGF2ZSBxdWl0ZSBkaWZmZXJlbnQgc2VtYW50aWNzICh0aGUgU2hpbnkKICAgICAgLy8gYmluZGluZ3MgcmVjZWl2ZSBkYXRhIHRoYXQgaW5jbHVkZXMgbG90cyBvZiBtZXRhZGF0YSB0aGF0IGl0CiAgICAgIC8vIHN0cmlwcyBvZmYgYmVmb3JlIGNhbGxpbmcgaHRtbHdpZGdldHMgcmVuZGVyVmFsdWUpLiBXZSBjYW4ndAogICAgICAvLyBqdXN0IGlnbm9yZSB0aGUgZGlmZmVyZW5jZSBiZWNhdXNlIGluIHNvbWUgd2lkZ2V0cyBpdCdzIGhlbHBmdWwKICAgICAgLy8gdG8gY2FsbCB0aGlzLnJlbmRlclZhbHVlKCkgZnJvbSBpbnNpZGUgb2YgcmVzaXplKCksIGFuZCBpZgogICAgICAvLyB3ZSdyZSBub3QgZGVsZWdhdGluZywgdGhlbiB0aGF0IGNhbGwgd2lsbCBnbyB0byB0aGUgU2hpbnkKICAgICAgLy8gdmVyc2lvbiBpbnN0ZWFkIG9mIHRoZSBodG1sd2lkZ2V0cyB2ZXJzaW9uLgoKICAgICAgLy8gTWVyZ2UgZGVmYXVsdHMgd2l0aCBkZWZpbml0aW9uLCB3aXRob3V0IG11dGF0aW5nIGVpdGhlci4KICAgICAgdmFyIGJpbmRpbmdEZWYgPSBleHRlbmQoe30sIGRlZmF1bHRzLCBkZWZpbml0aW9uKTsKCiAgICAgIC8vIFRoaXMgb2JqZWN0IHdpbGwgYmUgb3VyIGFjdHVhbCBTaGlueSBiaW5kaW5nLgogICAgICB2YXIgc2hpbnlCaW5kaW5nID0gbmV3IFNoaW55Lk91dHB1dEJpbmRpbmcoKTsKCiAgICAgIC8vIFdpdGggYSBmZXcgZXhjZXB0aW9ucywgd2UnbGwgd2FudCB0byBzaW1wbHkgdXNlIHRoZSBiaW5kaW5nRGVmJ3MKICAgICAgLy8gdmVyc2lvbiBvZiBtZXRob2RzIGlmIHRoZXkgYXJlIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIGZhbGwgYmFjayB0bwogICAgICAvLyBTaGlueSdzIGRlZmF1bHRzLiBOT1RFOiBJZiBTaGlueSdzIG91dHB1dCBiaW5kaW5ncyBnYWluIGFkZGl0aW9uYWwKICAgICAgLy8gbWV0aG9kcyBpbiB0aGUgZnV0dXJlLCBhbmQgd2Ugd2FudCB0aGVtIHRvIGJlIG92ZXJyaWRlYWJsZSBieQogICAgICAvLyBIVE1MV2lkZ2V0IGJpbmRpbmcgZGVmaW5pdGlvbnMsIHRoZW4gd2UnbGwgbmVlZCB0byBhZGQgdGhlbSB0byB0aGlzCiAgICAgIC8vIGxpc3QuCiAgICAgIGRlbGVnYXRlTWV0aG9kKHNoaW55QmluZGluZywgYmluZGluZ0RlZiwgImdldElkIik7CiAgICAgIGRlbGVnYXRlTWV0aG9kKHNoaW55QmluZGluZywgYmluZGluZ0RlZiwgIm9uVmFsdWVDaGFuZ2UiKTsKICAgICAgZGVsZWdhdGVNZXRob2Qoc2hpbnlCaW5kaW5nLCBiaW5kaW5nRGVmLCAib25WYWx1ZUVycm9yIik7CiAgICAgIGRlbGVnYXRlTWV0aG9kKHNoaW55QmluZGluZywgYmluZGluZ0RlZiwgInJlbmRlckVycm9yIik7CiAgICAgIGRlbGVnYXRlTWV0aG9kKHNoaW55QmluZGluZywgYmluZGluZ0RlZiwgImNsZWFyRXJyb3IiKTsKICAgICAgZGVsZWdhdGVNZXRob2Qoc2hpbnlCaW5kaW5nLCBiaW5kaW5nRGVmLCAic2hvd1Byb2dyZXNzIik7CgogICAgICAvLyBUaGUgZmluZCwgcmVuZGVyVmFsdWUsIGFuZCByZXNpemUgYXJlIGhhbmRsZWQgZGlmZmVyZW50bHksIGJlY2F1c2Ugd2UKICAgICAgLy8gd2FudCB0byBhY3R1YWxseSBkZWNvcmF0ZSB0aGUgYmVoYXZpb3Igb2YgdGhlIGJpbmRpbmdEZWYgbWV0aG9kcy4KCiAgICAgIHNoaW55QmluZGluZy5maW5kID0gZnVuY3Rpb24oc2NvcGUpIHsKICAgICAgICB2YXIgcmVzdWx0cyA9IGJpbmRpbmdEZWYuZmluZChzY29wZSk7CgogICAgICAgIC8vIE9ubHkgcmV0dXJuIGVsZW1lbnRzIHRoYXQgYXJlIFNoaW55IG91dHB1dHMsIG5vdCBzdGF0aWMgb25lcwogICAgICAgIHZhciBkeW5hbWljUmVzdWx0cyA9IHJlc3VsdHMuZmlsdGVyKCIuaHRtbC13aWRnZXQtb3V0cHV0Iik7CgogICAgICAgIC8vIEl0J3MgcG9zc2libGUgdGhhdCB3aGF0ZXZlciBjYXVzZWQgU2hpbnkgdG8gdGhpbmsgdGhlcmUgbWlnaHQgYmUKICAgICAgICAvLyBuZXcgZHluYW1pYyBvdXRwdXRzLCBhbHNvIGNhdXNlZCB0aGVyZSB0byBiZSBuZXcgc3RhdGljIG91dHB1dHMuCiAgICAgICAgLy8gU2luY2UgdGhlcmUgbWlnaHQgYmUgbG90cyBvZiBkaWZmZXJlbnQgaHRtbHdpZGdldHMgYmluZGluZ3MsIHdlCiAgICAgICAgLy8gc2NoZWR1bGUgZXhlY3V0aW9uIGZvciBsYXRlci0tbm8gbmVlZCB0byBzdGF0aWNSZW5kZXIgbXVsdGlwbGUKICAgICAgICAvLyB0aW1lcy4KICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggIT09IGR5bmFtaWNSZXN1bHRzLmxlbmd0aCkKICAgICAgICAgIHNjaGVkdWxlU3RhdGljUmVuZGVyKCk7CgogICAgICAgIHJldHVybiBkeW5hbWljUmVzdWx0czsKICAgICAgfTsKCiAgICAgIC8vIFdyYXAgcmVuZGVyVmFsdWUgdG8gaGFuZGxlIGluaXRpYWxpemF0aW9uLCB3aGljaCB1bmZvcnR1bmF0ZWx5IGlzbid0CiAgICAgIC8vIHN1cHBvcnRlZCBuYXRpdmVseSBieSBTaGlueSBhdCB0aGUgdGltZSBvZiB0aGlzIHdyaXRpbmcuCgogICAgICBzaGlueUJpbmRpbmcucmVuZGVyVmFsdWUgPSBmdW5jdGlvbihlbCwgZGF0YSkgewogICAgICAgIC8vIFJlc29sdmUgc3RyaW5ncyBtYXJrZWQgYXMgamF2YXNjcmlwdCBsaXRlcmFscyB0byBvYmplY3RzCiAgICAgICAgaWYgKCEoZGF0YS5ldmFscyBpbnN0YW5jZW9mIEFycmF5KSkgZGF0YS5ldmFscyA9IFtkYXRhLmV2YWxzXTsKICAgICAgICBmb3IgKHZhciBpID0gMDsgZGF0YS5ldmFscyAmJiBpIDwgZGF0YS5ldmFscy5sZW5ndGg7IGkrKykgewogICAgICAgICAgd2luZG93LkhUTUxXaWRnZXRzLmV2YWx1YXRlU3RyaW5nTWVtYmVyKGRhdGEueCwgZGF0YS5ldmFsc1tpXSk7CiAgICAgICAgfQogICAgICAgIGlmICghYmluZGluZ0RlZi5yZW5kZXJPbk51bGxWYWx1ZSkgewogICAgICAgICAgaWYgKGRhdGEueCA9PT0gbnVsbCkgewogICAgICAgICAgICBlbC5zdHlsZS52aXNpYmlsaXR5ID0gImhpZGRlbiI7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGVsLnN0eWxlLnZpc2liaWxpdHkgPSAiaW5oZXJpdCI7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICghZWxlbWVudERhdGEoZWwsICJpbml0aWFsaXplZCIpKSB7CiAgICAgICAgICBpbml0U2l6aW5nKGVsKTsKCiAgICAgICAgICBlbGVtZW50RGF0YShlbCwgImluaXRpYWxpemVkIiwgdHJ1ZSk7CiAgICAgICAgICBpZiAoYmluZGluZ0RlZi5pbml0aWFsaXplKSB7CiAgICAgICAgICAgIHZhciByZXN1bHQgPSBiaW5kaW5nRGVmLmluaXRpYWxpemUoZWwsIGVsLm9mZnNldFdpZHRoLAogICAgICAgICAgICAgIGVsLm9mZnNldEhlaWdodCk7CiAgICAgICAgICAgIGVsZW1lbnREYXRhKGVsLCAiaW5pdF9yZXN1bHQiLCByZXN1bHQpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBTaGlueS5yZW5kZXJEZXBlbmRlbmNpZXMoZGF0YS5kZXBzKTsKICAgICAgICBiaW5kaW5nRGVmLnJlbmRlclZhbHVlKGVsLCBkYXRhLngsIGVsZW1lbnREYXRhKGVsLCAiaW5pdF9yZXN1bHQiKSk7CiAgICAgICAgZXZhbEFuZFJ1bihkYXRhLmpzSG9va3MucmVuZGVyLCBlbGVtZW50RGF0YShlbCwgImluaXRfcmVzdWx0IiksIFtlbCwgZGF0YS54XSk7CiAgICAgIH07CgogICAgICAvLyBPbmx5IG92ZXJyaWRlIHJlc2l6ZSBpZiBiaW5kaW5nRGVmIGltcGxlbWVudHMgaXQKICAgICAgaWYgKGJpbmRpbmdEZWYucmVzaXplKSB7CiAgICAgICAgc2hpbnlCaW5kaW5nLnJlc2l6ZSA9IGZ1bmN0aW9uKGVsLCB3aWR0aCwgaGVpZ2h0KSB7CiAgICAgICAgICAvLyBTaGlueSBjYW4gY2FsbCByZXNpemUgYmVmb3JlIGluaXRpYWxpemUvcmVuZGVyVmFsdWUgaGF2ZSBiZWVuCiAgICAgICAgICAvLyBjYWxsZWQsIHdoaWNoIGRvZXNuJ3QgbWFrZSBzZW5zZSBmb3Igd2lkZ2V0cy4KICAgICAgICAgIGlmIChlbGVtZW50RGF0YShlbCwgImluaXRpYWxpemVkIikpIHsKICAgICAgICAgICAgYmluZGluZ0RlZi5yZXNpemUoZWwsIHdpZHRoLCBoZWlnaHQsIGVsZW1lbnREYXRhKGVsLCAiaW5pdF9yZXN1bHQiKSk7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgfQoKICAgICAgU2hpbnkub3V0cHV0QmluZGluZ3MucmVnaXN0ZXIoc2hpbnlCaW5kaW5nLCBiaW5kaW5nRGVmLm5hbWUpOwogICAgfQogIH07CgogIHZhciBzY2hlZHVsZVN0YXRpY1JlbmRlclRpbWVySWQgPSBudWxsOwogIGZ1bmN0aW9uIHNjaGVkdWxlU3RhdGljUmVuZGVyKCkgewogICAgaWYgKCFzY2hlZHVsZVN0YXRpY1JlbmRlclRpbWVySWQpIHsKICAgICAgc2NoZWR1bGVTdGF0aWNSZW5kZXJUaW1lcklkID0gc2V0VGltZW91dChmdW5jdGlvbigpIHsKICAgICAgICBzY2hlZHVsZVN0YXRpY1JlbmRlclRpbWVySWQgPSBudWxsOwogICAgICAgIHdpbmRvdy5IVE1MV2lkZ2V0cy5zdGF0aWNSZW5kZXIoKTsKICAgICAgfSwgMSk7CiAgICB9CiAgfQoKICAvLyBSZW5kZXIgc3RhdGljIHdpZGdldHMgYWZ0ZXIgdGhlIGRvY3VtZW50IGZpbmlzaGVzIGxvYWRpbmcKICAvLyBTdGF0aWNhbGx5IHJlbmRlciBhbGwgZWxlbWVudHMgdGhhdCBhcmUgb2YgdGhpcyB3aWRnZXQncyBjbGFzcwogIHdpbmRvdy5IVE1MV2lkZ2V0cy5zdGF0aWNSZW5kZXIgPSBmdW5jdGlvbigpIHsKICAgIHZhciBiaW5kaW5ncyA9IHdpbmRvdy5IVE1MV2lkZ2V0cy53aWRnZXRzIHx8IFtdOwogICAgZm9yRWFjaChiaW5kaW5ncywgZnVuY3Rpb24oYmluZGluZykgewogICAgICB2YXIgbWF0Y2hlcyA9IGJpbmRpbmcuZmluZChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpOwogICAgICBmb3JFYWNoKG1hdGNoZXMsIGZ1bmN0aW9uKGVsKSB7CiAgICAgICAgdmFyIHNpemVPYmogPSBpbml0U2l6aW5nKGVsLCBiaW5kaW5nKTsKCiAgICAgICAgaWYgKGhhc0NsYXNzKGVsLCAiaHRtbC13aWRnZXQtc3RhdGljLWJvdW5kIikpCiAgICAgICAgICByZXR1cm47CiAgICAgICAgZWwuY2xhc3NOYW1lID0gZWwuY2xhc3NOYW1lICsgIiBodG1sLXdpZGdldC1zdGF0aWMtYm91bmQiOwoKICAgICAgICB2YXIgaW5pdFJlc3VsdDsKICAgICAgICBpZiAoYmluZGluZy5pbml0aWFsaXplKSB7CiAgICAgICAgICBpbml0UmVzdWx0ID0gYmluZGluZy5pbml0aWFsaXplKGVsLAogICAgICAgICAgICBzaXplT2JqID8gc2l6ZU9iai5nZXRXaWR0aCgpIDogZWwub2Zmc2V0V2lkdGgsCiAgICAgICAgICAgIHNpemVPYmogPyBzaXplT2JqLmdldEhlaWdodCgpIDogZWwub2Zmc2V0SGVpZ2h0CiAgICAgICAgICApOwogICAgICAgICAgZWxlbWVudERhdGEoZWwsICJpbml0X3Jlc3VsdCIsIGluaXRSZXN1bHQpOwogICAgICAgIH0KCiAgICAgICAgaWYgKGJpbmRpbmcucmVzaXplKSB7CiAgICAgICAgICB2YXIgbGFzdFNpemUgPSB7fTsKICAgICAgICAgIHZhciByZXNpemVIYW5kbGVyID0gZnVuY3Rpb24oZSkgewogICAgICAgICAgICB2YXIgc2l6ZSA9IHsKICAgICAgICAgICAgICB3OiBzaXplT2JqID8gc2l6ZU9iai5nZXRXaWR0aCgpIDogZWwub2Zmc2V0V2lkdGgsCiAgICAgICAgICAgICAgaDogc2l6ZU9iaiA/IHNpemVPYmouZ2V0SGVpZ2h0KCkgOiBlbC5vZmZzZXRIZWlnaHQKICAgICAgICAgICAgfTsKICAgICAgICAgICAgaWYgKHNpemUudyA9PT0gMCAmJiBzaXplLmggPT09IDApCiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICBpZiAoc2l6ZS53ID09PSBsYXN0U2l6ZS53ICYmIHNpemUuaCA9PT0gbGFzdFNpemUuaCkKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIGxhc3RTaXplID0gc2l6ZTsKICAgICAgICAgICAgYmluZGluZy5yZXNpemUoZWwsIHNpemUudywgc2l6ZS5oLCBpbml0UmVzdWx0KTsKICAgICAgICAgIH07CgogICAgICAgICAgb24od2luZG93LCAicmVzaXplIiwgcmVzaXplSGFuZGxlcik7CgogICAgICAgICAgLy8gVGhpcyBpcyBuZWVkZWQgZm9yIGNhc2VzIHdoZXJlIHdlJ3JlIHJ1bm5pbmcgaW4gYSBTaGlueQogICAgICAgICAgLy8gYXBwLCBidXQgdGhlIHdpZGdldCBpdHNlbGYgaXMgbm90IGEgU2hpbnkgb3V0cHV0LCBidXQKICAgICAgICAgIC8vIHJhdGhlciBhIHNpbXBsZSBzdGF0aWMgd2lkZ2V0LiBPbmUgZXhhbXBsZSBvZiB0aGlzIGlzCiAgICAgICAgICAvLyBhbiBybWFya2Rvd24gZG9jdW1lbnQgdGhhdCBoYXMgcnVudGltZTpzaGlueSBhbmQgd2lkZ2V0CiAgICAgICAgICAvLyB0aGF0IGlzbid0IGluIGEgcmVuZGVyIGZ1bmN0aW9uLiBTaGlueSBvbmx5IGtub3dzIHRvCiAgICAgICAgICAvLyBjYWxsIHJlc2l6ZSBoYW5kbGVycyBmb3IgU2hpbnkgb3V0cHV0cywgbm90IGZvciBzdGF0aWMKICAgICAgICAgIC8vIHdpZGdldHMsIHNvIHdlIGRvIGl0IG91cnNlbHZlcy4KICAgICAgICAgIGlmICh3aW5kb3cualF1ZXJ5KSB7CiAgICAgICAgICAgIHdpbmRvdy5qUXVlcnkoZG9jdW1lbnQpLm9uKAogICAgICAgICAgICAgICJzaG93bi5odG1sd2lkZ2V0cyBzaG93bi5icy50YWIuaHRtbHdpZGdldHMgc2hvd24uYnMuY29sbGFwc2UuaHRtbHdpZGdldHMiLAogICAgICAgICAgICAgIHJlc2l6ZUhhbmRsZXIKICAgICAgICAgICAgKTsKICAgICAgICAgICAgd2luZG93LmpRdWVyeShkb2N1bWVudCkub24oCiAgICAgICAgICAgICAgImhpZGRlbi5odG1sd2lkZ2V0cyBoaWRkZW4uYnMudGFiLmh0bWx3aWRnZXRzIGhpZGRlbi5icy5jb2xsYXBzZS5odG1sd2lkZ2V0cyIsCiAgICAgICAgICAgICAgcmVzaXplSGFuZGxlcgogICAgICAgICAgICApOwogICAgICAgICAgfQoKICAgICAgICAgIC8vIFRoaXMgaXMgbmVlZGVkIGZvciB0aGUgc3BlY2lmaWMgY2FzZSBvZiBpb3NsaWRlcywgd2hpY2gKICAgICAgICAgIC8vIGZsaXBzIHNsaWRlcyBiZXR3ZWVuIGRpc3BsYXk6bm9uZSBhbmQgZGlzcGxheTpibG9jay4KICAgICAgICAgIC8vIElkZWFsbHkgd2Ugd291bGQgbm90IGhhdmUgdG8gaGF2ZSBpb3NsaWRlLXNwZWNpZmljIGNvZGUKICAgICAgICAgIC8vIGhlcmUsIGJ1dCByYXRoZXIgaGF2ZSBpb3NsaWRlcyByYWlzZSBhIGdlbmVyaWMgZXZlbnQsCiAgICAgICAgICAvLyBidXQgdGhlIHJtYXJrZG93biBwYWNrYWdlIGp1c3Qgd2VudCB0byBDUkFOIHNvIHRoZQogICAgICAgICAgLy8gd2luZG93IHRvIGdldHRpbmcgdGhhdCBmaXhlZCBtYXkgYmUgbG9uZy4KICAgICAgICAgIGlmICh3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcikgewogICAgICAgICAgICAvLyBJdCdzIE9LIHRvIGxpbWl0IHRoaXMgdG8gd2luZG93LmFkZEV2ZW50TGlzdGVuZXIKICAgICAgICAgICAgLy8gYnJvd3NlcnMgYmVjYXVzZSBpb3NsaWRlcyBpdHNlbGYgb25seSBzdXBwb3J0cwogICAgICAgICAgICAvLyBzdWNoIGJyb3dzZXJzLgogICAgICAgICAgICBvbihkb2N1bWVudCwgInNsaWRlZW50ZXIiLCByZXNpemVIYW5kbGVyKTsKICAgICAgICAgICAgb24oZG9jdW1lbnQsICJzbGlkZWxlYXZlIiwgcmVzaXplSGFuZGxlcik7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB2YXIgc2NyaXB0RGF0YSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoInNjcmlwdFtkYXRhLWZvcj0nIiArIGVsLmlkICsgIiddW3R5cGU9J2FwcGxpY2F0aW9uL2pzb24nXSIpOwogICAgICAgIGlmIChzY3JpcHREYXRhKSB7CiAgICAgICAgICB2YXIgZGF0YSA9IEpTT04ucGFyc2Uoc2NyaXB0RGF0YS50ZXh0Q29udGVudCB8fCBzY3JpcHREYXRhLnRleHQpOwogICAgICAgICAgLy8gUmVzb2x2ZSBzdHJpbmdzIG1hcmtlZCBhcyBqYXZhc2NyaXB0IGxpdGVyYWxzIHRvIG9iamVjdHMKICAgICAgICAgIGlmICghKGRhdGEuZXZhbHMgaW5zdGFuY2VvZiBBcnJheSkpIGRhdGEuZXZhbHMgPSBbZGF0YS5ldmFsc107CiAgICAgICAgICBmb3IgKHZhciBrID0gMDsgZGF0YS5ldmFscyAmJiBrIDwgZGF0YS5ldmFscy5sZW5ndGg7IGsrKykgewogICAgICAgICAgICB3aW5kb3cuSFRNTFdpZGdldHMuZXZhbHVhdGVTdHJpbmdNZW1iZXIoZGF0YS54LCBkYXRhLmV2YWxzW2tdKTsKICAgICAgICAgIH0KICAgICAgICAgIGJpbmRpbmcucmVuZGVyVmFsdWUoZWwsIGRhdGEueCwgaW5pdFJlc3VsdCk7CiAgICAgICAgICBldmFsQW5kUnVuKGRhdGEuanNIb29rcy5yZW5kZXIsIGluaXRSZXN1bHQsIFtlbCwgZGF0YS54XSk7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0pOwoKICAgIGludm9rZVBvc3RSZW5kZXJIYW5kbGVycygpOwogIH0KCiAgLy8gV2FpdCB1bnRpbCBhZnRlciB0aGUgZG9jdW1lbnQgaGFzIGxvYWRlZCB0byByZW5kZXIgdGhlIHdpZGdldHMuCiAgaWYgKGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIpIHsKICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoIkRPTUNvbnRlbnRMb2FkZWQiLCBmdW5jdGlvbigpIHsKICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigiRE9NQ29udGVudExvYWRlZCIsIGFyZ3VtZW50cy5jYWxsZWUsIGZhbHNlKTsKICAgICAgd2luZG93LkhUTUxXaWRnZXRzLnN0YXRpY1JlbmRlcigpOwogICAgfSwgZmFsc2UpOwogIH0gZWxzZSBpZiAoZG9jdW1lbnQuYXR0YWNoRXZlbnQpIHsKICAgIGRvY3VtZW50LmF0dGFjaEV2ZW50KCJvbnJlYWR5c3RhdGVjaGFuZ2UiLCBmdW5jdGlvbigpIHsKICAgICAgaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICJjb21wbGV0ZSIpIHsKICAgICAgICBkb2N1bWVudC5kZXRhY2hFdmVudCgib25yZWFkeXN0YXRlY2hhbmdlIiwgYXJndW1lbnRzLmNhbGxlZSk7CiAgICAgICAgd2luZG93LkhUTUxXaWRnZXRzLnN0YXRpY1JlbmRlcigpOwogICAgICB9CiAgICB9KTsKICB9CgoKICB3aW5kb3cuSFRNTFdpZGdldHMuZ2V0QXR0YWNobWVudFVybCA9IGZ1bmN0aW9uKGRlcG5hbWUsIGtleSkgewogICAgLy8gSWYgbm8ga2V5LCBkZWZhdWx0IHRvIHRoZSBmaXJzdCBpdGVtCiAgICBpZiAodHlwZW9mKGtleSkgPT09ICJ1bmRlZmluZWQiKQogICAgICBrZXkgPSAxOwoKICAgIHZhciBsaW5rID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZGVwbmFtZSArICItIiArIGtleSArICItYXR0YWNobWVudCIpOwogICAgaWYgKCFsaW5rKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiQXR0YWNobWVudCAiICsgZGVwbmFtZSArICIvIiArIGtleSArICIgbm90IGZvdW5kIGluIGRvY3VtZW50Iik7CiAgICB9CiAgICByZXR1cm4gbGluay5nZXRBdHRyaWJ1dGUoImhyZWYiKTsKICB9OwoKICB3aW5kb3cuSFRNTFdpZGdldHMuZGF0YWZyYW1lVG9EMyA9IGZ1bmN0aW9uKGRmKSB7CiAgICB2YXIgbmFtZXMgPSBbXTsKICAgIHZhciBsZW5ndGg7CiAgICBmb3IgKHZhciBuYW1lIGluIGRmKSB7CiAgICAgICAgaWYgKGRmLmhhc093blByb3BlcnR5KG5hbWUpKQogICAgICAgICAgICBuYW1lcy5wdXNoKG5hbWUpOwogICAgICAgIGlmICh0eXBlb2YoZGZbbmFtZV0pICE9PSAib2JqZWN0IiB8fCB0eXBlb2YoZGZbbmFtZV0ubGVuZ3RoKSA9PT0gInVuZGVmaW5lZCIpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJBbGwgZmllbGRzIG11c3QgYmUgYXJyYXlzIik7CiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YobGVuZ3RoKSAhPT0gInVuZGVmaW5lZCIgJiYgbGVuZ3RoICE9PSBkZltuYW1lXS5sZW5ndGgpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJBbGwgZmllbGRzIG11c3QgYmUgYXJyYXlzIG9mIHRoZSBzYW1lIGxlbmd0aCIpOwogICAgICAgIH0KICAgICAgICBsZW5ndGggPSBkZltuYW1lXS5sZW5ndGg7CiAgICB9CiAgICB2YXIgcmVzdWx0cyA9IFtdOwogICAgdmFyIGl0ZW07CiAgICBmb3IgKHZhciByb3cgPSAwOyByb3cgPCBsZW5ndGg7IHJvdysrKSB7CiAgICAgICAgaXRlbSA9IHt9OwogICAgICAgIGZvciAodmFyIGNvbCA9IDA7IGNvbCA8IG5hbWVzLmxlbmd0aDsgY29sKyspIHsKICAgICAgICAgICAgaXRlbVtuYW1lc1tjb2xdXSA9IGRmW25hbWVzW2NvbF1dW3Jvd107CiAgICAgICAgfQogICAgICAgIHJlc3VsdHMucHVzaChpdGVtKTsKICAgIH0KICAgIHJldHVybiByZXN1bHRzOwogIH07CgogIHdpbmRvdy5IVE1MV2lkZ2V0cy50cmFuc3Bvc2VBcnJheTJEID0gZnVuY3Rpb24oYXJyYXkpIHsKICAgICAgaWYgKGFycmF5Lmxlbmd0aCA9PT0gMCkgcmV0dXJuIGFycmF5OwogICAgICB2YXIgbmV3QXJyYXkgPSBhcnJheVswXS5tYXAoZnVuY3Rpb24oY29sLCBpKSB7CiAgICAgICAgICByZXR1cm4gYXJyYXkubWFwKGZ1bmN0aW9uKHJvdykgewogICAgICAgICAgICAgIHJldHVybiByb3dbaV0KICAgICAgICAgIH0pCiAgICAgIH0pOwogICAgICByZXR1cm4gbmV3QXJyYXk7CiAgfTsKICAvLyBTcGxpdCB2YWx1ZSBhdCBzcGxpdENoYXIsIGJ1dCBhbGxvdyBzcGxpdENoYXIgdG8gYmUgZXNjYXBlZAogIC8vIHVzaW5nIGVzY2FwZUNoYXIuIEFueSBvdGhlciBjaGFyYWN0ZXJzIGVzY2FwZWQgYnkgZXNjYXBlQ2hhcgogIC8vIHdpbGwgYmUgaW5jbHVkZWQgYXMgdXN1YWwgKGluY2x1ZGluZyBlc2NhcGVDaGFyIGl0c2VsZikuCiAgZnVuY3Rpb24gc3BsaXRXaXRoRXNjYXBlKHZhbHVlLCBzcGxpdENoYXIsIGVzY2FwZUNoYXIpIHsKICAgIHZhciByZXN1bHRzID0gW107CiAgICB2YXIgZXNjYXBlTW9kZSA9IGZhbHNlOwogICAgdmFyIGN1cnJlbnRSZXN1bHQgPSAiIjsKICAgIGZvciAodmFyIHBvcyA9IDA7IHBvcyA8IHZhbHVlLmxlbmd0aDsgcG9zKyspIHsKICAgICAgaWYgKCFlc2NhcGVNb2RlKSB7CiAgICAgICAgaWYgKHZhbHVlW3Bvc10gPT09IHNwbGl0Q2hhcikgewogICAgICAgICAgcmVzdWx0cy5wdXNoKGN1cnJlbnRSZXN1bHQpOwogICAgICAgICAgY3VycmVudFJlc3VsdCA9ICIiOwogICAgICAgIH0gZWxzZSBpZiAodmFsdWVbcG9zXSA9PT0gZXNjYXBlQ2hhcikgewogICAgICAgICAgZXNjYXBlTW9kZSA9IHRydWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGN1cnJlbnRSZXN1bHQgKz0gdmFsdWVbcG9zXTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY3VycmVudFJlc3VsdCArPSB2YWx1ZVtwb3NdOwogICAgICAgIGVzY2FwZU1vZGUgPSBmYWxzZTsKICAgICAgfQogICAgfQogICAgaWYgKGN1cnJlbnRSZXN1bHQgIT09ICIiKSB7CiAgICAgIHJlc3VsdHMucHVzaChjdXJyZW50UmVzdWx0KTsKICAgIH0KICAgIHJldHVybiByZXN1bHRzOwogIH0KICAvLyBGdW5jdGlvbiBhdXRob3JlZCBieSBZaWh1aS9KSiBBbGxhaXJlCiAgd2luZG93LkhUTUxXaWRnZXRzLmV2YWx1YXRlU3RyaW5nTWVtYmVyID0gZnVuY3Rpb24obywgbWVtYmVyKSB7CiAgICB2YXIgcGFydHMgPSBzcGxpdFdpdGhFc2NhcGUobWVtYmVyLCAnLicsICdcXCcpOwogICAgZm9yICh2YXIgaSA9IDAsIGwgPSBwYXJ0cy5sZW5ndGg7IGkgPCBsOyBpKyspIHsKICAgICAgdmFyIHBhcnQgPSBwYXJ0c1tpXTsKICAgICAgLy8gcGFydCBtYXkgYmUgYSBjaGFyYWN0ZXIgb3IgJ251bWVyaWMnIG1lbWJlciBuYW1lCiAgICAgIGlmIChvICE9PSBudWxsICYmIHR5cGVvZiBvID09PSAib2JqZWN0IiAmJiBwYXJ0IGluIG8pIHsKICAgICAgICBpZiAoaSA9PSAobCAtIDEpKSB7IC8vIGlmIHdlIGFyZSBhdCB0aGUgZW5kIG9mIHRoZSBsaW5lIHRoZW4gZXZhbHVsYXRlCiAgICAgICAgICBpZiAodHlwZW9mIG9bcGFydF0gPT09ICJzdHJpbmciKQogICAgICAgICAgICBvW3BhcnRdID0gZXZhbCgiKCIgKyBvW3BhcnRdICsgIikiKTsKICAgICAgICB9IGVsc2UgeyAvLyBvdGhlcndpc2UgY29udGludWUgdG8gbmV4dCBlbWJlZGRlZCBvYmplY3QKICAgICAgICAgIG8gPSBvW3BhcnRdOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH07CgogIC8vIFJldHJpZXZlIHRoZSBIVE1MV2lkZ2V0IGluc3RhbmNlIChpLmUuIHRoZSByZXR1cm4gdmFsdWUgb2YgYW4KICAvLyBIVE1MV2lkZ2V0IGJpbmRpbmcncyBpbml0aWFsaXplKCkgb3IgZmFjdG9yeSgpIGZ1bmN0aW9uKQogIC8vIGFzc29jaWF0ZWQgd2l0aCBhbiBlbGVtZW50LCBvciBudWxsIGlmIG5vbmUuCiAgd2luZG93LkhUTUxXaWRnZXRzLmdldEluc3RhbmNlID0gZnVuY3Rpb24oZWwpIHsKICAgIHJldHVybiBlbGVtZW50RGF0YShlbCwgImluaXRfcmVzdWx0Iik7CiAgfTsKCiAgLy8gRmluZHMgdGhlIGZpcnN0IGVsZW1lbnQgaW4gdGhlIHNjb3BlIHRoYXQgbWF0Y2hlcyB0aGUgc2VsZWN0b3IsCiAgLy8gYW5kIHJldHVybnMgdGhlIEhUTUxXaWRnZXQgaW5zdGFuY2UgKGkuZS4gdGhlIHJldHVybiB2YWx1ZSBvZgogIC8vIGFuIEhUTUxXaWRnZXQgYmluZGluZydzIGluaXRpYWxpemUoKSBvciBmYWN0b3J5KCkgZnVuY3Rpb24pCiAgLy8gYXNzb2NpYXRlZCB3aXRoIHRoYXQgZWxlbWVudCwgaWYgYW55LiBJZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlCiAgLy8gc2VsZWN0b3IsIG9yIHRoZSBmaXJzdCBtYXRjaGluZyBlbGVtZW50IGhhcyBubyBIVE1MV2lkZ2V0CiAgLy8gaW5zdGFuY2UgYXNzb2NpYXRlZCB3aXRoIGl0LCB0aGVuIG51bGwgaXMgcmV0dXJuZWQuCiAgLy8KICAvLyBUaGUgc2NvcGUgYXJndW1lbnQgaXMgb3B0aW9uYWwsIGFuZCBkZWZhdWx0cyB0byB3aW5kb3cuZG9jdW1lbnQuCiAgd2luZG93LkhUTUxXaWRnZXRzLmZpbmQgPSBmdW5jdGlvbihzY29wZSwgc2VsZWN0b3IpIHsKICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09IDEpIHsKICAgICAgc2VsZWN0b3IgPSBzY29wZTsKICAgICAgc2NvcGUgPSBkb2N1bWVudDsKICAgIH0KCiAgICB2YXIgZWwgPSBzY29wZS5xdWVyeVNlbGVjdG9yKHNlbGVjdG9yKTsKICAgIGlmIChlbCA9PT0gbnVsbCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiB3aW5kb3cuSFRNTFdpZGdldHMuZ2V0SW5zdGFuY2UoZWwpOwogICAgfQogIH07CgogIC8vIEZpbmRzIGFsbCBlbGVtZW50cyBpbiB0aGUgc2NvcGUgdGhhdCBtYXRjaCB0aGUgc2VsZWN0b3IsIGFuZAogIC8vIHJldHVybnMgdGhlIEhUTUxXaWRnZXQgaW5zdGFuY2VzIChpLmUuIHRoZSByZXR1cm4gdmFsdWVzIG9mCiAgLy8gYW4gSFRNTFdpZGdldCBiaW5kaW5nJ3MgaW5pdGlhbGl6ZSgpIG9yIGZhY3RvcnkoKSBmdW5jdGlvbikKICAvLyBhc3NvY2lhdGVkIHdpdGggdGhlIGVsZW1lbnRzLCBpbiBhbiBhcnJheS4gSWYgZWxlbWVudHMgdGhhdAogIC8vIG1hdGNoIHRoZSBzZWxlY3RvciBkb24ndCBoYXZlIGFuIGFzc29jaWF0ZWQgSFRNTFdpZGdldAogIC8vIGluc3RhbmNlLCB0aGUgcmV0dXJuZWQgYXJyYXkgd2lsbCBjb250YWluIG51bGxzLgogIC8vCiAgLy8gVGhlIHNjb3BlIGFyZ3VtZW50IGlzIG9wdGlvbmFsLCBhbmQgZGVmYXVsdHMgdG8gd2luZG93LmRvY3VtZW50LgogIHdpbmRvdy5IVE1MV2lkZ2V0cy5maW5kQWxsID0gZnVuY3Rpb24oc2NvcGUsIHNlbGVjdG9yKSB7CiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PSAxKSB7CiAgICAgIHNlbGVjdG9yID0gc2NvcGU7CiAgICAgIHNjb3BlID0gZG9jdW1lbnQ7CiAgICB9CgogICAgdmFyIG5vZGVzID0gc2NvcGUucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7CiAgICB2YXIgcmVzdWx0cyA9IFtdOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykgewogICAgICByZXN1bHRzLnB1c2god2luZG93LkhUTUxXaWRnZXRzLmdldEluc3RhbmNlKG5vZGVzW2ldKSk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0czsKICB9OwoKICB2YXIgcG9zdFJlbmRlckhhbmRsZXJzID0gW107CiAgZnVuY3Rpb24gaW52b2tlUG9zdFJlbmRlckhhbmRsZXJzKCkgewogICAgd2hpbGUgKHBvc3RSZW5kZXJIYW5kbGVycy5sZW5ndGgpIHsKICAgICAgdmFyIGhhbmRsZXIgPSBwb3N0UmVuZGVySGFuZGxlcnMuc2hpZnQoKTsKICAgICAgaWYgKGhhbmRsZXIpIHsKICAgICAgICBoYW5kbGVyKCk7CiAgICAgIH0KICAgIH0KICB9CgogIC8vIFJlZ2lzdGVyIHRoZSBnaXZlbiBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBpbnZva2VkIGFmdGVyIHRoZQogIC8vIG5leHQgdGltZSBzdGF0aWMgd2lkZ2V0cyBhcmUgcmVuZGVyZWQuCiAgd2luZG93LkhUTUxXaWRnZXRzLmFkZFBvc3RSZW5kZXJIYW5kbGVyID0gZnVuY3Rpb24oY2FsbGJhY2spIHsKICAgIHBvc3RSZW5kZXJIYW5kbGVycy5wdXNoKGNhbGxiYWNrKTsKICB9OwoKICAvLyBUYWtlcyBhIG5ldy1zdHlsZSBpbnN0YW5jZS1ib3VuZCBkZWZpbml0aW9uLCBhbmQgcmV0dXJucyBhbgogIC8vIG9sZC1zdHlsZSBjbGFzcy1ib3VuZCBkZWZpbml0aW9uLiBUaGlzIHNhdmVzIHVzIGZyb20gaGF2aW5nCiAgLy8gdG8gcmV3cml0ZSBhbGwgdGhlIGxvZ2ljIGluIHRoaXMgZmlsZSB0byBhY2NvbW9kYXRlIGJvdGgKICAvLyB0eXBlcyBvZiBkZWZpbml0aW9ucy4KICBmdW5jdGlvbiBjcmVhdGVMZWdhY3lEZWZpbml0aW9uQWRhcHRlcihkZWZuKSB7CiAgICB2YXIgcmVzdWx0ID0gewogICAgICBuYW1lOiBkZWZuLm5hbWUsCiAgICAgIHR5cGU6IGRlZm4udHlwZSwKICAgICAgaW5pdGlhbGl6ZTogZnVuY3Rpb24oZWwsIHdpZHRoLCBoZWlnaHQpIHsKICAgICAgICByZXR1cm4gZGVmbi5mYWN0b3J5KGVsLCB3aWR0aCwgaGVpZ2h0KTsKICAgICAgfSwKICAgICAgcmVuZGVyVmFsdWU6IGZ1bmN0aW9uKGVsLCB4LCBpbnN0YW5jZSkgewogICAgICAgIHJldHVybiBpbnN0YW5jZS5yZW5kZXJWYWx1ZSh4KTsKICAgICAgfSwKICAgICAgcmVzaXplOiBmdW5jdGlvbihlbCwgd2lkdGgsIGhlaWdodCwgaW5zdGFuY2UpIHsKICAgICAgICByZXR1cm4gaW5zdGFuY2UucmVzaXplKHdpZHRoLCBoZWlnaHQpOwogICAgICB9CiAgICB9OwoKICAgIGlmIChkZWZuLmZpbmQpCiAgICAgIHJlc3VsdC5maW5kID0gZGVmbi5maW5kOwogICAgaWYgKGRlZm4ucmVuZGVyRXJyb3IpCiAgICAgIHJlc3VsdC5yZW5kZXJFcnJvciA9IGRlZm4ucmVuZGVyRXJyb3I7CiAgICBpZiAoZGVmbi5jbGVhckVycm9yKQogICAgICByZXN1bHQuY2xlYXJFcnJvciA9IGRlZm4uY2xlYXJFcnJvcjsKCiAgICByZXR1cm4gcmVzdWx0OwogIH0KfSkoKTsKCg==&#34;&gt;&lt;/script&gt;
&lt;link href=&#34;data:text/css;charset=utf-8,%2Ebk%2Droot%7Bfont%2Dfamily%3A%22Helvetica%20Neue%22%2CHelvetica%2CArial%2Csans%2Dserif%3Bfont%2Dsize%3A10pt%3Bposition%3Arelative%3Bwidth%3A100%25%3Bheight%3A100%25%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%7Bdisplay%3Ainline%2Dblock%3Bmargin%2Dbottom%3A0%3Bfont%2Dweight%3Anormal%3Btext%2Dalign%3Acenter%3Bvertical%2Dalign%3Amiddle%3Bcursor%3Apointer%3Bbackground%2Dimage%3Anone%3Bborder%3A1px%20solid%20transparent%3Bwhite%2Dspace%3Anowrap%3Bpadding%3A6px%2012px%3Bfont%2Dsize%3A12px%3Bline%2Dheight%3A1%2E42857143%3Bborder%2Dradius%3A4px%3B%2Dwebkit%2Duser%2Dselect%3Anone%3B%2Dmoz%2Duser%2Dselect%3Anone%3B%2Dms%2Duser%2Dselect%3Anone%3Buser%2Dselect%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%3Aactive%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ebk%2Dbs%2Dactive%3Afocus%7Boutline%3Athin%20dotted%3Boutline%3A5px%20auto%20%2Dwebkit%2Dfocus%2Dring%2Dcolor%3Boutline%2Doffset%3A%2D2px%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%3Afocus%7Bcolor%3A%23333%3Btext%2Ddecoration%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ebk%2Dbs%2Dactive%7Boutline%3A0%3Bbackground%2Dimage%3Anone%3B%2Dwebkit%2Dbox%2Dshadow%3Ainset%200%203px%205px%20rgba%280%2C0%2C0%2C0%2E125%29%3Bbox%2Dshadow%3Ainset%200%203px%205px%20rgba%280%2C0%2C0%2C0%2E125%29%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ebk%2Dbs%2Ddisabled%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%5Bdisabled%5D%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%7Bcursor%3Anot%2Dallowed%3Bpointer%2Devents%3Anone%3Bopacity%3A%2E65%3Bfilter%3Aalpha%28opacity%3D65%29%3B%2Dwebkit%2Dbox%2Dshadow%3Anone%3Bbox%2Dshadow%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%7Bcolor%3A%23333%3Bbackground%2Dcolor%3A%23fff%3Bborder%2Dcolor%3A%23ccc%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%7Bcolor%3A%23333%3Bbackground%2Dcolor%3A%23ebebeb%3Bborder%2Dcolor%3A%23adadad%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%7Bbackground%2Dimage%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%2Ebk%2Dbs%2Ddisabled%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%5Bdisabled%5D%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%2Ebk%2Dbs%2Ddisabled%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%5Bdisabled%5D%3Ahover%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%2Ebk%2Dbs%2Ddisabled%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%5Bdisabled%5D%3Afocus%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%2Ebk%2Dbs%2Ddisabled%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%5Bdisabled%5D%3Aactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%2Ebk%2Dbs%2Ddisabled%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%5Bdisabled%5D%2Ebk%2Dbs%2Dactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%2Ebk%2Dbs%2Dactive%7Bbackground%2Dcolor%3A%23fff%3Bborder%2Dcolor%3A%23ccc%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddefault%20%2Ebk%2Dbs%2Dbadge%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%23333%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%23428bca%3Bborder%2Dcolor%3A%23357ebd%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%233276b1%3Bborder%2Dcolor%3A%23285e8e%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%7Bbackground%2Dimage%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%2Ebk%2Dbs%2Ddisabled%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%5Bdisabled%5D%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%2Ebk%2Dbs%2Ddisabled%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%5Bdisabled%5D%3Ahover%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%2Ebk%2Dbs%2Ddisabled%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%5Bdisabled%5D%3Afocus%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%2Ebk%2Dbs%2Ddisabled%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%5Bdisabled%5D%3Aactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%2Ebk%2Dbs%2Ddisabled%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%5Bdisabled%5D%2Ebk%2Dbs%2Dactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%2Ebk%2Dbs%2Dactive%7Bbackground%2Dcolor%3A%23428bca%3Bborder%2Dcolor%3A%23357ebd%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dprimary%20%2Ebk%2Dbs%2Dbadge%7Bcolor%3A%23428bca%3Bbackground%2Dcolor%3A%23fff%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%235cb85c%3Bborder%2Dcolor%3A%234cae4c%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%2347a447%3Bborder%2Dcolor%3A%23398439%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%7Bbackground%2Dimage%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%2Ebk%2Dbs%2Ddisabled%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%5Bdisabled%5D%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%2Ebk%2Dbs%2Ddisabled%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%5Bdisabled%5D%3Ahover%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%2Ebk%2Dbs%2Ddisabled%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%5Bdisabled%5D%3Afocus%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%2Ebk%2Dbs%2Ddisabled%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%5Bdisabled%5D%3Aactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%2Ebk%2Dbs%2Ddisabled%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%5Bdisabled%5D%2Ebk%2Dbs%2Dactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%2Ebk%2Dbs%2Dactive%7Bbackground%2Dcolor%3A%235cb85c%3Bborder%2Dcolor%3A%234cae4c%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsuccess%20%2Ebk%2Dbs%2Dbadge%7Bcolor%3A%235cb85c%3Bbackground%2Dcolor%3A%23fff%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%235bc0de%3Bborder%2Dcolor%3A%2346b8da%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%2339b3d7%3Bborder%2Dcolor%3A%23269abc%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%7Bbackground%2Dimage%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%2Ebk%2Dbs%2Ddisabled%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%5Bdisabled%5D%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%2Ebk%2Dbs%2Ddisabled%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%5Bdisabled%5D%3Ahover%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%2Ebk%2Dbs%2Ddisabled%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%5Bdisabled%5D%3Afocus%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%2Ebk%2Dbs%2Ddisabled%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%5Bdisabled%5D%3Aactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%2Ebk%2Dbs%2Ddisabled%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%5Bdisabled%5D%2Ebk%2Dbs%2Dactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%2Ebk%2Dbs%2Dactive%7Bbackground%2Dcolor%3A%235bc0de%3Bborder%2Dcolor%3A%2346b8da%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dinfo%20%2Ebk%2Dbs%2Dbadge%7Bcolor%3A%235bc0de%3Bbackground%2Dcolor%3A%23fff%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%23f0ad4e%3Bborder%2Dcolor%3A%23eea236%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%23ed9c28%3Bborder%2Dcolor%3A%23d58512%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%7Bbackground%2Dimage%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%2Ebk%2Dbs%2Ddisabled%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%5Bdisabled%5D%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%2Ebk%2Dbs%2Ddisabled%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%5Bdisabled%5D%3Ahover%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%2Ebk%2Dbs%2Ddisabled%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%5Bdisabled%5D%3Afocus%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%2Ebk%2Dbs%2Ddisabled%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%5Bdisabled%5D%3Aactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%2Ebk%2Dbs%2Ddisabled%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%5Bdisabled%5D%2Ebk%2Dbs%2Dactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%2Ebk%2Dbs%2Dactive%7Bbackground%2Dcolor%3A%23f0ad4e%3Bborder%2Dcolor%3A%23eea236%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dwarning%20%2Ebk%2Dbs%2Dbadge%7Bcolor%3A%23f0ad4e%3Bbackground%2Dcolor%3A%23fff%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%23d9534f%3Bborder%2Dcolor%3A%23d43f3a%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%23d2322d%3Bborder%2Dcolor%3A%23ac2925%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%7Bbackground%2Dimage%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%2Ebk%2Dbs%2Ddisabled%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%5Bdisabled%5D%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%2Ebk%2Dbs%2Ddisabled%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%5Bdisabled%5D%3Ahover%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%2Ebk%2Dbs%2Ddisabled%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%5Bdisabled%5D%3Afocus%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%2Ebk%2Dbs%2Ddisabled%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%5Bdisabled%5D%3Aactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%2Ebk%2Dbs%2Ddisabled%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%5Bdisabled%5D%2Ebk%2Dbs%2Dactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%2Ebk%2Dbs%2Dactive%7Bbackground%2Dcolor%3A%23d9534f%3Bborder%2Dcolor%3A%23d43f3a%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Ddanger%20%2Ebk%2Dbs%2Dbadge%7Bcolor%3A%23d9534f%3Bbackground%2Dcolor%3A%23fff%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%7Bcolor%3A%23428bca%3Bfont%2Dweight%3Anormal%3Bcursor%3Apointer%3Bborder%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%5Bdisabled%5D%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%7Bbackground%2Dcolor%3Atransparent%3B%2Dwebkit%2Dbox%2Dshadow%3Anone%3Bbox%2Dshadow%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%3Aactive%7Bborder%2Dcolor%3Atransparent%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%3Afocus%7Bcolor%3A%232a6496%3Btext%2Ddecoration%3Aunderline%3Bbackground%2Dcolor%3Atransparent%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%5Bdisabled%5D%3Ahover%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%5Bdisabled%5D%3Afocus%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlink%3Afocus%7Bcolor%3A%23999%3Btext%2Ddecoration%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlg%7Bpadding%3A10px%2016px%3Bfont%2Dsize%3A15px%3Bline%2Dheight%3A1%2E33%3Bborder%2Dradius%3A6px%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dsm%7Bpadding%3A5px%2010px%3Bfont%2Dsize%3A11px%3Bline%2Dheight%3A1%2E5%3Bborder%2Dradius%3A3px%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dxs%7Bpadding%3A1px%205px%3Bfont%2Dsize%3A11px%3Bline%2Dheight%3A1%2E5%3Bborder%2Dradius%3A3px%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dblock%7Bdisplay%3Ablock%3Bwidth%3A100%25%3Bpadding%2Dleft%3A0%3Bpadding%2Dright%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dblock%2B%2Ebk%2Dbs%2Dbtn%2Dblock%7Bmargin%2Dtop%3A5px%7D%2Ebk%2Droot%20input%5Btype%3D%22submit%22%5D%2Ebk%2Dbs%2Dbtn%2Dblock%2C%2Ebk%2Droot%20input%5Btype%3D%22reset%22%5D%2Ebk%2Dbs%2Dbtn%2Dblock%2C%2Ebk%2Droot%20input%5Btype%3D%22button%22%5D%2Ebk%2Dbs%2Dbtn%2Dblock%7Bwidth%3A100%25%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%7Bposition%3Arelative%3Bdisplay%3Ainline%2Dblock%3Bvertical%2Dalign%3Amiddle%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%7Bposition%3Arelative%3Bfloat%3Aleft%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2Ebk%2Dbs%2Dactive%7Bz%2Dindex%3A2%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%3Afocus%7Boutline%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%20%2Ebk%2Dbs%2Dbtn%2B%2Ebk%2Dbs%2Dbtn%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%20%2Ebk%2Dbs%2Dbtn%2B%2Ebk%2Dbs%2Dbtn%2Dgroup%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2B%2Ebk%2Dbs%2Dbtn%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2B%2Ebk%2Dbs%2Dbtn%2Dgroup%7Bmargin%2Dleft%3A%2D1px%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dtoolbar%7Bmargin%2Dleft%3A%2D5px%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dtoolbar%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dtoolbar%20%2Ebk%2Dbs%2Dinput%2Dgroup%7Bfloat%3Aleft%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dtoolbar%3E%2Ebk%2Dbs%2Dbtn%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dtoolbar%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dtoolbar%3E%2Ebk%2Dbs%2Dinput%2Dgroup%7Bmargin%2Dleft%3A5px%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%3Anot%28%3Afirst%2Dchild%29%3Anot%28%3Alast%2Dchild%29%3Anot%28%2Ebk%2Dbs%2Ddropdown%2Dtoggle%29%7Bborder%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%3Afirst%2Dchild%7Bmargin%2Dleft%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%3Afirst%2Dchild%3Anot%28%3Alast%2Dchild%29%3Anot%28%2Ebk%2Dbs%2Ddropdown%2Dtoggle%29%7Bborder%2Dbottom%2Dright%2Dradius%3A0%3Bborder%2Dtop%2Dright%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%3Alast%2Dchild%3Anot%28%3Afirst%2Dchild%29%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Ddropdown%2Dtoggle%3Anot%28%3Afirst%2Dchild%29%7Bborder%2Dbottom%2Dleft%2Dradius%3A0%3Bborder%2Dtop%2Dleft%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%7Bfloat%3Aleft%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%3Anot%28%3Afirst%2Dchild%29%3Anot%28%3Alast%2Dchild%29%3E%2Ebk%2Dbs%2Dbtn%7Bborder%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%3Afirst%2Dchild%3E%2Ebk%2Dbs%2Dbtn%3Alast%2Dchild%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%3Afirst%2Dchild%3E%2Ebk%2Dbs%2Ddropdown%2Dtoggle%7Bborder%2Dbottom%2Dright%2Dradius%3A0%3Bborder%2Dtop%2Dright%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%3Alast%2Dchild%3E%2Ebk%2Dbs%2Dbtn%3Afirst%2Dchild%7Bborder%2Dbottom%2Dleft%2Dradius%3A0%3Bborder%2Dtop%2Dleft%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%7Boutline%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%2B%2Ebk%2Dbs%2Ddropdown%2Dtoggle%7Bpadding%2Dleft%3A8px%3Bpadding%2Dright%3A8px%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%2Dlg%2B%2Ebk%2Dbs%2Ddropdown%2Dtoggle%7Bpadding%2Dleft%3A12px%3Bpadding%2Dright%3A12px%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%7B%2Dwebkit%2Dbox%2Dshadow%3Ainset%200%203px%205px%20rgba%280%2C0%2C0%2C0%2E125%29%3Bbox%2Dshadow%3Ainset%200%203px%205px%20rgba%280%2C0%2C0%2C0%2E125%29%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Dbs%2Dbtn%2Dlink%7B%2Dwebkit%2Dbox%2Dshadow%3Anone%3Bbox%2Dshadow%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%20%2Ebk%2Dbs%2Dcaret%7Bmargin%2Dleft%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dlg%20%2Ebk%2Dbs%2Dcaret%7Bborder%2Dwidth%3A5px%205px%200%3Bborder%2Dbottom%2Dwidth%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropup%20%2Ebk%2Dbs%2Dbtn%2Dlg%20%2Ebk%2Dbs%2Dcaret%7Bborder%2Dwidth%3A0%205px%205px%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%7Bdisplay%3Ablock%3Bfloat%3Anone%3Bwidth%3A100%25%3Bmax%2Dwidth%3A100%25%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%3E%2Ebk%2Dbs%2Dbtn%7Bfloat%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2B%2Ebk%2Dbs%2Dbtn%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2B%2Ebk%2Dbs%2Dbtn%2Dgroup%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%2B%2Ebk%2Dbs%2Dbtn%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%2B%2Ebk%2Dbs%2Dbtn%2Dgroup%7Bmargin%2Dtop%3A%2D1px%3Bmargin%2Dleft%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%3Anot%28%3Afirst%2Dchild%29%3Anot%28%3Alast%2Dchild%29%7Bborder%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%3Afirst%2Dchild%3Anot%28%3Alast%2Dchild%29%7Bborder%2Dtop%2Dright%2Dradius%3A4px%3Bborder%2Dbottom%2Dright%2Dradius%3A0%3Bborder%2Dbottom%2Dleft%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%3Alast%2Dchild%3Anot%28%3Afirst%2Dchild%29%7Bborder%2Dbottom%2Dleft%2Dradius%3A4px%3Bborder%2Dtop%2Dright%2Dradius%3A0%3Bborder%2Dtop%2Dleft%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%3Anot%28%3Afirst%2Dchild%29%3Anot%28%3Alast%2Dchild%29%3E%2Ebk%2Dbs%2Dbtn%7Bborder%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%3Afirst%2Dchild%3Anot%28%3Alast%2Dchild%29%3E%2Ebk%2Dbs%2Dbtn%3Alast%2Dchild%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%3Afirst%2Dchild%3Anot%28%3Alast%2Dchild%29%3E%2Ebk%2Dbs%2Ddropdown%2Dtoggle%7Bborder%2Dbottom%2Dright%2Dradius%3A0%3Bborder%2Dbottom%2Dleft%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Dvertical%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%3Alast%2Dchild%3Anot%28%3Afirst%2Dchild%29%3E%2Ebk%2Dbs%2Dbtn%3Afirst%2Dchild%7Bborder%2Dtop%2Dright%2Dradius%3A0%3Bborder%2Dtop%2Dleft%2Dradius%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Djustified%7Bdisplay%3Atable%3Bwidth%3A100%25%3Btable%2Dlayout%3Afixed%3Bborder%2Dcollapse%3Aseparate%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Djustified%3E%2Ebk%2Dbs%2Dbtn%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Djustified%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%7Bfloat%3Anone%3Bdisplay%3Atable%2Dcell%3Bwidth%3A1%25%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2Djustified%3E%2Ebk%2Dbs%2Dbtn%2Dgroup%20%2Ebk%2Dbs%2Dbtn%7Bwidth%3A100%25%7D%2Ebk%2Droot%20%5Bdata%2Dbk%2Dbs%2Dtoggle%3D%22buttons%22%5D%3E%2Ebk%2Dbs%2Dbtn%3Einput%5Btype%3D%22radio%22%5D%2C%2Ebk%2Droot%20%5Bdata%2Dbk%2Dbs%2Dtoggle%3D%22buttons%22%5D%3E%2Ebk%2Dbs%2Dbtn%3Einput%5Btype%3D%22checkbox%22%5D%7Bdisplay%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dcaret%7Bdisplay%3Ainline%2Dblock%3Bwidth%3A0%3Bheight%3A0%3Bmargin%2Dleft%3A2px%3Bvertical%2Dalign%3Amiddle%3Bborder%2Dtop%3A4px%20solid%3Bborder%2Dright%3A4px%20solid%20transparent%3Bborder%2Dleft%3A4px%20solid%20transparent%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%7Bposition%3Arelative%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%3Afocus%7Boutline%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%7Bposition%3Aabsolute%3Btop%3A100%25%3Bleft%3A0%3Bz%2Dindex%3A1000%3Bdisplay%3Anone%3Bfloat%3Aleft%3Bmin%2Dwidth%3A160px%3Bpadding%3A5px%200%3Bmargin%3A2px%200%200%3Blist%2Dstyle%3Anone%3Bfont%2Dsize%3A12px%3Bbackground%2Dcolor%3A%23fff%3Bborder%3A1px%20solid%20%23ccc%3Bborder%3A1px%20solid%20rgba%280%2C0%2C0%2C0%2E15%29%3Bborder%2Dradius%3A4px%3B%2Dwebkit%2Dbox%2Dshadow%3A0%206px%2012px%20rgba%280%2C0%2C0%2C0%2E175%29%3Bbox%2Dshadow%3A0%206px%2012px%20rgba%280%2C0%2C0%2C0%2E175%29%3Bbackground%2Dclip%3Apadding%2Dbox%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%2Ebk%2Dbs%2Dpull%2Dright%7Bright%3A0%3Bleft%3Aauto%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%20%2Ebk%2Dbs%2Ddivider%7Bheight%3A1px%3Bmargin%3A7%2E5px%200%3Boverflow%3Ahidden%3Bbackground%2Dcolor%3A%23e5e5e5%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%3Eli%3Ea%7Bdisplay%3Ablock%3Bpadding%3A3px%2020px%3Bclear%3Aboth%3Bfont%2Dweight%3Anormal%3Bline%2Dheight%3A1%2E42857143%3Bcolor%3A%23333%3Bwhite%2Dspace%3Anowrap%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%3Eli%3Ea%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%3Eli%3Ea%3Afocus%7Btext%2Ddecoration%3Anone%3Bcolor%3A%23262626%3Bbackground%2Dcolor%3A%23f5f5f5%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%3E%2Ebk%2Dbs%2Dactive%3Ea%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%3E%2Ebk%2Dbs%2Dactive%3Ea%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%3E%2Ebk%2Dbs%2Dactive%3Ea%3Afocus%7Bcolor%3A%23fff%3Btext%2Ddecoration%3Anone%3Boutline%3A0%3Bbackground%2Dcolor%3A%23428bca%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%3E%2Ebk%2Dbs%2Ddisabled%3Ea%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%3E%2Ebk%2Dbs%2Ddisabled%3Ea%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%3E%2Ebk%2Dbs%2Ddisabled%3Ea%3Afocus%7Bcolor%3A%23999%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%3E%2Ebk%2Dbs%2Ddisabled%3Ea%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%3E%2Ebk%2Dbs%2Ddisabled%3Ea%3Afocus%7Btext%2Ddecoration%3Anone%3Bbackground%2Dcolor%3Atransparent%3Bbackground%2Dimage%3Anone%3Bfilter%3Aprogid%3ADXImageTransform%2Ebk%2Dbs%2DMicrosoft%2Ebk%2Dbs%2Dgradient%28enabled%20%3D%20false%29%3Bcursor%3Anot%2Dallowed%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dopen%3E%2Ebk%2Dbs%2Ddropdown%2Dmenu%7Bdisplay%3Ablock%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dopen%3Ea%7Boutline%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%2Dright%7Bleft%3Aauto%3Bright%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%2Dleft%7Bleft%3A0%3Bright%3Aauto%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dheader%7Bdisplay%3Ablock%3Bpadding%3A3px%2020px%3Bfont%2Dsize%3A11px%3Bline%2Dheight%3A1%2E42857143%3Bcolor%3A%23999%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropdown%2Dbackdrop%7Bposition%3Afixed%3Bleft%3A0%3Bright%3A0%3Bbottom%3A0%3Btop%3A0%3Bz%2Dindex%3A990%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dpull%2Dright%3E%2Ebk%2Dbs%2Ddropdown%2Dmenu%7Bright%3A0%3Bleft%3Aauto%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropup%20%2Ebk%2Dbs%2Dcaret%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dnavbar%2Dfixed%2Dbottom%20%2Ebk%2Dbs%2Ddropdown%20%2Ebk%2Dbs%2Dcaret%7Bborder%2Dtop%3A0%3Bborder%2Dbottom%3A4px%20solid%3Bcontent%3A%22%22%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Ddropup%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%2C%2Ebk%2Droot%20%2Ebk%2Dbs%2Dnavbar%2Dfixed%2Dbottom%20%2Ebk%2Dbs%2Ddropdown%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%7Btop%3Aauto%3Bbottom%3A100%25%3Bmargin%2Dbottom%3A1px%7D%40media%28min%2Dwidth%3A768px%29%7B%2Ebk%2Droot%20%2Ebk%2Dbs%2Dnavbar%2Dright%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%7Bleft%3Aauto%3Bright%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dnavbar%2Dright%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%2Dleft%7Bleft%3A0%3Bright%3Aauto%7D%7D%2Ebk%2Droot%20%2Ebk%2Dplot%3Aafter%2C%2Ebk%2Droot%20%2Ebk%2Dcanvas%2Dwrapper%3Aafter%2C%2Ebk%2Droot%20%2Ebk%2Dsidebar%3Aafter%2C%2Ebk%2Droot%20%2Ebk%2Dbox%3Aafter%7Bcontent%3A%22%20%22%3Bheight%3A0%3Bdisplay%3Ablock%3Bclear%3Aboth%7D%2Ebk%2Droot%20%2Ebk%2Dcanvas%2Dwrapper%20%2Ebk%2Dresize%2Dpopup%7Bposition%3Aabsolute%3Bleft%3A0%3Btop%3A0%3Bwidth%3A40px%3Bheight%3A40px%3Boverflow%3Ahidden%3Bbackground%2Dimage%3Aurl%28data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1%2B%2FAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAEnSURBVEiJzZXBioQwDIb%2FXQuF6U3wCRSEvv8zeFOoB2%2B%2BQD14aqHSOntYtthxdHesDptTk4Z%2BhKR%2FPqqquuNi%2B7wa8DYIWTplWSJN0yDBGAMhBJxzhyFBJY8AACCErGKv2u4L1lp0XRdVBfBLTwghuN1uUYBNiDHGn4uiQJZl50GmaYJSCm3bou%2F700BBT4QQAL57IaUEAOR57kEAMAxDHMRaG1wuQc45aK1fBqwgz%2BwHpJSCUuoayBJ01P6%2FdjHG%2FjR1hzWDMQbOuZedvak7XAljzAMe%2FxGlFEmSeP9wJVv%2FSGsNzjmcc2iaJg6yBbLWghASqHf0dEkpAwl6thpOGWGl1O46iIZQSsE5Dxp9OsQ5h3meV%2FFxHP05erdaa1HX9W7OW2TlC31ceRWbb5%2BAAAAAAElFTkSuQmCC%29%3Bbackground%2Dposition%3Abottom%20right%3Bbackground%2Drepeat%3Ano%2Drepeat%3Bcursor%3Ase%2Dresize%7D%2Ebk%2Droot%20%2Ebk%2Dcanvas%2Dwrapper%3Ahover%20%2Ebk%2Dresize%2Dpopup%7Bdisplay%3Ablock%7D%2Ebk%2Droot%20%2Ebk%2Dlogo%7Bmargin%3A5px%3Bposition%3Arelative%3Bdisplay%3Ablock%3Bbackground%2Drepeat%3Ano%2Drepeat%7D%2Ebk%2Droot%20%2Ebk%2Dlogo%2Egrey%7Bfilter%3Aurl%28%22data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnPjxmaWx0ZXIgaWQ9J2dyYXlzY2FsZSc%2BPGZlQ29sb3JNYXRyaXggdHlwZT0nbWF0cml4JyB2YWx1ZXM9JzAuMzMzMyAwLjMzMzMgMC4zMzMzIDAgMCAwLjMzMzMgMC4zMzMzIDAuMzMzMyAwIDAgMC4zMzMzIDAuMzMzMyAwLjMzMzMgMCAwIDAgMCAwIDEgMCcvPjwvZmlsdGVyPjwvc3ZnPg%3D%3D%22%29%3Bfilter%3Agray%3B%2Dwebkit%2Dfilter%3Agrayscale%28100%25%29%7D%2Ebk%2Droot%20%2Ebk%2Dlogo%2Dnotebook%7Bdisplay%3Ainline%2Dblock%3Bvertical%2Dalign%3Amiddle%3Bmargin%2Dright%3A5px%7D%2Ebk%2Droot%20%2Ebk%2Dlogo%2Dsmall%7Bwidth%3A20px%3Bheight%3A20px%3Bbackground%2Dimage%3Aurl%28data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1%2B%2FAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAOkSURBVDiNjZRtaJVlGMd%2F1%2F08zzln5zjP1LWcU9N0NkN8m2CYjpgQYQXqSs0I84OLIC0hkEKoPtiH3gmKoiJDU7QpLgoLjLIQCpEsNJ1vqUOdO7ppbuec5%2BV%2Brj4ctwzd8IIbbi6u%2B8f1539dt3A78eXC7QizUF7gyV1fD1Yqg4JWz84yffhm0qkFqBogB9rM8tZdtwVsPUhWhGcFJngGeWrPzHm5oaMmkfEg1usvLFyc8jLRqDOMru7AyC8saQr7GG7f5fvDeH7Ej8CM66nIF%2B8yngt6HWaKh7k49Soy9nXurCi1o3qUbS3zWfrYeQDTB%2FQj6kX6Ybhw4B%2BbOYoLKCC9H3Nu%2FleUTZ1JdRWkkn2ldcCamzrcf47KKXdAJllSlxAOkRgyHsGC%2FzRday5Qld9DyoM4%2Fq%2FrUoy%2FCXh3jzOu3bHUVZeU%2BDEn8FInkPBFlu3%2BnW3Nw0mk6vCDiWg8CeJaxEwuHS3%2Bz5RgY%2BYBR6V1Z1nxSOfoaPa4LASWxxdNp%2BVWTk7%2B4vzaou8v8PN%2Bxo%2BKY2xsw6une2frhw05CTYOmQvsEhjhWjn0bmXPjpE1%2BkplmmkP3suftwTubK9Vq22qKmrBhpY4jvd5afdRA3wGjFAgcnTK2s4hY0%2FGPNIb0nErGMCRxWOOX64Z8RAC4oCXdklmEvcL8o0BfkNK4lUg9HTl%2BoPlQxdNo3Mg4Nv175e%2F1LDGzZen30MEjRUtmXSfiTVu1kK8W4txyV6BMKlbgk3lMwYCiusNy9fVfvvwMxv8Ynl6vxoByANLTWplvuj%2FnF9m2%2BPDtt1eiHPBr1oIfhCChQMBw6Aw0UulqTKZdfVvfG7VcfIqLG9bcldL%2F%2BpdWTLxLUy8Qq38heUIjh4XlzZxzQm19lLFlr8vdQ97rjZVOLf8nclzckbcD4wxXMidpX30sFd37Fv%2FGtwwhzhxGVAprjbg0gCAEeIgwCZyTV2Z1REEW8O4py0wsjeloKoMr6iCY6dP92H6Vw%2FoTyICIthibxjm%2FDfN9lVz8IqtqKYLUXfoKVMVQVVJOElGjrnnUt9T9wbgp8AyYKaGlqingHZU%2FuG2NTZSVqwHQTWkx9hxjkpWDaCg6Ckj5qebgBVbT3V3NNXMSiWSDdGV3hrtzla7J%2BduwPOToIg42ChPQOQjspnSlp1V%2BGjdged7%2B8UN5CRAV7a5EdFNwCjEaBR27b3W890TE7g24NAP%2FmMDXRWrGoFPQI9ls%2FMWO2dWFAar%2FxcOIImbbpA3zgAAAABJRU5ErkJggg%3D%3D%29%7D%2Ebk%2Droot%20%2Ebk%2Dlogo%2Dmedium%7Bwidth%3A35px%3Bheight%3A35px%3Bbackground%2Dimage%3Aurl%28data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAYAAAAe2bNZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK6wAACusBgosNWgAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAf9SURBVFiFvZh7cFTVHcc%2F59y7793sJiFAwkvAYDRqFWwdraLVlj61diRYsDjqCFbFKrYo0CltlSq1tLaC2GprGIriGwqjFu10OlrGv8RiK%2FIICYECSWBDkt3s695zTv9IAtlHeOn0O7Mzu797z%2B%2F3Ob%2Fz%2Bp0VfBq9doNFljuABwAXw2PcvGHt6bgwxhz7Ls4YZNVXxxANLENwE2D1W9PAGmAhszZ0%2FX9gll5yCbHoOirLzmaQs0F6F8QMZq1v%2F8xgNm7DYwwjgXJLYL4witQ16%2Bsv%2FU9HdDmV4WrKw6B06cZC%2FRMrM4MZ7xz61DAbtzEXmAvUAX4pMOVecg9%2FMFFu3j3Gz7gQBLygS2RGumBkL0cubiFRsR3LzVBV1UMk3IrW73PT9C2lYOwhQB4ClhX1AuKpjLcV27oEjyUpNUJCg1CvcejykWTCXyQgzic2HIIBjg3pS6%2BuRLKAhumZvD4U%2Btq0jTrgkVKQQtLekfTtxIPAkhTNF6G7kZm7aPp6M9myKVQEoaYaIhEQYvD781DML%2FRfBGNZXAl4irJiwBa07e%2Fy7cQnBaJghIX6ENl2GR%2FfGCBoz6cm5qeyEqQA5ZYA5x5eeiV0Qph4gjFAUSwAr6QllQgcxS%2FJm25Cr2Tmpsk03XI9NfI31FTZBEOgVOk51adqDBNPCNPSRlkiDXbBEwOU2WxH%2BI7itQZ62g56OjM33suq1YsZHVtGZSUI2QdyYgkgOthQNIF7BIGDnRAJgJSgj69cUx1gB8PkOGwL4E1gPrM27gIg7NlGKLQApc7BmEnAxP5g%2Frw4YqBrCDB5xHkw5rdR%2F1qTrN%2FhKNo6YUwVDNpFsnjYS8RbidBPcPXFP6R6yfExuOXmN4A3jv1%2B8ZUwgY9D2OWjUZE6lO88jDwHI8ZixGiMKSeYTBamCoDk6kDAb6y1OcH1a6KpD%2FfZesoFw5FlIXAVCIiH4PxrV%2Bp2npVDToTBmtjY8t1swh2V61E9KqWiyuPEjM8dbfxuvfa49Zayf9R136Wr8mBSf%2FT7bNteA8zwaGEUbFpckWwq95n59dUIywKl2fbOIS5e8bWSu0tJ1a5redAYfqkdjesodFajcgaVNWhXo1C9SrkN3Usmv3UMJrc6%2FDDwkwEntkEJLe67tSLhvyzK8rHDQWleve5CGk4VZEB1r%2B5bg2E2si%2BY0QatDK6jUVkX5eg2YYlp%2B%2BZM%2BrfMNYamAj8Y7MAVWFqaR1f%2Ft2xzU4IHjybBtthzuiAASqv7jTF7jOqDMAakFHgDNsFyP%2BFhwZHBmH9F7cutIYkQCylYYv1AZSqsn1%2F%2BbX51OMMjPSl2nAnM7hnjOx2v53YgNWAzHM9Q%2F9l0lQWPSCBSyokAtOBC1Rj%2Bw%2F1Xs%2BSTDp4%2FE5g7Rs2zm2%2BoeVd7PUuHKDf6A4r5EsPT5K3gfCnBXNUYnvGzb%2BKcCczYYWOnLpy4eOXuG2oec0PBN8XQQAnpvS35AvAykr56rWhPBiV4MvtceGLxk5Mr6A1O8IfK7rl7xJ0r9kyumuP4fa0lMqTBLJIAJqEf1J3qE92lMBndlyfRD2YBghHC4hlny7ASqCeWo5zaoDdIWfnIefNGTb9fC73QDfhyBUCNOxrGPSUBfPem9us253YTV%2B3mcBbdkUYfzmHiLqZbYdIGHHON2ZlemXouaJUOO6TqtdHEQuXYY8Yt%2BEbDgmlS6RdzkaDTv2P9A3gICiq93sWhb5mc5wVhuU3Y7m5hOc3So7qFT3SLgOXHb%2FcyOfMn7xROegoC%2FPTcn3v8gbKPgDopJFk3R%2FuBPWQiwQ%2B2%2FGJevRMObLUzqe%2FsaJjQUQTTftEVMW9tWxPgAocwcj9abNcZe7s%2B6t2R2xXZG7zyYLp8Q1PiRBBHym5bYuXi8Qt%2B%2FLvGu9f%2F5YDAxABsaRNPH6Xr4D4Sk87a897SOy9v%2FfKwjoF2eQel95yDESGEF6gEMwKhLwKus3wOVjTtes7qzgLdXTMnNCNoEpbcrtNuq6N7Xh%2F%2Beqcbj94xQkp7mdKpW5XbtbR8Z26kgMCAf2UU5YEovRUVRHbu2b3vK1UdDFkDCyMRQxbpdv8nhKAGIa7QaQedzT07fFPny53R738JoVYBdVrnsNx9XZ9v33UeGO%2BAA2MMUkgqQ5UcdDLZSFeVgONnXeHqSAC5Ew1BXwko0D1Zct3dT1duOjS3MzZnEUJtBuoQAq3SGOLR4ekjn9NC5nVOaYXf9lETrUkmOJy3pOz8OKIb2A1cWhJCCEzOxU2mUPror%2B2%2FL3yyM3pkM7jTjr1nBOgkGeyQ7erxpdJsMAS9wb2F9rzMxNY1K2PMU0WtZV82VU8Wp6vbKJVo9Lx%2F%2B4cydORdxCCQ%2FkDGTZCWsRpLu7VD7bfKqL8V2orKTp%2FPtzaXy42jr6TwAuisi%2B7JolUG4wY%2B8vyrISCMtRrLKWpvjAOqx%2FQGhp0rjRo5xD3x98CWQuOQN8qumRMmI7jKZPUEpzNVZsj4Zbaq1to5tZZsKIydLWojhIXrJnES79EaOzv3du2NytKuxzJKAA6wF8xqEE8s2jo%2F1wd%2FkhslQGxd81Zg62Bbp31XBH%2BiETt7Y3ELA0iU6iGDlQ5mexe0VEx4a3x8V1AaYwFJgTiwaOsDmeK2J8nMUOqsnB1A%2BdcA04ucCYt0urkjmflk9iT2v30q%2FgZn5rQPvor4n9Ou634PeBzoznes%2Fiot%2F7WnClKoM%2F%2BzCIjH5kwT8ChQjTHPIPTjFV3PpU%2FHx%2BDM%2FA9U3IXI4SPCYAAAAABJRU5ErkJggg%3D%3D%29%7D%2Ebk%2Droot%20%2Ebk%2Dlogo%2Dlarge%7Bwidth%3A75px%3Bheight%3A75px%3Bbackground%2Dimage%3Aurl%28data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAYAAAA4TnrqAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1%2B%2FAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAABNHSURBVHiczZx5nFxVlce%2F576q6uqq6q7e0t0habIRgQScfEBAJ4MLo4gogY9CAkkIApElCqOCI8IAKriMg6MwoqiBgERMIJEECCoIKKIYWcImS9KEJCxJOr2kt1rfu2f%2BeN2d7qS7tu4Efp9Pf7rqvvvOOfV759577r3nPuG9hF%2FPmQXmZEQ%2FCkwEtqLyV8Q%2ByPz7nn03TFLVgc%2FybhiwD%2B469WiQLwOfAmqHqbEb1bWo%2FJCFa148kKa9t8hafuqVGLkWCBVQuxvVy1mw9hf726x%2BvDfIOqMxzCdm3U4sPK%2Foe1V%2FwIK1X98PVg2j6t0m63uzx2O95YyLn0BlFKwtRcrPmb%2FmorE2bW8MJsvsb2X74PsfmoToAwScEwgFAM17ywi4kLtO%2B78xtCwvDixZPzjuGMQ8CRxFwIFgALRksgC%2BxF2n%2FWyMrMuLMWmG9zxLRQjGIYxjGFc5tJLsOX8%2B%2FIj1LbX%2Fg2gDVqE8BI3VYEdFVj9uYf6ai8dC0N4Y3AwDpQpZs4GZYjgVmCNwEBAFIsPV3ZXFa4wmo2QDEMr6hcGSVe8L8S7il0sitM66l2Ci1S%2FUXqz2kEgYKmKdTJray%2BlzukejpmiLVz9NNBjgOoRLASdffQGs0tOTDbyO0WkDF8rGiCwnk6FnQged0xcRTC4aKPcdopfaWkNNdRtepouVq5pRfQbVFZw1d2Oxqorqs377DNXBIL9H%2BAoFENVvc9CwvTVV9iLSN%2BoZ6euvijV3L5hsM11Nt9F%2BpIs6DAi0FkSgujpK%2FbhygsGJwAxgDiLfwpiXWLnqTn5z96Si1BVacd0GAo7DauDfilEAINDd3FnxGkb9Dj3ggFMQ1yPDZO6h9cjraX%2F%2FSYidgFhftrVQXg4NDVAV90nbdxAJAgsx5klWrPpowSoLregKF4vwsULrD4Zj2NKbLOtA1H%2F4AQeMKXUk9Ah2XcimT19BYuJ1ONnJgE%2BSMVBTA%2FXjIFzml%2BXWMR7ht6y458hCFBdE1r0bKBfhskLqDocywyuo%2BLpUIRQAp6SBeBOBnuP5%2B9V3E3bvx7hNA94UiUBjA8QrfW8qPNCtRmQZd63MO90qiCwHPgYU1b4HI2R4hUxwC4r%2F9EuJr1RvoXzzUTx30RYan38O0RkD3lTb503BYCHeNByOxphT8lUqrBkaPl2s9sEYF2ETGccftgUIOsV07i2ozmfB2ot5%2Bgaoeesh0ElDvKmy0q85qgBXFuarURBZIkwZhRWp2nq2EvKCoOAU41n6R6x%2BhAVrf8MNP6qi%2BuUHsfYIHGcsvGkohKNZsbw8V5W8ZH34mwQzLvVSeqy%2FE2gj4AZR%2FP4qv7As8A3a3E%2BycO2r%2FPDGCpQ%2FYPV4YrE93qQ6epL2oAYNTc9VIW9kOLOJirdaiU%2Bq952iBNteF8Hlu24YFEJBvymOLOdFVJewYO0TACy5KkA2u5RQ6FiqqiAW9WuVtlKRC2WINOSqkNezGuLYzl681i4%2FliwWqmz1NXm9gBJ0GHlKqrcAsweIOuPcIJNqfkUsNpfGBqiIjbU3DUYAqMlXISdCIeJA3a5OqIxAtAy8Ih6qgL8M7Ho7CQVdAk5wnx%2Br%2Bg7IpSxYu3qg7MabY4isJBY9mVjMLxt7b9obORXk9SwRykWIWgs7OsDT4pYqFPw5mKcOASME9oncH%2FY78TWrh5QKh1MVL6eiYiOqqf3kTUUhr2dpX3dsDHQloLUTGqvALewhewov%2BZ8sOI7imP5lmTToNSTlBs6%2Fb19pl37xKeAElq%2BqxrF1iEwGZoAciXA40AjUAZUFWTIGyEvWG0HKJmcJO%2Fh9VstuiIUhEs7fKlR5Wyy7AD9iLws6fReeBZawYO36vBYuPL0D6AA2AQ8PlC%2F%2FdTmB0DRgKiJTQN8HchjooSCNFDjRLwZ5yTq%2FI3Tc47EMGfG1uxa2d8DUhpHmqHsgwitzjiLha3KEsqBB9Zdk7OWce3%2FXqCxfuCCJ77UvDZQtXSZURCpQUw8cBnIEwmHAwYP%2BgiMLzd3Wc5KVWhaZH0o5N0UwyTWxlDUQdQx0JWFXFzRUg%2BflUN3fXwGEAq9izGc4a826XDpHhcXnKtDV99cMPDDk%2BjNX19E2oZHuimNxAx9AZCb%2BwmUVSB0BN5NL%2FIhkpZZFFojIHR7qHJkKJjyrq1dVpY%2BPWaYYgZZOqCz3V4e9kZ%2FHawOfvvbEDmC%2FEHXQT1%2BemOnNzPLSWqtWRVURI2qMGHHMeFQCoiYrv5OsqHFVbJ2KdYCXbTDb7oYyh9hAts64gY92wX0j6RmWrNSyyJlGzJ2AKJAVjcxKBz%2Byrce7fkPEvb5MaHA92L4bJtePGGMqyhtjQ0duROJl4Ug8fKebtlVu2sXLeHiuxctarKeIKCoW6V%2FpGDSciw0QSgZADYj9cu33n9vYdsWsW4bTs0%2FokFoWWdBP1ODyrGHSnN7yU7Ien3LhZcdAZy%2B0dvmR%2FTDoPlBkNS%2BY1uyEnEvClSFi4yLEJ1RQNaGCqgkx4uOjRGvKCUWCmIAgBtQq1lPUKqqKiqLGQ0UF5KfV39swZzg9QwhJLYvMM2LuIkf8FczKFytmdq%2B8so1%2FoEw1BqaPh7LQPqPj5myGmZ87htRYEFIIDl259XaEc6Av3hEZcHtVnxwvY3EzLm7a4mU9vIz%2FfwiEXuvZE3f%2F11F%2FG3ZHOn179GhB%2FgLknHkDGsw4x5w%2BuXPnB9I86lmmxyMwpWHorpYqT5w6i%2BNH%2BfuLwrTlr9cEQoH1wCEj1RERMH0bKZ5irWJdi5tyyaY9vIyHdS3W1R29HcmTkv993PP99xqA5K3hqKgsIz9RAJINeatXvVjX3g3HO8ITnYl9m6MIL5T6o0vF6wuntVu155Njmq6qqOc3QwQcxxAMByivClPZGKW6qZKqCRXED4o1jp9R99tD79l2UP%2B9BsAxznkIBa1D92FStib1s%2B%2Bewk5VTjPCUzt3QzLjR%2Fq%2BVRS91TQW2DRvyuOKfqegyoOap1qfRLWKE3QIRYOUxUJTQX%2FaX92kbi2vQuS8oq0SFqWXRRddeSptBj6RdvndO%2B0MPFPlwHtWP1Kkvqmqfyn1%2FsEECnLqoXdvXQhgjGOOB95filARuTF1W2z6FXPo3LaLOZ29rGjtBseQQXmrVGNHi21zD%2FOsp58Hdo%2BFPBG57JCVWyoMyL9SeoJIlRGWJW6NOUu%2FgHv1HSxo6%2BbB7iTJujitY2FoqWieP2Wzqn51jMTNckTOMKo0jUqMMNsxXAvAvdi3Wjm9tZPzurpIjoWVo8HGeZOXKXrnGImbJ%2BllsZtFWDIqMUpW0U%2BUndv75zEybMww7e7N1QGcZ2BUmy4Au4zAk6O2SAiKyM2p2yoO2NpSLnx1%2BlUnXdB0aRPA63OndljPfp48q6AFYJxR1T8B20YpCGCmiD2gmXgjoSZas7giXPH4%2FPrzDgfYdNaUx1X1%2BtFJ1S2m7LzetzTHTLsYiMiizO2x%2BWMhq1R8%2B7DrTNAJ1MXL45MrwhX3LWq8cBpAWtPXKTxRqlyFJ%2FrzD24CesfEWuVHqdvKp46JrBIQCEerrdpJZaEyqiPVh4QCwYcumHjJkVvPPNRV9EL8ta5i4aGy3ACUndu7yaq9CsEPIkaTPCnUG%2BMs7bmtesyXdQs0oB5ostZSFa0iWhadaoXHvtB0yfGb5k5%2B2ap%2BpViJCus8Yx4ZiK%2FC5yZu1KS9R3usvx%2FcT1z%2Fn1AMiR8LSuaA5KnvDRXbRN%2F6uyDUxGpwjKkVZM1F4y%2F60KZ5k29TkbuLEJlVa7%2FVfPpEd0gwmlqX%2BLzX4v7R25HFbs9iW1x0t4cmFXXVH0%2BMFESeiHw7fXvsgK469On9YP9nq5ZwIEx1eTWK1miw7KEl9ReeuvGMg%2BepSHMh8hS9fOO8yc%2FCXpF7%2FH4S6tqFePYFTSnaY7HtHnaAvCy21UW7PDRpwWMPaYM90Icjyi8SS8MHNJwQlSH5CopSFamiPFSOVRvzwuFV%2Fxmcd%2BLbH2yai0g2j7ibXjtj0k39X%2FaZ5kSvd3ci%2BjkMu4YQ4OF7WKeLbfWwLS7eO1mfyA4P7bJoSsFlMHmHOcHATXvr2K8Qjhj8VVUREWqiNRg%2Fny7Q2djw4JKDP9vYW199lY6Qk6Dw89fmTvqPwWXDzgnLr3GbrbWfVHQXjgWjezzHkT13eYqmFN3tYXe52B1ZvB1ZvO1ZbKuH9lhI23NSS6N5c5%2FGAtf8y3fiDHOqzKqlPFhOdaQaqxZEnJ7xB635zJnfkGyk%2FA9qhtKg6E82zp20z1GXEXd3ot90N%2FReFb5I02W%2FwrFtUpZ9XkLuDsAiqhjdLtCDNSG1EkQlgJIm472JxdFeD%2FXJDWrUvD56KvIj7JS%2FD6gf7pqqEo%2FESWQSJLNJCARCgXTmO8f%2B4Pa7%2FvG1c94MpDNNxvUAfr5x7uRLhpORc9%2Bw9%2BEjHg5N6ehEqEKZoWg9Vl5Q2KiJsiczOyu2jn96%2Fbu2FNMSO3OWZ3sC4xMPPA0gKk0IZcPVVRQjhppYDdt3b0dR3HAoMO6lTXNnLF%2B3c9PnPo4XcH7W%2FNmJI86Tc5IVnLIrjHEEqESoFJiG0eMEoDJFeWWK3YdMfRNhm8JWVDcBL4C%2Bqso7mUymu%2FHed3Jsw5aO9qoLL7Re7w3JTMs3gacBVPRQyTFE9zfHqkgV7T3tiBGy5eHwwX96elKoJ3H%2Fvfd%2FMeeCQu7teykguhKagCaB2Xsy%2BsSCdoTD4X%2FuPmtKM8g%2FVfUtYKOqt6Vm5baSF%2BVaK89vMMb8WOBMqxlct71i0OWcmXvge1g8EieRTpByUxgx2GCApseeeizfvWN4gGYIjIjUAh8G%2BTD07apAj0igveOsqTtR3Qg8L8Ir1upWYGfNyi0tuYS2Vy4%2BESO3AFMQg%2Bt1ASoA35v1Y%2BMnheSGquKIQ02shh2dO1AUQUhVV7bTk%2Fve%2FUXWSIgBMYGDETkGWABgjICwbffcKW96vdk7ate99cvBN7VULg4GhOsR%2BRoDni5Ym0Dpa%2BWiFcBhhRhh1RItixIvj9OeaMcRBwrg4kCTNTyMoGnvYLc3Hde099TgS23xxYeLyE%2BAE%2FaUCqoWz0tC3xaJhzvBIZAzzXEwrPpzx0QmQdpNI8g7ec3Mc33%2FHgvu6%2BO8rjSZtsTr6fbEcfWPtjzXf7ktvvhiEfk7Q4jym7S1CaxNIQSMX2ZmFaNaVXGMQ22sFhFB0bz9aD7PSgBjP5r1ba1rxsXrzOBl3Dc81z1p4vrOZoC2qsUHifK%2FiIxw2NzB2hTWpkCc8SgIganFLoZaa4mEIsTL49rS1ZJ30yZnheoVW7sZo%2B2kAYiAgtedJtuWxGay3cDZBz3R4RNVef6JgvxpZKIAFGsT%2BORI2JfLzFLMsWqpjlRnmmoO7shXt4CcUn1VkJIMGYI%2Bb7IpF68ng2ZcUDoQTmt4bNdf34wsCkWCoWtF5Mr8wiyu1wsYHPUyAKo6odQ%2Bw4jpriyL5T3lWsh%2B4SMl2jDYGt%2BbutK47UmfKJGUBjKfqX%2Bs9fG2qsVHRUNljxZGlN%2FfeF4XIDh42VPmrI%2BP5siMopvTmeSOvD8jryTLOqC0s8VC30jnkm1L4HWn%2Bz3Mw0kvaPhj59%2Fa4ouX9GXvzC5UqGra79xFcHDTkzvfrkMZV5KNgCrPXv3SFfmWa%2FKTVb3yjW2qOmwmXE70901dKbJtCTTr9R%2FRyGhFy8k8vHtde%2BUF94jIzYxwEH14sQbP60HV9b%2Bj1Q3d22YiMuycsDCZ%2BqtC6hW0be9lvWsV%2FWthmgEj2Ey%2FN2X6ksoEjEUj7fND913dFohf8AJGTy9I5hDxBtfrHSDLwxkX8tIfKPlIgfKHbzz71YL2Tgsiq271tqRm9GRFH80tTcAqbmfK75v2eBM4bkKtXBt85OIZWrlzPcL7CtE9FIJisV7vwHeLMSpOMelSg9FmxSs4H6LghJCa1Vu6rJc9GfQaVPdN%2BhDBJl0%2FHOjJDJQB4GRTdDTeF1w%2Fbzah9LcRLXHnR7CaxbMp%2Bs8EKMb05boXizbgs1c9e%2FnLhWsvAe1nTKoXx5wuIv8OTEWp83rStV5v1oJGh5wnFIvZNSVhNh%2FbiZMd7%2Bc%2Flwa%2Fv0rR1f0U4GFU6Q3FNj4wc%2F5E1wQjRgsLSlV5CLVXXPncZRvy1x3Dtxy1njW13HSn49nWRFzKjMWYGCJRQGwo3eC0Ns1wmj%2F0rb7U6VHpEnHIZHbR0%2Fs8IgEC6tISG88j00%2FrdU3AGLXD%2FR5L%2F0EC1ccVXX3lhst%2BX6jOMXm9Sj%2FqfrM5CSSBEeKUTtoqZjeL4y0v5Ahrbgie103%2FM%2FbEIZxJfNfDrnUFDQxHluJa67599fNf3zk63ft7ojwIbfHF80XkDkbxgESC9PQ%2BTyazE5GAp%2FClafpq8WFNEXhX3p9V27n0LlV7dukSBNUsnpcASKnaM%2FY3UXvjgL4%2Fq7bz1hVW9WxKWMnoD0atzWxX7EnT2HjvfjAxJw74m9nqOpcuV9VFQLq4OxVV3exp4tOHsPldyTA88K%2Bxw2%2BSKB%2FHP%2BZWEKz1VgSdcbOn80be4X5%2F4V199eau%2BOJaB5YgcjbD78x4oH9W1VtqO2%2B950DbB%2B%2BFt0nuhfbKL0yyhk8JepIohwApFZ5BdVUy2f34xMzdRTbZscNgsv4fCI1BY5O1DJEAAAAASUVORK5CYII%3D%29%7D%2Ebk%2Droot%20%2Ebk%2Dsidebar%7Bbox%2Dsizing%3Aborder%2Dbox%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbs%2Ddropdown%20a%7Bcolor%3Atransparent%3Bfont%2Dsize%3A0%3Bdisplay%3Ablock%3Bfloat%3Aleft%3Bwidth%3A13px%3Bheight%3A13px%3Bmargin%2Dbottom%3A5px%3Bbackground%2Dimage%3Aurl%28data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6%2BR8AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1%2B%2FAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAGdSURBVCiRXZJPSxtRFMV%2FdyYTunBREASRIkKwddPSjYIL%2Bx2K9plR%2BowR7K7L7vsZutIkZqhO8jZ%2Bh25aQilUkbaUgv2zEOpGpAsZnbld%2BBJC7ubAvYd77uEeYaTaB25bhJqi44Kcq9LYWDOt%2FlxVkQG542ZFaQP3gB6wBLwDFoGfKtQ2qua7qhIAJB1XEeUE9CtSPLCxWQbObGxWEL0P%2Bk2Uk3barQBImrrgWvmE8NnGpgaQpO4OcArM2Nhc%2Bd4e8DCUcL6UwZYIk0WYzw9Zy4CnHm%2B9hNcvJI%2F%2B3GhuJUndR%2BA3yCpoCGQ2NkWfnKQuAMqo5Ih2gakScBeYBj32vE3gw5DqAtBCFGAcuCwBF8CRIFX1SiNf6AGPQXLwSgq7Aq%2BzMGPLrPdNB16h50%2B92uvul4MiWlJ4FZShAZxFebQztL0MHHoEICiiBvCrRJiI31wBvii8zQt9WV9f%2FZek7sjG5lFzvzsWBvJGYA2Ye1599mOQiKTjZlVpCcwA74En%2FUQonIqwaX0ihJFKUlcH6sAE8Bdo2tg0B%2F9S5T8JNaZ11wlT0wAAAABJRU5ErkJggg%3D%3D%29%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%7Bmargin%3A0%3Bpadding%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%3Eli%7Blist%2Dstyle%2Dtype%3Anone%3Bposition%3Arelative%3Bfloat%3Aleft%3Bdisplay%3Ablock%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%3Eli%3Alast%2Dchild%3Aafter%7Bcontent%3A%22%20%22%3Bbackground%2Dcolor%3Alightgray%3Bfloat%3Aleft%3Bheight%3A10px%3Bwidth%3A1px%3Bmargin%3A10px%203px%200%203px%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%7Bpadding%3A10px%208px%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%20li%7Bfloat%3Anone%3Bclear%3Aboth%3Bfont%2Dfamily%3AHelvetica%2Csans%2Dserif%3Bline%2Dheight%3A1%2E5em%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%20li%20input%7Bmargin%2Dright%3A8px%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dtoolbar%2Dbutton%7Bwidth%3A30px%3Bheight%3A28px%3Bpadding%3A5px%3Bborder%3A0%3Bborder%2Dradius%3A0%20%21important%3B%2Dmoz%2Dborder%2Dradius%3A0%20%21important%3B%2Dwebkit%2Dborder%2Dradius%3A0%20%21important%3Bbackground%3Atransparent%20%21important%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dtoolbar%2Dbutton%20%2Ebk%2Dbtn%2Dicon%7Bdisplay%3Ablock%3Bposition%3Arelative%3Bheight%3A16px%3Bmargin%3A0%3Bborder%3A0%3Bbackground%2Dsize%3Acontain%3Bbackground%2Dcolor%3Atransparent%3Bbackground%2Drepeat%3Ano%2Drepeat%3Bbackground%2Dposition%3Acenter%20center%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dtoolbar%2Dbutton%20span%2Etip%7Bdisplay%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dtoolbar%2Dbutton%20span%2Etip%3Abefore%7Bdisplay%3Anone%3Bcontent%3A%22%20%22%3Bposition%3Arelative%3Bwidth%3A100%25%3Bbackground%2Dposition%3Atop%20left%3Bbackground%2Drepeat%3Ano%2Drepeat%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20li%3Ahover%20%2Ebk%2Dtoolbar%2Dbutton%20%2Etip%3Abefore%7Bdisplay%3Ainline%2Dblock%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20li%3A%3Ahover%20%2Ebk%2Dtoolbar%2Dbutton%7Bbackground%3Atransparent%20%21important%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20li%3Ahover%20%2Ebk%2Dtoolbar%2Dbutton%20%2Etip%7Bz%2Dindex%3A100%3Bwhite%2Dspace%3Anowrap%3Bbackground%2Dcolor%3A%23fff%3Bopacity%3A%2E95%3Bborder%3A%23e5e5e5%20solid%201px%3Bdisplay%3Ainline%2Dblock%3Bposition%3Arelative%3Bfloat%3Aleft%3Bpadding%3A5px%2010px%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20li%3Ahover%20%2Ebk%2Dtoolbar%2Dbutton%20%2Etip%3Abefore%7Bdisplay%3Ablock%20%21important%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dabove%20%2Ebk%2Dbutton%2Dbar%2Dlist%20li%3Ahover%20%2Ebk%2Dtoolbar%2Dbutton%20%2Etip%7Btop%3A10px%3Bleft%3A%2D10px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbelow%20%2Ebk%2Dbutton%2Dbar%2Dlist%20li%3Ahover%20%2Ebk%2Dtoolbar%2Dbutton%20%2Etip%7Btop%3A%2D50px%3Bleft%3A%2D10px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dbutton%2Dbar%2Dlist%20li%3Ahover%20%2Ebk%2Dtoolbar%2Dbutton%20%2Etip%7Btop%3A%2D22px%3Bleft%3A26px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%2Dlist%20li%3Ahover%20%2Ebk%2Dtoolbar%2Dbutton%20%2Etip%7Bfloat%3Aright%3Btop%3A%2D22px%3Bleft%3A%2D26px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dabove%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dtoolbar%2Dbutton%2Eactive%7Bborder%2Dbottom%3A2px%20solid%20%2326aae1%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbelow%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dtoolbar%2Dbutton%2Eactive%7Bborder%2Dtop%3A2px%20solid%20%2326aae1%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dtoolbar%2Dbutton%2Eactive%7Bborder%2Dleft%3A2px%20solid%20%2326aae1%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dtoolbar%2Dbutton%2Eactive%7Bborder%2Dright%3A2px%20solid%20%2326aae1%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%3E%2Ebk%2Dtoolbar%2Dbutton%2Eactive%7Bborder%2Dbottom%3A1px%20solid%20%2326aae1%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dabove%2Ebk%2Dtoolbar%2Dnot%2Dsticky%7Bborder%2Dbottom%3A1px%20solid%20%23e5e5e5%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbelow%2Ebk%2Dtoolbar%2Dnot%2Dsticky%7Bborder%2Dtop%3A1px%20solid%20%23e5e5e5%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%2Ebk%2Dtoolbar%2Dnot%2Dsticky%7Bborder%2Dright%3A1px%20solid%20%23e5e5e5%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%2Ebk%2Dtoolbar%2Dnot%2Dsticky%7Bborder%2Dleft%3A1px%20solid%20%23e5e5e5%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dabove%20%2Ebk%2Dbutton%2Dbar%7Btop%3A2px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%7Bleft%3A1px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dabove%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbelow%7Bmargin%3A0%3Bposition%3Aabsolute%3Bright%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dabove%20%2Ebk%2Dlogo%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbelow%20%2Ebk%2Dlogo%7Bfloat%3Aright%3Bmargin%2Dright%3A%2D1px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dabove%20%2Ebk%2Dbutton%2Dbar%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbelow%20%2Ebk%2Dbutton%2Dbar%7Bpadding%3A0%3Bfloat%3Aright%3Bposition%3Arelative%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dabove%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbelow%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%7Bfloat%3Aleft%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dabove%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%5Btype%3D%27help%27%5D%20%2Ebk%2Dtoolbar%2Dbutton%20%2Etip%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbelow%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%5Btype%3D%27help%27%5D%20%2Ebk%2Dtoolbar%2Dbutton%20%2Etip%7Bfloat%3Aright%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dabove%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%2Ebk%2Dbs%2Ddropdown%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbelow%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%2Ebk%2Dbs%2Ddropdown%7Bpadding%3A7px%2010px%200%205px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dabove%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbelow%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%7Bleft%3A%2D120px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%7Bmargin%3A0%3Bposition%3Aabsolute%3Btop%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dlogo%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dlogo%7Bmargin%2Dtop%3A%2D1px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dbutton%2Dbar%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%7Bposition%3Arelative%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dbutton%2Dbar%3Abefore%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%3Abefore%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dbutton%2Dbar%3Aafter%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%3Aafter%7Bcontent%3A%22%20%22%3Bdisplay%3Ablock%3Bheight%3A0%3Bclear%3Aboth%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%5Btype%3D%27help%27%5D%3Eli%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%5Btype%3D%27help%27%5D%3Eli%7Bheight%3A24px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%5Btype%3D%27help%27%5D%3Eli%3Alast%2Dchild%3Aafter%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%5Btype%3D%27help%27%5D%3Eli%3Alast%2Dchild%3Aafter%7Bdisplay%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%2Ebk%2Dbs%2Ddropdown%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%2Ebk%2Dbs%2Ddropdown%7Bfloat%3Aleft%3Bpadding%3A7px%2010px%200%205px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%7Btop%3A0%3Bleft%3A30px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%3Eli%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%3Eli%7Bclear%3Aboth%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dleft%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%3Eli%3Alast%2Dchild%3Aafter%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%3Eli%3Alast%2Dchild%3Aafter%7Bcontent%3A%22%20%22%3Bfloat%3Anone%3Bclear%3Aboth%3Bdisplay%3Ablock%3Bheight%3A1px%3Bwidth%3A10px%3Bpadding%3A0%3Bmargin%3A2px%200%202px%2010px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbox%20%2Ebk%2Dtoolbar%2Dbelow%7Btop%3A%2D1px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbox%20%2Ebk%2Dtoolbar%2Dright%7Btop%3A%2D1px%3Bright%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dright%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%7Bleft%3A%2D180px%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dtoolbar%2Dbutton%2Eactive%7Bbackground%3A%23fff%3B%2Dbox%2Dshadow%3Anone%20%21important%3B%2Dwebkit%2Dbox%2Dshadow%3Anone%20%21important%3B%2Dmoz%2Dbox%2Dshadow%3Anone%20%21important%3Boutline%3Anone%20%21important%7D%2Ebk%2Droot%20%2Ebk%2Dbs%2Dcaret%7Bcolor%3Alightgray%3Bdisplay%3Ainline%2Dblock%3Bwidth%3A0%3Bheight%3A0%3Bposition%3Arelative%3Bleft%3A11px%3Btop%3A3px%3Bvertical%2Dalign%3Amiddle%3Bborder%2Dtop%3A4px%20solid%3Bborder%2Dright%3A4px%20solid%20transparent%3Bborder%2Dleft%3A4px%20solid%20transparent%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%2Dlist%20%2Ebk%2Dbs%2Ddropdown%2Dmenu%7Bz%2Dindex%3A100%3Bbackground%2Dcolor%3A%23fff%3Bopacity%3A%2E95%3Bborder%3A%23e5e5e5%20solid%201px%3Bborder%2Dradius%3Ainherit%3Bbox%2Dshadow%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%7Bmargin%2Dtop%3A0%3Bmargin%2Dbottom%3A0%3Bpadding%2Dtop%3A0%3Bpadding%2Dbottom%3A2px%3Bposition%3Arelative%3Bdisplay%3Ainline%2Dblock%3Bvertical%2Dalign%3Amiddle%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%3E%2Ebk%2Dbs%2Dbtn%7Bposition%3Arelative%3Bfloat%3Aleft%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%3E%2Ebk%2Dbs%2Dbtn%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%3E%2Ebk%2Dbs%2Dbtn%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%3E%2Ebk%2Dbs%2Dbtn%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%3E%2Ebk%2Dbs%2Dbtn%2Ebk%2Dbs%2Dactive%7Bz%2Dindex%3A2%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%3E%2Ebk%2Dbs%2Dbtn%3Afocus%7Boutline%3A0%7D%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbs%2Dbtn%2B%2Ebk%2Dbs%2Dbtn%2C%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbs%2Dbtn%2B%2Ebk%2Dbs%2Dbtn%2Dgroup%2C%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2B%2Ebk%2Dbs%2Dbtn%2C%2Ebk%2Droot%20%2Ebk%2Dbutton%2Dbar%20%2Ebk%2Dbs%2Dbtn%2Dgroup%2B%2Ebk%2Dbs%2Dbtn%2Dgroup%7Bmargin%2Dleft%3A%2D1px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%7Bdisplay%3Ainline%2Dblock%3Bmargin%2Dbottom%3A0%3Bfont%2Dweight%3Anormal%3Btext%2Dalign%3Acenter%3Bvertical%2Dalign%3Amiddle%3Bcursor%3Apointer%3Bbackground%2Dimage%3Anone%3Bborder%3A1px%20solid%20transparent%3Bwhite%2Dspace%3Anowrap%3Bpadding%3A6px%2012px%3Bfont%2Dsize%3A12px%3Bline%2Dheight%3A1%2E42857143%3Bborder%2Dradius%3A4px%3B%2Dwebkit%2Duser%2Dselect%3Anone%3B%2Dmoz%2Duser%2Dselect%3Anone%3B%2Dms%2Duser%2Dselect%3Anone%3Buser%2Dselect%3Anone%3Bpadding%3A5px%2010px%3Bfont%2Dsize%3A11px%3Bline%2Dheight%3A1%2E5%3Bborder%2Dradius%3A3px%3Bcolor%3A%23333%3Bbackground%2Dcolor%3A%23fff%3Bborder%2Dcolor%3A%23ccc%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Aactive%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ebk%2Dbs%2Dactive%3Afocus%7Boutline%3Athin%20dotted%3Boutline%3A5px%20auto%20%2Dwebkit%2Dfocus%2Dring%2Dcolor%3Boutline%2Doffset%3A%2D2px%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Afocus%7Bcolor%3A%23333%3Btext%2Ddecoration%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ebk%2Dbs%2Dactive%7Boutline%3A0%3Bbackground%2Dimage%3Anone%3B%2Dwebkit%2Dbox%2Dshadow%3Ainset%200%203px%205px%20rgba%280%2C0%2C0%2C0%2E125%29%3Bbox%2Dshadow%3Ainset%200%203px%205px%20rgba%280%2C0%2C0%2C0%2E125%29%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ebk%2Dbs%2Ddisabled%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%5Bdisabled%5D%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%7Bcursor%3Anot%2Dallowed%3Bpointer%2Devents%3Anone%3Bopacity%3A%2E65%3Bfilter%3Aalpha%28opacity%3D65%29%3B%2Dwebkit%2Dbox%2Dshadow%3Anone%3Bbox%2Dshadow%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%7Bcolor%3A%23333%3Bbackground%2Dcolor%3A%23ebebeb%3Bborder%2Dcolor%3A%23adadad%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Dbs%2Dopen%20%2Ebk%2Dbs%2Ddropdown%2Dtoggle%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%7Bbackground%2Dimage%3Anone%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ebk%2Dbs%2Ddisabled%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%5Bdisabled%5D%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ebk%2Dbs%2Ddisabled%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%5Bdisabled%5D%3Ahover%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Ahover%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ebk%2Dbs%2Ddisabled%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%5Bdisabled%5D%3Afocus%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Afocus%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ebk%2Dbs%2Ddisabled%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%5Bdisabled%5D%3Aactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%3Aactive%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ebk%2Dbs%2Ddisabled%2Ebk%2Dbs%2Dactive%2C%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%5Bdisabled%5D%2Ebk%2Dbs%2Dactive%2Cfieldset%5Bdisabled%5D%20%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ebk%2Dbs%2Dactive%7Bbackground%2Dcolor%3A%23fff%3Bborder%2Dcolor%3A%23ccc%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%20%2Ebk%2Dbs%2Dbadge%7Bcolor%3A%23fff%3Bbackground%2Dcolor%3A%23333%7D%2Ebk%2Droot%20%2Ebk%2Dcanvas%2Dwrapper%7Bposition%3Arelative%3Bfont%2Dsize%3A12pt%3Bfloat%3Aleft%7D%2Ebk%2Droot%20%2Ebk%2Dcanvas%7Bclear%3Aboth%3Bposition%3Aabsolute%3Bfont%2Dsize%3A12pt%7D%2Ebk%2Droot%20%2Ebk%2Dcanvas%2Dwrapper%20%2Ebk%2Dcanvas%2Dmap%7Bposition%3Aabsolute%20%21important%3Bz%2Dindex%3A%2D5%7D%2Ebk%2Droot%20%2Ebk%2Dtooltip%7Bfont%2Dfamily%3A%22HelveticaNeue%2DLight%22%2C%22Helvetica%20Neue%20Light%22%2C%22Helvetica%20Neue%22%2CHelvetica%2CArial%2C%22Lucida%20Grande%22%2Csans%2Dserif%3Bfont%2Dweight%3A300%3Bfont%2Dsize%3A12px%3Bposition%3Aabsolute%3Bpadding%3A5px%3Bborder%3A1px%20solid%20%23e5e5e5%3Bbackground%2Dcolor%3Awhite%3Bpointer%2Devents%3Anone%3Bopacity%3A%2E95%7D%2Ebk%2Droot%20%2Ebk%2Dtooltip%3Ediv%3Anot%28%3Afirst%2Dchild%29%7Bmargin%2Dtop%3A5px%3Bborder%2Dtop%3A%23e5e5e5%201px%20dashed%7D%2Ebk%2Droot%20%2Ebk%2Dtooltip%2Ebk%2Dleft%2Ebk%2Dtooltip%2Darrow%3A%3Abefore%7Bposition%3Aabsolute%3Bmargin%3A%2D7px%200%200%200%3Btop%3A50%25%3Bwidth%3A0%3Bheight%3A0%3Bborder%2Dstyle%3Asolid%3Bborder%2Dwidth%3A7px%200%207px%200%3Bborder%2Dcolor%3Atransparent%3Bcontent%3A%22%20%22%3Bdisplay%3Ablock%3Bleft%3A%2D10px%3Bborder%2Dright%2Dwidth%3A10px%3Bborder%2Dright%2Dcolor%3A%23909599%7D%2Ebk%2Droot%20%2Ebk%2Dtooltip%2Ebk%2Dleft%3A%3Abefore%7Bleft%3A%2D10px%3Bborder%2Dright%2Dwidth%3A10px%3Bborder%2Dright%2Dcolor%3A%23909599%7D%2Ebk%2Droot%20%2Ebk%2Dtooltip%2Ebk%2Dright%2Ebk%2Dtooltip%2Darrow%3A%3Aafter%7Bposition%3Aabsolute%3Bmargin%3A%2D7px%200%200%200%3Btop%3A50%25%3Bwidth%3A0%3Bheight%3A0%3Bborder%2Dstyle%3Asolid%3Bborder%2Dwidth%3A7px%200%207px%200%3Bborder%2Dcolor%3Atransparent%3Bcontent%3A%22%20%22%3Bdisplay%3Ablock%3Bright%3A%2D10px%3Bborder%2Dleft%2Dwidth%3A10px%3Bborder%2Dleft%2Dcolor%3A%23909599%7D%2Ebk%2Droot%20%2Ebk%2Dtooltip%2Ebk%2Dright%3A%3Aafter%7Bright%3A%2D10px%3Bborder%2Dleft%2Dwidth%3A10px%3Bborder%2Dleft%2Dcolor%3A%23909599%7D%2Ebk%2Droot%20%2Ebk%2Dtooltip%2Ebk%2Dabove%3A%3Abefore%7Bposition%3Aabsolute%3Bmargin%3A0%200%200%20%2D7px%3Bleft%3A50%25%3Bwidth%3A0%3Bheight%3A0%3Bborder%2Dstyle%3Asolid%3Bborder%2Dwidth%3A0%207px%200%207px%3Bborder%2Dcolor%3Atransparent%3Bcontent%3A%22%20%22%3Bdisplay%3Ablock%3Btop%3A%2D10px%3Bborder%2Dbottom%2Dwidth%3A10px%3Bborder%2Dbottom%2Dcolor%3A%23909599%7D%2Ebk%2Droot%20%2Ebk%2Dtooltip%2Ebk%2Dbelow%3A%3Aafter%7Bposition%3Aabsolute%3Bmargin%3A0%200%200%20%2D7px%3Bleft%3A50%25%3Bwidth%3A0%3Bheight%3A0%3Bborder%2Dstyle%3Asolid%3Bborder%2Dwidth%3A0%207px%200%207px%3Bborder%2Dcolor%3Atransparent%3Bcontent%3A%22%20%22%3Bdisplay%3Ablock%3Bbottom%3A%2D10px%3Bborder%2Dtop%2Dwidth%3A10px%3Bborder%2Dtop%2Dcolor%3A%23909599%7D%2Ebk%2Droot%20%2Ebk%2Dtooltip%2Drow%2Dlabel%7Btext%2Dalign%3Aright%3Bcolor%3A%2326aae1%7D%2Ebk%2Droot%20%2Ebk%2Dtooltip%2Drow%2Dvalue%7Bcolor%3Adefault%7D%2Ebk%2Droot%20%2Ebk%2Dtooltip%2Dcolor%2Dblock%7Bwidth%3A12px%3Bheight%3A12px%3Bmargin%2Dleft%3A5px%3Bmargin%2Dright%3A5px%3Boutline%3A%23ddd%20solid%201px%3Bdisplay%3Ainline%2Dblock%7D%2Ebk%2Droot%20%2Ebk%2Dcanvas%2Dmap%7Bposition%3Aabsolute%3Bborder%3A0%3Bz%2Dindex%3A%2D5%7D%2Ebk%2Droot%20%2Ebk%2Dshading%7Bposition%3Aabsolute%3Bdisplay%3Ablock%3Bborder%3A1px%20dashed%20green%3Bz%2Dindex%3A100%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dbutton%2Ehover%3Afocus%7Boutline%3A0%7D%2Ebk%2Droot%20%2Ebox%20%2Ebk%2Dgrid%2Dcolumn%7Boverflow%2Dx%3Aauto%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dbox%2Dselect%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACQAAAAgCAYAAAB6kdqOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpBODVDNDBCRjIwQjMxMUU0ODREQUYzNzM5QTM2MjBCRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpBODVDNDBDMDIwQjMxMUU0ODREQUYzNzM5QTM2MjBCRSI%2BIDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkE4NUM0MEJEMjBCMzExRTQ4NERBRjM3MzlBMzYyMEJFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkE4NUM0MEJFMjBCMzExRTQ4NERBRjM3MzlBMzYyMEJFIi8%2BIDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY%2BIDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8%2BhdQ7dQAAAJdJREFUeNpiXLhs5X8GBPgIxAJQNjZxfiD%2BwIAKGCkUZ0SWZGIYZIAF3YVoPkEHH6kojhUMyhD6jydEaAlgaWnwh9BAgf9DKpfxDxYHjeay0Vw2bHMZw2guG81lwyXKRnMZWlt98JdDTFAX%2Fx9NQwPkIH6kGMAVEyjyo7lstC4jouc69Moh9L42rlyBTZyYXDS00xBAgAEAqsguPe03%2BcYAAAAASUVORK5CYII%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dbox%2Dzoom%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACIAAAAgCAYAAAB3j6rJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozMjFERDhEMjIwQjIxMUU0ODREQUYzNzM5QTM2MjBCRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozMjFERDhEMzIwQjIxMUU0ODREQUYzNzM5QTM2MjBCRSI%2BIDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjMyMUREOEQwMjBCMjExRTQ4NERBRjM3MzlBMzYyMEJFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjMyMUREOEQxMjBCMjExRTQ4NERBRjM3MzlBMzYyMEJFIi8%2BIDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY%2BIDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8%2Ba2Q0KAAAAmVJREFUeNq8V19EpFEUvzOtmKfpJSJKDL2WiLJExKaUEq0eeikiaolZLT2lVUpPydqHqIlIo1ilFOmphxj1miKWWHppnobIt7%2BzeyZ3jjvz%2Fbnf9OPHd8%2F9d77z3XN%2B94ts7ew6SqksWKX%2Bw1GFiLjYdVSAfeAQ2Ag2sf0GvAXT4C%2Fwle1x3lt9UOGBNk6BrYa%2BFuYIeAWOsmNviGqe6W%2Bq081OmAGvizgh0cpjZ3RjGBFZBpMG%2Bxn4wM8NYJfWFwNXwXrwS96RiIUTwwYn6AxMgb%2BFvQ5c4zOUxzR4Ce5GLZyo5LfSsQP2G5xQbKO%2BbWFfoLWinA1OAEcoM2rFRpMe5sloJWgtm4j0iPZcPhVdkOWxBWvZONIi2uc%2B5sqxbTaO1Ij2o4%2B5T6JdGy1SF4Kg2mLsi01E%2Foh2l4%2B5HTKaNlmTEe0ka40XyNqTsYnIkWiTwC16rMRNci0bR0hJ7w1veizqy9uB5D4ZDZKBtI3WvLCCJoT9E3jHny4j1DdmWOcbrWWjNYuGoqaL2kdmKayTztio7yzTJprz4A%2F9PuI3a8YMh5IKVC9fetxAY5rB79pNzXdESMJ%2FGrSjm8%2FDCTjAgpjQZCDDh5I%2Bw4HuQBBHOsE9USty4KB2KF85m9J%2Bv5XX9KXr3T7fQZS26WefYlcU%2BayJlxhDIT40jBnn21hQOPrfgFtEqAhdGETqK7gZ4h%2FAv4g4Jf5TUoYquQSuqJDhFpEJca3b4EoYOtyyhrSkHTzlcj4R4t4FZ9NL%2Bj6yMzlT%2FocZES9aky3D3r6y5t2gaw3xWXgs7XFhdyzsgSpr2fFXgAEAmp2J9DuX%2FWgAAAAASUVORK5CYII%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dhelp%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpBODVDNDBDMzIwQjMxMUU0ODREQUYzNzM5QTM2MjBCRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpBODVDNDBDNDIwQjMxMUU0ODREQUYzNzM5QTM2MjBCRSI%2BIDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkE4NUM0MEMxMjBCMzExRTQ4NERBRjM3MzlBMzYyMEJFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkE4NUM0MEMyMjBCMzExRTQ4NERBRjM3MzlBMzYyMEJFIi8%2BIDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY%2BIDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8%2BmR%2BSmAAAA%2FBJREFUeNq8lulPU1kUwOnjCS2yL12pFZFRoBU1MYpCRVGD0cREo4kziX%2FffDDxkzNmcEUUd0cBGYdhKYXSln0riyz%2BmNvceb6W15dxMvdDc3rfvb9z7rnn3HMsW1tbWTsPvkaisfFoND4xiTw9M8tkaUmxxWKxV5S7nE6304FsQLDspGB5ZeVDd89wKLz25YvB%2Fpxdu%2Fb6vA0Bv81qNatgY2PjY%2B%2Bnvs%2F96%2Bvr%2FC0pLvJWetxOZ3Z2NrYzwzlYE4lGw6NjM7NzzKiqWnug5lB9HWsyKMDwRx2dk1PTyD5v5ZFDgcLCAoMTzM8vvP%2FYHQqPIpeXlZ4JNumO8o0CTIO%2BlEjk5%2B9ubjxRUV6WZW5MTE51POtiY57NdvZ0szioXgG2373XnlhedtgrWppP5ebkpLoukVguKMhPq2N1be3x02ex%2BAQ6LrWdl%2BdIKtjc3Lx3%2FyGecTrs51qCiqLInajs7ftjYHBY3nZRUeE%2Bn%2B%2BHmmqdEUDaHz1BB75qO3dWQJIK8GN3bx%2FWXTzfas3N1TrtweMODpdqMhcbPNVY6XZpJ1dWV3%2F57f7i4lKgvpb7Y0YRNhIzCE0njmvp6H7a9UJL1zqXGMPv7NUqYDsQBIDi07aCnk99rCZmdLdKis3NzQsZS3%2B6ce1y24Ufr1%2F1uJxSx%2BBQSHcyEhAUn8BuK0DqHxhCEifSDhJYyseOHhExjmeOHm6Q8zOzs6neEyiwwJXwWITwIHJS431pKSEEAkMbPDbbP5Ge9p0ABRAscDUWjzPlcblS151uOpk2IkMjo1IuKS5OuwYg4QRcEbluPqeGR8Kv372XD9H%2B6qq0ywQQuLqwsChC2wz9c%2F%2FAyzdvk46yWltbgqn5KHOFX%2BCqSB9syUgfCo28evtOerk12LxTVksgcDXL9CCfRVZysSSqNmMMhiJVZVzKQySdk5EuHaOIY%2FLqZlTAMyDzK%2BNiAQSuUE%2BQqIhZ%2F%2BkQQOCqw27%2F869BypO%2F7qDxnls3b5hXEPn7FQCueD1u3gCSwoyXTA5Q0VgcLHCeFnX%2Fvr0E%2BO%2FdPTy%2FBpf28%2B07Qt6dl3ftymUDBaD4ramuAr79mgbq65BI0anpme83n6oFCqC%2Frjb5XPOW0RMgdDzvovJ9D51Io4QgAASbVMCg4yC5yewnnc%2BpfP%2BOzkZKEBBQAPVFnw%2B%2Ftj%2FAhJ2KvvGQRZ8cpO7KV%2BSbtoU7oG2h1PE5eLKxrLTEfNvS%2BeIlJuIWWiPtRqPGq8q353DAb%2FCiiXPTMHCrphov2f986OmlaiPwF3O8HsqwQ9c6jkdj4bExEXh84lYb%2FPWZW8f%2Fo%2FnVBQa9RWR8HC%2Fr2ndqltvlon3Xdmmp46sAAwDlJz2CuiavpwAAAABJRU5ErkJggg%3D%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dinspector%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADEUlEQVRYR81XXVIaQRCeHqug8CXmBNETaE4gniDwIgpVspxAbxC9ATkBkCpQ8gKeQDiB5AQxNyAvUlrldr7eHxyGXZi1rMJ5opbp7m%2B%2B7un%2BhtSGF204vsoMoNXrlzSpfWa1oxQfhAegCZGaEtPorHo8znIoJwCt6%2Btd8uk7ApUQCIHTF4BNAWzImq8ap6cP68CsBdDp9i9ZqXM7ML79g%2FEnCWD%2BjgMKENKqWT%2BtXK0CkQqgNRjs0OxpQIqKhoMxaG6%2F6JeRnK7T6yO2UvVqhYSlLX%2BryORfgKn9ORDFIy7ky41yGcwsr0QAQfDH5zucOswx819fs4egI9OFCcD8DjBF7VNbEX0JzdWEt3NHSSASAcCxBDqMgt%2F623kvyTgNgNjJIfTjk4D4FqaJR1715MjmYAmA5Bx3AwUXQL%2Bt105KaTlcBSC26XRvhjEIoLiq1yqXpr8FAGG16%2Fug4IT27fxBWu7EiQuAiImJpEMKE6nYM30uAIDDttSUOPfJP7JzbjPhAiBIh9QE67vIvoOi9WJfCwDavf40ulpjbCqmUf%2BW753ezURuh7Dg1SqflwAEHU6pgfyBq9Y4qx0LG%2B%2B2fnZ%2FeUzcstmdM2AWH%2Bjfc%2BliWdBJfSENf8Lifi3GVwC9mybOfi5dzatWVrbbLIHNva8p5h%2F16gkaFiLGGxbufkoE6XguwePiXLF3XmMfCUCUAqtKXU7sumd1CowOuJEi3Pg1FBpjitIGhyvVSfvmjci6ZR%2BrFQfDiPVE2jFYeICQ%2BPoewwjC5h7CZld6DBdyu6nDSKgzOyIMhmhK5TTqXYbRorZYM46TmpKAAOrGWwSJJekSB1yqJNOzp1Gs7YJ0EDeySDIMtJbQHh6Kf%2FuFfNFZkolJICRmz0P8DKWZuIG2g1hpok%2BMk0Qphs0h9lzMtWRoNvYLuVImUWrmPJDlBKeRBDfATGOpHkhw670QSHWGLLckmF1PTsMlYqMJpyUbiO0weiMMceqLVTcotnMCYAYJJbcuQrVgZFP0NOOJYpr62pf3AmrHfWUG4O7abefGAfwH7EXSMJafOlYAAAAASUVORK5CYII%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dlasso%2Dselect%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACQAAAAgCAYAAAB6kdqOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3NzIwRUFGMDYyMjE2ODExOTdBNUNBNjVEQTY5OTRDRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1ODBEQzAzNDQ0RTMxMUU0QTE0ODk2NTE1M0M0MkZENCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1ODBEQzAzMzQ0RTMxMUU0QTE0ODk2NTE1M0M0MkZENCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgTWFjaW50b3NoIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OTU0QzIwMUM1RjIxNjgxMUE3QkFFMzhGRjc2NTI3MjgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NzcyMEVBRjA2MjIxNjgxMTk3QTVDQTY1REE2OTk0Q0UiLz4gPC9yZGY6RGVzY3JpcHRpb24%2BIDwvcmRmOlJERj4gPC94OnhtcG1ldGE%2BIDw%2FeHBhY2tldCBlbmQ9InIiPz7r0xDwAAAC9klEQVR42sSXb2hNcRjHz50rt1aslNQitSimq6VESW6SFMvFyJ%2BUknnhhVhkRIkX%2FiRbSPMnyt95sblZFvMC02patEKtaE3Km1taqWlxfZ%2F6Hj39%2Bp17zr3nHJ76dO4953d%2B53ue5%2Fk9v%2Bck2jseORHYRDAXpHmcDSar84McNwLegwHQa5soGULENFAPMmApH%2B5laXVcw9%2FfwA1wDYyFEbQI7FITl2vTQTPYDnaCj3KyooQJVoNu0BmBGG0zQc71YhAPzQEnGRY%2F%2B8R8%2BQGGVCjcXEqBZQy3tkrQBpYnfRL1EGgEEzzGSB48AT2gT%2BeCj8nLbQCbDU9lk0USto35Ytov0MWE7C8zTL3kKbiiFsQqWw7VcaBNzD2wGOwJIUabePeB%2Bl9tCloI2i0xlnCsBAfAVyda69Pe1yGbBW4ywVwbB2fBRSc%2B0y8%2F5AqSpL0KpqqLo2BHRKHxMnnuFvW%2FxxUkD65VF76DBpb5OG0vy8rfFVtBrzQbA%2Ff9AzFZ0KT%2Bt0iKiKCNRt7kuMriNAlTq6pvkti33Eq9whh8N0YhUqlPcP9ybRjs1pvrfEv5j8NkyzgFatS5PNjKo%2BNurinjxtqIhcgedh3cN8SIZ9by6GhBI8YEkuBVHpNXlyAkQyHP2SloG7CJcQW9tOzu3VwFlVyFl8Bn8AZ8AMctnk1RxFHwDtyxCBG7DNbrMGlLoIWVXfaVR8f3ExQsDxf7wpeZwp067eMxaUsOg7fFBiUZsiPgjOX6pCL3zgDbAvZIp8HjIHF2K%2FVturDVqElhrJ8tShdbFqcUQW4rIK3FfrCpTGHS47wGHZbFEsjM9iPP8M3j%2FpYPOI%2BsmgV8kZZyxRRr8sfZlh4LOI%2F0UReiiLPfV4e4%2FpwlB3571J3GsIKCfHWcp7cyLIzyNfGCHqkzxjaxzR0tV1CiUChYLzzszPndKx3mM0vyH%2BSqdRrW1UfnIT2Zh7hhtilZ4%2FwSV1AcOeRntmJXE2dS%2B9mg5VzV%2FxRkq1NjYSb8I8AAdTOa%2BzQjMmsAAAAASUVORK5CYII%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dpan%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCRTI5MDhEODIwQjUxMUU0ODREQUYzNzM5QTM2MjBCRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCRTI5MDhEOTIwQjUxMUU0ODREQUYzNzM5QTM2MjBCRSI%2BIDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkJFMjkwOEQ2MjBCNTExRTQ4NERBRjM3MzlBMzYyMEJFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkJFMjkwOEQ3MjBCNTExRTQ4NERBRjM3MzlBMzYyMEJFIi8%2BIDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY%2BIDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8%2BOXzPwwAAAKNJREFUeNrsVsEKgCAM3cyj0f8fuwT9XdEHrLyVIOKYY4kPPDim0%2BfenF%2B3HZi4nhFec%2BRs4oCPAALwjDVUsKMWA6DNAFX6YXcMYIERdRWIYBzAZbKYGsSKex6mVUAK8Za0TphgoFTbpSvlx3%2FI0EQOILO2i%2FibegLk%2FmgVONM4JvuBVizgkGH3XTGrR%2FxlV0ycbO8qCeMN54wdtVQwSTFwCzAATqEZUn8W8W4AAAAASUVORK5CYII%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dpolygon%2Dselect%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACQAAAAgCAYAAAB6kdqOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpFMzNBREIxOTQ0MUExMUU0QTE0ODk2NTE1M0M0MkZENCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpFMzNBREIxQTQ0MUExMUU0QTE0ODk2NTE1M0M0MkZENCI%2BIDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkUzM0FEQjE3NDQxQTExRTRBMTQ4OTY1MTUzQzQyRkQ0IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkUzM0FEQjE4NDQxQTExRTRBMTQ4OTY1MTUzQzQyRkQ0Ii8%2BIDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY%2BIDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8%2BxB9jgwAAAe5JREFUeNrsmL1LAzEYxu9KUVDBW8RBhRscXNSCoyA6uIl0kYqIXFcXBRdBoYpuDi7iYEFbkFZPpX6sin%2BBtAhODloHRZTaSkEUUZ%2FA23rUer275mjFBn40hJA8eZI3ea%2BiGjn4FL5LCkigHiQ5trM5HEPuQaFQcQhlVpy0GoFWpF2hmKe%2FlfaUWUHZYsRSM2Vn%2F9CSQ5LNu2Bq%2FLI7Qw6KgqSNc5gavywdqgiqRFklyv7doS7q7flrUbYImkG61FvmAU9gBvhLHWUrYIucfwdxM6kNL4fqwBzV18AHOAaNYJo1BsOqDFyiKAp68BA0Cx6BD4yDc8ql%2B0FC008Gp4HQtttOh6JgAVSDF%2FBM7WmdZyQCUct6giSTkdYCpqjup%2B0JghqwaXCMSYhibknFOFQFwnRIl0AbWKXtUSy42wuuIMplNcoewDB9XdyB2gLbYzQTiEKUYtShHjBK9RM6JxOgCZxxvCo2IIohOX%2FpwMJ1D3STCBWMgTeCZyYQI%2BI%2F3jKNmFuNe5d0zyRsSt68yojnOl%2BUeUEXuAc3dLew67WTs5gYzZUpvtxD3UEurINdam8HDeCIsyNMTB8cCeA344qCsyNrBbFOrfQPxQWHyCkkJhPR8%2FlcYoJe6XJj98GAXXkIE6IRI%2BS4lHXoS4ABAP0ljy6tE4wBAAAAAElFTkSuQmCC%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dredo%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACgAAAAgCAYAAABgrToAAAAABmJLR0QA%2FwD%2FAP%2BgvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wwGEDEBYlsi0wAAAYBJREFUWMPtl71Lw0AYxn9ppVAodKoUBGfHDtJJR0FRFAc5uMEbBFcdBcXi4G5Hhw5ZAkFQHASho07i0L%2BhUCi4KBSKQsHlLYSS0iQ0rcI9EMjHfTz3e58LCVhZWf1vOVEbup6fBTbkWAOyQEUet4AB8Ao0gabRajATg67nl4ErQAHFiON%2BAT5QM1p1UzHoen4eOAdOgELC8XtAHbg2WvWnZlCoPQLVKUXpDdhLQtMJMVcRc8sh7TvAA%2FAEfEj2kCyWgG1gH1ga03fHaNVKbFDIvYdM0AVqQGNS%2BGUzHUluyyEmV%2BOQdAID54CXkLI%2BAwdGq16clbueXwDugM2Qcq8brX6ijLMQOL8MMVc3Wp0mCZ0saMv1%2FBvZaENVZa6Lqb4Hk0pKfg%2FsjuzuFaNVZ1L%2FTNoGJbOHkr%2BhCsDZnyAYIHkM3AZu9YHFSdnOMDs1gHbgOj9S9tkTdD2%2FCHzGjIQzL4Lpfs2kTXKUnCU4hmQO%2BI5Cbl4ES%2FYfwcrKyiqefgEvB2gLTkQWKgAAAABJRU5ErkJggg%3D%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dreset%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACgAAAAgCAYAAABgrToAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCRTI5MDhFMDIwQjUxMUU0ODREQUYzNzM5QTM2MjBCRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyOUMzNDE3NDIwQkIxMUU0ODREQUYzNzM5QTM2MjBCRSI%2BIDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkJFMjkwOERFMjBCNTExRTQ4NERBRjM3MzlBMzYyMEJFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkJFMjkwOERGMjBCNTExRTQ4NERBRjM3MzlBMzYyMEJFIi8%2BIDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY%2BIDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8%2BkFHGtQAAAm1JREFUeNrMmE9ExFEQx3%2B7ZYmlLrEsUUTHaEV0iESJVqduXaJr1xKlFB1bdYqoQ9GlFBFdikgpIhLd0rLqUsQqrW2G7%2BYZr%2B2993vaHT6H3583M795897M%2B0U2t3cCR6kh%2BkA3rtvx7IYoEGfEMSi4GIk4OJgg5ogRot5wzBvBhmaJnI2xqMW7dcQC8UCMWzgX4N1xjF2ALq8OctROiGkiHrhLHDpOoNOLg5xXF0Sn5lmWWCUGiBRRC1K4t4p3pLCuKyVnnXMwAUVJcT%2BHfFo3SH5ePGPI24TmA1Pl8rJcBGPEvsa5I6KVWDNcmQW824qxqiRhI%2Bbi4IxmWjOYuneH%2FHvH2Ixmumd8bjNhhad8lxgSzrfp8jUa%2FL%2FwlI8KZ3h1T4bdB30Kb9zz4t6YbgurlIMBdoBHUQiGTBx8JYoKPqVe0ftFNInnW8J20SSCjRWM8k8E1S%2BTNfbZYyQ59yJEg0kjw1QyB42k1iI6ReXLfEWSK8iHJnJVsYqN8jtammuFc%2FFOr3juU7Ia%2B39uM7fiuq8aVrEqp%2BJ6BPWzahw8IPLKdTPKUNU4yJ3Fhqb1inu0y7qeRNVYsWkWFkXPl0QZ8iVbohFmW0s2DmY1jSUX8mUPzi1rmoLML2eXsvsgR%2FFO3JtAix53nNZ96FDlDrasW35eKGniRRPJeywck9VdOjTdayL3Ahv5MC1%2Fxy%2BHp1Iq7BGHMHatjOEqMUgMlxmbVsaEOpMk4GSnp0VyCedyLtuMTlhRD1ZaPoRjeejoMf1HE7VUPkW04Jz7Ztm9rGHslM1Hhjl2xlCn%2B4muQP%2F77RyHdf799uli5FuAAQC%2Bl5Sj5nEBdwAAAABJRU5ErkJggg%3D%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dresize%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACIAAAAgCAYAAAB3j6rJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpBODVDNDBCQjIwQjMxMUU0ODREQUYzNzM5QTM2MjBCRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpBODVDNDBCQzIwQjMxMUU0ODREQUYzNzM5QTM2MjBCRSI%2BIDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjMyMUREOEQ4MjBCMjExRTQ4NERBRjM3MzlBMzYyMEJFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkE4NUM0MEJBMjBCMzExRTQ4NERBRjM3MzlBMzYyMEJFIi8%2BIDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY%2BIDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8%2BnIbQ0AAAAIJJREFUeNpiXLhs5X8G7ICRgTYAq31MDIMEwBzyERoCyJhWAN2ej4MqRFiIjUMahczgSyMsNE4PxACBQZlrcAFsuYkcLECpQwZNiIw6ZNQhow4ZdcioQ0YdMuoQerRZkQE%2FvdqwgypqQD7%2BMIBuANn9f1CnEcbRXIMjd4zM0QCAAAMAbdAPQaze1JcAAAAASUVORK5CYII%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dsave%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozMjFERDhENjIwQjIxMUU0ODREQUYzNzM5QTM2MjBCRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozMjFERDhENzIwQjIxMUU0ODREQUYzNzM5QTM2MjBCRSI%2BIDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjMyMUREOEQ0MjBCMjExRTQ4NERBRjM3MzlBMzYyMEJFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjMyMUREOEQ1MjBCMjExRTQ4NERBRjM3MzlBMzYyMEJFIi8%2BIDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY%2BIDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8%2Bh5hT8AAAAKBJREFUeNpiWbhs5QcGBgZ%2BhgECTAwDDGAO%2BAjEjGj4Lw5xUrAAkl3ocr8IhQAzjT3PRu0o%2BI%2BEHw65NDDqgJHrABYC8t9JMIuRmiHACS2IKC0LOKH0X1JDAOTzs0BsBs3XlIKz5KSBRCA%2BRQXLjwNxNDlp4BoQm9Mo7fGPZsNRB4w6YNQBI94BfwfaAV9G08CoA9DbA%2FxUavkMvRAACDAAaPgYViexODkAAAAASUVORK5CYII%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dtap%2Dselect%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3NzIwRUFGMDYyMjE2ODExOTdBNUNBNjVEQTY5OTRDRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCOTJBQzE0RDQ0RDUxMUU0QTE0ODk2NTE1M0M0MkZENCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCOTJBQzE0QzQ0RDUxMUU0QTE0ODk2NTE1M0M0MkZENCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgTWFjaW50b3NoIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OTQ0QzIwMUM1RjIxNjgxMUE3QkFFMzhGRjc2NTI3MjgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NzcyMEVBRjA2MjIxNjgxMTk3QTVDQTY1REE2OTk0Q0UiLz4gPC9yZGY6RGVzY3JpcHRpb24%2BIDwvcmRmOlJERj4gPC94OnhtcG1ldGE%2BIDw%2FeHBhY2tldCBlbmQ9InIiPz6eYZ88AAADLklEQVR42rSXf2TUYRzHv7tuGcfE6Vwb5zLSSjEj7Y9KWqfEmFZJP%2ByPMdKKmUrrn0iUfjhWlLFi6YfNrF%2BStBoTo39iYkTGco4xxxG59P7k%2FT2PT8%2F37nu3bx9ezvPj%2Bzyf5%2FPreS78bGLS8SmrwE6yje3NHJsDBTALpknBz6JhH3NiYAB0gHqPOVv52wJ6QQ48BzdAttTioRJjdeA8mAHHS2xuk3p%2BM8M16ipVQE49Ds6CiFO9RLjGONf05QLx6wPQaBlbBlPgJVgkP0ETiIJ2sB%2FE1XfimjfgBOOlKDUqCGOcqBcQnw6BYW5YTo4wbvQhMmCfGRemC2rBiGXzWUb%2BkM%2FNRZ6CHWBM9ce5R61NgX6ayhSJ5EPlItlDRNkz4JbFHf06BkSzHjXxM%2BgDv1S%2FmPUo2AXWgt9UUHL%2FIVhS8yUV1%2FEbV3o4N%2BNaoE9Fu%2Fi827K5pNYHnqAVJECShWmAaddpscYFFXwR7vnXBRGlnUN%2FL6kqKJlxnRUuDbaDBiL%2Bvst5d4gpcpBrqk%2F2jIgCKVUolhntplzivHmwh4stGOPfwBWwl%2F2dpp8p7xjQZqFLiQJtauKkivYm%2BkzccpK57yXfOUe%2BP23JqAnVbhMFmlXntCWnxbT31am9ZJ4BJifsUmNTqt0cYhA5ypympPg7VkEKunPbVb8cIG%2B0kyHLJZNR7fUMooUKFHAPkfQo58VLK%2BRzwRDd4FdWG9mjpaAXzqkJa1R7kQttqEABWXMjOOxxVRfnhRm5URX1prk%2F0pQHwNcKlchZ%2BjdpC%2BhFdVqO0my9Hj5dkYgCn1Rfh%2FKdlNDHrJhPqlDih%2BIfBd6qwpOgEqYMsorJ2HtWxtagLJDn%2FW3KRfPOZhoeBJfZPgVeGKeKrkQBh5dLXl25Ny3pc4%2F1fkTdbvFqFQgbxWeYD0hXulhQ0pYiM1jG547fcbMQpVnHTZEn9W3ljsCzwHxCdVteNHIZvQa7%2F7cC7nV6zHIfyFP9EXjFa7YxKAVqPP4bxhhoLWW%2Bz9JyCb6M%2FMREg59%2FRlmmXbmneIybB%2BYC%2Fay%2ByrffqEddDzwGvKxxDmzhc0tc80XVgblqFfgjwAAPubcGjAOl1wAAAABJRU5ErkJggg%3D%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dundo%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACgAAAAgCAYAAABgrToAAAAABmJLR0QA%2FwD%2FAP%2BgvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wwGEAgO%2FGCy%2BAAAAXlJREFUWMPtlr1LQzEUxX%2B1ohQKuhQK%2FSc6SCcdBUVQFCSQwQwOjjoKisXB3a5Ch7c8CA6iKAgddRKHjs6FQtGpUBCEoksK5RE179FPyIEs%2Bbg59%2BTcJODh4THdSA0qUBDqNLBq2jKQBopmuA50gWegBtSUFN2REAxCnQfOAQEsOC5rAxooKylaQyEYhDoDnACHQDZhmA5QAS6UFJ8DI2hUuwVKA3LIC7BlUzOVgFwRuAcKluEmcAM8AB%2FGexgv5oANYPuXtQ1Dsp6YoFHu1bJBCygD1f%2FMb4pp3%2Fg2b0lwqV%2FJVAxyc8CT5VgfgV0lRSdmslngGlizHPeKkuILYDZGzDMLuYqS4iiJ6UxC60GoL02h9VAye506KxiEugC8Rar1Dthxvc%2BSYsZx3nGEXBPYGzY5JwWNV96BTF%2F3gZLiahRPnYuCmxFyDaA6trc4CPV3zBiLSor2uD04eb8ZByWHqtz0K%2FiHkvO9W35SqjiKnP%2Fne3h4eIwOP9GxagtPmsh6AAAAAElFTkSuQmCC%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dtool%2Dicon%2Dwheel%2Dzoom%7Bbackground%2Dimage%3Aurl%28%22data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAACwAAAAgCAYAAABpRpp6AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw%2FeHBhY2tldCBiZWdpbj0i77u%2FIiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8%2BIDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNS4xIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCRTI5MDhEQzIwQjUxMUU0ODREQUYzNzM5QTM2MjBCRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCRTI5MDhERDIwQjUxMUU0ODREQUYzNzM5QTM2MjBCRSI%2BIDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkJFMjkwOERBMjBCNTExRTQ4NERBRjM3MzlBMzYyMEJFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkJFMjkwOERCMjBCNTExRTQ4NERBRjM3MzlBMzYyMEJFIi8%2BIDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY%2BIDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8%2BsFLapAAAA8xJREFUeNq8WH9k1VEU%2F%2B67ecTYxKM8xlJiifKIMUqUKMvy1CqbEmUxJZbSlGXTLBuJpYi18dpqStOzacT%2BWcTXpkiRUjziETEeY9bnzHm5O53vj%2Fte7fDx3r3fc%2B%2F9fM%2F3nHPPvWWP0mOOIlVAC3AQqOc2SRZ4A9Cg58CSNrj1%2BFEnSIYfPynHTyOQArYCO%2FjRPPAJGAcmMM9f87vKfG3AF%2BAucMAgS5LgRZ4CH%2FmFrARkieAs8Aw4ASSBckaS%2B%2BjZLOv6El4HjAKDwPoIa28GXgLdFmQv4WcO2BVBnXTmeIxK%2BD5wzLGXa8D1CGT78NPPhjFlGnjAmBbPSLefx65IBf%2BeZZ81hfznIfsr%2BW0eaACa2G3MhbuAt8CUD1kyRIfongDa4affhW4Nu2Oj0d2Bfg%2B6Y2UIukr2x4ShkAMOMQlNyLcmgVqj7z2wk17UDDosFOOYMOdPQ%2BdkyBcZFkb8DGxz2ckTwrKHA8g6HMn7gQWjbzsHqZSUmJ8sej6Cq7WzrhkzKVeYnmSEXSBM6I17RZ%2BWNWRfJ6z7K2xy1umUc7lGDizIkDL%2BAsNRXs6U3YpOUrRfWwS01K2noIuLzg%2BiTcFSiFLKlQPi8%2BaNAIwri24QlstaEM6JdoIsHBOdiyJl9RntfiXazUljEdJb3IKw1F10Q%2FKrtin0KaSD5Ido77MYK10sG0S4ByjzwW2LRT3pYlxLRBFpGM91%2Fr9kRJuC%2FFbEnVEmhEwQYRqw7IMuC8LjnAKllSeBhEI0Qc8U636luWinWxYPqoFCnuxmX16VR9ldCvINqOH%2FNK5alpe8NY8qL5Nnl%2FGMFJhU6g2SZtqaw1xCkrss2pGEFhLp0CxuGow83%2BBDdoDn%2BFP8hJFeYusNlODL9LI%2FubKLRRxDKfamuaNWRBx4o9TI49NDD9yjSdn9NKFa5jTGrdrIKpw1FJCtU8h6Rp%2FHwbVyBNOOSGtKGHJKtGdAao%2FNBO4aWrecS9mwQiuU8KLoi1nOEfepQ6TsFXVxnnO0NWFZEdVZjK8RaSgXoHtGbihwh4ViCM%2BLvhaL8VJ3xscdqnwOCk4xhDNKYNRHPOZfCakbzGOS%2BSWyloX8KsIj4lNScLwIuTsgsq%2BASnFkmor4JdJayopKeEHZGOJ8OzMoatIkF0XvxIm5cGhcUtyhVqlrh4rNNoU8fI%2BjOCUs3cYIk14L63py9yo2D7fyBZ%2Bt3AGuWgTmiFOCuCIvHuHFo6QbCpxm4GLIxZ%2B880j%2FK8Lm593EVZqnXF9N8UXIFt7zgwoeunDZCJzju44M%2BnKlEP4twAAD1RclkNDukAAAAABJRU5ErkJggg%3D%3D%22%29%7D%2Ebk%2Droot%20%2Ebk%2Dlayout%2Dfixed%2C%2Ebk%2Droot%20%2Ebk%2Dlayout%2Dscale%5Fwidth%2C%2Ebk%2Droot%20%2Ebk%2Dlayout%2Dscale%5Fheight%7Bposition%3Arelative%7D%2Ebk%2Droot%20%2Ebk%2Dlayout%2Dfixed%2Ebk%2Dgrid%2Drow%3Ediv%2C%2Ebk%2Droot%20%2Ebk%2Dlayout%2Dscale%5Fwidth%2Ebk%2Dgrid%2Drow%3Ediv%2C%2Ebk%2Droot%20%2Ebk%2Dlayout%2Dscale%5Fheight%2Ebk%2Dgrid%2Drow%3Ediv%7Bdisplay%3Ainline%2Dblock%3Bfloat%3Aleft%7D%2Ebk%2Droot%20%2Ebk%2Dgrid%2Drow%7Bclear%3Aboth%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dwrapper%7Bposition%3Arelative%7D%2Ebk%2Droot%20%2Ebk%2Dcanvas%2C%2Ebk%2Droot%20%2Ebk%2Dcanvas%2Doverlays%2C%2Ebk%2Droot%20%2Ebk%2Dcanvas%2Devents%7Btop%3A0%3Bleft%3A0%3Bposition%3Aabsolute%3Bwidth%3A100%25%3Bheight%3A100%25%7D%2Ebk%2Droot%20%2Ebk%2Dcanvas%2Dwrapper%7Bz%2Dindex%3A50%7D%2Ebk%2Droot%20%2Ebk%2Dcanvas%2Doverlays%7Bz%2Dindex%3A75%7D%2Ebk%2Droot%20%2Ebk%2Dcanvas%2Devents%7Bz%2Dindex%3A100%7D%2Ebk%2Droot%20%2Ebk%2Dtoolbar%2Dwrapper%7Bz%2Dindex%3A125%7D%2Erendered%5Fhtml%20%2Ebk%2Droot%20%2Ebk%2Dtooltip%20table%2C%2Erendered%5Fhtml%20%2Ebk%2Droot%20%2Ebk%2Dtooltip%20tr%2C%2Erendered%5Fhtml%20%2Ebk%2Droot%20%2Ebk%2Dtooltip%20th%2C%2Erendered%5Fhtml%20%2Ebk%2Droot%20%2Ebk%2Dtooltip%20td%7Bborder%3A0%3Bpadding%3A1px%7D%0A%0A&#34; rel=&#34;stylesheet&#34; /&gt; &lt;link href=&#34;data:text/css;charset=utf-8,%2Ebk%2Dloader%20%7B%0Amargin%3A%20auto%3B%0Afont%2Dsize%3A%2010px%3B%0Aposition%3A%20relative%3B%0Atext%2Dindent%3A%20%2D9999em%3B%0Aborder%2Dtop%3A%208px%20solid%20rgba%28102%2C102%2C102%2C%200%2E2%29%3B%0Aborder%2Dright%3A%208px%20solid%20rgba%28102%2C102%2C102%2C%200%2E2%29%3B%0Aborder%2Dbottom%3A%208px%20solid%20rgba%28102%2C102%2C102%2C%200%2E2%29%3B%0Aborder%2Dleft%3A%208px%20solid%20%23666666%3B%0A%2Dwebkit%2Dtransform%3A%20translateZ%280%29%3B%0A%2Dms%2Dtransform%3A%20translateZ%280%29%3B%0Atransform%3A%20translateZ%280%29%3B%0A%2Dwebkit%2Danimation%3A%20bk%2Dload8%201%2E1s%20infinite%20linear%3B%0Aanimation%3A%20bk%2Dload8%201%2E1s%20infinite%20linear%3B%0A%2Dwebkit%2Dtransition%3A%20opacity%200%2E7s%20step%2Dend%3B%0Atransition%3A%20opacity%200%2E7s%20step%2Dend%3B%0Aposition%3A%20absolute%3B%0A%7D%0A%2Ebk%2Dloader%2C%0A%2Ebk%2Dloader%3Aafter%20%7B%0Aborder%2Dradius%3A%2050%25%3B%0Awidth%3A%2070px%3B%0Aheight%3A%2070px%3B%0A%7D%0A%40%2Dwebkit%2Dkeyframes%20bk%2Dload8%20%7B%0A0%25%20%7B%0A%2Dwebkit%2Dtransform%3A%20rotate%280deg%29%3B%0Atransform%3A%20rotate%280deg%29%3B%0A%7D%0A100%25%20%7B%0A%2Dwebkit%2Dtransform%3A%20rotate%28360deg%29%3B%0Atransform%3A%20rotate%28360deg%29%3B%0A%7D%0A%7D%0A%40keyframes%20bk%2Dload8%20%7B%0A0%25%20%7B%0A%2Dwebkit%2Dtransform%3A%20rotate%280deg%29%3B%0Atransform%3A%20rotate%280deg%29%3B%0A%7D%0A100%25%20%7B%0A%2Dwebkit%2Dtransform%3A%20rotate%28360deg%29%3B%0Atransform%3A%20rotate%28360deg%29%3B%0A%7D%0A%7D%0A&#34; rel=&#34;stylesheet&#34; /&gt;
&lt;script src=&#34;data:application/x-javascript;base64,d2luZG93LkJva2VoPUJva2VoPWZ1bmN0aW9uKCl7dmFyIHQ9dm9pZCAwO3JldHVybiBmdW5jdGlvbiBlKHQscixuKXtmdW5jdGlvbiBvKGkpe2lmKCFyW2ldKXtpZighdFtpXSl7dmFyIHM9bmV3IEVycm9yKCJDYW5ub3QgZmluZCBtb2R1bGUgJyIraSsiJyIpO3Rocm93IHMuY29kZT0iTU9EVUxFX05PVF9GT1VORCIsc312YXIgYT1yW2ldPXtleHBvcnRzOnt9fSxsPWZ1bmN0aW9uKGUpe3ZhciByPXRbaV1bMV1bZV07cmV0dXJuIG8ocj9yOmUpfTtsLm1vZHVsZXM9by5tb2R1bGVzLHRbaV1bMF0uY2FsbChhLmV4cG9ydHMsbCxhLGEuZXhwb3J0cyxlLHQscixuKX1yZXR1cm4gcltpXS5leHBvcnRzfW8ubW9kdWxlcz10O2Zvcih2YXIgaT1udWxsLHM9MDtzPG4ubGVuZ3RoO3MrKylpPW8obltzXSk7cmV0dXJuIGl9KHtiYXNlOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHA9e30uaGFzT3duUHJvcGVydHk7bz10KCJ1bmRlcnNjb3JlIiksdT10KCIuL2NvcmUvbG9nZ2luZyIpLmxvZ2dlcix0KCIuL2NvcmUvdXRpbC91bmRlcnNjb3JlIikucGF0Y2goKSxsPXQoIi4vY29tbW9uL21vZGVscyIpLGM9e30saD1mdW5jdGlvbih0KXt2YXIgZSxyLG4saSxzLGEsbCx1LGg7cz17fTtmb3IobiBpbiB0KWlmKGE9dFtuXSxvLmlzQXJyYXkoYSkpe3U9YVswXSxoPW51bGwhPShpPWFbMV0pP2k6IiI7Zm9yKGwgaW4gdSllPXVbbF0scj1sK2gsc1tyXT1lfWVsc2Ugc1tuXT1hO3JldHVybiBzfSxzPW51bGwsaT1mdW5jdGlvbigpe3JldHVybiBudWxsPT1zJiYocz1oKGwpKSxzfSxuPWZ1bmN0aW9uKHQpe3ZhciBlLHI7aWYocj1pKCksY1t0XSlyZXR1cm4gY1t0XTtpZihlPXJbdF0sbnVsbD09ZSl0aHJvdyBuZXcgRXJyb3IoIk1vZHVsZSBgIit0KyInIGRvZXMgbm90IGV4aXN0cy4gVGhlIHByb2JsZW0gbWF5IGJlIHR3byBmb2xkLiBFaXRoZXIgYSBtb2RlbCB3YXMgcmVxdWVzdGVkIHRoYXQncyBhdmFpbGFibGUgaW4gYW4gZXh0cmEgYnVuZGxlLCBlLmcuIGEgd2lkZ2V0LCBvciBhIGN1c3RvbSBtb2RlbCB3YXMgcmVxdWVzdGVkLCBidXQgaXQgd2Fzbid0IHJlZ2lzdGVyZWQgYmVmb3JlIGZpcnN0IHVzYWdlLiIpO3JldHVybiBlLk1vZGVsfSxuLnJlZ2lzdGVyPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIGNbdF09ZX0sbi51bnJlZ2lzdGVyPWZ1bmN0aW9uKHQpe3JldHVybiBkZWxldGUgY1t0XX0sbi5yZWdpc3Rlcl9sb2NhdGlvbnM9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8scyxhLGw7bnVsbD09ZSYmKGU9ITEpLG51bGw9PXImJihyPW51bGwpLG89aSgpLG49aCh0KSxsPVtdO2ZvcihhIGluIG4pcC5jYWxsKG4sYSkmJihzPW5bYV0sZXx8IW8uaGFzT3duUHJvcGVydHkoYSk/bC5wdXNoKG9bYV09cyk6bC5wdXNoKCJmdW5jdGlvbiI9PXR5cGVvZiByP3IoYSk6dm9pZCAwKSk7cmV0dXJuIGx9LG4ucmVnaXN0ZXJlZF9uYW1lcz1mdW5jdGlvbigpe3JldHVybiBPYmplY3Qua2V5cyhpKCkpfSxhPXt9LGUuZXhwb3J0cz17b3ZlcnJpZGVzOmMsaW5kZXg6YSxNb2RlbHM6bn19LHsiLi9jb21tb24vbW9kZWxzIjoiY29tbW9uL21vZGVscyIsIi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi9jb3JlL3V0aWwvdW5kZXJzY29yZSI6ImNvcmUvdXRpbC91bmRlcnNjb3JlIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLGNsaWVudDpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5O2Q9dCgidW5kZXJzY29yZSIpLGM9dCgiZXM2LXByb21pc2UiKS5Qcm9taXNlLGw9dCgiLi9jb3JlL2hhc19wcm9wcyIpLGY9dCgiLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIseT10KCIuL2RvY3VtZW50IiksYT15LkRvY3VtZW50LGg9eS5Nb2RlbENoYW5nZWRFdmVudCxwPXkuUm9vdEFkZGVkRXZlbnQsXz15LlJvb3RSZW1vdmVkRXZlbnQsaT0id3M6Ly9sb2NhbGhvc3Q6NTAwNi93cyIscz0iZGVmYXVsdCIsdT1mdW5jdGlvbigpe2Z1bmN0aW9uIHQodCxlLHIpe3RoaXMuaGVhZGVyPXQsdGhpcy5tZXRhZGF0YT1lLHRoaXMuY29udGVudD1yLHRoaXMuYnVmZmVycz1bXX1yZXR1cm4gdC5hc3NlbWJsZT1mdW5jdGlvbihlLHIsbil7dmFyIG8saSxzLGEsbDt0cnl7cmV0dXJuIGE9SlNPTi5wYXJzZShlKSxsPUpTT04ucGFyc2Uociksbz1KU09OLnBhcnNlKG4pLG5ldyB0KGEsbCxvKX1jYXRjaChzKXt0aHJvdyBpPXMsZi5lcnJvcigiRmFpbHVyZSBwYXJzaW5nIGpzb24gIitpKyIgIitlKyIgIityKyIgIituLGkpLGl9fSx0LmNyZWF0ZV9oZWFkZXI9ZnVuY3Rpb24odCxlKXt2YXIgcjtyZXR1cm4gcj17bXNnaWQ6ZC51bmlxdWVJZCgpLG1zZ3R5cGU6dH0sZC5leHRlbmQocixlKX0sdC5jcmVhdGU9ZnVuY3Rpb24oZSxyLG4pe3ZhciBvO3JldHVybiBudWxsPT1uJiYobj17fSksbz10LmNyZWF0ZV9oZWFkZXIoZSxyKSxuZXcgdChvLHt9LG4pfSx0LnByb3RvdHlwZS5zZW5kPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGk7dHJ5e3JldHVybiBvPUpTT04uc3RyaW5naWZ5KHRoaXMuaGVhZGVyKSxpPUpTT04uc3RyaW5naWZ5KHRoaXMubWV0YWRhdGEpLGU9SlNPTi5zdHJpbmdpZnkodGhpcy5jb250ZW50KSx0LnNlbmQobyksdC5zZW5kKGkpLHQuc2VuZChlKX1jYXRjaChuKXt0aHJvdyByPW4sZi5lcnJvcigiRXJyb3Igc2VuZGluZyAiLHRoaXMscikscn19LHQucHJvdG90eXBlLmNvbXBsZXRlPWZ1bmN0aW9uKCl7cmV0dXJuIG51bGwhPXRoaXMuaGVhZGVyJiZudWxsIT10aGlzLm1ldGFkYXRhJiZudWxsIT10aGlzLmNvbnRlbnQmJighKCJudW1fYnVmZmVycyJpbiB0aGlzLmhlYWRlcil8fHRoaXMuYnVmZmVycy5sZW5ndGg9PT10aGlzLmhlYWRlci5udW1fYnVmZmVycyl9LHQucHJvdG90eXBlLmFkZF9idWZmZXI9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuYnVmZmVycy5wdXNoKHQpfSx0LnByb3RvdHlwZS5faGVhZGVyX2ZpZWxkPWZ1bmN0aW9uKHQpe3JldHVybiB0IGluIHRoaXMuaGVhZGVyP3RoaXMuaGVhZGVyW3RdOm51bGx9LHQucHJvdG90eXBlLm1zZ2lkPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2hlYWRlcl9maWVsZCgibXNnaWQiKX0sdC5wcm90b3R5cGUubXNndHlwZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9oZWFkZXJfZmllbGQoIm1zZ3R5cGUiKX0sdC5wcm90b3R5cGUuc2Vzc2lkPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2hlYWRlcl9maWVsZCgic2Vzc2lkIil9LHQucHJvdG90eXBlLnJlcWlkPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2hlYWRlcl9maWVsZCgicmVxaWQiKX0sdC5wcm90b3R5cGUucHJvYmxlbT1mdW5jdGlvbigpe3JldHVybiJtc2dpZCJpbiB0aGlzLmhlYWRlcj8ibXNndHlwZSJpbiB0aGlzLmhlYWRlcj9udWxsOiJObyBtc2d0eXBlIGluIGhlYWRlciI6Ik5vIG1zZ2lkIGluIGhlYWRlciJ9LHR9KCksbT17IlBBVENILURPQyI6ZnVuY3Rpb24odCxlKXtyZXR1cm4gdC5fZm9yX3Nlc3Npb24oZnVuY3Rpb24odCl7cmV0dXJuIHQuX2hhbmRsZV9wYXRjaChlKX0pfSxPSzpmdW5jdGlvbih0LGUpe3JldHVybiBmLmRlYnVnKCJVbmhhbmRsZWQgT0sgcmVwbHkgdG8gIitlLnJlcWlkKCkpfSxFUlJPUjpmdW5jdGlvbih0LGUpe3JldHVybiBmLmVycm9yKCJVbmhhbmRsZWQgRVJST1IgcmVwbHkgdG8gIitlLnJlcWlkKCkrIjogIitlLmNvbnRlbnQudGV4dCl9fSxuPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdChlLHIsbixvKXt0aGlzLnVybD1lLHRoaXMuaWQ9cix0aGlzLl9vbl9oYXZlX3Nlc3Npb25faG9vaz1uLHRoaXMuX29uX2Nsb3NlZF9wZXJtYW5lbnRseV9ob29rPW8sdGhpcy5fbnVtYmVyPXQuX2Nvbm5lY3Rpb25fY291bnQsdC5fY29ubmVjdGlvbl9jb3VudD10aGlzLl9udW1iZXIrMSxudWxsPT10aGlzLnVybCYmKHRoaXMudXJsPWkpLG51bGw9PXRoaXMuaWQmJih0aGlzLmlkPXMpLGYuZGVidWcoIkNyZWF0aW5nIHdlYnNvY2tldCAiK3RoaXMuX251bWJlcisiIHRvICciK3RoaXMudXJsKyInIHNlc3Npb24gJyIrdGhpcy5pZCsiJyIpLHRoaXMuc29ja2V0PW51bGwsdGhpcy5jbG9zZWRfcGVybWFuZW50bHk9ITEsdGhpcy5fZnJhZ21lbnRzPVtdLHRoaXMuX3BhcnRpYWw9bnVsbCx0aGlzLl9jdXJyZW50X2hhbmRsZXI9bnVsbCx0aGlzLl9wZW5kaW5nX2Fjaz1udWxsLHRoaXMuX3BlbmRpbmdfcmVwbGllcz17fSx0aGlzLnNlc3Npb249bnVsbH1yZXR1cm4gdC5fY29ubmVjdGlvbl9jb3VudD0wLHQucHJvdG90eXBlLl9mb3Jfc2Vzc2lvbj1mdW5jdGlvbih0KXtpZihudWxsIT09dGhpcy5zZXNzaW9uKXJldHVybiB0KHRoaXMuc2Vzc2lvbil9LHQucHJvdG90eXBlLmNvbm5lY3Q9ZnVuY3Rpb24oKXt2YXIgdCxlLHI7aWYodGhpcy5jbG9zZWRfcGVybWFuZW50bHkpcmV0dXJuIGMucmVqZWN0KG5ldyBFcnJvcigiQ2Fubm90IGNvbm5lY3QoKSBhIGNsb3NlZCBDbGllbnRDb25uZWN0aW9uIikpO2lmKG51bGwhPXRoaXMuc29ja2V0KXJldHVybiBjLnJlamVjdChuZXcgRXJyb3IoIkFscmVhZHkgY29ubmVjdGVkIikpO3RoaXMuX2ZyYWdtZW50cz1bXSx0aGlzLl9wYXJ0aWFsPW51bGwsdGhpcy5fcGVuZGluZ19yZXBsaWVzPXt9LHRoaXMuX2N1cnJlbnRfaGFuZGxlcj1udWxsO3RyeXtyZXR1cm4gcj10aGlzLnVybCsiP2Jva2VoLXByb3RvY29sLXZlcnNpb249MS4wJmJva2VoLXNlc3Npb24taWQ9Iit0aGlzLmlkLG51bGwhPXdpbmRvdy5Nb3pXZWJTb2NrZXQ/dGhpcy5zb2NrZXQ9bmV3IE1veldlYlNvY2tldChyKTp0aGlzLnNvY2tldD1uZXcgV2ViU29ja2V0KHIpLG5ldyBjKGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihlLHIpe3JldHVybiB0LnNvY2tldC5iaW5hcnl0eXBlPSJhcnJheWJ1ZmZlciIsdC5zb2NrZXQub25vcGVuPWZ1bmN0aW9uKCl7cmV0dXJuIHQuX29uX29wZW4oZSxyKX0sdC5zb2NrZXQub25tZXNzYWdlPWZ1bmN0aW9uKGUpe3JldHVybiB0Ll9vbl9tZXNzYWdlKGUpfSx0LnNvY2tldC5vbmNsb3NlPWZ1bmN0aW9uKGUpe3JldHVybiB0Ll9vbl9jbG9zZShlKX0sdC5zb2NrZXQub25lcnJvcj1mdW5jdGlvbigpe3JldHVybiB0Ll9vbl9lcnJvcihyKX19fSh0aGlzKSl9Y2F0Y2goZSl7cmV0dXJuIHQ9ZSxmLmVycm9yKCJ3ZWJzb2NrZXQgY3JlYXRpb24gZmFpbGVkIHRvIHVybDogIit0aGlzLnVybCksZi5lcnJvcigiIC0gIit0KSxjLnJlamVjdCh0KX19LHQucHJvdG90eXBlLmNsb3NlPWZ1bmN0aW9uKCl7aWYoIXRoaXMuY2xvc2VkX3Blcm1hbmVudGx5JiYoZi5kZWJ1ZygiUGVybWFuZW50bHkgY2xvc2luZyB3ZWJzb2NrZXQgY29ubmVjdGlvbiAiK3RoaXMuX251bWJlciksdGhpcy5jbG9zZWRfcGVybWFuZW50bHk9ITAsbnVsbCE9dGhpcy5zb2NrZXQmJnRoaXMuc29ja2V0LmNsb3NlKDFlMywiY2xvc2UgbWV0aG9kIGNhbGxlZCBvbiBDbGllbnRDb25uZWN0aW9uICIrdGhpcy5fbnVtYmVyKSx0aGlzLl9mb3Jfc2Vzc2lvbihmdW5jdGlvbih0KXtyZXR1cm4gdC5fY29ubmVjdGlvbl9jbG9zZWQoKX0pLG51bGwhPXRoaXMuX29uX2Nsb3NlZF9wZXJtYW5lbnRseV9ob29rKSlyZXR1cm4gdGhpcy5fb25fY2xvc2VkX3Blcm1hbmVudGx5X2hvb2soKSx0aGlzLl9vbl9jbG9zZWRfcGVybWFuZW50bHlfaG9vaz1udWxsfSx0LnByb3RvdHlwZS5fc2NoZWR1bGVfcmVjb25uZWN0PWZ1bmN0aW9uKHQpe3ZhciBlO3JldHVybiBlPWZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbigpe3QuY2xvc2VkX3Blcm1hbmVudGx5fHxmLmluZm8oIldlYnNvY2tldCBjb25uZWN0aW9uICIrdC5fbnVtYmVyKyIgZGlzY29ubmVjdGVkLCB3aWxsIG5vdCBhdHRlbXB0IHRvIHJlY29ubmVjdCIpfX0odGhpcyksc2V0VGltZW91dChlLHQpfSx0LnByb3RvdHlwZS5zZW5kPWZ1bmN0aW9uKHQpe3ZhciBlLHI7dHJ5e2lmKG51bGw9PT10aGlzLnNvY2tldCl0aHJvdyBuZXcgRXJyb3IoIm5vdCBjb25uZWN0ZWQgc28gY2Fubm90IHNlbmQgIit0KTtyZXR1cm4gdC5zZW5kKHRoaXMuc29ja2V0KX1jYXRjaChyKXtyZXR1cm4gZT1yLGYuZXJyb3IoIkVycm9yIHNlbmRpbmcgbWVzc2FnZSAiLGUsdCl9fSx0LnByb3RvdHlwZS5zZW5kX3dpdGhfcmVwbHk9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9bmV3IGMoZnVuY3Rpb24oZSl7cmV0dXJuIGZ1bmN0aW9uKHIsbil7cmV0dXJuIGUuX3BlbmRpbmdfcmVwbGllc1t0Lm1zZ2lkKCldPVtyLG5dLGUuc2VuZCh0KX19KHRoaXMpKSxlLnRoZW4oZnVuY3Rpb24odCl7aWYoIkVSUk9SIj09PXQubXNndHlwZSgpKXRocm93IG5ldyBFcnJvcigiRXJyb3IgcmVwbHkgIit0LmNvbnRlbnQudGV4dCk7cmV0dXJuIHR9LGZ1bmN0aW9uKHQpe3Rocm93IHR9KX0sdC5wcm90b3R5cGUuX3B1bGxfZG9jX2pzb249ZnVuY3Rpb24oKXt2YXIgdCxlO3JldHVybiB0PXUuY3JlYXRlKCJQVUxMLURPQy1SRVEiLHt9KSxlPXRoaXMuc2VuZF93aXRoX3JlcGx5KHQpLGUudGhlbihmdW5jdGlvbih0KXtpZighKCJkb2MiaW4gdC5jb250ZW50KSl0aHJvdyBuZXcgRXJyb3IoIk5vICdkb2MnIGZpZWxkIGluIFBVTEwtRE9DLVJFUExZIik7cmV0dXJuIHQuY29udGVudC5kb2N9LGZ1bmN0aW9uKHQpe3Rocm93IHR9KX0sdC5wcm90b3R5cGUuX3JlcHVsbF9zZXNzaW9uX2RvYz1mdW5jdGlvbigpe3JldHVybiBudWxsPT09dGhpcy5zZXNzaW9uP2YuZGVidWcoIlB1bGxpbmcgc2Vzc2lvbiBmb3IgZmlyc3QgdGltZSIpOmYuZGVidWcoIlJlcHVsbGluZyBzZXNzaW9uIiksdGhpcy5fcHVsbF9kb2NfanNvbigpLnRoZW4oZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKGUpe3ZhciByLG4saTtyZXR1cm4gbnVsbCE9PXQuc2Vzc2lvbj8odC5zZXNzaW9uLmRvY3VtZW50LnJlcGxhY2Vfd2l0aF9qc29uKGUpLGYuZGVidWcoIlVwZGF0ZWQgZXhpc3Rpbmcgc2Vzc2lvbiB3aXRoIG5ldyBwdWxsZWQgZG9jIikpOnQuY2xvc2VkX3Blcm1hbmVudGx5P2YuZGVidWcoIkdvdCBuZXcgZG9jdW1lbnQgYWZ0ZXIgY29ubmVjdGlvbiB3YXMgYWxyZWFkeSBjbG9zZWQiKToocj1hLmZyb21fanNvbihlKSxuPWEuX2NvbXB1dGVfcGF0Y2hfc2luY2VfanNvbihlLHIpLG4uZXZlbnRzLmxlbmd0aD4wJiYoZi5kZWJ1ZygiU2VuZGluZyAiK24uZXZlbnRzLmxlbmd0aCsiIGNoYW5nZXMgZnJvbSBtb2RlbCBjb25zdHJ1Y3Rpb24gYmFjayB0byBzZXJ2ZXIiKSxpPXUuY3JlYXRlKCJQQVRDSC1ET0MiLHt9LG4pLHQuc2VuZChpKSksdC5zZXNzaW9uPW5ldyBvKHQscix0LmlkKSxmLmRlYnVnKCJDcmVhdGVkIGEgbmV3IHNlc3Npb24gZnJvbSBuZXcgcHVsbGVkIGRvYyIpLG51bGwhPXQuX29uX2hhdmVfc2Vzc2lvbl9ob29rPyh0Ll9vbl9oYXZlX3Nlc3Npb25faG9vayh0LnNlc3Npb24pLHQuX29uX2hhdmVfc2Vzc2lvbl9ob29rPW51bGwpOnZvaWQgMCl9fSh0aGlzKSxmdW5jdGlvbih0KXt0aHJvdyB0fSlbImNhdGNoIl0oZnVuY3Rpb24odCl7cmV0dXJuIG51bGwhPWNvbnNvbGUudHJhY2UmJmNvbnNvbGUudHJhY2UodCksZi5lcnJvcigiRmFpbGVkIHRvIHJlcHVsbCBzZXNzaW9uICIrdCl9KX0sdC5wcm90b3R5cGUuX29uX29wZW49ZnVuY3Rpb24odCxlKXtyZXR1cm4gZi5pbmZvKCJXZWJzb2NrZXQgY29ubmVjdGlvbiAiK3RoaXMuX251bWJlcisiIGlzIG5vdyBvcGVuIiksdGhpcy5fcGVuZGluZ19hY2s9W3QsZV0sdGhpcy5fY3VycmVudF9oYW5kbGVyPWZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihlKXtyZXR1cm4gdC5fYXdhaXRpbmdfYWNrX2hhbmRsZXIoZSl9fSh0aGlzKX0sdC5wcm90b3R5cGUuX29uX21lc3NhZ2U9ZnVuY3Rpb24odCl7dmFyIGUscjt0cnl7cmV0dXJuIHRoaXMuX29uX21lc3NhZ2VfdW5jaGVja2VkKHQpfWNhdGNoKHIpe3JldHVybiBlPXIsZi5lcnJvcigiRXJyb3IgaGFuZGxpbmcgbWVzc2FnZTogIitlKyIsICIrdCl9fSx0LnByb3RvdHlwZS5fb25fbWVzc2FnZV91bmNoZWNrZWQ9ZnVuY3Rpb24odCl7dmFyIGUscjtpZihudWxsPT10aGlzLl9jdXJyZW50X2hhbmRsZXImJmYuZXJyb3IoImdvdCBhIG1lc3NhZ2UgYnV0IGhhdmVuJ3Qgc2V0IF9jdXJyZW50X2hhbmRsZXIiKSx0LmRhdGEgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcj9udWxsPT10aGlzLl9wYXJ0aWFsfHx0aGlzLl9wYXJ0aWFsLmNvbXBsZXRlKCk/dGhpcy5fY2xvc2VfYmFkX3Byb3RvY29sKCJHb3QgYmluYXJ5IGZyb20gd2Vic29ja2V0IGJ1dCB3ZSB3ZXJlIGV4cGVjdGluZyB0ZXh0Iik6dGhpcy5fcGFydGlhbC5hZGRfYnVmZmVyKHQuZGF0YSk6bnVsbCE9dGhpcy5fcGFydGlhbD90aGlzLl9jbG9zZV9iYWRfcHJvdG9jb2woIkdvdCB0ZXh0IGZyb20gd2Vic29ja2V0IGJ1dCB3ZSB3ZXJlIGV4cGVjdGluZyBiaW5hcnkiKToodGhpcy5fZnJhZ21lbnRzLnB1c2godC5kYXRhKSwzPT09dGhpcy5fZnJhZ21lbnRzLmxlbmd0aCYmKHRoaXMuX3BhcnRpYWw9dS5hc3NlbWJsZSh0aGlzLl9mcmFnbWVudHNbMF0sdGhpcy5fZnJhZ21lbnRzWzFdLHRoaXMuX2ZyYWdtZW50c1syXSksdGhpcy5fZnJhZ21lbnRzPVtdLHI9dGhpcy5fcGFydGlhbC5wcm9ibGVtKCksbnVsbCE9PXImJnRoaXMuX2Nsb3NlX2JhZF9wcm90b2NvbChyKSkpLG51bGwhPXRoaXMuX3BhcnRpYWwmJnRoaXMuX3BhcnRpYWwuY29tcGxldGUoKSlyZXR1cm4gZT10aGlzLl9wYXJ0aWFsLHRoaXMuX3BhcnRpYWw9bnVsbCx0aGlzLl9jdXJyZW50X2hhbmRsZXIoZSl9LHQucHJvdG90eXBlLl9vbl9jbG9zZT1mdW5jdGlvbih0KXt2YXIgZSxyO2ZvcihmLmluZm8oIkxvc3Qgd2Vic29ja2V0ICIrdGhpcy5fbnVtYmVyKyIgY29ubmVjdGlvbiwgIit0LmNvZGUrIiAoIit0LnJlYXNvbisiKSIpLHRoaXMuc29ja2V0PW51bGwsbnVsbCE9dGhpcy5fcGVuZGluZ19hY2smJih0aGlzLl9wZW5kaW5nX2Fja1sxXShuZXcgRXJyb3IoIkxvc3Qgd2Vic29ja2V0IGNvbm5lY3Rpb24sICIrdC5jb2RlKyIgKCIrdC5yZWFzb24rIikiKSksdGhpcy5fcGVuZGluZ19hY2s9bnVsbCksZT1mdW5jdGlvbigpe3ZhciB0LGUscjtlPXRoaXMuX3BlbmRpbmdfcmVwbGllcztmb3IociBpbiBlKXJldHVybiB0PWVbcl0sZGVsZXRlIHRoaXMuX3BlbmRpbmdfcmVwbGllc1tyXSx0O3JldHVybiBudWxsfSxyPWUoKTtudWxsIT09cjspclsxXSgiRGlzY29ubmVjdGVkIikscj1lKCk7aWYoIXRoaXMuY2xvc2VkX3Blcm1hbmVudGx5KXJldHVybiB0aGlzLl9zY2hlZHVsZV9yZWNvbm5lY3QoMmUzKX0sdC5wcm90b3R5cGUuX29uX2Vycm9yPWZ1bmN0aW9uKHQpe3JldHVybiBmLmRlYnVnKCJXZWJzb2NrZXQgZXJyb3Igb24gc29ja2V0ICAiK3RoaXMuX251bWJlciksdChuZXcgRXJyb3IoIkNvdWxkIG5vdCBvcGVuIHdlYnNvY2tldCIpKX0sdC5wcm90b3R5cGUuX2Nsb3NlX2JhZF9wcm90b2NvbD1mdW5jdGlvbih0KXtpZihmLmVycm9yKCJDbG9zaW5nIGNvbm5lY3Rpb246ICIrdCksbnVsbCE9dGhpcy5zb2NrZXQpcmV0dXJuIHRoaXMuc29ja2V0LmNsb3NlKDEwMDIsdCl9LHQucHJvdG90eXBlLl9hd2FpdGluZ19hY2tfaGFuZGxlcj1mdW5jdGlvbih0KXtyZXR1cm4iQUNLIiE9PXQubXNndHlwZSgpP3RoaXMuX2Nsb3NlX2JhZF9wcm90b2NvbCgiRmlyc3QgbWVzc2FnZSB3YXMgbm90IGFuIEFDSyIpOih0aGlzLl9jdXJyZW50X2hhbmRsZXI9ZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKGUpe3JldHVybiB0Ll9zdGVhZHlfc3RhdGVfaGFuZGxlcihlKX19KHRoaXMpLHRoaXMuX3JlcHVsbF9zZXNzaW9uX2RvYygpLG51bGwhPXRoaXMuX3BlbmRpbmdfYWNrPyh0aGlzLl9wZW5kaW5nX2Fja1swXSh0aGlzKSx0aGlzLl9wZW5kaW5nX2Fjaz1udWxsKTp2b2lkIDApfSx0LnByb3RvdHlwZS5fc3RlYWR5X3N0YXRlX2hhbmRsZXI9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIHQucmVxaWQoKWluIHRoaXMuX3BlbmRpbmdfcmVwbGllcz8oZT10aGlzLl9wZW5kaW5nX3JlcGxpZXNbdC5yZXFpZCgpXSxkZWxldGUgdGhpcy5fcGVuZGluZ19yZXBsaWVzW3QucmVxaWQoKV0sZVswXSh0KSk6dC5tc2d0eXBlKClpbiBtP21bdC5tc2d0eXBlKCldKHRoaXMsdCk6Zi5kZWJ1ZygiRG9pbmcgbm90aGluZyB3aXRoIG1lc3NhZ2UgIit0Lm1zZ3R5cGUoKSl9LHR9KCksbz1mdW5jdGlvbigpe2Z1bmN0aW9uIHQodCxlLHIpe3RoaXMuX2Nvbm5lY3Rpb249dCx0aGlzLmRvY3VtZW50PWUsdGhpcy5pZD1yLHRoaXMuX2N1cnJlbnRfcGF0Y2g9bnVsbCx0aGlzLmRvY3VtZW50X2xpc3RlbmVyPWZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihlKXtyZXR1cm4gdC5fZG9jdW1lbnRfY2hhbmdlZChlKX19KHRoaXMpLHRoaXMuZG9jdW1lbnQub25fY2hhbmdlKHRoaXMuZG9jdW1lbnRfbGlzdGVuZXIpfXJldHVybiB0LnByb3RvdHlwZS5jbG9zZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9jb25uZWN0aW9uLmNsb3NlKCl9LHQucHJvdG90eXBlLl9jb25uZWN0aW9uX2Nsb3NlZD1mdW5jdGlvbigpe3JldHVybiB0aGlzLmRvY3VtZW50LnJlbW92ZV9vbl9jaGFuZ2UodGhpcy5kb2N1bWVudF9saXN0ZW5lcil9LHQucHJvdG90eXBlLnJlcXVlc3Rfc2VydmVyX2luZm89ZnVuY3Rpb24oKXt2YXIgdCxlO3JldHVybiB0PXUuY3JlYXRlKCJTRVJWRVItSU5GTy1SRVEiLHt9KSxlPXRoaXMuX2Nvbm5lY3Rpb24uc2VuZF93aXRoX3JlcGx5KHQpLGUudGhlbihmdW5jdGlvbih0KXtyZXR1cm4gdC5jb250ZW50fSl9LHQucHJvdG90eXBlLmZvcmNlX3JvdW5kdHJpcD1mdW5jdGlvbigpe3JldHVybiB0aGlzLnJlcXVlc3Rfc2VydmVyX2luZm8oKS50aGVuKGZ1bmN0aW9uKHQpe30pfSx0LnByb3RvdHlwZS5fc2hvdWxkX3N1cHByZXNzX29uX2NoYW5nZT1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpLHMsYSx1LGMsZixtLGcseSx2LGI7aWYoZSBpbnN0YW5jZW9mIGgpe2ZvcihnPXQuY29udGVudC5ldmVudHMsbj0wLGE9Zy5sZW5ndGg7bjxhO24rKylpZihyPWdbbl0sIk1vZGVsQ2hhbmdlZCI9PT1yLmtpbmQmJnIubW9kZWwuaWQ9PT1lLm1vZGVsLmlkJiZyLmF0dHI9PT1lLmF0dHIpaWYobT1yWyJuZXciXSxlLm5ld18gaW5zdGFuY2VvZiBsKXtpZigib2JqZWN0Ij09dHlwZW9mIG0mJiJpZCJpbiBtJiZtLmlkPT09ZS5uZXdfLmlkKXJldHVybiEwfWVsc2UgaWYoZC5pc0VxdWFsKG0sZS5uZXdfKSlyZXR1cm4hMH1lbHNlIGlmKGUgaW5zdGFuY2VvZiBwKXtmb3IoeT10LmNvbnRlbnQuZXZlbnRzLG89MCx1PXkubGVuZ3RoO288dTtvKyspaWYocj15W29dLCJSb290QWRkZWQiPT09ci5raW5kJiZyLm1vZGVsLmlkPT09ZS5tb2RlbC5pZClyZXR1cm4hMH1lbHNlIGlmKGUgaW5zdGFuY2VvZiBfKXtmb3Iodj10LmNvbnRlbnQuZXZlbnRzLGk9MCxjPXYubGVuZ3RoO2k8YztpKyspaWYocj12W2ldLCJSb290UmVtb3ZlZCI9PT1yLmtpbmQmJnIubW9kZWwuaWQ9PT1lLm1vZGVsLmlkKXJldHVybiEwfWVsc2UgaWYoZSBpbnN0YW5jZW9mIFRpdGxlQ2hhbmdlZEV2ZW50KWZvcihiPXQuY29udGVudC5ldmVudHMscz0wLGY9Yi5sZW5ndGg7czxmO3MrKylpZihyPWJbc10sIlRpdGxlQ2hhbmdlZCI9PT1yLmtpbmQmJnIudGl0bGU9PT1lLnRpdGxlKXJldHVybiEwO3JldHVybiExfSx0LnByb3RvdHlwZS5fZG9jdW1lbnRfY2hhbmdlZD1mdW5jdGlvbih0KXt2YXIgZTtpZighKG51bGwhPXRoaXMuX2N1cnJlbnRfcGF0Y2gmJnRoaXMuX3Nob3VsZF9zdXBwcmVzc19vbl9jaGFuZ2UodGhpcy5fY3VycmVudF9wYXRjaCx0KXx8dCBpbnN0YW5jZW9mIGgmJiEodC5hdHRyIGluIHQubW9kZWwuc2VyaWFsaXphYmxlX2F0dHJpYnV0ZXMoKSkpKXJldHVybiBlPXUuY3JlYXRlKCJQQVRDSC1ET0MiLHt9LHRoaXMuZG9jdW1lbnQuY3JlYXRlX2pzb25fcGF0Y2goW3RdKSksdGhpcy5fY29ubmVjdGlvbi5zZW5kKGUpfSx0LnByb3RvdHlwZS5faGFuZGxlX3BhdGNoPWZ1bmN0aW9uKHQpe3RoaXMuX2N1cnJlbnRfcGF0Y2g9dDt0cnl7cmV0dXJuIHRoaXMuZG9jdW1lbnQuYXBwbHlfanNvbl9wYXRjaCh0LmNvbnRlbnQpfWZpbmFsbHl7dGhpcy5fY3VycmVudF9wYXRjaD1udWxsfX0sdH0oKSxnPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbyxpO3JldHVybiBpPW51bGwscj1udWxsLG89bmV3IGMoZnVuY3Rpb24obyxpKXtyZXR1cm4gcj1uZXcgbih0LGUsZnVuY3Rpb24odCl7dmFyIGUscjt0cnl7cmV0dXJuIG8odCl9Y2F0Y2gocil7dGhyb3cgZT1yLGYuZXJyb3IoIlByb21pc2UgaGFuZGxlciB0aHJldyBhbiBlcnJvciwgY2xvc2luZyBzZXNzaW9uICIrZXJyb3IpLHQuY2xvc2UoKSxlfX0sZnVuY3Rpb24oKXtyZXR1cm4gaShuZXcgRXJyb3IoIkNvbm5lY3Rpb24gd2FzIGNsb3NlZCBiZWZvcmUgd2Ugc3VjY2Vzc2Z1bGx5IHB1bGxlZCBhIHNlc3Npb24iKSl9KSxyLmNvbm5lY3QoKS50aGVuKGZ1bmN0aW9uKHQpe30sZnVuY3Rpb24odCl7dGhyb3cgZi5lcnJvcigiRmFpbGVkIHRvIGNvbm5lY3QgdG8gQm9rZWggc2VydmVyICIrdCksdH0pfSksby5jbG9zZT1mdW5jdGlvbigpe3JldHVybiByLmNsb3NlKCl9LG99LGUuZXhwb3J0cz17cHVsbF9zZXNzaW9uOmcsREVGQVVMVF9TRVJWRVJfV0VCU09DS0VUX1VSTDppLERFRkFVTFRfU0VTU0lPTl9JRDpzfX0seyIuL2NvcmUvaGFzX3Byb3BzIjoiY29yZS9oYXNfcHJvcHMiLCIuL2NvcmUvbG9nZ2luZyI6ImNvcmUvbG9nZ2luZyIsIi4vZG9jdW1lbnQiOiJkb2N1bWVudCIsImVzNi1wcm9taXNlIjoiZXM2LXByb21pc2UiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sImNvbW1vbi9idWlsZF92aWV3cyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk7bj10KCJ1bmRlcnNjb3JlIiksbz1mdW5jdGlvbih0LGUscixvKXt2YXIgcyxhLGwsdSxoLGMscCxfLGQsZixtO2ZvcihudWxsPT1vJiYobz1bXSkscz1bXSxkPW4uZmlsdGVyKGUsZnVuY3Rpb24oZSl7cmV0dXJuIW4uaGFzKHQsZS5pZCl9KSxsPWE9MCxjPWQubGVuZ3RoO2E8YztsPSsrYSlfPWRbbF0sbT1uLmV4dGVuZCh7fSxyLHttb2RlbDpffSksbDxvLmxlbmd0aD90W18uaWRdPW5ldyBvW2xdKG0pOnRbXy5pZF09bmV3IF8uZGVmYXVsdF92aWV3KG0pLHRbXy5pZF0uJGVsLmZpbmQoIipbY2xhc3MqPSd1aS0nXSIpLmVhY2goZnVuY3Rpb24odCxlKXtyZXR1cm4gZS5jbGFzc05hbWU9aShlKX0pLHMucHVzaCh0W18uaWRdKTtmb3IoZj1uLmRpZmZlcmVuY2Uobi5rZXlzKHQpLG4ucGx1Y2soZSwiaWQiKSksdT0wLHA9Zi5sZW5ndGg7dTxwO3UrKyloPWZbdV0sdFtoXS5yZW1vdmUoKSxkZWxldGUgdFtoXTtyZXR1cm4gc30saT1mdW5jdGlvbih0KXt2YXIgZSxyO2lmKG51bGwhPXQuY2xhc3NOYW1lKXJldHVybiBlPXQuY2xhc3NOYW1lLnNwbGl0KCIgIikscj1uLm1hcChlLGZ1bmN0aW9uKHQpe3JldHVybiB0PXQudHJpbSgpLDA9PT10LmluZGV4T2YoInVpLSIpPyJiay0iK3Q6dH0pLHIuam9pbigiICIpfSxvLmpRdWVyeVVJUHJlZml4ZXI9aSxlLmV4cG9ydHM9bz1vfSx7dW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwiY29tbW9uL2hpdHRlc3QiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHA7aD1mdW5jdGlvbih0LGUscixuKXt2YXIgbyxpLHMsYSxsLHUsaCxjO2ZvcihpPSExLGw9cltyLmxlbmd0aC0xXSxoPW5bbi5sZW5ndGgtMV0sbz1zPTAsYT1yLmxlbmd0aDswPD1hP3M8YTpzPmE7bz0wPD1hPysrczotLXMpdT1yW29dLGM9bltvXSxoPGUhPWM8ZSYmbCsoZS1oKS8oYy1oKSoodS1sKTx0JiYoaT0haSksbD11LGg9YztyZXR1cm4gaX0sdT1mdW5jdGlvbigpe3JldHVybiBudWxsfSxuPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCgpe3RoaXNbIjBkIl09e2dseXBoOm51bGwsZ2V0X3ZpZXc6dSxpbmRpY2VzOltdfSx0aGlzWyIxZCJdPXtpbmRpY2VzOltdfSx0aGlzWyIyZCJdPXt9fXJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkodC5wcm90b3R5cGUsIl8wZCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzWyIwZCJdfX0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LnByb3RvdHlwZSwiXzFkIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXNbIjFkIl19fSksT2JqZWN0LmRlZmluZVByb3BlcnR5KHQucHJvdG90eXBlLCJfMmQiLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc1siMmQiXX19KSx0LnByb3RvdHlwZS5pc19lbXB0eT1mdW5jdGlvbigpe3JldHVybiAwPT09dGhpcy5fMGQuaW5kaWNlcy5sZW5ndGgmJjA9PT10aGlzLl8xZC5pbmRpY2VzLmxlbmd0aH0sdH0oKSxpPWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBufSxwPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLGkscyxhO3JldHVybiBvPXRbMF0saT10WzFdLHM9ZVswXSxhPWVbMV0sbz5pJiYocj1baSxvXSxvPXJbMF0saT1yWzFdKSxzPmEmJihuPVthLHNdLHM9blswXSxhPW5bMV0pLHttaW5YOm8sbWluWTpzLG1heFg6aSxtYXhZOmF9fSxjPWZ1bmN0aW9uKHQpe3JldHVybiB0KnR9LHM9ZnVuY3Rpb24odCxlLHIsbil7cmV0dXJuIGModC1yKStjKGUtbil9LGw9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG87cmV0dXJuIG49cyhlLngsZS55LHIueCxyLnkpLDA9PT1uP3ModC54LHQueSxlLngsZS55KToobz0oKHQueC1lLngpKihyLngtZS54KSsodC55LWUueSkqKHIueS1lLnkpKS9uLG88MD9zKHQueCx0LnksZS54LGUueSk6bz4xP3ModC54LHQueSxyLngsci55KTpzKHQueCx0LnksZS54K28qKHIueC1lLngpLGUueStvKihyLnktZS55KSkpfSxhPWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gTWF0aC5zcXJ0KGwodCxlLHIpKX0sbz1mdW5jdGlvbih0LGUscixuLG8saSxzLGEpe3ZhciBsLHUsaCxjLHAsXyxkO3JldHVybiBoPShhLWkpKihyLXQpLShzLW8pKihuLWUpLDA9PT1oP3toaXQ6ITEseDpudWxsLHk6bnVsbH06KGw9ZS1pLHU9dC1vLGM9KHMtbykqbC0oYS1pKSp1LHA9KHItdCkqbC0obi1lKSp1LGw9Yy9oLHU9cC9oLF89dCtsKihyLXQpLGQ9ZStsKihuLWUpLHtoaXQ6bD4wJiZsPDEmJnU+MCYmdTwxLHg6Xyx5OmR9KX0sZS5leHBvcnRzPXtwb2ludF9pbl9wb2x5OmgsSGl0VGVzdFJlc3VsdDpuLGNyZWF0ZV9oaXRfdGVzdF9yZXN1bHQ6aSxkaXN0XzJfcHRzOnMsZGlzdF90b19zZWdtZW50OmEsY2hlY2tfMl9zZWdtZW50c19pbnRlcnNlY3Q6byx2YWxpZGF0ZV9iYm94X2Nvb3JkczpwfX0se31dLCJjb21tb24vbW9kZWxzIjpbZnVuY3Rpb24odCxlLHIpe2UuZXhwb3J0cz17U2VsZWN0aW9uTWFuYWdlcjp0KCIuL3NlbGVjdGlvbl9tYW5hZ2VyIiksU2VsZWN0b3I6dCgiLi9zZWxlY3RvciIpLFRvb2xFdmVudHM6dCgiLi90b29sX2V2ZW50cyIpLEFycm93OnQoIi4uL21vZGVscy9hbm5vdGF0aW9ucy9hcnJvdyIpLEJveEFubm90YXRpb246dCgiLi4vbW9kZWxzL2Fubm90YXRpb25zL2JveF9hbm5vdGF0aW9uIiksQ29sb3JCYXI6dCgiLi4vbW9kZWxzL2Fubm90YXRpb25zL2NvbG9yX2JhciIpLExhYmVsOnQoIi4uL21vZGVscy9hbm5vdGF0aW9ucy9sYWJlbCIpLExhYmVsU2V0OnQoIi4uL21vZGVscy9hbm5vdGF0aW9ucy9sYWJlbF9zZXQiKSxMZWdlbmQ6dCgiLi4vbW9kZWxzL2Fubm90YXRpb25zL2xlZ2VuZCIpLFBvbHlBbm5vdGF0aW9uOnQoIi4uL21vZGVscy9hbm5vdGF0aW9ucy9wb2x5X2Fubm90YXRpb24iKSxTcGFuOnQoIi4uL21vZGVscy9hbm5vdGF0aW9ucy9zcGFuIiksVGl0bGU6dCgiLi4vbW9kZWxzL2Fubm90YXRpb25zL3RpdGxlIiksVG9vbHRpcDp0KCIuLi9tb2RlbHMvYW5ub3RhdGlvbnMvdG9vbHRpcCIpLE9wZW5IZWFkOnQoIi4uL21vZGVscy9hbm5vdGF0aW9ucy9hcnJvd19oZWFkIikuT3BlbkhlYWQsTm9ybWFsSGVhZDp0KCIuLi9tb2RlbHMvYW5ub3RhdGlvbnMvYXJyb3dfaGVhZCIpLk5vcm1hbEhlYWQsVmVlSGVhZDp0KCIuLi9tb2RlbHMvYW5ub3RhdGlvbnMvYXJyb3dfaGVhZCIpLlZlZUhlYWQsQ2F0ZWdvcmljYWxBeGlzOnQoIi4uL21vZGVscy9heGVzL2NhdGVnb3JpY2FsX2F4aXMiKSxEYXRldGltZUF4aXM6dCgiLi4vbW9kZWxzL2F4ZXMvZGF0ZXRpbWVfYXhpcyIpLExpbmVhckF4aXM6dCgiLi4vbW9kZWxzL2F4ZXMvbGluZWFyX2F4aXMiKSxMb2dBeGlzOnQoIi4uL21vZGVscy9heGVzL2xvZ19heGlzIiksQ3VzdG9tSlM6dCgiLi4vbW9kZWxzL2NhbGxiYWNrcy9jdXN0b21qcyIpLE9wZW5VUkw6dCgiLi4vbW9kZWxzL2NhbGxiYWNrcy9vcGVuX3VybCIpLENhbnZhczp0KCIuLi9tb2RlbHMvY2FudmFzL2NhbnZhcyIpLENhcnRlc2lhbkZyYW1lOnQoIi4uL21vZGVscy9jYW52YXMvY2FydGVzaWFuX2ZyYW1lIiksQmFzaWNUaWNrRm9ybWF0dGVyOnQoIi4uL21vZGVscy9mb3JtYXR0ZXJzL2Jhc2ljX3RpY2tfZm9ybWF0dGVyIiksQ2F0ZWdvcmljYWxUaWNrRm9ybWF0dGVyOnQoIi4uL21vZGVscy9mb3JtYXR0ZXJzL2NhdGVnb3JpY2FsX3RpY2tfZm9ybWF0dGVyIiksRGF0ZXRpbWVUaWNrRm9ybWF0dGVyOnQoIi4uL21vZGVscy9mb3JtYXR0ZXJzL2RhdGV0aW1lX3RpY2tfZm9ybWF0dGVyIiksTG9nVGlja0Zvcm1hdHRlcjp0KCIuLi9tb2RlbHMvZm9ybWF0dGVycy9sb2dfdGlja19mb3JtYXR0ZXIiKSxGdW5jVGlja0Zvcm1hdHRlcjp0KCIuLi9tb2RlbHMvZm9ybWF0dGVycy9mdW5jX3RpY2tfZm9ybWF0dGVyIiksTnVtZXJhbFRpY2tGb3JtYXR0ZXI6dCgiLi4vbW9kZWxzL2Zvcm1hdHRlcnMvbnVtZXJhbF90aWNrX2Zvcm1hdHRlciIpLFByaW50ZlRpY2tGb3JtYXR0ZXI6dCgiLi4vbW9kZWxzL2Zvcm1hdHRlcnMvcHJpbnRmX3RpY2tfZm9ybWF0dGVyIiksQW5udWxhcldlZGdlOnQoIi4uL21vZGVscy9nbHlwaHMvYW5udWxhcl93ZWRnZSIpLEFubnVsdXM6dCgiLi4vbW9kZWxzL2dseXBocy9hbm51bHVzIiksQXJjOnQoIi4uL21vZGVscy9nbHlwaHMvYXJjIiksQmV6aWVyOnQoIi4uL21vZGVscy9nbHlwaHMvYmV6aWVyIiksQ2lyY2xlOnQoIi4uL21vZGVscy9nbHlwaHMvY2lyY2xlIiksRWxsaXBzZTp0KCIuLi9tb2RlbHMvZ2x5cGhzL2VsbGlwc2UiKSxHZWFyOnQoIi4uL21vZGVscy9nbHlwaHMvZ2VhciIpLEhCYXI6dCgiLi4vbW9kZWxzL2dseXBocy9oYmFyIiksSW1hZ2U6dCgiLi4vbW9kZWxzL2dseXBocy9pbWFnZSIpLEltYWdlUkdCQTp0KCIuLi9tb2RlbHMvZ2x5cGhzL2ltYWdlX3JnYmEiKSxJbWFnZVVSTDp0KCIuLi9tb2RlbHMvZ2x5cGhzL2ltYWdlX3VybCIpLExpbmU6dCgiLi4vbW9kZWxzL2dseXBocy9saW5lIiksTXVsdGlMaW5lOnQoIi4uL21vZGVscy9nbHlwaHMvbXVsdGlfbGluZSIpLE92YWw6dCgiLi4vbW9kZWxzL2dseXBocy9vdmFsIiksUGF0Y2g6dCgiLi4vbW9kZWxzL2dseXBocy9wYXRjaCIpLFBhdGNoZXM6dCgiLi4vbW9kZWxzL2dseXBocy9wYXRjaGVzIiksUXVhZDp0KCIuLi9tb2RlbHMvZ2x5cGhzL3F1YWQiKSxRdWFkcmF0aWM6dCgiLi4vbW9kZWxzL2dseXBocy9xdWFkcmF0aWMiKSxSYXk6dCgiLi4vbW9kZWxzL2dseXBocy9yYXkiKSxSZWN0OnQoIi4uL21vZGVscy9nbHlwaHMvcmVjdCIpLFNlZ21lbnQ6dCgiLi4vbW9kZWxzL2dseXBocy9zZWdtZW50IiksVGV4dDp0KCIuLi9tb2RlbHMvZ2x5cGhzL3RleHQiKSxWQmFyOnQoIi4uL21vZGVscy9nbHlwaHMvdmJhciIpLFdlZGdlOnQoIi4uL21vZGVscy9nbHlwaHMvd2VkZ2UiKSxHcmlkOnQoIi4uL21vZGVscy9ncmlkcy9ncmlkIiksQ29sdW1uOnQoIi4uL21vZGVscy9sYXlvdXRzL2NvbHVtbiIpLFJvdzp0KCIuLi9tb2RlbHMvbGF5b3V0cy9yb3ciKSxTcGFjZXI6dCgiLi4vbW9kZWxzL2xheW91dHMvc3BhY2VyIiksV2lkZ2V0Qm94OnQoIi4uL21vZGVscy9sYXlvdXRzL3dpZGdldF9ib3giKSxDYXRlZ29yaWNhbE1hcHBlcjp0KCIuLi9tb2RlbHMvbWFwcGVycy9jYXRlZ29yaWNhbF9tYXBwZXIiKSxHcmlkTWFwcGVyOnQoIi4uL21vZGVscy9tYXBwZXJzL2dyaWRfbWFwcGVyIiksTGluZWFyQ29sb3JNYXBwZXI6dCgiLi4vbW9kZWxzL21hcHBlcnMvbGluZWFyX2NvbG9yX21hcHBlciIpLExpbmVhck1hcHBlcjp0KCIuLi9tb2RlbHMvbWFwcGVycy9saW5lYXJfbWFwcGVyIiksTG9nQ29sb3JNYXBwZXI6dCgiLi4vbW9kZWxzL21hcHBlcnMvbG9nX2NvbG9yX21hcHBlciIpLExvZ01hcHBlcjp0KCIuLi9tb2RlbHMvbWFwcGVycy9sb2dfbWFwcGVyIiksVHJhbnNmb3JtOnQoIi4uL21vZGVscy90cmFuc2Zvcm1zL3RyYW5zZm9ybSIpLEppdHRlcjp0KCIuLi9tb2RlbHMvdHJhbnNmb3Jtcy9qaXR0ZXIiKSxJbnRlcnBvbGF0b3I6dCgiLi4vbW9kZWxzL3RyYW5zZm9ybXMvaW50ZXJwb2xhdG9yIiksTGluZWFySW50ZXJwb2xhdG9yOnQoIi4uL21vZGVscy90cmFuc2Zvcm1zL2xpbmVhcl9pbnRlcnBvbGF0b3IiKSxTdGVwSW50ZXJwb2xhdG9yOnQoIi4uL21vZGVscy90cmFuc2Zvcm1zL3N0ZXBfaW50ZXJwb2xhdG9yIiksQXN0ZXJpc2s6dCgiLi4vbW9kZWxzL21hcmtlcnMvaW5kZXgiKS5Bc3RlcmlzayxDaXJjbGVDcm9zczp0KCIuLi9tb2RlbHMvbWFya2Vycy9pbmRleCIpLkNpcmNsZUNyb3NzLENpcmNsZVg6dCgiLi4vbW9kZWxzL21hcmtlcnMvaW5kZXgiKS5DaXJjbGVYLENyb3NzOnQoIi4uL21vZGVscy9tYXJrZXJzL2luZGV4IikuQ3Jvc3MsRGlhbW9uZDp0KCIuLi9tb2RlbHMvbWFya2Vycy9pbmRleCIpLkRpYW1vbmQsRGlhbW9uZENyb3NzOnQoIi4uL21vZGVscy9tYXJrZXJzL2luZGV4IikuRGlhbW9uZENyb3NzLEludmVydGVkVHJpYW5nbGU6dCgiLi4vbW9kZWxzL21hcmtlcnMvaW5kZXgiKS5JbnZlcnRlZFRyaWFuZ2xlLFNxdWFyZTp0KCIuLi9tb2RlbHMvbWFya2Vycy9pbmRleCIpLlNxdWFyZSxTcXVhcmVDcm9zczp0KCIuLi9tb2RlbHMvbWFya2Vycy9pbmRleCIpLlNxdWFyZUNyb3NzLFNxdWFyZVg6dCgiLi4vbW9kZWxzL21hcmtlcnMvaW5kZXgiKS5TcXVhcmVYLFRyaWFuZ2xlOnQoIi4uL21vZGVscy9tYXJrZXJzL2luZGV4IikuVHJpYW5nbGUsWDp0KCIuLi9tb2RlbHMvbWFya2Vycy9pbmRleCIpLlgsUGxvdDp0KCIuLi9tb2RlbHMvcGxvdHMvcGxvdCIpLEdNYXBQbG90OnQoIi4uL21vZGVscy9wbG90cy9nbWFwX3Bsb3QiKSxEYXRhUmFuZ2UxZDp0KCIuLi9tb2RlbHMvcmFuZ2VzL2RhdGFfcmFuZ2UxZCIpLEZhY3RvclJhbmdlOnQoIi4uL21vZGVscy9yYW5nZXMvZmFjdG9yX3JhbmdlIiksUmFuZ2UxZDp0KCIuLi9tb2RlbHMvcmFuZ2VzL3JhbmdlMWQiKSxHbHlwaFJlbmRlcmVyOnQoIi4uL21vZGVscy9yZW5kZXJlcnMvZ2x5cGhfcmVuZGVyZXIiKSxBamF4RGF0YVNvdXJjZTp0KCIuLi9tb2RlbHMvc291cmNlcy9hamF4X2RhdGFfc291cmNlIiksQ29sdW1uRGF0YVNvdXJjZTp0KCIuLi9tb2RlbHMvc291cmNlcy9jb2x1bW5fZGF0YV9zb3VyY2UiKSxHZW9KU09ORGF0YVNvdXJjZTp0KCIuLi9tb2RlbHMvc291cmNlcy9nZW9qc29uX2RhdGFfc291cmNlIiksQWRhcHRpdmVUaWNrZXI6dCgiLi4vbW9kZWxzL3RpY2tlcnMvYWRhcHRpdmVfdGlja2VyIiksQmFzaWNUaWNrZXI6dCgiLi4vbW9kZWxzL3RpY2tlcnMvYmFzaWNfdGlja2VyIiksQ2F0ZWdvcmljYWxUaWNrZXI6dCgiLi4vbW9kZWxzL3RpY2tlcnMvY2F0ZWdvcmljYWxfdGlja2VyIiksQ29tcG9zaXRlVGlja2VyOnQoIi4uL21vZGVscy90aWNrZXJzL2NvbXBvc2l0ZV90aWNrZXIiKSxDb250aW51b3VzVGlja2VyOnQoIi4uL21vZGVscy90aWNrZXJzL2NvbnRpbnVvdXNfdGlja2VyIiksRGF0ZXRpbWVUaWNrZXI6dCgiLi4vbW9kZWxzL3RpY2tlcnMvZGF0ZXRpbWVfdGlja2VyIiksRGF5c1RpY2tlcjp0KCIuLi9tb2RlbHMvdGlja2Vycy9kYXlzX3RpY2tlciIpLEZpeGVkVGlja2VyOnQoIi4uL21vZGVscy90aWNrZXJzL2ZpeGVkX3RpY2tlciIpLExvZ1RpY2tlcjp0KCIuLi9tb2RlbHMvdGlja2Vycy9sb2dfdGlja2VyIiksTW9udGhzVGlja2VyOnQoIi4uL21vZGVscy90aWNrZXJzL21vbnRoc190aWNrZXIiKSxTaW5nbGVJbnRlcnZhbFRpY2tlcjp0KCIuLi9tb2RlbHMvdGlja2Vycy9zaW5nbGVfaW50ZXJ2YWxfdGlja2VyIiksWWVhcnNUaWNrZXI6dCgiLi4vbW9kZWxzL3RpY2tlcnMveWVhcnNfdGlja2VyIiksVGlsZVJlbmRlcmVyOnQoIi4uL21vZGVscy90aWxlcy90aWxlX3JlbmRlcmVyIiksVGlsZVNvdXJjZTp0KCIuLi9tb2RlbHMvdGlsZXMvdGlsZV9zb3VyY2UiKSxUTVNUaWxlU291cmNlOnQoIi4uL21vZGVscy90aWxlcy90bXNfdGlsZV9zb3VyY2UiKSxXTVRTVGlsZVNvdXJjZTp0KCIuLi9tb2RlbHMvdGlsZXMvd210c190aWxlX3NvdXJjZSIpLFFVQURLRVlUaWxlU291cmNlOnQoIi4uL21vZGVscy90aWxlcy9xdWFka2V5X3RpbGVfc291cmNlIiksQkJveFRpbGVTb3VyY2U6dCgiLi4vbW9kZWxzL3RpbGVzL2Jib3hfdGlsZV9zb3VyY2UiKSxEeW5hbWljSW1hZ2VSZW5kZXJlcjp0KCIuLi9tb2RlbHMvdGlsZXMvZHluYW1pY19pbWFnZV9yZW5kZXJlciIpLEltYWdlU291cmNlOnQoIi4uL21vZGVscy90aWxlcy9pbWFnZV9zb3VyY2UiKSxUb29sYmFyOnQoIi4uL21vZGVscy90b29scy90b29sYmFyIiksVG9vbGJhckJveDp0KCIuLi9tb2RlbHMvdG9vbHMvdG9vbGJhcl9ib3giKSxCdXR0b25Ub29sOnQoIi4uL21vZGVscy90b29scy9idXR0b25fdG9vbCIpLEFjdGlvblRvb2w6dCgiLi4vbW9kZWxzL3Rvb2xzL2FjdGlvbnMvYWN0aW9uX3Rvb2wiKSxTYXZlVG9vbDp0KCIuLi9tb2RlbHMvdG9vbHMvYWN0aW9ucy9zYXZlX3Rvb2wiKSxVbmRvVG9vbDp0KCIuLi9tb2RlbHMvdG9vbHMvYWN0aW9ucy91bmRvX3Rvb2wiKSxSZWRvVG9vbDp0KCIuLi9tb2RlbHMvdG9vbHMvYWN0aW9ucy9yZWRvX3Rvb2wiKSxSZXNldFRvb2w6dCgiLi4vbW9kZWxzL3Rvb2xzL2FjdGlvbnMvcmVzZXRfdG9vbCIpLEhlbHBUb29sOnQoIi4uL21vZGVscy90b29scy9hY3Rpb25zL2hlbHBfdG9vbCIpLEJveFNlbGVjdFRvb2w6dCgiLi4vbW9kZWxzL3Rvb2xzL2dlc3R1cmVzL2JveF9zZWxlY3RfdG9vbCIpLEJveFpvb21Ub29sOnQoIi4uL21vZGVscy90b29scy9nZXN0dXJlcy9ib3hfem9vbV90b29sIiksR2VzdHVyZVRvb2w6dCgiLi4vbW9kZWxzL3Rvb2xzL2dlc3R1cmVzL2dlc3R1cmVfdG9vbCIpLExhc3NvU2VsZWN0VG9vbDp0KCIuLi9tb2RlbHMvdG9vbHMvZ2VzdHVyZXMvbGFzc29fc2VsZWN0X3Rvb2wiKSxQYW5Ub29sOnQoIi4uL21vZGVscy90b29scy9nZXN0dXJlcy9wYW5fdG9vbCIpLFBvbHlTZWxlY3RUb29sOnQoIi4uL21vZGVscy90b29scy9nZXN0dXJlcy9wb2x5X3NlbGVjdF90b29sIiksU2VsZWN0VG9vbDp0KCIuLi9tb2RlbHMvdG9vbHMvZ2VzdHVyZXMvc2VsZWN0X3Rvb2wiKSxSZXNpemVUb29sOnQoIi4uL21vZGVscy90b29scy9nZXN0dXJlcy9yZXNpemVfdG9vbCIpLFRhcFRvb2w6dCgiLi4vbW9kZWxzL3Rvb2xzL2dlc3R1cmVzL3RhcF90b29sIiksV2hlZWxab29tVG9vbDp0KCIuLi9tb2RlbHMvdG9vbHMvZ2VzdHVyZXMvd2hlZWxfem9vbV90b29sIiksQ3Jvc3NoYWlyVG9vbDp0KCIuLi9tb2RlbHMvdG9vbHMvaW5zcGVjdG9ycy9jcm9zc2hhaXJfdG9vbCIpLEhvdmVyVG9vbDp0KCIuLi9tb2RlbHMvdG9vbHMvaW5zcGVjdG9ycy9ob3Zlcl90b29sIiksSW5zcGVjdFRvb2w6dCgiLi4vbW9kZWxzL3Rvb2xzL2luc3BlY3RvcnMvaW5zcGVjdF90b29sIil9fSx7Ii4uL21vZGVscy9hbm5vdGF0aW9ucy9hcnJvdyI6Im1vZGVscy9hbm5vdGF0aW9ucy9hcnJvdyIsIi4uL21vZGVscy9hbm5vdGF0aW9ucy9hcnJvd19oZWFkIjoibW9kZWxzL2Fubm90YXRpb25zL2Fycm93X2hlYWQiLCIuLi9tb2RlbHMvYW5ub3RhdGlvbnMvYm94X2Fubm90YXRpb24iOiJtb2RlbHMvYW5ub3RhdGlvbnMvYm94X2Fubm90YXRpb24iLCIuLi9tb2RlbHMvYW5ub3RhdGlvbnMvY29sb3JfYmFyIjoibW9kZWxzL2Fubm90YXRpb25zL2NvbG9yX2JhciIsIi4uL21vZGVscy9hbm5vdGF0aW9ucy9sYWJlbCI6Im1vZGVscy9hbm5vdGF0aW9ucy9sYWJlbCIsIi4uL21vZGVscy9hbm5vdGF0aW9ucy9sYWJlbF9zZXQiOiJtb2RlbHMvYW5ub3RhdGlvbnMvbGFiZWxfc2V0IiwiLi4vbW9kZWxzL2Fubm90YXRpb25zL2xlZ2VuZCI6Im1vZGVscy9hbm5vdGF0aW9ucy9sZWdlbmQiLCIuLi9tb2RlbHMvYW5ub3RhdGlvbnMvcG9seV9hbm5vdGF0aW9uIjoibW9kZWxzL2Fubm90YXRpb25zL3BvbHlfYW5ub3RhdGlvbiIsIi4uL21vZGVscy9hbm5vdGF0aW9ucy9zcGFuIjoibW9kZWxzL2Fubm90YXRpb25zL3NwYW4iLCIuLi9tb2RlbHMvYW5ub3RhdGlvbnMvdGl0bGUiOiJtb2RlbHMvYW5ub3RhdGlvbnMvdGl0bGUiLCIuLi9tb2RlbHMvYW5ub3RhdGlvbnMvdG9vbHRpcCI6Im1vZGVscy9hbm5vdGF0aW9ucy90b29sdGlwIiwiLi4vbW9kZWxzL2F4ZXMvY2F0ZWdvcmljYWxfYXhpcyI6Im1vZGVscy9heGVzL2NhdGVnb3JpY2FsX2F4aXMiLCIuLi9tb2RlbHMvYXhlcy9kYXRldGltZV9heGlzIjoibW9kZWxzL2F4ZXMvZGF0ZXRpbWVfYXhpcyIsIi4uL21vZGVscy9heGVzL2xpbmVhcl9heGlzIjoibW9kZWxzL2F4ZXMvbGluZWFyX2F4aXMiLCIuLi9tb2RlbHMvYXhlcy9sb2dfYXhpcyI6Im1vZGVscy9heGVzL2xvZ19heGlzIiwiLi4vbW9kZWxzL2NhbGxiYWNrcy9jdXN0b21qcyI6Im1vZGVscy9jYWxsYmFja3MvY3VzdG9tanMiLCIuLi9tb2RlbHMvY2FsbGJhY2tzL29wZW5fdXJsIjoibW9kZWxzL2NhbGxiYWNrcy9vcGVuX3VybCIsIi4uL21vZGVscy9jYW52YXMvY2FudmFzIjoibW9kZWxzL2NhbnZhcy9jYW52YXMiLCIuLi9tb2RlbHMvY2FudmFzL2NhcnRlc2lhbl9mcmFtZSI6Im1vZGVscy9jYW52YXMvY2FydGVzaWFuX2ZyYW1lIiwiLi4vbW9kZWxzL2Zvcm1hdHRlcnMvYmFzaWNfdGlja19mb3JtYXR0ZXIiOiJtb2RlbHMvZm9ybWF0dGVycy9iYXNpY190aWNrX2Zvcm1hdHRlciIsIi4uL21vZGVscy9mb3JtYXR0ZXJzL2NhdGVnb3JpY2FsX3RpY2tfZm9ybWF0dGVyIjoibW9kZWxzL2Zvcm1hdHRlcnMvY2F0ZWdvcmljYWxfdGlja19mb3JtYXR0ZXIiLCIuLi9tb2RlbHMvZm9ybWF0dGVycy9kYXRldGltZV90aWNrX2Zvcm1hdHRlciI6Im1vZGVscy9mb3JtYXR0ZXJzL2RhdGV0aW1lX3RpY2tfZm9ybWF0dGVyIiwiLi4vbW9kZWxzL2Zvcm1hdHRlcnMvZnVuY190aWNrX2Zvcm1hdHRlciI6Im1vZGVscy9mb3JtYXR0ZXJzL2Z1bmNfdGlja19mb3JtYXR0ZXIiLCIuLi9tb2RlbHMvZm9ybWF0dGVycy9sb2dfdGlja19mb3JtYXR0ZXIiOiJtb2RlbHMvZm9ybWF0dGVycy9sb2dfdGlja19mb3JtYXR0ZXIiLCIuLi9tb2RlbHMvZm9ybWF0dGVycy9udW1lcmFsX3RpY2tfZm9ybWF0dGVyIjoibW9kZWxzL2Zvcm1hdHRlcnMvbnVtZXJhbF90aWNrX2Zvcm1hdHRlciIsIi4uL21vZGVscy9mb3JtYXR0ZXJzL3ByaW50Zl90aWNrX2Zvcm1hdHRlciI6Im1vZGVscy9mb3JtYXR0ZXJzL3ByaW50Zl90aWNrX2Zvcm1hdHRlciIsIi4uL21vZGVscy9nbHlwaHMvYW5udWxhcl93ZWRnZSI6Im1vZGVscy9nbHlwaHMvYW5udWxhcl93ZWRnZSIsIi4uL21vZGVscy9nbHlwaHMvYW5udWx1cyI6Im1vZGVscy9nbHlwaHMvYW5udWx1cyIsIi4uL21vZGVscy9nbHlwaHMvYXJjIjoibW9kZWxzL2dseXBocy9hcmMiLCIuLi9tb2RlbHMvZ2x5cGhzL2JlemllciI6Im1vZGVscy9nbHlwaHMvYmV6aWVyIiwiLi4vbW9kZWxzL2dseXBocy9jaXJjbGUiOiJtb2RlbHMvZ2x5cGhzL2NpcmNsZSIsIi4uL21vZGVscy9nbHlwaHMvZWxsaXBzZSI6Im1vZGVscy9nbHlwaHMvZWxsaXBzZSIsIi4uL21vZGVscy9nbHlwaHMvZ2VhciI6Im1vZGVscy9nbHlwaHMvZ2VhciIsIi4uL21vZGVscy9nbHlwaHMvaGJhciI6Im1vZGVscy9nbHlwaHMvaGJhciIsIi4uL21vZGVscy9nbHlwaHMvaW1hZ2UiOiJtb2RlbHMvZ2x5cGhzL2ltYWdlIiwiLi4vbW9kZWxzL2dseXBocy9pbWFnZV9yZ2JhIjoibW9kZWxzL2dseXBocy9pbWFnZV9yZ2JhIiwiLi4vbW9kZWxzL2dseXBocy9pbWFnZV91cmwiOiJtb2RlbHMvZ2x5cGhzL2ltYWdlX3VybCIsIi4uL21vZGVscy9nbHlwaHMvbGluZSI6Im1vZGVscy9nbHlwaHMvbGluZSIsIi4uL21vZGVscy9nbHlwaHMvbXVsdGlfbGluZSI6Im1vZGVscy9nbHlwaHMvbXVsdGlfbGluZSIsIi4uL21vZGVscy9nbHlwaHMvb3ZhbCI6Im1vZGVscy9nbHlwaHMvb3ZhbCIsIi4uL21vZGVscy9nbHlwaHMvcGF0Y2giOiJtb2RlbHMvZ2x5cGhzL3BhdGNoIiwiLi4vbW9kZWxzL2dseXBocy9wYXRjaGVzIjoibW9kZWxzL2dseXBocy9wYXRjaGVzIiwiLi4vbW9kZWxzL2dseXBocy9xdWFkIjoibW9kZWxzL2dseXBocy9xdWFkIiwiLi4vbW9kZWxzL2dseXBocy9xdWFkcmF0aWMiOiJtb2RlbHMvZ2x5cGhzL3F1YWRyYXRpYyIsIi4uL21vZGVscy9nbHlwaHMvcmF5IjoibW9kZWxzL2dseXBocy9yYXkiLCIuLi9tb2RlbHMvZ2x5cGhzL3JlY3QiOiJtb2RlbHMvZ2x5cGhzL3JlY3QiLCIuLi9tb2RlbHMvZ2x5cGhzL3NlZ21lbnQiOiJtb2RlbHMvZ2x5cGhzL3NlZ21lbnQiLCIuLi9tb2RlbHMvZ2x5cGhzL3RleHQiOiJtb2RlbHMvZ2x5cGhzL3RleHQiLCIuLi9tb2RlbHMvZ2x5cGhzL3ZiYXIiOiJtb2RlbHMvZ2x5cGhzL3ZiYXIiLCIuLi9tb2RlbHMvZ2x5cGhzL3dlZGdlIjoibW9kZWxzL2dseXBocy93ZWRnZSIsIi4uL21vZGVscy9ncmlkcy9ncmlkIjoibW9kZWxzL2dyaWRzL2dyaWQiLCIuLi9tb2RlbHMvbGF5b3V0cy9jb2x1bW4iOiJtb2RlbHMvbGF5b3V0cy9jb2x1bW4iLCIuLi9tb2RlbHMvbGF5b3V0cy9yb3ciOiJtb2RlbHMvbGF5b3V0cy9yb3ciLCIuLi9tb2RlbHMvbGF5b3V0cy9zcGFjZXIiOiJtb2RlbHMvbGF5b3V0cy9zcGFjZXIiLCIuLi9tb2RlbHMvbGF5b3V0cy93aWRnZXRfYm94IjoibW9kZWxzL2xheW91dHMvd2lkZ2V0X2JveCIsIi4uL21vZGVscy9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciI6Im1vZGVscy9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciIsIi4uL21vZGVscy9tYXBwZXJzL2dyaWRfbWFwcGVyIjoibW9kZWxzL21hcHBlcnMvZ3JpZF9tYXBwZXIiLCIuLi9tb2RlbHMvbWFwcGVycy9saW5lYXJfY29sb3JfbWFwcGVyIjoibW9kZWxzL21hcHBlcnMvbGluZWFyX2NvbG9yX21hcHBlciIsIi4uL21vZGVscy9tYXBwZXJzL2xpbmVhcl9tYXBwZXIiOiJtb2RlbHMvbWFwcGVycy9saW5lYXJfbWFwcGVyIiwiLi4vbW9kZWxzL21hcHBlcnMvbG9nX2NvbG9yX21hcHBlciI6Im1vZGVscy9tYXBwZXJzL2xvZ19jb2xvcl9tYXBwZXIiLCIuLi9tb2RlbHMvbWFwcGVycy9sb2dfbWFwcGVyIjoibW9kZWxzL21hcHBlcnMvbG9nX21hcHBlciIsIi4uL21vZGVscy9tYXJrZXJzL2luZGV4IjoibW9kZWxzL21hcmtlcnMvaW5kZXgiLCIuLi9tb2RlbHMvcGxvdHMvZ21hcF9wbG90IjoibW9kZWxzL3Bsb3RzL2dtYXBfcGxvdCIsIi4uL21vZGVscy9wbG90cy9wbG90IjoibW9kZWxzL3Bsb3RzL3Bsb3QiLCIuLi9tb2RlbHMvcmFuZ2VzL2RhdGFfcmFuZ2UxZCI6Im1vZGVscy9yYW5nZXMvZGF0YV9yYW5nZTFkIiwiLi4vbW9kZWxzL3Jhbmdlcy9mYWN0b3JfcmFuZ2UiOiJtb2RlbHMvcmFuZ2VzL2ZhY3Rvcl9yYW5nZSIsIi4uL21vZGVscy9yYW5nZXMvcmFuZ2UxZCI6Im1vZGVscy9yYW5nZXMvcmFuZ2UxZCIsIi4uL21vZGVscy9yZW5kZXJlcnMvZ2x5cGhfcmVuZGVyZXIiOiJtb2RlbHMvcmVuZGVyZXJzL2dseXBoX3JlbmRlcmVyIiwiLi4vbW9kZWxzL3NvdXJjZXMvYWpheF9kYXRhX3NvdXJjZSI6Im1vZGVscy9zb3VyY2VzL2FqYXhfZGF0YV9zb3VyY2UiLCIuLi9tb2RlbHMvc291cmNlcy9jb2x1bW5fZGF0YV9zb3VyY2UiOiJtb2RlbHMvc291cmNlcy9jb2x1bW5fZGF0YV9zb3VyY2UiLCIuLi9tb2RlbHMvc291cmNlcy9nZW9qc29uX2RhdGFfc291cmNlIjoibW9kZWxzL3NvdXJjZXMvZ2VvanNvbl9kYXRhX3NvdXJjZSIsIi4uL21vZGVscy90aWNrZXJzL2FkYXB0aXZlX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL2FkYXB0aXZlX3RpY2tlciIsIi4uL21vZGVscy90aWNrZXJzL2Jhc2ljX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL2Jhc2ljX3RpY2tlciIsIi4uL21vZGVscy90aWNrZXJzL2NhdGVnb3JpY2FsX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL2NhdGVnb3JpY2FsX3RpY2tlciIsIi4uL21vZGVscy90aWNrZXJzL2NvbXBvc2l0ZV90aWNrZXIiOiJtb2RlbHMvdGlja2Vycy9jb21wb3NpdGVfdGlja2VyIiwiLi4vbW9kZWxzL3RpY2tlcnMvY29udGludW91c190aWNrZXIiOiJtb2RlbHMvdGlja2Vycy9jb250aW51b3VzX3RpY2tlciIsIi4uL21vZGVscy90aWNrZXJzL2RhdGV0aW1lX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL2RhdGV0aW1lX3RpY2tlciIsIi4uL21vZGVscy90aWNrZXJzL2RheXNfdGlja2VyIjoibW9kZWxzL3RpY2tlcnMvZGF5c190aWNrZXIiLCIuLi9tb2RlbHMvdGlja2Vycy9maXhlZF90aWNrZXIiOiJtb2RlbHMvdGlja2Vycy9maXhlZF90aWNrZXIiLCIuLi9tb2RlbHMvdGlja2Vycy9sb2dfdGlja2VyIjoibW9kZWxzL3RpY2tlcnMvbG9nX3RpY2tlciIsIi4uL21vZGVscy90aWNrZXJzL21vbnRoc190aWNrZXIiOiJtb2RlbHMvdGlja2Vycy9tb250aHNfdGlja2VyIiwiLi4vbW9kZWxzL3RpY2tlcnMvc2luZ2xlX2ludGVydmFsX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL3NpbmdsZV9pbnRlcnZhbF90aWNrZXIiLCIuLi9tb2RlbHMvdGlja2Vycy95ZWFyc190aWNrZXIiOiJtb2RlbHMvdGlja2Vycy95ZWFyc190aWNrZXIiLCIuLi9tb2RlbHMvdGlsZXMvYmJveF90aWxlX3NvdXJjZSI6Im1vZGVscy90aWxlcy9iYm94X3RpbGVfc291cmNlIiwiLi4vbW9kZWxzL3RpbGVzL2R5bmFtaWNfaW1hZ2VfcmVuZGVyZXIiOiJtb2RlbHMvdGlsZXMvZHluYW1pY19pbWFnZV9yZW5kZXJlciIsIi4uL21vZGVscy90aWxlcy9pbWFnZV9zb3VyY2UiOiJtb2RlbHMvdGlsZXMvaW1hZ2Vfc291cmNlIiwiLi4vbW9kZWxzL3RpbGVzL3F1YWRrZXlfdGlsZV9zb3VyY2UiOiJtb2RlbHMvdGlsZXMvcXVhZGtleV90aWxlX3NvdXJjZSIsIi4uL21vZGVscy90aWxlcy90aWxlX3JlbmRlcmVyIjoibW9kZWxzL3RpbGVzL3RpbGVfcmVuZGVyZXIiLCIuLi9tb2RlbHMvdGlsZXMvdGlsZV9zb3VyY2UiOiJtb2RlbHMvdGlsZXMvdGlsZV9zb3VyY2UiLCIuLi9tb2RlbHMvdGlsZXMvdG1zX3RpbGVfc291cmNlIjoibW9kZWxzL3RpbGVzL3Rtc190aWxlX3NvdXJjZSIsIi4uL21vZGVscy90aWxlcy93bXRzX3RpbGVfc291cmNlIjoibW9kZWxzL3RpbGVzL3dtdHNfdGlsZV9zb3VyY2UiLCIuLi9tb2RlbHMvdG9vbHMvYWN0aW9ucy9hY3Rpb25fdG9vbCI6Im1vZGVscy90b29scy9hY3Rpb25zL2FjdGlvbl90b29sIiwiLi4vbW9kZWxzL3Rvb2xzL2FjdGlvbnMvaGVscF90b29sIjoibW9kZWxzL3Rvb2xzL2FjdGlvbnMvaGVscF90b29sIiwiLi4vbW9kZWxzL3Rvb2xzL2FjdGlvbnMvcmVkb190b29sIjoibW9kZWxzL3Rvb2xzL2FjdGlvbnMvcmVkb190b29sIiwiLi4vbW9kZWxzL3Rvb2xzL2FjdGlvbnMvcmVzZXRfdG9vbCI6Im1vZGVscy90b29scy9hY3Rpb25zL3Jlc2V0X3Rvb2wiLCIuLi9tb2RlbHMvdG9vbHMvYWN0aW9ucy9zYXZlX3Rvb2wiOiJtb2RlbHMvdG9vbHMvYWN0aW9ucy9zYXZlX3Rvb2wiLCIuLi9tb2RlbHMvdG9vbHMvYWN0aW9ucy91bmRvX3Rvb2wiOiJtb2RlbHMvdG9vbHMvYWN0aW9ucy91bmRvX3Rvb2wiLCIuLi9tb2RlbHMvdG9vbHMvYnV0dG9uX3Rvb2wiOiJtb2RlbHMvdG9vbHMvYnV0dG9uX3Rvb2wiLCIuLi9tb2RlbHMvdG9vbHMvZ2VzdHVyZXMvYm94X3NlbGVjdF90b29sIjoibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL2JveF9zZWxlY3RfdG9vbCIsIi4uL21vZGVscy90b29scy9nZXN0dXJlcy9ib3hfem9vbV90b29sIjoibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL2JveF96b29tX3Rvb2wiLCIuLi9tb2RlbHMvdG9vbHMvZ2VzdHVyZXMvZ2VzdHVyZV90b29sIjoibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL2dlc3R1cmVfdG9vbCIsIi4uL21vZGVscy90b29scy9nZXN0dXJlcy9sYXNzb19zZWxlY3RfdG9vbCI6Im1vZGVscy90b29scy9nZXN0dXJlcy9sYXNzb19zZWxlY3RfdG9vbCIsIi4uL21vZGVscy90b29scy9nZXN0dXJlcy9wYW5fdG9vbCI6Im1vZGVscy90b29scy9nZXN0dXJlcy9wYW5fdG9vbCIsIi4uL21vZGVscy90b29scy9nZXN0dXJlcy9wb2x5X3NlbGVjdF90b29sIjoibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL3BvbHlfc2VsZWN0X3Rvb2wiLCIuLi9tb2RlbHMvdG9vbHMvZ2VzdHVyZXMvcmVzaXplX3Rvb2wiOiJtb2RlbHMvdG9vbHMvZ2VzdHVyZXMvcmVzaXplX3Rvb2wiLCIuLi9tb2RlbHMvdG9vbHMvZ2VzdHVyZXMvc2VsZWN0X3Rvb2wiOiJtb2RlbHMvdG9vbHMvZ2VzdHVyZXMvc2VsZWN0X3Rvb2wiLCIuLi9tb2RlbHMvdG9vbHMvZ2VzdHVyZXMvdGFwX3Rvb2wiOiJtb2RlbHMvdG9vbHMvZ2VzdHVyZXMvdGFwX3Rvb2wiLCIuLi9tb2RlbHMvdG9vbHMvZ2VzdHVyZXMvd2hlZWxfem9vbV90b29sIjoibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL3doZWVsX3pvb21fdG9vbCIsIi4uL21vZGVscy90b29scy9pbnNwZWN0b3JzL2Nyb3NzaGFpcl90b29sIjoibW9kZWxzL3Rvb2xzL2luc3BlY3RvcnMvY3Jvc3NoYWlyX3Rvb2wiLCIuLi9tb2RlbHMvdG9vbHMvaW5zcGVjdG9ycy9ob3Zlcl90b29sIjoibW9kZWxzL3Rvb2xzL2luc3BlY3RvcnMvaG92ZXJfdG9vbCIsIi4uL21vZGVscy90b29scy9pbnNwZWN0b3JzL2luc3BlY3RfdG9vbCI6Im1vZGVscy90b29scy9pbnNwZWN0b3JzL2luc3BlY3RfdG9vbCIsIi4uL21vZGVscy90b29scy90b29sYmFyIjoibW9kZWxzL3Rvb2xzL3Rvb2xiYXIiLCIuLi9tb2RlbHMvdG9vbHMvdG9vbGJhcl9ib3giOiJtb2RlbHMvdG9vbHMvdG9vbGJhcl9ib3giLCIuLi9tb2RlbHMvdHJhbnNmb3Jtcy9pbnRlcnBvbGF0b3IiOiJtb2RlbHMvdHJhbnNmb3Jtcy9pbnRlcnBvbGF0b3IiLCIuLi9tb2RlbHMvdHJhbnNmb3Jtcy9qaXR0ZXIiOiJtb2RlbHMvdHJhbnNmb3Jtcy9qaXR0ZXIiLCIuLi9tb2RlbHMvdHJhbnNmb3Jtcy9saW5lYXJfaW50ZXJwb2xhdG9yIjoibW9kZWxzL3RyYW5zZm9ybXMvbGluZWFyX2ludGVycG9sYXRvciIsIi4uL21vZGVscy90cmFuc2Zvcm1zL3N0ZXBfaW50ZXJwb2xhdG9yIjoibW9kZWxzL3RyYW5zZm9ybXMvc3RlcF9pbnRlcnBvbGF0b3IiLCIuLi9tb2RlbHMvdHJhbnNmb3Jtcy90cmFuc2Zvcm0iOiJtb2RlbHMvdHJhbnNmb3Jtcy90cmFuc2Zvcm0iLCIuL3NlbGVjdGlvbl9tYW5hZ2VyIjoiY29tbW9uL3NlbGVjdGlvbl9tYW5hZ2VyIiwiLi9zZWxlY3RvciI6ImNvbW1vbi9zZWxlY3RvciIsIi4vdG9vbF9ldmVudHMiOiJjb21tb24vdG9vbF9ldmVudHMifV0sImNvbW1vbi9zZWxlY3Rpb25fbWFuYWdlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbj10KCIuLi9jb3JlL2hhc19wcm9wcyIpLGw9dCgiLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLGk9dCgiLi9zZWxlY3RvciIpLGE9dCgiLi9oaXR0ZXN0IiksdT10KCIuLi9jb3JlL3Byb3BlcnRpZXMiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBoKGUsdCksZS5wcm90b3R5cGUudHlwZT0iU2VsZWN0aW9uTWFuYWdlciIsZS5pbnRlcm5hbCh7c291cmNlOlt1LkFueV19KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5zZWxlY3RvcnM9e30sdGhpcy5pbnNwZWN0b3JzPXt9LHRoaXMubGFzdF9pbnNwZWN0aW9uX3dhc19lbXB0eT17fX0sZS5wcm90b3R5cGUuc2VsZWN0PWZ1bmN0aW9uKHQsZSxyLG4sbyl7dmFyIGkscyxhO3JldHVybiBudWxsPT1vJiYobz0hMSksYT10aGlzLmdldCgic291cmNlIiksYSE9PWUubWdldCgiZGF0YV9zb3VyY2UiKSYmbC53YXJuKCJzZWxlY3QgY2FsbGVkIHdpdGggbWlzLW1hdGNoZWQgZGF0YSBzb3VyY2VzIiksaT1lLmhpdF90ZXN0KHIpLG51bGwhPWkmJihzPXRoaXMuX2dldF9zZWxlY3RvcihlKSxzLnVwZGF0ZShpLG4sbyksdGhpcy5nZXQoInNvdXJjZSIpLnNldCh7c2VsZWN0ZWQ6cy5nZXQoImluZGljZXMiKX0pLGEudHJpZ2dlcigic2VsZWN0IiksYS50cmlnZ2VyKCJzZWxlY3QtIitlLm1nZXQoImlkIikpLCFpLmlzX2VtcHR5KCkpfSxlLnByb3RvdHlwZS5pbnNwZWN0PWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBvLGkscyxhO2lmKGE9dGhpcy5nZXQoInNvdXJjZSIpLGEhPT1lLm1nZXQoImRhdGFfc291cmNlIikmJmwud2FybigiaW5zcGVjdCBjYWxsZWQgd2l0aCBtaXMtbWF0Y2hlZCBkYXRhIHNvdXJjZXMiKSxvPWUuaGl0X3Rlc3QociksbnVsbCE9byl7aWYocz1lLm1vZGVsLmlkLG8uaXNfZW1wdHkoKSl7aWYobnVsbD09dGhpcy5sYXN0X2luc3BlY3Rpb25fd2FzX2VtcHR5W3NdJiYodGhpcy5sYXN0X2luc3BlY3Rpb25fd2FzX2VtcHR5W3NdPSExKSx0aGlzLmxhc3RfaW5zcGVjdGlvbl93YXNfZW1wdHlbc10pcmV0dXJuO3RoaXMubGFzdF9pbnNwZWN0aW9uX3dhc19lbXB0eVtzXT0hMH1lbHNlIHRoaXMubGFzdF9pbnNwZWN0aW9uX3dhc19lbXB0eVtzXT0hMTtyZXR1cm4gaT10aGlzLl9nZXRfaW5zcGVjdG9yKGUpLGkudXBkYXRlKG8sITAsITEsITApLHRoaXMuZ2V0KCJzb3VyY2UiKS5zZXQoe2luc3BlY3RlZDppLmdldCgiaW5kaWNlcyIpfSx7c2lsZW50OiEwfSksYS50cmlnZ2VyKCJpbnNwZWN0IixvLHQsZSxhLG4pLGEudHJpZ2dlcigiaW5zcGVjdCIrZS5tZ2V0KCJpZCIpLG8sdCxlLGEsbiksIW8uaXNfZW1wdHkoKX1yZXR1cm4hMX0sZS5wcm90b3R5cGUuY2xlYXI9ZnVuY3Rpb24odCl7dmFyIGUscixuLG87aWYobnVsbCE9dClvPXRoaXMuX2dldF9zZWxlY3Rvcih0KSxvLmNsZWFyKCk7ZWxzZXtyPXRoaXMuc2VsZWN0b3JzO2ZvcihlIGluIHIpbj1yW2VdLG4uY2xlYXIoKX1yZXR1cm4gdGhpcy5nZXQoInNvdXJjZSIpLnNldCh7c2VsZWN0ZWQ6YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCl9KX0sZS5wcm90b3R5cGUuX2dldF9zZWxlY3Rvcj1mdW5jdGlvbih0KXtyZXR1cm4gcy5zZXRkZWZhdWx0KHRoaXMuc2VsZWN0b3JzLHQubW9kZWwuaWQsbmV3IGkpLHRoaXMuc2VsZWN0b3JzW3QubW9kZWwuaWRdfSxlLnByb3RvdHlwZS5fZ2V0X2luc3BlY3Rvcj1mdW5jdGlvbih0KXtyZXR1cm4gcy5zZXRkZWZhdWx0KHRoaXMuaW5zcGVjdG9ycyx0Lm1vZGVsLmlkLG5ldyBpKSx0aGlzLmluc3BlY3RvcnNbdC5tb2RlbC5pZF19LGV9KG4pLGUuZXhwb3J0cz1vfSx7Ii4uL2NvcmUvaGFzX3Byb3BzIjoiY29yZS9oYXNfcHJvcHMiLCIuLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuL2hpdHRlc3QiOiJjb21tb24vaGl0dGVzdCIsIi4vc2VsZWN0b3IiOiJjb21tb24vc2VsZWN0b3IiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sImNvbW1vbi9zZWxlY3RvciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpaC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxoPXt9Lmhhc093blByb3BlcnR5O2k9dCgidW5kZXJzY29yZSIpLG49dCgiLi4vY29yZS9oYXNfcHJvcHMiKSxzPXQoIi4vaGl0dGVzdCIpLGE9dCgiLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLGw9dCgiLi4vY29yZS9wcm9wZXJ0aWVzIiksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLnR5cGU9IlNlbGVjdG9yIixlLnByb3RvdHlwZS51cGRhdGU9ZnVuY3Rpb24odCxlLHIsbil7cmV0dXJuIG51bGw9PW4mJihuPSExKSx0aGlzLnNldCgidGltZXN0YW1wIixuZXcgRGF0ZSx7c2lsZW50Om59KSx0aGlzLnNldCgiZmluYWwiLGUse3NpbGVudDpufSksciYmKHRbIjBkIl0uaW5kaWNlcz1pLnVuaW9uKHRoaXMuZ2V0KCJpbmRpY2VzIilbIjBkIl0uaW5kaWNlcyx0WyIwZCJdLmluZGljZXMpLAp0WyIwZCJdLmdseXBoPXRoaXMuZ2V0KCJpbmRpY2VzIilbIjBkIl0uZ2x5cGh8fHRbIjBkIl0uZ2x5cGgsdFsiMWQiXS5pbmRpY2VzPWkudW5pb24odGhpcy5nZXQoImluZGljZXMiKVsiMWQiXS5pbmRpY2VzLHRbIjFkIl0uaW5kaWNlcyksdFsiMmQiXS5pbmRpY2VzPWkudW5pb24odGhpcy5nZXQoImluZGljZXMiKVsiMmQiXS5pbmRpY2VzLHRbIjJkIl0uaW5kaWNlcykpLHRoaXMuc2V0KCJpbmRpY2VzIix0LHtzaWxlbnQ6bn0pfSxlLnByb3RvdHlwZS5jbGVhcj1mdW5jdGlvbigpe3JldHVybiB0aGlzLnNldCgidGltZXN0YW1wIixuZXcgRGF0ZSksdGhpcy5zZXQoImZpbmFsIiwhMCksdGhpcy5zZXQoImluZGljZXMiLHMuY3JlYXRlX2hpdF90ZXN0X3Jlc3VsdCgpKX0sZS5pbnRlcm5hbCh7aW5kaWNlczpbbC5BbnksZnVuY3Rpb24oKXtyZXR1cm4gcy5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCl9XSwiZmluYWwiOltsLkJvb2xlYW5dLHRpbWVzdGFtcDpbbC5BbnldfSksZX0obiksZS5leHBvcnRzPW99LHsiLi4vY29yZS9oYXNfcHJvcHMiOiJjb3JlL2hhc19wcm9wcyIsIi4uL2NvcmUvbG9nZ2luZyI6ImNvcmUvbG9nZ2luZyIsIi4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vaGl0dGVzdCI6ImNvbW1vbi9oaXR0ZXN0Iix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJjb21tb24vdG9vbF9ldmVudHMiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl1LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHU9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIiksbj10KCIuLi9tb2RlbCIpLHM9dCgiLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLGE9dCgiLi4vY29yZS9wcm9wZXJ0aWVzIiksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUucHJvdG90eXBlLnR5cGU9IlRvb2xFdmVudHMiLGUuZGVmaW5lKHtnZW9tZXRyaWVzOlthLkFycmF5LFtdXX0pLGV9KG4pLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vbW9kZWwiOiJtb2RlbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwiY29tbW9uL3VpX2V2ZW50cyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpaC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxoPXt9Lmhhc093blByb3BlcnR5O249dCgianF1ZXJ5Iiksbz10KCJiYWNrYm9uZSIpLGk9dCgiaGFtbWVyanMiKSxsPXQoImpxdWVyeS1tb3VzZXdoZWVsIikobiksYT10KCIuLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIscz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLl9oYW1tZXJfZWxlbWVudCgpfSxlLnByb3RvdHlwZS5faGFtbWVyX2VsZW1lbnQ9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gdD10aGlzLmdldCgiaGl0X2FyZWEiKSx0aGlzLmhhbW1lcj1uZXcgaSh0WzBdKSx0aGlzLmhhbW1lci5nZXQoImRvdWJsZXRhcCIpLnJlY29nbml6ZVdpdGgoInRhcCIpLHRoaXMuaGFtbWVyLmdldCgidGFwIikucmVxdWlyZUZhaWx1cmUoImRvdWJsZXRhcCIpLHRoaXMuaGFtbWVyLmdldCgiZG91YmxldGFwIikuZHJvcFJlcXVpcmVGYWlsdXJlKCJ0YXAiKSx0aGlzLmhhbW1lci5vbigiZG91YmxldGFwIixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSl7cmV0dXJuIHQuX2RvdWJsZXRhcChlKX19KHRoaXMpKSx0aGlzLmhhbW1lci5vbigidGFwIixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSl7cmV0dXJuIHQuX3RhcChlKX19KHRoaXMpKSx0aGlzLmhhbW1lci5vbigicHJlc3MiLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihlKXtyZXR1cm4gdC5fcHJlc3MoZSl9fSh0aGlzKSksdGhpcy5oYW1tZXIuZ2V0KCJwYW4iKS5zZXQoe2RpcmVjdGlvbjppLkRJUkVDVElPTl9BTEx9KSx0aGlzLmhhbW1lci5vbigicGFuc3RhcnQiLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihlKXtyZXR1cm4gdC5fcGFuX3N0YXJ0KGUpfX0odGhpcykpLHRoaXMuaGFtbWVyLm9uKCJwYW4iLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihlKXtyZXR1cm4gdC5fcGFuKGUpfX0odGhpcykpLHRoaXMuaGFtbWVyLm9uKCJwYW5lbmQiLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihlKXtyZXR1cm4gdC5fcGFuX2VuZChlKX19KHRoaXMpKSx0aGlzLmhhbW1lci5nZXQoInBpbmNoIikuc2V0KHtlbmFibGU6ITB9KSx0aGlzLmhhbW1lci5vbigicGluY2hzdGFydCIsZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKGUpe3JldHVybiB0Ll9waW5jaF9zdGFydChlKX19KHRoaXMpKSx0aGlzLmhhbW1lci5vbigicGluY2giLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihlKXtyZXR1cm4gdC5fcGluY2goZSl9fSh0aGlzKSksdGhpcy5oYW1tZXIub24oInBpbmNoZW5kIixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSl7cmV0dXJuIHQuX3BpbmNoX2VuZChlKX19KHRoaXMpKSx0aGlzLmhhbW1lci5nZXQoInJvdGF0ZSIpLnNldCh7ZW5hYmxlOiEwfSksdGhpcy5oYW1tZXIub24oInJvdGF0ZXN0YXJ0IixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSl7cmV0dXJuIHQuX3JvdGF0ZV9zdGFydChlKX19KHRoaXMpKSx0aGlzLmhhbW1lci5vbigicm90YXRlIixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSl7cmV0dXJuIHQuX3JvdGF0ZShlKX19KHRoaXMpKSx0aGlzLmhhbW1lci5vbigicm90YXRlZW5kIixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSl7cmV0dXJuIHQuX3JvdGF0ZV9lbmQoZSl9fSh0aGlzKSksdC5tb3VzZW1vdmUoZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKGUpe3JldHVybiB0Ll9tb3VzZV9tb3ZlKGUpfX0odGhpcykpLHQubW91c2VlbnRlcihmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSl7cmV0dXJuIHQuX21vdXNlX2VudGVyKGUpfX0odGhpcykpLHQubW91c2VsZWF2ZShmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSl7cmV0dXJuIHQuX21vdXNlX2V4aXQoZSl9fSh0aGlzKSksdC5tb3VzZXdoZWVsKGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihlLHIpe3JldHVybiB0Ll9tb3VzZV93aGVlbChlLHIpfX0odGhpcykpLG4oZG9jdW1lbnQpLmtleWRvd24oZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKGUpe3JldHVybiB0Ll9rZXlfZG93bihlKX19KHRoaXMpKSxuKGRvY3VtZW50KS5rZXl1cChmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSl7cmV0dXJuIHQuX2tleV91cChlKX19KHRoaXMpKX0sZS5wcm90b3R5cGUucmVnaXN0ZXJfdG9vbD1mdW5jdGlvbih0KXt2YXIgZSxyLG47cmV0dXJuIGU9dC5tb2RlbC5ldmVudF90eXBlLHI9dC5tb2RlbC5pZCxuPXQubW9kZWwudHlwZSxudWxsPT1lP3ZvaWQgYS5kZWJ1ZygiQnV0dG9uIHRvb2w6ICIrbik6KCJwYW4iPT09ZXx8InBpbmNoIj09PWV8fCJyb3RhdGUiPT09ZT8oYS5kZWJ1ZygiUmVnaXN0ZXJpbmcgdG9vbDogIituKyIgZm9yIGV2ZW50ICciK2UrIiciKSxudWxsIT10WyJfIitlKyJfc3RhcnQiXSYmdC5saXN0ZW5Ubyh0aGlzLGUrIjpzdGFydDoiK3IsdFsiXyIrZSsiX3N0YXJ0Il0pLHRbIl8iK2VdJiZ0Lmxpc3RlblRvKHRoaXMsZSsiOiIrcix0WyJfIitlXSksdFsiXyIrZSsiX2VuZCJdJiZ0Lmxpc3RlblRvKHRoaXMsZSsiOmVuZDoiK3IsdFsiXyIrZSsiX2VuZCJdKSk6Im1vdmUiPT09ZT8oYS5kZWJ1ZygiUmVnaXN0ZXJpbmcgdG9vbDogIituKyIgZm9yIGV2ZW50ICciK2UrIiciKSxudWxsIT10Ll9tb3ZlX2VudGVyJiZ0Lmxpc3RlblRvKHRoaXMsIm1vdmU6ZW50ZXIiLHQuX21vdmVfZW50ZXIpLHQubGlzdGVuVG8odGhpcywibW92ZSIsdC5fbW92ZSksbnVsbCE9dC5fbW92ZV9leGl0JiZ0Lmxpc3RlblRvKHRoaXMsIm1vdmU6ZXhpdCIsdC5fbW92ZV9leGl0KSk6KGEuZGVidWcoIlJlZ2lzdGVyaW5nIHRvb2w6ICIrbisiIGZvciBldmVudCAnIitlKyInIiksdC5saXN0ZW5Ubyh0aGlzLGUrIjoiK3IsdFsiXyIrZV0pKSxudWxsIT10Ll9rZXlkb3duJiYoYS5kZWJ1ZygiUmVnaXN0ZXJpbmcgdG9vbDogIituKyIgZm9yIGV2ZW50ICdrZXlkb3duJyIpLHQubGlzdGVuVG8odGhpcywia2V5ZG93biIsdC5fa2V5ZG93bikpLG51bGwhPXQuX2tleXVwJiYoYS5kZWJ1ZygiUmVnaXN0ZXJpbmcgdG9vbDogIituKyIgZm9yIGV2ZW50ICdrZXl1cCciKSx0Lmxpc3RlblRvKHRoaXMsImtleXVwIix0Ll9rZXl1cCkpLG51bGwhPXQuX2RvdWJsZXRhcCYmKGEuZGVidWcoIlJlZ2lzdGVyaW5nIHRvb2w6ICIrbisiIGZvciBldmVudCAnZG91YmxldGFwJyIpLHQubGlzdGVuVG8odGhpcywiZG91YmxldGFwIix0Ll9kb3VibGV0YXApKSwoIm9udG91Y2hzdGFydCJpbiB3aW5kb3d8fG5hdmlnYXRvci5tYXhUb3VjaFBvaW50cz4wKSYmInBpbmNoIj09PWU/KGEuZGVidWcoIlJlZ2lzdGVyaW5nIHNjcm9sbCBvbiB0b3VjaCBzY3JlZW4iKSx0Lmxpc3RlblRvKHRoaXMsInNjcm9sbDoiK3IsdC5fc2Nyb2xsKSk6dm9pZCAwKX0sZS5wcm90b3R5cGUuX3RyaWdnZXI9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saTtpZihpPXRoaXMuZ2V0KCJ0b29sYmFyIiksbj10LnNwbGl0KCI6IilbMF0sKCJvbnRvdWNoc3RhcnQiaW4gd2luZG93fHxuYXZpZ2F0b3IubWF4VG91Y2hQb2ludHM+MCkmJiJzY3JvbGwiPT09dCYmKG49InBpbmNoIiksbz1pLmdldCgiZ2VzdHVyZXMiKSxyPW9bbl0uYWN0aXZlLG51bGwhPXIpcmV0dXJuIHRoaXMuX3RyaWdnZXJfZXZlbnQodCxyLGUpfSxlLnByb3RvdHlwZS5fdHJpZ2dlcl9ldmVudD1mdW5jdGlvbih0LGUscil7aWYoZS5nZXQoImFjdGl2ZSIpPT09ITApcmV0dXJuInNjcm9sbCI9PT10JiYoci5wcmV2ZW50RGVmYXVsdCgpLHIuc3RvcFByb3BhZ2F0aW9uKCkpLHRoaXMudHJpZ2dlcih0KyI6IitlLmlkLHIpfSxlLnByb3RvdHlwZS5fYm9raWZ5X2hhbW1lcj1mdW5jdGlvbih0KXt2YXIgZSxyLG8saSxzLGEsbDtyZXR1cm4ibW91c2UiPT09dC5wb2ludGVyVHlwZT8oYT10LnNyY0V2ZW50LnBhZ2VYLGw9dC5zcmNFdmVudC5wYWdlWSk6KGE9dC5wb2ludGVyc1swXS5wYWdlWCxsPXQucG9pbnRlcnNbMF0ucGFnZVkpLHI9bih0LnRhcmdldCkub2Zmc2V0KCksZT1udWxsIT0obz1yLmxlZnQpP286MCxzPW51bGwhPShpPXIudG9wKT9pOjAsdC5ib2tlaD17c3g6YS1lLHN5Omwtc319LGUucHJvdG90eXBlLl9ib2tpZnlfanE9ZnVuY3Rpb24odCl7dmFyIGUscixvLGkscztyZXR1cm4gcj1uKHQuY3VycmVudFRhcmdldCkub2Zmc2V0KCksZT1udWxsIT0obz1yLmxlZnQpP286MCxzPW51bGwhPShpPXIudG9wKT9pOjAsdC5ib2tlaD17c3g6dC5wYWdlWC1lLHN5OnQucGFnZVktc319LGUucHJvdG90eXBlLl90YXA9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2Jva2lmeV9oYW1tZXIodCksdGhpcy5fdHJpZ2dlcigidGFwIix0KX0sZS5wcm90b3R5cGUuX2RvdWJsZXRhcD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fYm9raWZ5X2hhbW1lcih0KSx0aGlzLnRyaWdnZXIoImRvdWJsZXRhcCIsdCl9LGUucHJvdG90eXBlLl9wcmVzcz1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fYm9raWZ5X2hhbW1lcih0KSx0aGlzLl90cmlnZ2VyKCJwcmVzcyIsdCl9LGUucHJvdG90eXBlLl9wYW5fc3RhcnQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2Jva2lmeV9oYW1tZXIodCksdC5ib2tlaC5zeC09dC5kZWx0YVgsdC5ib2tlaC5zeS09dC5kZWx0YVksdGhpcy5fdHJpZ2dlcigicGFuOnN0YXJ0Iix0KX0sZS5wcm90b3R5cGUuX3Bhbj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fYm9raWZ5X2hhbW1lcih0KSx0aGlzLl90cmlnZ2VyKCJwYW4iLHQpfSxlLnByb3RvdHlwZS5fcGFuX2VuZD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fYm9raWZ5X2hhbW1lcih0KSx0aGlzLl90cmlnZ2VyKCJwYW46ZW5kIix0KX0sZS5wcm90b3R5cGUuX3BpbmNoX3N0YXJ0PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9ib2tpZnlfaGFtbWVyKHQpLHRoaXMuX3RyaWdnZXIoInBpbmNoOnN0YXJ0Iix0KX0sZS5wcm90b3R5cGUuX3BpbmNoPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9ib2tpZnlfaGFtbWVyKHQpLHRoaXMuX3RyaWdnZXIoInBpbmNoIix0KX0sZS5wcm90b3R5cGUuX3BpbmNoX2VuZD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fYm9raWZ5X2hhbW1lcih0KSx0aGlzLl90cmlnZ2VyKCJwaW5jaDplbmQiLHQpfSxlLnByb3RvdHlwZS5fcm90YXRlX3N0YXJ0PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9ib2tpZnlfaGFtbWVyKHQpLHRoaXMuX3RyaWdnZXIoInJvdGF0ZTpzdGFydCIsdCl9LGUucHJvdG90eXBlLl9yb3RhdGU9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2Jva2lmeV9oYW1tZXIodCksdGhpcy5fdHJpZ2dlcigicm90YXRlIix0KX0sZS5wcm90b3R5cGUuX3JvdGF0ZV9lbmQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2Jva2lmeV9oYW1tZXIodCksdGhpcy5fdHJpZ2dlcigicm90YXRlOmVuZCIsdCl9LGUucHJvdG90eXBlLl9tb3VzZV9lbnRlcj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fYm9raWZ5X2pxKHQpLHRoaXMudHJpZ2dlcigibW92ZTplbnRlciIsdCl9LGUucHJvdG90eXBlLl9tb3VzZV9tb3ZlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9ib2tpZnlfanEodCksdGhpcy50cmlnZ2VyKCJtb3ZlIix0KX0sZS5wcm90b3R5cGUuX21vdXNlX2V4aXQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2Jva2lmeV9qcSh0KSx0aGlzLnRyaWdnZXIoIm1vdmU6ZXhpdCIsdCl9LGUucHJvdG90eXBlLl9tb3VzZV93aGVlbD1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLl9ib2tpZnlfanEodCksdC5ib2tlaC5kZWx0YT1lLHRoaXMuX3RyaWdnZXIoInNjcm9sbCIsdCl9LGUucHJvdG90eXBlLl9rZXlfZG93bj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy50cmlnZ2VyKCJrZXlkb3duIix0KX0sZS5wcm90b3R5cGUuX2tleV91cD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy50cmlnZ2VyKCJrZXl1cCIsdCl9LGV9KG8uTW9kZWwpLGUuZXhwb3J0cz1zfSx7Ii4uL2NvcmUvbG9nZ2luZyI6ImNvcmUvbG9nZ2luZyIsYmFja2JvbmU6ImJhY2tib25lIixoYW1tZXJqczoiaGFtbWVyanMvaGFtbWVyIixqcXVlcnk6ImpxdWVyeSIsImpxdWVyeS1tb3VzZXdoZWVsIjoianF1ZXJ5LW1vdXNld2hlZWwifV0sImNvcmUvYm9rZWhfdmlldyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscz1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxhPXt9Lmhhc093blByb3BlcnR5O2k9dCgidW5kZXJzY29yZSIpLG49dCgiYmFja2JvbmUiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBzKGUsdCksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtpZighaS5oYXModCwiaWQiKSlyZXR1cm4gdGhpcy5pZD1pLnVuaXF1ZUlkKCJCb2tlaFZpZXciKX0sZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXt9LGUucHJvdG90eXBlLnJlbW92ZT1mdW5jdGlvbigpe3ZhciB0LHIsbjtpZihpLmhhcyh0aGlzLCJldmVudGVycyIpKXt0PXRoaXMuZXZlbnRlcnM7Zm9yKHIgaW4gdClhLmNhbGwodCxyKSYmKG49dFtyXSxuLm9mZihudWxsLG51bGwsdGhpcykpfXJldHVybiB0aGlzLnRyaWdnZXIoInJlbW92ZSIsdGhpcyksZS5fX3N1cGVyX18ucmVtb3ZlLmNhbGwodGhpcyl9LGUucHJvdG90eXBlLm1nZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tb2RlbC5nZXQuYXBwbHkodGhpcy5tb2RlbCxhcmd1bWVudHMpfSxlLnByb3RvdHlwZS5tc2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubW9kZWwuc2V0LmFwcGx5KHRoaXMubW9kZWwsYXJndW1lbnRzKX0sZX0obi5WaWV3KSxlLmV4cG9ydHM9b30se2JhY2tib25lOiJiYWNrYm9uZSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwiY29yZS9lbnVtcyI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9e0FuZ2xlVW5pdHM6WyJkZWciLCJyYWQiXSxEaW1lbnNpb246WyJ3aWR0aCIsImhlaWdodCJdLERpcmVjdGlvbjpbImNsb2NrIiwiYW50aWNsb2NrIl0sRm9udFN0eWxlOlsibm9ybWFsIiwiaXRhbGljIiwiYm9sZCJdLExpbmVDYXA6WyJidXR0Iiwicm91bmQiLCJzcXVhcmUiXSxMaW5lSm9pbjpbIm1pdGVyIiwicm91bmQiLCJiZXZlbCJdLExvY2F0aW9uOlsiYWJvdmUiLCJiZWxvdyIsImxlZnQiLCJyaWdodCJdLExlZ2VuZExvY2F0aW9uOlsidG9wX2xlZnQiLCJ0b3BfY2VudGVyIiwidG9wX3JpZ2h0IiwibGVmdF9jZW50ZXIiLCJjZW50ZXIiLCJyaWdodF9jZW50ZXIiLCJib3R0b21fbGVmdCIsImJvdHRvbV9jZW50ZXIiLCJib3R0b21fcmlnaHQiXSxPcmllbnRhdGlvbjpbInZlcnRpY2FsIiwiaG9yaXpvbnRhbCJdLFJlbmRlckxldmVsOlsiaW1hZ2UiLCJ1bmRlcmxheSIsImdseXBoIiwiYW5ub3RhdGlvbiIsIm92ZXJsYXkiLCJ0b29sIl0sUmVuZGVyTW9kZTpbImNhbnZhcyIsImNzcyJdLFNpZGU6WyJsZWZ0IiwicmlnaHQiXSxTcGF0aWFsVW5pdHM6WyJzY3JlZW4iLCJkYXRhIl0sU3RhcnRFbmQ6WyJzdGFydCIsImVuZCJdLFRleHRBbGlnbjpbImxlZnQiLCJyaWdodCIsImNlbnRlciJdLFRleHRCYXNlbGluZTpbInRvcCIsIm1pZGRsZSIsImJvdHRvbSIsImFscGhhYmV0aWMiLCJoYW5naW5nIiwiaWRlb2dyYXBoaWMiXSxEaXN0cmlidXRpb25UeXBlczpbInVuaWZvcm0iLCJub3JtYWwiXSxUcmFuc2Zvcm1TdGVwTW9kZXM6WyJhZnRlciIsImJlZm9yZSIsImNlbnRlciJdLFNpemluZ01vZGU6WyJzdHJldGNoX2JvdGgiLCJzY2FsZV93aWR0aCIsInNjYWxlX2hlaWdodCIsInNjYWxlX2JvdGgiLCJmaXhlZCJdfX0se31dLCJjb3JlL2hhc19wcm9wcyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHkscD1bXS5zbGljZTtuPXQoImpxdWVyeSIpLHM9dCgidW5kZXJzY29yZSIpLG89dCgiYmFja2JvbmUiKSxhPXQoIi4vbG9nZ2luZyIpLmxvZ2dlcixsPXQoIi4vcHJvcGVydHlfbWl4aW5zIiksdT10KCIuL3V0aWwvcmVmcyIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSh0LGUpe3ZhciByLG4sbyxpLGEsbDt0aGlzLmRvY3VtZW50PW51bGwscj10fHx7fSxlfHwoZT17fSksdGhpcy5jaWQ9cy51bmlxdWVJZCgiYyIpLHRoaXMuYXR0cmlidXRlcz17fSx0aGlzLnByb3BlcnRpZXM9e30saT10aGlzLnByb3BzO2ZvcihvIGluIGkpe2lmKGE9aVtvXSxsPWEudHlwZSxuPWEuZGVmYXVsdF92YWx1ZSxudWxsPT1sKXRocm93IG5ldyBFcnJvcigidW5kZWZpbmVkIHByb3BlcnR5IHR5cGUgZm9yICIrdGhpcy50eXBlKyIuIitvKTt0aGlzLnByb3BlcnRpZXNbb109bmV3IGwoe29iajp0aGlzLGF0dHI6byxkZWZhdWx0X3ZhbHVlOm59KX1lLnBhcnNlJiYocj10aGlzLnBhcnNlKHIsZSl8fHt9KSx0aGlzLl9zZXRfYWZ0ZXJfZGVmYXVsdHM9e30sdGhpcy5zZXQocixlKSx0aGlzLmNoYW5nZWQ9e30sdGhpcy5fY29tcHV0ZWQ9e30scy5oYXMocix0aGlzLmlkQXR0cmlidXRlKXx8KHRoaXMuaWQ9cy51bmlxdWVJZCh0aGlzLnR5cGUpLHRoaXMuYXR0cmlidXRlc1t0aGlzLmlkQXR0cmlidXRlXT10aGlzLmlkKSxlLmRlZmVyX2luaXRpYWxpemF0aW9ufHx0aGlzLmluaXRpYWxpemUuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBoKGUsdCksZS5wcm90b3R5cGUucHJvcHM9e30sZS5wcm90b3R5cGUubWl4aW5zPVtdLGUuZGVmaW5lPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbjtuPVtdO2ZvcihlIGluIHQpcj10W2VdLG4ucHVzaChmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSxyKXt2YXIgbixvLGksYSxsO2lmKG51bGwhPXQucHJvdG90eXBlLnByb3BzW2VdKXRocm93IG5ldyBFcnJvcigiYXR0ZW1wdGVkIHRvIHJlZGVmaW5lIHByb3BlcnR5ICciK3QubmFtZSsiLiIrZSsiJyIpO2lmKG51bGwhPXQucHJvdG90eXBlW2VdJiYidXJsIiE9PWUpdGhyb3cgbmV3IEVycm9yKCJhdHRlbXB0ZWQgdG8gcmVkZWZpbmUgYXR0cmlidXRlICciK3QubmFtZSsiLiIrZSsiJyIpO3JldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkodC5wcm90b3R5cGUsZSx7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZ2V0KGUpfSxzZXQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuc2V0KGUsdCl9fSx7Y29uZmlndXJhYmxlOiExLGVudW1lcmFibGU6ITB9KSxsPXJbMF0sbj1yWzFdLG89clsyXSxhPXt0eXBlOmwsZGVmYXVsdF92YWx1ZTpuLGludGVybmFsOm51bGwhPW8mJm99LGk9cy5jbG9uZSh0LnByb3RvdHlwZS5wcm9wcyksaVtlXT1hLHQucHJvdG90eXBlLnByb3BzPWl9fSh0aGlzKShlLHIpKTtyZXR1cm4gbn0sZS5pbnRlcm5hbD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbztlPXt9LHI9ZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKHQscil7dmFyIG4sbztyZXR1cm4gbz1yWzBdLG49clsxXSxlW3RdPVtvLG4sITBdfX0odGhpcyk7Zm9yKG4gaW4gdClvPXRbbl0scihuLG8pO3JldHVybiB0aGlzLmRlZmluZShlKX0sZS5taXhpbj1mdW5jdGlvbigpe3ZhciB0LGU7cmV0dXJuIGU9MTw9YXJndW1lbnRzLmxlbmd0aD9wLmNhbGwoYXJndW1lbnRzLDApOltdLHRoaXMuZGVmaW5lKGwuY3JlYXRlKGUpKSx0PXRoaXMucHJvdG90eXBlLm1peGlucy5jb25jYXQoZSksdGhpcy5wcm90b3R5cGUubWl4aW5zPXR9LGUubWl4aW5zPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLm1peGluLmFwcGx5KHRoaXMsdCl9LGUub3ZlcnJpZGU9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG87cy5pc1N0cmluZyh0KT8obj17fSxuW3JdPWUpOm49dCxvPVtdO2ZvcihyIGluIG4pZT1uW3JdLG8ucHVzaChmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSxyKXt2YXIgbixvO2lmKG89dC5wcm90b3R5cGUucHJvcHNbZV0sbnVsbD09byl0aHJvdyBuZXcgRXJyb3IoImF0dGVtcHRlZCB0byBvdmVycmlkZSBub25leGlzdGVudCAnIit0Lm5hbWUrIi4iK2UrIiciKTtyZXR1cm4gbj1zLmNsb25lKHQucHJvdG90eXBlLnByb3BzKSxuW2VdPXMuZXh0ZW5kKHt9LG8se2RlZmF1bHRfdmFsdWU6cn0pLHQucHJvdG90eXBlLnByb3BzPW59fSh0aGlzKShyLGUpKTtyZXR1cm4gb30sZS5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy50eXBlKyIoIit0aGlzLmlkKyIpIn0sZS5wcm90b3R5cGUuZGVzdHJveT1mdW5jdGlvbih0KXtyZXR1cm4gZS5fX3N1cGVyX18uZGVzdHJveS5jYWxsKHRoaXMsdCksdGhpcy5zdG9wTGlzdGVuaW5nKCl9LGUucHJvdG90eXBlLnNldD1mdW5jdGlvbih0LHIsbil7dmFyIG8saSxhLGwsdTtzLmlzT2JqZWN0KHQpfHxudWxsPT09dD8obz10LG49cik6KG89e30sb1t0XT1yKTtmb3IodCBpbiBvKWlmKGMuY2FsbChvLHQpKXtpZih1PW9bdF0sYT10LCJpZCIhPT1hJiYhdGhpcy5wcm9wc1thXSl0aHJvdyBuZXcgRXJyb3IodGhpcy50eXBlKyIuc2V0KCciK2ErIicpOiAiK2ErIiB3YXNuJ3QgZGVjbGFyZWQiKTtudWxsIT1uJiZuLmRlZmF1bHRzfHwodGhpcy5fc2V0X2FmdGVyX2RlZmF1bHRzW3RdPSEwKX1pZighcy5pc0VtcHR5KG8pKXtpPXt9O2Zvcih0IGluIG8pcj1vW3RdLGlbdF09dGhpcy5nZXQodCk7aWYoZS5fX3N1cGVyX18uc2V0LmNhbGwodGhpcyxvLG4pLG51bGw9PShudWxsIT1uP24uc2lsZW50OnZvaWQgMCkpe2w9W107Zm9yKHQgaW4gbylyPW9bdF0sbC5wdXNoKHRoaXMuX3RlbGxfZG9jdW1lbnRfYWJvdXRfY2hhbmdlKHQsaVt0XSx0aGlzLmdldCh0KSkpO3JldHVybiBsfX19LGUucHJvdG90eXBlLmFkZF9kZXBlbmRlbmNpZXM9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxhLGw7Zm9yKHMuaXNBcnJheShyKXx8KHI9W3JdKSxhPXRoaXMuX2NvbXB1dGVkW3RdLGEuZGVwZW5kZW5jaWVzPWEuZGVwZW5kZW5jaWVzLmNvbmNhdCh7b2JqOmUsZmllbGRzOnJ9KSxsPVtdLG89MCxpPXIubGVuZ3RoO288aTtvKyspbj1yW29dLGwucHVzaCh0aGlzLmxpc3RlblRvKGUsImNoYW5nZToiK24sYS5jYWxsYmFja3MuY2hhbmdlZGVwKSk7cmV0dXJuIGx9LGUucHJvdG90eXBlLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eT1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpO2lmKG51bGw9PXImJihyPSEwKSxudWxsIT10aGlzLnByb3BzW3RdJiZjb25zb2xlLmxvZygiYXR0ZW1wdGVkIHRvIHJlZGVmaW5lIGV4aXN0aW5nIHByb3BlcnR5ICIrdGhpcy50eXBlKyIuIit0KSxzLmhhcyh0aGlzLl9jb21wdXRlZCx0KSl0aHJvdyBuZXcgRXJyb3IoImF0dGVtcHRlZCB0byByZWRlZmluZSBleGlzdGluZyBjb21wdXRlZCBwcm9wZXJ0eSAiK3RoaXMudHlwZSsiLiIrdCk7cmV0dXJuIG49ZnVuY3Rpb24oZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGUudHJpZ2dlcigiY2hhbmdlZGVwOiIrdCl9fSh0aGlzKSxpPWZ1bmN0aW9uKGUpe3JldHVybiBmdW5jdGlvbigpe3ZhciByLG4saTtpZihyPSEwLG8udXNlX2NhY2hlJiYoaT1vLmNhY2hlLG8uY2FjaGU9dm9pZCAwLG49ZS5nZXQodCkscj1uIT09aSkscilyZXR1cm4gZS50cmlnZ2VyKCJjaGFuZ2U6Iit0LGUsZS5nZXQodCkpLGUudHJpZ2dlcigiY2hhbmdlIixlKX19KHRoaXMpLG89e2dldHRlcjplLGRlcGVuZGVuY2llczpbXSx1c2VfY2FjaGU6cixjYWxsYmFja3M6e2NoYW5nZWRlcDpuLHByb3BjaGFuZ2U6aX19LHRoaXMuX2NvbXB1dGVkW3RdPW8sdGhpcy5saXN0ZW5Ubyh0aGlzLCJjaGFuZ2VkZXA6Iit0LG8uY2FsbGJhY2tzLnByb3BjaGFuZ2UpLG99LGUucHJvdG90eXBlLm92ZXJyaWRlX2NvbXB1dGVkX3Byb3BlcnR5PWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gbnVsbD09ciYmKHI9ITApLHMuaGFzKHRoaXMuX2NvbXB1dGVkLHQpJiZ0aGlzLl9yZW1vdmVfY29tcHV0ZWRfcHJvcGVydHkodCksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkodCxlLHIpfSxlLnByb3RvdHlwZS5fcmVtb3ZlX2NvbXB1dGVkX3Byb3BlcnR5PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGwsdSxoO2Zvcih1PXRoaXMuX2NvbXB1dGVkW3RdLHI9dS5kZXBlbmRlbmNpZXMsbz0wLHM9ci5sZW5ndGg7bzxzO28rKylmb3IoZT1yW29dLGw9ZS5vYmosaD1lLmZpZWxkcyxpPTAsYT1oLmxlbmd0aDtpPGE7aSsrKW49aFtpXSxsLm9mZigiY2hhbmdlOiIrbix1LmNhbGxiYWNrcy5jaGFuZ2VkZXAsdGhpcyk7cmV0dXJuIHRoaXMub2ZmKCJjaGFuZ2VkZXA6IitlKSxkZWxldGUgdGhpcy5fY29tcHV0ZWRbdF19LGUucHJvdG90eXBlLmdldD1mdW5jdGlvbih0KXtpZihzLmhhcyh0aGlzLl9jb21wdXRlZCx0KSlyZXR1cm4gdGhpcy5fZ2V0X3Byb3AodCk7aWYoImlkIiE9PXQmJiF0aGlzLnByb3BzW3RdKXRocm93IG5ldyBFcnJvcih0aGlzLnR5cGUrIi5nZXQoJyIrdCsiJyk6ICIrdCsiIHdhc24ndCBkZWNsYXJlZCIpO3JldHVybiBlLl9fc3VwZXJfXy5nZXQuY2FsbCh0aGlzLHQpfSxlLnByb3RvdHlwZS5fZ2V0X3Byb3A9ZnVuY3Rpb24odCl7dmFyIGUscixuO3JldHVybiBuPXRoaXMuX2NvbXB1dGVkW3RdLG4udXNlX2NhY2hlJiZuLmNhY2hlP24uY2FjaGU6KHI9bi5nZXR0ZXIsZT1yLmFwcGx5KHRoaXMsW3RdKSxuLnVzZV9jYWNoZSYmKG4uY2FjaGU9ZSksZSl9LGUucHJvdG90eXBlLnJlZj1mdW5jdGlvbigpe3JldHVybiB1LmNyZWF0ZV9yZWYodGhpcyl9LGUucHJvdG90eXBlLnNldF9zdWJ0eXBlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9zdWJ0eXBlPXR9LGUucHJvdG90eXBlLnN5bmM9ZnVuY3Rpb24odCxlLHIpe3JldHVybiByLnN1Y2Nlc3MoZS5hdHRyaWJ1dGVzLG51bGwse30pfSxlLnByb3RvdHlwZS5kZWZhdWx0cz1mdW5jdGlvbigpe3Rocm93IG5ldyBFcnJvcigiZG9uJ3QgdXNlIEhhc1Byb3BzLmRlZmF1bHRzIGFueW1vcmUiKX0sZS5wcm90b3R5cGUuYXR0cmlidXRlX2lzX3NlcmlhbGl6YWJsZT1mdW5jdGlvbih0KXt2YXIgZTtpZigiaWQiPT09dClyZXR1cm4hMDtpZihlPXRoaXMucHJvcHNbdF0sbnVsbD09ZSl0aHJvdyBuZXcgRXJyb3IodGhpcy50eXBlKyIuYXR0cmlidXRlX2lzX3NlcmlhbGl6YWJsZSgnIit0KyInKTogIit0KyIgd2Fzbid0IGRlY2xhcmVkIik7cmV0dXJuIWUuaW50ZXJuYWx9LGUucHJvdG90eXBlLnNlcmlhbGl6YWJsZV9hdHRyaWJ1dGVzPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47dD17fSxyPXRoaXMuYXR0cmlidXRlcztmb3IoZSBpbiByKW49cltlXSx0aGlzLmF0dHJpYnV0ZV9pc19zZXJpYWxpemFibGUoZSkmJih0W2VdPW4pO3JldHVybiB0fSxlLnByb3RvdHlwZS50b0pTT049ZnVuY3Rpb24odCl7dGhyb3cgbmV3IEVycm9yKCJidWc6IHRvSlNPTiBzaG91bGQgbm90IGJlIGNhbGxlZCBvbiAiK3RoaXMrIiwgbW9kZWxzIHJlcXVpcmUgc3BlY2lhbCBzZXJpYWxpemF0aW9uIG1lYXN1cmVzIil9LGUuX3ZhbHVlX3RvX2pzb249ZnVuY3Rpb24odCxyLG4pe3ZhciBvLGksYSxsLHUsaCxwO2lmKHIgaW5zdGFuY2VvZiBlKXJldHVybiByLnJlZigpO2lmKHMuaXNBcnJheShyKSl7Zm9yKGw9W10sbz1pPTAsYT1yLmxlbmd0aDtpPGE7bz0rK2kpcD1yW29dLGwucHVzaChlLl92YWx1ZV90b19qc29uKG8scCxyKSk7cmV0dXJuIGx9aWYocy5pc09iamVjdChyKSl7dT17fTtmb3IoaCBpbiByKWMuY2FsbChyLGgpJiYodVtoXT1lLl92YWx1ZV90b19qc29uKGgscltoXSxyKSk7cmV0dXJuIHV9cmV0dXJuIHJ9LGUucHJvdG90eXBlLmF0dHJpYnV0ZXNfYXNfanNvbj1mdW5jdGlvbih0LHIpe3ZhciBuLG8saSxzO251bGw9PXQmJih0PSEwKSxudWxsPT1yJiYocj1lLl92YWx1ZV90b19qc29uKSxuPXt9LGk9dGhpcy5zZXJpYWxpemFibGVfYXR0cmlidXRlcygpO2ZvcihvIGluIGkpYy5jYWxsKGksbykmJihzPWlbb10sdD9uW29dPXM6byBpbiB0aGlzLl9zZXRfYWZ0ZXJfZGVmYXVsdHMmJihuW29dPXMpKTtyZXR1cm4gcigiYXR0cmlidXRlcyIsbix0aGlzKX0sZS5fanNvbl9yZWNvcmRfcmVmZXJlbmNlcz1mdW5jdGlvbih0LHIsbixvKXt2YXIgaSxhLGwsaCxwLF8sZDtpZihudWxsPT09cik7ZWxzZSBpZih1LmlzX3JlZihyKSl7aWYoIShyLmlkIGluIG4pKXJldHVybiBwPXQuZ2V0X21vZGVsX2J5X2lkKHIuaWQpLGUuX3ZhbHVlX3JlY29yZF9yZWZlcmVuY2VzKHAsbixvKX1lbHNle2lmKHMuaXNBcnJheShyKSl7Zm9yKF89W10sYT0wLGg9ci5sZW5ndGg7YTxoO2ErKylpPXJbYV0sXy5wdXNoKGUuX2pzb25fcmVjb3JkX3JlZmVyZW5jZXModCxpLG4sbykpO3JldHVybiBffWlmKHMuaXNPYmplY3Qocikpe2Q9W107Zm9yKGwgaW4gciljLmNhbGwocixsKSYmKGk9cltsXSxkLnB1c2goZS5fanNvbl9yZWNvcmRfcmVmZXJlbmNlcyh0LGksbixvKSkpO3JldHVybiBkfX19LGUuX3ZhbHVlX3JlY29yZF9yZWZlcmVuY2VzPWZ1bmN0aW9uKHQscixuKXt2YXIgbyxpLGEsbCx1LGgscCxfLGQsZixtO2lmKG51bGw9PT10KTtlbHNlIGlmKHQgaW5zdGFuY2VvZiBlKXtpZighKHQuaWQgaW4gcikmJihyW3QuaWRdPXQsbikpe2ZvcihpPXQuX2ltbWVkaWF0ZV9yZWZlcmVuY2VzKCksZD1bXSxhPTAsaD1pLmxlbmd0aDthPGg7YSsrKV89aVthXSxkLnB1c2goZS5fdmFsdWVfcmVjb3JkX3JlZmVyZW5jZXMoXyxyLCEwKSk7cmV0dXJuIGR9fWVsc2V7aWYocy5pc0FycmF5KHQpKXtmb3IoZj1bXSx1PTAscD10Lmxlbmd0aDt1PHA7dSsrKW89dFt1XSxmLnB1c2goZS5fdmFsdWVfcmVjb3JkX3JlZmVyZW5jZXMobyxyLG4pKTtyZXR1cm4gZn1pZihzLmlzT2JqZWN0KHQpKXttPVtdO2ZvcihsIGluIHQpYy5jYWxsKHQsbCkmJihvPXRbbF0sbS5wdXNoKGUuX3ZhbHVlX3JlY29yZF9yZWZlcmVuY2VzKG8scixuKSkpO3JldHVybiBtfX19LGUucHJvdG90eXBlLl9pbW1lZGlhdGVfcmVmZXJlbmNlcz1mdW5jdGlvbigpe3ZhciB0LHIsbixvO249e30sdD10aGlzLnNlcmlhbGl6YWJsZV9hdHRyaWJ1dGVzKCk7Zm9yKHIgaW4gdClvPXRbcl0sZS5fdmFsdWVfcmVjb3JkX3JlZmVyZW5jZXMobyxuLCExKTtyZXR1cm4gcy52YWx1ZXMobil9LGUucHJvdG90eXBlLnJlZmVyZW5jZXM9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gdD17fSxlLl92YWx1ZV9yZWNvcmRfcmVmZXJlbmNlcyh0aGlzLHQsITApLHMudmFsdWVzKHQpfSxlLnByb3RvdHlwZS5hdHRhY2hfZG9jdW1lbnQ9ZnVuY3Rpb24odCl7dmFyIGUscixuO2lmKG51bGwhPT10aGlzLmRvY3VtZW50JiZ0aGlzLmRvY3VtZW50IT09dCl0aHJvdyBuZXcgRXJyb3IoIm1vZGVscyBtdXN0IGJlIG93bmVkIGJ5IG9ubHkgYSBzaW5nbGUgZG9jdW1lbnQiKTt0aGlzLmRvY3VtZW50PXQsbj10aGlzLnByb3BlcnRpZXM7Zm9yKGUgaW4gbilyPW5bZV0sci51cGRhdGUoKTtpZihudWxsIT10aGlzLl9kb2NfYXR0YWNoZWQpcmV0dXJuIHRoaXMuX2RvY19hdHRhY2hlZCgpfSxlLnByb3RvdHlwZS5kZXRhY2hfZG9jdW1lbnQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kb2N1bWVudD1udWxsfSxlLnByb3RvdHlwZS5fdGVsbF9kb2N1bWVudF9hYm91dF9jaGFuZ2U9ZnVuY3Rpb24odCxyLG4pe3ZhciBvLGkscyxhLGwsdSxoO2lmKHRoaXMuYXR0cmlidXRlX2lzX3NlcmlhbGl6YWJsZSh0KSYmbnVsbCE9PXRoaXMuZG9jdW1lbnQpe2E9e30sZS5fdmFsdWVfcmVjb3JkX3JlZmVyZW5jZXMobixhLCExKSxoPXt9LGUuX3ZhbHVlX3JlY29yZF9yZWZlcmVuY2VzKHIsaCwhMSksbz0hMTtmb3IoaSBpbiBhKWlmKHM9YVtpXSwhKGkgaW4gaCkpe289ITA7YnJlYWt9aWYoIW8pZm9yKGwgaW4gaClpZih1PWhbbF0sIShsIGluIGEpKXtvPSEwO2JyZWFrfXJldHVybiBvJiZ0aGlzLmRvY3VtZW50Ll9pbnZhbGlkYXRlX2FsbF9tb2RlbHMoKSx0aGlzLmRvY3VtZW50Ll9ub3RpZnlfY2hhbmdlKHRoaXMsdCxyLG4pfX0sZX0oby5Nb2RlbCksZS5leHBvcnRzPWl9LHsiLi9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi9wcm9wZXJ0eV9taXhpbnMiOiJjb3JlL3Byb3BlcnR5X21peGlucyIsIi4vdXRpbC9yZWZzIjoiY29yZS91dGlsL3JlZnMiLGJhY2tib25lOiJiYWNrYm9uZSIsanF1ZXJ5OiJqcXVlcnkiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sImNvcmUvbGF5b3V0L2xheW91dF9jYW52YXMiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHA9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKV8uY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sXz17fS5oYXNPd25Qcm9wZXJ0eTt1PXQoInVuZGVyc2NvcmUiKSxjPXQoIi4vc29sdmVyIiksbD1jLlZhcmlhYmxlLG49Yy5FUSxvPWMuR0UsYT1jLlN0cmVuZ3RoLHM9dCgiLi4vLi4vbW9kZWwiKSxoPXQoIi4uL3Byb3BlcnRpZXMiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBwKGUsdCksZS5wcm90b3R5cGUudHlwZT0iTGF5b3V0Q2FudmFzIixlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5fdG9wPW5ldyBsKCJ0b3AgIit0aGlzLmlkKSx0aGlzLl9sZWZ0PW5ldyBsKCJsZWZ0ICIrdGhpcy5pZCksdGhpcy5fd2lkdGg9bmV3IGwoIndpZHRoICIrdGhpcy5pZCksdGhpcy5faGVpZ2h0PW5ldyBsKCJoZWlnaHQgIit0aGlzLmlkKSx0aGlzLl9yaWdodD1uZXcgbCgicmlnaHQgIit0aGlzLmlkKSx0aGlzLl9ib3R0b209bmV3IGwoImJvdHRvbSAiK3RoaXMuaWQpLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJoZWlnaHQiLHRoaXMuX2dldF92YXIsITEpLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJ3aWR0aCIsdGhpcy5fZ2V0X3ZhciwhMSksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoInJpZ2h0Iix0aGlzLl9nZXRfdmFyLCExKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgibGVmdCIsdGhpcy5fZ2V0X3ZhciwhMSksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoInRvcCIsdGhpcy5fZ2V0X3ZhciwhMSksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoImJvdHRvbSIsdGhpcy5fZ2V0X3ZhciwhMSl9LGUuaW50ZXJuYWwoe2xheW91dF9sb2NhdGlvbjpbaC5BbnldfSksZS5wcm90b3R5cGUuZ2V0X2VkaXRfdmFyaWFibGVzPWZ1bmN0aW9uKCl7dmFyIHQ7cmV0dXJuIHQ9W10sdC5wdXNoKHtlZGl0X3ZhcmlhYmxlOnRoaXMuX3RvcCxzdHJlbmd0aDphLnN0cm9uZ30pLHQucHVzaCh7ZWRpdF92YXJpYWJsZTp0aGlzLl9sZWZ0LHN0cmVuZ3RoOmEuc3Ryb25nfSksdC5wdXNoKHtlZGl0X3ZhcmlhYmxlOnRoaXMuX3dpZHRoLHN0cmVuZ3RoOmEuc3Ryb25nfSksdC5wdXNoKHtlZGl0X3ZhcmlhYmxlOnRoaXMuX2hlaWdodCxzdHJlbmd0aDphLnN0cm9uZ30pLHR9LGUucHJvdG90eXBlLmdldF9jb25zdHJhaW50cz1mdW5jdGlvbigpe3JldHVybltdfSxlLnByb3RvdHlwZS5fZ2V0X3Zhcj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpc1siXyIrdF0udmFsdWUoKX0sZX0ocyksZS5leHBvcnRzPXtNb2RlbDppfX0seyIuLi8uLi9tb2RlbCI6Im1vZGVsIiwiLi4vcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vc29sdmVyIjoiY29yZS9sYXlvdXQvc29sdmVyIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJjb3JlL2xheW91dC9zaWRlX3BhbmVsIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpUy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxTPXt9Lmhhc093blByb3BlcnR5O2Y9dCgidW5kZXJzY29yZSIpLGs9dCgiLi9zb2x2ZXIiKSxzPWsuRVEsYT1rLkdFLGg9dCgiLi9sYXlvdXRfY2FudmFzIiksdz10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSx4PXQoIi4uLy4uL2NvcmUvbG9nZ2luZyIpLmxvZ2dlcixNPU1hdGguUEkvMixuPSJhbHBoYWJldGljIixkPSJ0b3AiLG89ImJvdHRvbSIsYz0ibWlkZGxlIixsPSJoYW5naW5nIix1PSJsZWZ0IixwPSJyaWdodCIsaT0iY2VudGVyIix2PXthYm92ZTp7cGFyYWxsZWw6MCxub3JtYWw6LU0saG9yaXpvbnRhbDowLHZlcnRpY2FsOi1NfSxiZWxvdzp7cGFyYWxsZWw6MCxub3JtYWw6TSxob3Jpem9udGFsOjAsdmVydGljYWw6TX0sbGVmdDp7cGFyYWxsZWw6LU0sbm9ybWFsOjAsaG9yaXpvbnRhbDowLHZlcnRpY2FsOi1NfSxyaWdodDp7cGFyYWxsZWw6TSxub3JtYWw6MCxob3Jpem9udGFsOjAsdmVydGljYWw6TX19LGI9e2Fib3ZlOntqdXN0aWZpZWQ6ZCxwYXJhbGxlbDpuLG5vcm1hbDpjLGhvcml6b250YWw6bix2ZXJ0aWNhbDpjfSxiZWxvdzp7anVzdGlmaWVkOm8scGFyYWxsZWw6bCxub3JtYWw6Yyxob3Jpem9udGFsOmwsdmVydGljYWw6Y30sbGVmdDp7anVzdGlmaWVkOmQscGFyYWxsZWw6bixub3JtYWw6Yyxob3Jpem9udGFsOmMsdmVydGljYWw6bn0scmlnaHQ6e2p1c3RpZmllZDpkLHBhcmFsbGVsOm4sbm9ybWFsOmMsaG9yaXpvbnRhbDpjLHZlcnRpY2FsOm59fSxtPXthYm92ZTp7anVzdGlmaWVkOmkscGFyYWxsZWw6aSxub3JtYWw6dSxob3Jpem9udGFsOmksdmVydGljYWw6dX0sYmVsb3c6e2p1c3RpZmllZDppLHBhcmFsbGVsOmksbm9ybWFsOnUsaG9yaXpvbnRhbDppLHZlcnRpY2FsOnB9LGxlZnQ6e2p1c3RpZmllZDppLHBhcmFsbGVsOmksbm9ybWFsOnAsaG9yaXpvbnRhbDpwLHZlcnRpY2FsOml9LHJpZ2h0OntqdXN0aWZpZWQ6aSxwYXJhbGxlbDppLG5vcm1hbDp1LGhvcml6b250YWw6dSx2ZXJ0aWNhbDppfX0sZz17YWJvdmU6cCxiZWxvdzp1LGxlZnQ6cCxyaWdodDp1fSx5PXthYm92ZTp1LGJlbG93OnAsbGVmdDpwLHJpZ2h0OnV9LGo9ZnVuY3Rpb24odCl7dmFyIGUscixuLG87aWYobz10LChudWxsPT1vLm1vZGVsLnByb3BzLnZpc2libGV8fG8ubWdldCgidmlzaWJsZSIpIT09ITEpJiYobj1vLl9nZXRfc2l6ZSgpLG51bGw9PW8uX2xhc3Rfc2l6ZSYmKG8uX2xhc3Rfc2l6ZT0tMSksbiE9PW8uX2xhc3Rfc2l6ZSkpcmV0dXJuIGU9by5tb2RlbC5kb2N1bWVudC5zb2x2ZXIoKSxvLl9sYXN0X3NpemU9bixudWxsIT1vLl9zaXplX2NvbnN0cmFpbnQmJmUucmVtb3ZlX2NvbnN0cmFpbnQoby5fc2l6ZV9jb25zdHJhaW50KSxvLl9zaXplX2NvbnN0cmFpbnQ9YShvLm1vZGVsLnBhbmVsLl9zaXplLC1uKSxlLmFkZF9jb25zdHJhaW50KG8uX3NpemVfY29uc3RyYWludCksbnVsbD09by5fZnVsbF9zZXQmJihvLl9mdWxsX3NldD0hMSksby5fZnVsbF9zZXQ/dm9pZCAwOihyPW8ubW9kZWwucGFuZWwuZ2V0KCJzaWRlIiksImFib3ZlIiE9PXImJiJiZWxvdyIhPT1yfHxlLmFkZF9jb25zdHJhaW50KHMoby5tb2RlbC5wYW5lbC5fd2lkdGgsWy0xLG8ucGxvdF9tb2RlbC5jYW52YXMuX3dpZHRoXSkpLCJsZWZ0IiE9PXImJiJyaWdodCIhPT1yfHxlLmFkZF9jb25zdHJhaW50KHMoby5tb2RlbC5wYW5lbC5faGVpZ2h0LFstMSxvLnBsb3RfbW9kZWwuY2FudmFzLl9oZWlnaHRdKSksby5fZnVsbF9zZXQ9ITApfSxfPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBUKGUsdCksZS5pbnRlcm5hbCh7c2lkZTpbdy5TdHJpbmddLHBsb3Q6W3cuSW5zdGFuY2VdfSksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0LHIpe3ZhciBuO3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0LHIpLG49dGhpcy5nZXQoInNpZGUiKSwiYWJvdmUiPT09bj8odGhpcy5fZGltPTAsdGhpcy5fbm9ybWFscz1bMCwtMV0sdGhpcy5fc2l6ZT10aGlzLl9oZWlnaHQsdGhpcy5fYW5jaG9yPXRoaXMuX2JvdHRvbSk6ImJlbG93Ij09PW4/KHRoaXMuX2RpbT0wLHRoaXMuX25vcm1hbHM9WzAsMV0sdGhpcy5fc2l6ZT10aGlzLl9oZWlnaHQsdGhpcy5fYW5jaG9yPXRoaXMuX3RvcCk6ImxlZnQiPT09bj8odGhpcy5fZGltPTEsdGhpcy5fbm9ybWFscz1bLTEsMF0sdGhpcy5fc2l6ZT10aGlzLl93aWR0aCx0aGlzLl9hbmNob3I9dGhpcy5fcmlnaHQpOiJyaWdodCI9PT1uPyh0aGlzLl9kaW09MSx0aGlzLl9ub3JtYWxzPVsxLDBdLHRoaXMuX3NpemU9dGhpcy5fd2lkdGgsdGhpcy5fYW5jaG9yPXRoaXMuX2xlZnQpOnguZXJyb3IoInVucmVjb2duaXplZCBzaWRlOiAnIituKyInIil9LGUucHJvdG90eXBlLmdldF9jb25zdHJhaW50cz1mdW5jdGlvbigpe3ZhciB0O3JldHVybiB0PVtdLHQucHVzaChhKHRoaXMuX3RvcCkpLHQucHVzaChhKHRoaXMuX2JvdHRvbSkpLHQucHVzaChhKHRoaXMuX2xlZnQpKSx0LnB1c2goYSh0aGlzLl9yaWdodCkpLHQucHVzaChhKHRoaXMuX3dpZHRoKSksdC5wdXNoKGEodGhpcy5faGVpZ2h0KSksdC5wdXNoKHModGhpcy5fbGVmdCx0aGlzLl93aWR0aCxbLTEsdGhpcy5fcmlnaHRdKSksdC5wdXNoKHModGhpcy5fYm90dG9tLHRoaXMuX2hlaWdodCxbLTEsdGhpcy5fdG9wXSkpLHR9LGUucHJvdG90eXBlLmFwcGx5X2xhYmVsX3RleHRfaGV1cmlzdGljcz1mdW5jdGlvbih0LGUpe3ZhciByLG4sbztyZXR1cm4gbz10aGlzLmdldCgic2lkZSIpLGYuaXNTdHJpbmcoZSk/KG49YltvXVtlXSxyPW1bb11bZV0pOjA9PT1lPyhuPWJbb11bZV0scj1tW29dW2VdKTplPDA/KG49Im1pZGRsZSIscj1nW29dKTplPjAmJihuPSJtaWRkbGUiLHI9eVtvXSksdC50ZXh0QmFzZWxpbmU9bix0LnRleHRBbGlnbj1yLHR9LGUucHJvdG90eXBlLmdldF9sYWJlbF9hbmdsZV9oZXVyaXN0aWM9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9dGhpcy5nZXQoInNpZGUiKSx2W2VdW3RdfSxlfShoLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOl8sdXBkYXRlX2NvbnN0cmFpbnRzOmp9fSx7Ii4uLy4uL2NvcmUvbG9nZ2luZyI6ImNvcmUvbG9nZ2luZyIsIi4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vbGF5b3V0X2NhbnZhcyI6ImNvcmUvbGF5b3V0L2xheW91dF9jYW52YXMiLCIuL3NvbHZlciI6ImNvcmUvbGF5b3V0L3NvbHZlciIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwiY29yZS9sYXlvdXQvc29sdmVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF87aD10KCJ1bmRlcnNjb3JlIiksbj10KCJiYWNrYm9uZSIpLF89dCgia2l3aSIpLHU9Xy5WYXJpYWJsZSxpPV8uRXhwcmVzc2lvbixvPV8uQ29uc3RyYWludCxzPV8uT3BlcmF0b3IsbD1fLlN0cmVuZ3RoLGM9ZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKGUpe3JldHVybiBmdW5jdGlvbigpe3ZhciBlO3JldHVybiBlPU9iamVjdC5jcmVhdGUoaS5wcm90b3R5cGUpLGkuYXBwbHkoZSxhcmd1bWVudHMpLG5ldyBvKGUsdCl9fSh0aGlzKX0scD1mdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oKXt2YXIgZSxyLG4scztmb3Iocj1bbnVsbF0sbj0wLHM9YXJndW1lbnRzLmxlbmd0aDtuPHM7bisrKWU9YXJndW1lbnRzW25dLHIucHVzaChlKTtyZXR1cm4gbmV3IG8obmV3KEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kLmFwcGx5KGkscikpLHQsXy5TdHJlbmd0aC53ZWFrKX19LGE9ZnVuY3Rpb24oKXtmdW5jdGlvbiB0KCl7dGhpcy5zb2x2ZXI9bmV3IF8uU29sdmVyfXJldHVybiB0LnByb3RvdHlwZS5jbGVhcj1mdW5jdGlvbigpe3JldHVybiB0aGlzLnNvbHZlcj1uZXcgXy5Tb2x2ZXJ9LHQucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIlNvbHZlcltudW1fY29uc3RyYWludHM9Iit0aGlzLm51bV9jb25zdHJhaW50cygpKyIsIG51bV9lZGl0X3ZhcmlhYmxlcz0iK3RoaXMubnVtX2VkaXRfdmFyaWFibGVzKCkrIl0ifSx0LnByb3RvdHlwZS5udW1fY29uc3RyYWludHM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zb2x2ZXIuX2NuTWFwLl9hcnJheS5sZW5ndGh9LHQucHJvdG90eXBlLm51bV9lZGl0X3ZhcmlhYmxlcz1mdW5jdGlvbigpe3JldHVybiB0aGlzLnNvbHZlci5fZWRpdE1hcC5fYXJyYXkubGVuZ3RofSx0LnByb3RvdHlwZS51cGRhdGVfdmFyaWFibGVzPWZ1bmN0aW9uKHQpe2lmKG51bGw9PXQmJih0PSEwKSx0aGlzLnNvbHZlci51cGRhdGVWYXJpYWJsZXMoKSx0KXJldHVybiB0aGlzLnRyaWdnZXIoImxheW91dF91cGRhdGUiKX0sdC5wcm90b3R5cGUuYWRkX2NvbnN0cmFpbnQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuc29sdmVyLmFkZENvbnN0cmFpbnQodCl9LHQucHJvdG90eXBlLnJlbW92ZV9jb25zdHJhaW50PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnNvbHZlci5yZW1vdmVDb25zdHJhaW50KHQpfSx0LnByb3RvdHlwZS5hZGRfZWRpdF92YXJpYWJsZT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnNvbHZlci5hZGRFZGl0VmFyaWFibGUodCxlKX0sdC5wcm90b3R5cGUucmVtb3ZlX2VkaXRfdmFyaWFibGU9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuc29sdmVyLnJlbW92ZUVkaXRWYXJpYWJsZSh0LHN0cmVuZ3RoKX0sdC5wcm90b3R5cGUuc3VnZ2VzdF92YWx1ZT1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnNvbHZlci5zdWdnZXN0VmFsdWUodCxlKX0sdH0oKSxoLmV4dGVuZChhLnByb3RvdHlwZSxuLkV2ZW50cyksZS5leHBvcnRzPXtWYXJpYWJsZTp1LEV4cHJlc3Npb246aSxDb25zdHJhaW50Om8sT3BlcmF0b3I6cyxTdHJlbmd0aDpsLEVROmMocy5FcSksTEU6YyhzLkxlKSxHRTpjKHMuR2UpLFdFQUtfRVE6cChzLkVxKSxXRUFLX0xFOnAocy5MZSksV0VBS19HRTpwKHMuR2UpLFNvbHZlcjphfX0se2JhY2tib25lOiJiYWNrYm9uZSIsa2l3aToia2l3aSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwiY29yZS9sb2dnaW5nIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzO249dCgianNubG9nIikuSkwsaT1uKCJCb2tlaCIpLGkuc2V0T3B0aW9ucyh7YXBwZW5kZXJzOltuLmNyZWF0ZUNvbnNvbGVBcHBlbmRlcigiY29uc29sZUFwcGVuZGVyIildLGxldmVsOm4uZ2V0SW5mb0xldmVsKCl9KSxvPXt0cmFjZTpuLmdldFRyYWNlTGV2ZWwoKSxkZWJ1ZzpuLmdldERlYnVnTGV2ZWwoKSxpbmZvOm4uZ2V0SW5mb0xldmVsKCksd2FybjpuLmdldFdhcm5MZXZlbCgpLGVycm9yOm4uZ2V0RXJyb3JMZXZlbCgpLGZhdGFsOm4uZ2V0RmF0YWxMZXZlbCgpfSxzPWZ1bmN0aW9uKHQpe3JldHVybiB0IGluIG8/KGNvbnNvbGUubG9nKCJCb2tlaDogc2V0dGluZyBsb2cgbGV2ZWwgdG86ICciK3QrIiciKSxpLnNldE9wdGlvbnMoe2xldmVsOm9bdF19KSxudWxsKTooY29uc29sZS5sb2coIkJva2VoOiBVbnJlY29nbml6ZWQgbG9nZ2luZyBsZXZlbCAnIit0KyInIHBhc3NlZCB0byBCb2tlaC5zZXRfbG9nX2xldmVsLCBpZ25vcmluZy4iKSx2b2lkIGNvbnNvbGUubG9nKCJCb2tlaDogVmFsaWQgbG9nIGxldmVscyBhcmU6ICIrT2JqZWN0LmtleXMobykpKX0sZS5leHBvcnRzPXtsZXZlbHM6byxsb2dnZXI6aSxzZXRfbG9nX2xldmVsOnN9fSx7anNubG9nOiJqc25sb2cifV0sImNvcmUvcHJvcGVydGllcyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0sayxqLFQsUyx6LFAsRSxBLEMsTixPLHEsRCxJLFIsRixCLEwsRyxWLFUsWSxILFg9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKSQuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sJD17fS5oYXNPd25Qcm9wZXJ0eSxXPVtdLmluZGV4T2Z8fGZ1bmN0aW9uKHQpe2Zvcih2YXIgZT0wLHI9dGhpcy5sZW5ndGg7ZTxyO2UrKylpZihlIGluIHRoaXMmJnRoaXNbZV09PT10KXJldHVybiBlO3JldHVybi0xfTtCPXQoInVuZGVyc2NvcmUiKSx1PXQoImJhY2tib25lIiksRz10KCIuL2VudW1zIiksVT10KCIuL3V0aWwvc3ZnX2NvbG9ycyIpLEg9dCgiLi91dGlsL2NvbG9yIikudmFsaWRfcmdiLEU9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlLnByb3RvdHlwZS5kYXRhc3BlYz0hMSxlLnByb3RvdHlwZS5zcGVjaWZpZXJzPVsiZmllbGQiLCJ2YWx1ZSJdLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXt2YXIgbixvO3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0LHIpLHRoaXMuX2luaXQoITEpLG89dGhpcy5nZXQoIm9iaiIpLG49dGhpcy5nZXQoImF0dHIiKSx0aGlzLmxpc3RlblRvKG8sImNoYW5nZToiK24sZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5faW5pdCgpLG8udHJpZ2dlcigicHJvcGNoYW5nZSIpfSksdGhpcy5saXN0ZW5Ubyh0aGlzLCJjaGFuZ2U6b2JqIixmdW5jdGlvbigpe3Rocm93IG5ldyBFcnJvcigiYXR0ZW1wdGVkIHRvIHJlc2V0ICdvYmonIG9uIFByb3BlcnR5Iil9KSx0aGlzLmxpc3RlblRvKHRoaXMsImNoYW5nZTphdHRyIixmdW5jdGlvbigpe3Rocm93IG5ldyBFcnJvcigiYXR0ZW1wdGVkIHRvIHJlc2V0ICdhdHRyJyBvbiBQcm9wZXJ0eSIpfSl9LGUucHJvdG90eXBlLnVwZGF0ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9pbml0KCl9LGUucHJvdG90eXBlLmluaXQ9ZnVuY3Rpb24oKXt9LGUucHJvdG90eXBlLnRyYW5zZm9ybT1mdW5jdGlvbih0KXtyZXR1cm4gdH0sZS5wcm90b3R5cGUudmFsaWRhdGU9ZnVuY3Rpb24odCl7fSxlLnByb3RvdHlwZS52YWx1ZT1mdW5jdGlvbih0KXt2YXIgZTtpZihudWxsPT10JiYodD0hMCksQi5pc1VuZGVmaW5lZCh0aGlzLnNwZWMudmFsdWUpKXRocm93IG5ldyBFcnJvcigiYXR0ZW1wdGVkIHRvIHJldHJpZXZlIHByb3BlcnR5IHZhbHVlIGZvciBwcm9wZXJ0eSB3aXRob3V0IHZhbHVlIHNwZWNpZmljYXRpb24iKTtyZXR1cm4gZT10aGlzLnRyYW5zZm9ybShbdGhpcy5zcGVjLnZhbHVlXSlbMF0sbnVsbCE9dGhpcy5zcGVjLnRyYW5zZm9ybSYmdCYmKGU9dGhpcy5zcGVjLnRyYW5zZm9ybS5jb21wdXRlKGUpKSxlfSxlLnByb3RvdHlwZS5hcnJheT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpO2lmKCF0aGlzLmRhdGFzcGVjKXRocm93IG5ldyBFcnJvcigiYXR0ZW1wdGVkIHRvIHJldHJpZXZlIHByb3BlcnR5IGFycmF5IGZvciBub24tZGF0YXNwZWMgcHJvcGVydHkiKTtpZihlPXQuZ2V0KCJkYXRhIiksbnVsbCE9dGhpcy5zcGVjLmZpZWxkKXtpZighKHRoaXMuc3BlYy5maWVsZCBpbiBlKSl0aHJvdyBuZXcgRXJyb3IoImF0dGVtcHRlZCB0byByZXRyaWV2ZSBwcm9wZXJ0eSBhcnJheSBmb3Igbm9uZXhpc3RlbnQgZmllbGQgJyIrdGhpcy5zcGVjLmZpZWxkKyInIik7bz10aGlzLnRyYW5zZm9ybSh0LmdldF9jb2x1bW4odGhpcy5zcGVjLmZpZWxkKSl9ZWxzZSBuPXQuZ2V0X2xlbmd0aCgpLG51bGw9PW4mJihuPTEpLGk9dGhpcy52YWx1ZSghMSksbz1mdW5jdGlvbigpe3ZhciB0LGUsbztmb3Iobz1bXSxyPXQ9MCxlPW47MDw9ZT90PGU6dD5lO3I9MDw9ZT8rK3Q6LS10KW8ucHVzaChpKTtyZXR1cm4gb30oKTtyZXR1cm4gbnVsbCE9dGhpcy5zcGVjLnRyYW5zZm9ybSYmKG89dGhpcy5zcGVjLnRyYW5zZm9ybS52X2NvbXB1dGUobykpLG99LGUucHJvdG90eXBlLl9pbml0PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvO2lmKG51bGw9PXQmJih0PSEwKSxvPXRoaXMuZ2V0KCJvYmoiKSxudWxsPT1vKXRocm93IG5ldyBFcnJvcigibWlzc2luZyBwcm9wZXJ0eSBvYmplY3QiKTtpZihudWxsPT1vLnByb3BlcnRpZXMpdGhyb3cgbmV3IEVycm9yKCJwcm9wZXJ0eSBvYmplY3QgbXVzdCBiZSBhIEhhc1Byb3BzIik7aWYoZT10aGlzLmdldCgiYXR0ciIpLG51bGw9PWUpdGhyb3cgbmV3IEVycm9yKCJtaXNzaW5nIHByb3BlcnR5IGF0dHIiKTtpZihyPW8uZ2V0KGUpLEIuaXNVbmRlZmluZWQocikmJihuPXRoaXMuZ2V0KCJkZWZhdWx0X3ZhbHVlIikscj1mdW5jdGlvbigpe3N3aXRjaCghMSl7Y2FzZSFCLmlzVW5kZWZpbmVkKG4pOnJldHVybiBudWxsO2Nhc2UhQi5pc0FycmF5KG4pOnJldHVybiBCLmNsb25lKG4pO2Nhc2UhQi5pc0Z1bmN0aW9uKG4pOnJldHVybiBuKG8pO2RlZmF1bHQ6cmV0dXJuIG59fSgpLG8uc2V0KGUscix7c2lsZW50OiEwLGRlZmF1bHRzOiEwfSkpLEIuaXNBcnJheShyKT90aGlzLnNwZWM9e3ZhbHVlOnJ9OkIuaXNPYmplY3QocikmJjE9PT1CLnNpemUoQi5waWNrLmFwcGx5KG51bGwsW3JdLmNvbmNhdCh0aGlzLnNwZWNpZmllcnMpKSk/dGhpcy5zcGVjPXI6dGhpcy5zcGVjPXt2YWx1ZTpyfSxudWxsIT10aGlzLnNwZWMuZmllbGQmJiFCLmlzU3RyaW5nKHRoaXMuc3BlYy5maWVsZCkpdGhyb3cgbmV3IEVycm9yKCJmaWVsZCB2YWx1ZSBmb3IgcHJvcGVydHkgJyIrZSsiJyBpcyBub3QgYSBzdHJpbmciKTtpZihudWxsIT10aGlzLnNwZWMudmFsdWUmJnRoaXMudmFsaWRhdGUodGhpcy5zcGVjLnZhbHVlKSx0aGlzLmluaXQoKSx0KXJldHVybiB0aGlzLnRyaWdnZXIoImNoYW5nZSIpfSxlfSh1Lk1vZGVsKSxWPWZ1bmN0aW9uKHQsZSl7dmFyIHI7cmV0dXJuIHI9ZnVuY3Rpb24ocil7ZnVuY3Rpb24gbigpe3JldHVybiBuLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgobixyKSxuLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVybiB0KyIob2JqOiAiK3RoaXMuZ2V0KG9iaikuaWQrIiwgc3BlYzogIitKU09OLnN0cmluZ2lmeSh0aGlzLnNwZWMpKyIpIn0sbi5wcm90b3R5cGUudmFsaWRhdGU9ZnVuY3Rpb24ocil7dmFyIG47aWYoIWUocikpdGhyb3cgbj10aGlzLmdldCgiYXR0ciIpLG5ldyBFcnJvcih0KyIgcHJvcGVydHkgJyIrbisiJyBnaXZlbiBpbnZhbGlkIHZhbHVlOiAiK3IpfSxufShFKX0sYT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gWChlLHQpLGV9KFYoIkFueSIsZnVuY3Rpb24odCl7cmV0dXJuITB9KSksbD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gWChlLHQpLGV9KFYoIkFycmF5IixmdW5jdGlvbih0KXtyZXR1cm4gQi5pc0FycmF5KHQpfHx0IGluc3RhbmNlb2YgRmxvYXQ2NEFycmF5fSkpLGg9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShWKCJCb29sIixCLmlzQm9vbGVhbikpLGM9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShWKCJDb2xvciIsZnVuY3Rpb24odCl7cmV0dXJuIG51bGwhPVVbdC50b0xvd2VyQ2FzZSgpXXx8IiMiPT09dC5zdWJzdHJpbmcoMCwxKXx8SCh0KX0pKSx3PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKGUsdCksZX0oVigiSW5zdGFuY2UiLGZ1bmN0aW9uKHQpe3JldHVybiBudWxsIT10LnByb3BlcnRpZXN9KSksUz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gWChlLHQpLGV9KFYoIk51bWJlciIsZnVuY3Rpb24odCl7cmV0dXJuIEIuaXNOdW1iZXIodCl8fEIuaXNCb29sZWFuKHQpfSkpLHE9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShWKCJTdHJpbmciLEIuaXNTdHJpbmcpKSx2PWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKGUsdCksZX0ocSksTD1mdW5jdGlvbih0LGUpe3ZhciByO3JldHVybiByPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIHIoKXtyZXR1cm4gci5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKHIsZSksci5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdCsiKG9iajogIit0aGlzLmdldChvYmopLmlkKyIsIHNwZWM6ICIrSlNPTi5zdHJpbmdpZnkodGhpcy5zcGVjKSsiKSJ9LHJ9KFYodCxmdW5jdGlvbih0KXtyZXR1cm4gVy5jYWxsKGUsdCk+PTB9KSl9LG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShMKCJBbmNob3IiLEcuTGVnZW5kTG9jYXRpb24pKSxzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKGUsdCksZX0oTCgiQW5nbGVVbml0cyIsRy5BbmdsZVVuaXRzKSksZD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gWChlLHQpLGUucHJvdG90eXBlLnRyYW5zZm9ybT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbztmb3Iobz1uZXcgVWludDhBcnJheSh0Lmxlbmd0aCksZT1yPTAsbj10Lmxlbmd0aDswPD1uP3I8bjpyPm47ZT0wPD1uPysrcjotLXIpc3dpdGNoKHRbZV0pe2Nhc2UiY2xvY2siOm9bZV09ITE7YnJlYWs7Y2FzZSJhbnRpY2xvY2siOm9bZV09ITB9cmV0dXJuIG99LGV9KEwoIkRpcmVjdGlvbiIsRy5EaXJlY3Rpb24pKSxfPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKGUsdCksZX0oTCgiRGltZW5zaW9uIixHLkRpbWVuc2lvbikpLHg9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShMKCJGb250U3R5bGUiLEcuRm9udFN0eWxlKSksaz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gWChlLHQpLGV9KEwoIkxpbmVDYXAiLEcuTGluZUNhcCkpLGo9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShMKCJMaW5lSm9pbiIsRy5MaW5lSm9pbikpLE09ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShMKCJMZWdlbmRMb2NhdGlvbiIsRy5MZWdlbmRMb2NhdGlvbikpLFQ9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShMKCJMb2NhdGlvbiIsRy5Mb2NhdGlvbikpLFA9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShMKCJPcmllbnRhdGlvbiIsRy5PcmllbnRhdGlvbikpLEk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShMKCJUZXh0QWxpZ24iLEcuVGV4dEFsaWduKSksUj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gWChlLHQpLGV9KEwoIlRleHRCYXNlbGluZSIsRy5UZXh0QmFzZWxpbmUpKSxBPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKGUsdCksZX0oTCgiUmVuZGVyTGV2ZWwiLEcuUmVuZGVyTGV2ZWwpKSwKQz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gWChlLHQpLGV9KEwoIlJlbmRlck1vZGUiLEcuUmVuZGVyTW9kZSkpLE49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShMKCJTaXppbmdNb2RlIixHLlNpemluZ01vZGUpKSxPPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKGUsdCksZX0oTCgiU3BhdGlhbFVuaXRzIixHLlNwYXRpYWxVbml0cykpLHk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlfShMKCJEaXN0cmlidXRpb24iLEcuRGlzdHJpYnV0aW9uVHlwZXMpKSxGPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKGUsdCksZX0oTCgiVHJhbnNmb3JtU3RlcE1vZGUiLEcuVHJhbnNmb3JtU3RlcE1vZGVzKSksWT1mdW5jdGlvbih0LGUscil7dmFyIG47cmV0dXJuIG49ZnVuY3Rpb24obil7ZnVuY3Rpb24gbygpe3JldHVybiBvLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgobyxuKSxvLnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVybiB0KyIob2JqOiAiK3RoaXMuZ2V0KG9iaikuaWQrIiwgc3BlYzogIitKU09OLnN0cmluZ2lmeSh0aGlzLnNwZWMpKyIpIn0sby5wcm90b3R5cGUuaW5pdD1mdW5jdGlvbigpe3ZhciBuO2lmKG51bGw9PXRoaXMuc3BlYy51bml0cyYmKHRoaXMuc3BlYy51bml0cz1yKSx0aGlzLnVuaXRzPXRoaXMuc3BlYy51bml0cyxuPXRoaXMuc3BlYy51bml0cyxXLmNhbGwoZSxuKTwwKXRocm93IG5ldyBFcnJvcih0KyIgdW5pdHMgbXVzdCBiZSBvbmUgb2YgIitlKyIsIGdpdmVuIGludmFsaWQgdmFsdWU6ICIrbil9LG99KFMpfSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKGUsdCksZS5wcm90b3R5cGUudHJhbnNmb3JtPWZ1bmN0aW9uKHQpe3ZhciByO3JldHVybiJkZWciPT09dGhpcy5zcGVjLnVuaXRzJiYodD1mdW5jdGlvbigpe3ZhciBlLG4sbztmb3Iobz1bXSxlPTAsbj10Lmxlbmd0aDtlPG47ZSsrKXI9dFtlXSxvLnB1c2gocipNYXRoLlBJLzE4MCk7cmV0dXJuIG99KCkpLHQ9ZnVuY3Rpb24oKXt2YXIgZSxuLG87Zm9yKG89W10sZT0wLG49dC5sZW5ndGg7ZTxuO2UrKylyPXRbZV0sby5wdXNoKC1yKTtyZXR1cm4gb30oKSxlLl9fc3VwZXJfXy50cmFuc2Zvcm0uY2FsbCh0aGlzLHQpfSxlfShZKCJBbmdsZSIsRy5BbmdsZVVuaXRzLCJyYWQiKSksbT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gWChlLHQpLGV9KFkoIkRpc3RhbmNlIixHLlNwYXRpYWxVbml0cywiZGF0YSIpKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKGUsdCksZS5wcm90b3R5cGUuZGF0YXNwZWM9ITAsZX0obykscD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gWChlLHQpLGUucHJvdG90eXBlLmRhdGFzcGVjPSEwLGV9KGMpLGY9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlLnByb3RvdHlwZS5kYXRhc3BlYz0hMCxlfShtKSxnPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKGUsdCksZS5wcm90b3R5cGUuZGF0YXNwZWM9ITAsZX0obSksYj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gWChlLHQpLGUucHJvdG90eXBlLmRhdGFzcGVjPSEwLGV9KHEpLHo9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIFgoZSx0KSxlLnByb3RvdHlwZS5kYXRhc3BlYz0hMCxlfShTKSxEPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBYKGUsdCksZS5wcm90b3R5cGUuZGF0YXNwZWM9ITAsZX0ocSksZS5leHBvcnRzPXtQcm9wZXJ0eTpFLHNpbXBsZV9wcm9wOlYsZW51bV9wcm9wOkwsdW5pdHNfcHJvcDpZLEFuY2hvcjpuLEFueTphLEFuZ2xlOm8sQW5nbGVVbml0czpzLEFycmF5OmwsQm9vbDpoLEJvb2xlYW46aCxDb2xvcjpjLERpbWVuc2lvbjpfLERpcmVjdGlvbjpkLERpc3RhbmNlOm0sRm9udDp2LEZvbnRTdHlsZTp4LEluc3RhbmNlOncsTGVnZW5kTG9jYXRpb246TSxMaW5lQ2FwOmssTGluZUpvaW46aixMb2NhdGlvbjpULE51bWJlcjpTLEludDpTLE9yaWVudGF0aW9uOlAsUmVuZGVyTGV2ZWw6QSxSZW5kZXJNb2RlOkMsU2l6aW5nTW9kZTpOLFNwYXRpYWxVbml0czpPLFN0cmluZzpxLFRleHRBbGlnbjpJLFRleHRCYXNlbGluZTpSLERpc3RyaWJ1dGlvbjp5LFRyYW5zZm9ybVN0ZXBNb2RlOkYsQW5nbGVTcGVjOmksQ29sb3JTcGVjOnAsRGlyZWN0aW9uU3BlYzpmLERpc3RhbmNlU3BlYzpnLEZvbnRTaXplU3BlYzpiLE51bWJlclNwZWM6eixTdHJpbmdTcGVjOkR9fSx7Ii4vZW51bXMiOiJjb3JlL2VudW1zIiwiLi91dGlsL2NvbG9yIjoiY29yZS91dGlsL2NvbG9yIiwiLi91dGlsL3N2Z19jb2xvcnMiOiJjb3JlL3V0aWwvc3ZnX2NvbG9ycyIsYmFja2JvbmU6ImJhY2tib25lIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJjb3JlL3Byb3BlcnR5X21peGlucyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscDtuPXQoInVuZGVyc2NvcmUiKSxjPXQoIi4vcHJvcGVydGllcyIpLGk9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG87bj17fSxudWxsPT1lJiYoZT0iIik7Zm9yKHIgaW4gdClvPXRbcl0sbltlK3JdPW87cmV0dXJuIG59LHM9e2xpbmVfY29sb3I6W2MuQ29sb3JTcGVjLCJibGFjayJdLGxpbmVfd2lkdGg6W2MuTnVtYmVyU3BlYywxXSxsaW5lX2FscGhhOltjLk51bWJlclNwZWMsMV0sbGluZV9qb2luOltjLkxpbmVKb2luLCJtaXRlciJdLGxpbmVfY2FwOltjLkxpbmVDYXAsImJ1dHQiXSxsaW5lX2Rhc2g6W2MuQXJyYXksW11dLGxpbmVfZGFzaF9vZmZzZXQ6W2MuTnVtYmVyLDBdfSxoPWZ1bmN0aW9uKHQpe3JldHVybiBpKHMsdCl9LG89e2ZpbGxfY29sb3I6W2MuQ29sb3JTcGVjLCJncmF5Il0sZmlsbF9hbHBoYTpbYy5OdW1iZXJTcGVjLDFdfSx1PWZ1bmN0aW9uKHQpe3JldHVybiBpKG8sdCl9LGE9e3RleHRfZm9udDpbYy5Gb250LCJoZWx2ZXRpY2EiXSx0ZXh0X2ZvbnRfc2l6ZTpbYy5Gb250U2l6ZVNwZWMsIjEycHQiXSx0ZXh0X2ZvbnRfc3R5bGU6W2MuRm9udFN0eWxlLCJub3JtYWwiXSx0ZXh0X2NvbG9yOltjLkNvbG9yU3BlYywiIzQ0NDQ0NCJdLHRleHRfYWxwaGE6W2MuTnVtYmVyU3BlYywxXSx0ZXh0X2FsaWduOltjLlRleHRBbGlnbiwibGVmdCJdLHRleHRfYmFzZWxpbmU6W2MuVGV4dEJhc2VsaW5lLCJib3R0b20iXX0scD1mdW5jdGlvbih0KXtyZXR1cm4gaShhLHQpfSxsPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbyxpLHMsYSxsO2ZvcihsPXt9LHI9MCxpPXQubGVuZ3RoO3I8aTtyKyspe2lmKGU9dFtyXSxhPWUuc3BsaXQoIjoiKSxvPWFbMF0scz1hWzFdLG51bGw9PXRoaXNbb10pdGhyb3cgRXJyb3IoIlVua25vd24gcHJvcGVydHkgbWl4aW4ga2luZCAnIitvKyInIik7bD1uLmV4dGVuZChsLHRoaXNbb10ocykpfXJldHVybiBsfSxlLmV4cG9ydHM9e2xpbmU6aCxmaWxsOnUsdGV4dDpwLGNyZWF0ZTpsfX0seyIuL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sImNvcmUvdXRpbC9iYm94IjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG87bj1mdW5jdGlvbigpe3JldHVybnttaW5YOjEvMCxtaW5ZOjEvMCxtYXhYOi0oMS8wKSxtYXhZOi0oMS8wKX19LG89ZnVuY3Rpb24odCxlKXt2YXIgcjtyZXR1cm4gcj17fSxyLm1pblg9TWF0aC5taW4odC5taW5YLGUubWluWCksci5tYXhYPU1hdGgubWF4KHQubWF4WCxlLm1heFgpLHIubWluWT1NYXRoLm1pbih0Lm1pblksZS5taW5ZKSxyLm1heFk9TWF0aC5tYXgodC5tYXhZLGUubWF4WSkscn0sZS5leHBvcnRzPXtlbXB0eTpuLHVuaW9uOm99fSx7fV0sImNvcmUvdXRpbC9jYW52YXMiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsO2k9ZnVuY3Rpb24odCl7aWYodC5zZXRMaW5lRGFzaHx8KHQuc2V0TGluZURhc2g9ZnVuY3Rpb24oZSl7cmV0dXJuIHQubW96RGFzaD1lLHQud2Via2l0TGluZURhc2g9ZX0pLCF0LmdldExpbmVEYXNoKXJldHVybiB0LmdldExpbmVEYXNoPWZ1bmN0aW9uKCl7cmV0dXJuIHQubW96RGFzaH19LHM9ZnVuY3Rpb24odCl7cmV0dXJuIHQuc2V0TGluZURhc2hPZmZzZXQ9ZnVuY3Rpb24oZSl7cmV0dXJuIHQubGluZURhc2hPZmZzZXQ9ZSx0Lm1vekRhc2hPZmZzZXQ9ZSx0LndlYmtpdExpbmVEYXNoT2Zmc2V0PWV9LHQuZ2V0TGluZURhc2hPZmZzZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdC5tb3pEYXNoT2Zmc2V0fX0sbz1mdW5jdGlvbih0KXtyZXR1cm4gdC5zZXRJbWFnZVNtb290aGluZ0VuYWJsZWQ9ZnVuY3Rpb24oZSl7cmV0dXJuIHQuaW1hZ2VTbW9vdGhpbmdFbmFibGVkPWUsdC5tb3pJbWFnZVNtb290aGluZ0VuYWJsZWQ9ZSx0Lm9JbWFnZVNtb290aGluZ0VuYWJsZWQ9ZSx0LndlYmtpdEltYWdlU21vb3RoaW5nRW5hYmxlZD1lfSx0LmdldEltYWdlU21vb3RoaW5nRW5hYmxlZD1mdW5jdGlvbigpe3ZhciBlO3JldHVybiBudWxsPT0oZT10LmltYWdlU21vb3RoaW5nRW5hYmxlZCl8fGV9fSxhPWZ1bmN0aW9uKHQpe2lmKHQubWVhc3VyZVRleHQmJm51bGw9PXQuaHRtbDVNZWFzdXJlVGV4dClyZXR1cm4gdC5odG1sNU1lYXN1cmVUZXh0PXQubWVhc3VyZVRleHQsdC5tZWFzdXJlVGV4dD1mdW5jdGlvbihlKXt2YXIgcjtyZXR1cm4gcj10Lmh0bWw1TWVhc3VyZVRleHQoZSksci5hc2NlbnQ9MS42KnQuaHRtbDVNZWFzdXJlVGV4dCgibSIpLndpZHRoLHJ9fSxsPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbjtyZXR1cm4gZT8obj13aW5kb3cuZGV2aWNlUGl4ZWxSYXRpb3x8MSxyPXQud2Via2l0QmFja2luZ1N0b3JlUGl4ZWxSYXRpb3x8dC5tb3pCYWNraW5nU3RvcmVQaXhlbFJhdGlvfHx0Lm1zQmFja2luZ1N0b3JlUGl4ZWxSYXRpb3x8dC5vQmFja2luZ1N0b3JlUGl4ZWxSYXRpb3x8dC5iYWNraW5nU3RvcmVQaXhlbFJhdGlvfHwxLG4vcik6MX0sbj1mdW5jdGlvbih0KXt2YXIgZTtpZihlPWZ1bmN0aW9uKGUscixuLG8saSxzLGEsbCl7dmFyIHUsaCxjO251bGw9PWwmJihsPSExKSx1PS41NTE3ODQsdC50cmFuc2xhdGUoZSxyKSx0LnJvdGF0ZShpKSxoPW4sYz1vLGwmJihoPS1uLGM9LW8pLHQubW92ZVRvKC1oLDApLHQuYmV6aWVyQ3VydmVUbygtaCxjKnUsLWgqdSxjLDAsYyksdC5iZXppZXJDdXJ2ZVRvKGgqdSxjLGgsYyp1LGgsMCksdC5iZXppZXJDdXJ2ZVRvKGgsLWMqdSxoKnUsLWMsMCwtYyksdC5iZXppZXJDdXJ2ZVRvKC1oKnUsLWMsLWgsLWMqdSwtaCwwKSx0LnJvdGF0ZSgtaSksdC50cmFuc2xhdGUoLWUsLXIpfSwhdC5lbGxpcHNlKXJldHVybiB0LmVsbGlwc2U9ZX0sZS5leHBvcnRzPXtmaXh1cF9pbWFnZV9zbW9vdGhpbmc6byxmaXh1cF9saW5lX2Rhc2g6aSxmaXh1cF9saW5lX2Rhc2hfb2Zmc2V0OnMsZml4dXBfbWVhc3VyZV90ZXh0OmEsZ2V0X3NjYWxlX3JhdGlvOmwsZml4dXBfZWxsaXBzZTpufX0se31dLCJjb3JlL3V0aWwvY29sb3IiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsPVtdLmluZGV4T2Z8fGZ1bmN0aW9uKHQpe2Zvcih2YXIgZT0wLHI9dGhpcy5sZW5ndGg7ZTxyO2UrKylpZihlIGluIHRoaXMmJnRoaXNbZV09PT10KXJldHVybiBlO3JldHVybi0xfTtzPXQoIi4vc3ZnX2NvbG9ycyIpLG49ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9TnVtYmVyKHQpLnRvU3RyaW5nKDE2KSxlPTE9PT1lLmxlbmd0aD8iMCIrZTplfSxvPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbztyZXR1cm4gdCs9IiIsMD09PXQuaW5kZXhPZigiIyIpP3Q6bnVsbCE9c1t0XT9zW3RdOjA9PT10LmluZGV4T2YoInJnYiIpPyhyPXQubWF0Y2goL1xkKy9nKSxlPWZ1bmN0aW9uKCl7dmFyIHQsZSxpO2ZvcihpPVtdLHQ9MCxlPXIubGVuZ3RoO3Q8ZTt0Kyspbz1yW3RdLGkucHVzaChuKG8pKTtyZXR1cm4gaX0oKS5qb2luKCIiKSwiIyIrZS5zbGljZSgwLDgpKTp0fSxpPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixpO2lmKG51bGw9PWUmJihlPTEpLCF0KXJldHVyblswLDAsMCwwXTtmb3Iocj1vKHQpLHI9ci5yZXBsYWNlKC8gfCMvZywiIiksci5sZW5ndGg8PTQmJihyPXIucmVwbGFjZSgvKC4pL2csIiQxJDEiKSkscj1yLm1hdGNoKC8uLi9nKSxpPWZ1bmN0aW9uKCl7dmFyIHQsZSxvO2ZvcihvPVtdLHQ9MCxlPXIubGVuZ3RoO3Q8ZTt0Kyspbj1yW3RdLG8ucHVzaChwYXJzZUludChuLDE2KS8yNTUpO3JldHVybiBvfSgpO2kubGVuZ3RoPDM7KWkucHVzaCgwKTtyZXR1cm4gaS5sZW5ndGg8NCYmaS5wdXNoKGUpLGkuc2xpY2UoMCw0KX0sYT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbztzd2l0Y2godC5zdWJzdHJpbmcoMCw0KSl7Y2FzZSJyZ2JhIjpyPXtzdGFydDoicmdiYSgiLGxlbjo0LGFscGhhOiEwfTticmVhaztjYXNlInJnYigiOnI9e3N0YXJ0OiJyZ2IoIixsZW46MyxhbHBoYTohMX07YnJlYWs7ZGVmYXVsdDpyZXR1cm4hMX1pZihuZXcgUmVnRXhwKCIuKj8oXFwuKS4qKCwpIikudGVzdCh0KSl0aHJvdyBuZXcgRXJyb3IoImNvbG9yIGV4cGVjdHMgaW50ZWdlcnMgZm9yIHJnYiBpbiByZ2IvcmdiYSB0dXBsZSwgcmVjZWl2ZWQgIit0KTtpZihlPXQucmVwbGFjZShyLnN0YXJ0LCIiKS5yZXBsYWNlKCIpIiwiIikuc3BsaXQoIiwiKS5tYXAocGFyc2VGbG9hdCksZS5sZW5ndGghPT1yLmxlbil0aHJvdyBuZXcgRXJyb3IoImNvbG9yIGV4cGVjdHMgcmdiYSAiK2V4cGVjdF9sZW4rIi10dXBsZSwgcmVjZWl2ZWQgIit0KTtpZihyLmFscGhhJiYhKDA8PShuPWVbM10pJiZuPD0xKSl0aHJvdyBuZXcgRXJyb3IoImNvbG9yIGV4cGVjdHMgcmdiYSA0LXR1cGxlIHRvIGhhdmUgYWxwaGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxIik7aWYobC5jYWxsKGZ1bmN0aW9uKCl7dmFyIHQscixuLGk7Zm9yKG49ZS5zbGljZSgwLDMpLGk9W10sdD0wLHI9bi5sZW5ndGg7dDxyO3QrKylvPW5bdF0saS5wdXNoKDA8PW8mJm88PTI1NSk7cmV0dXJuIGl9KCksITEpPj0wKXRocm93IG5ldyBFcnJvcigiY29sb3IgZXhwZWN0cyByZ2IgdG8gaGF2ZSB2YWx1ZSBiZXR3ZWVuIDAgYW5kIDI1NSIpO3JldHVybiEwfSxlLmV4cG9ydHM9e2NvbG9yMmhleDpvLGNvbG9yMnJnYmE6aSx2YWxpZF9yZ2I6YX19LHsiLi9zdmdfY29sb3JzIjoiY29yZS91dGlsL3N2Z19jb2xvcnMifV0sImNvcmUvdXRpbC9kYXRhX3N0cnVjdHVyZXMiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpO2k9dCgidW5kZXJzY29yZSIpLG49ZnVuY3Rpb24oKXtmdW5jdGlvbiB0KCl7dGhpcy5fZGljdD17fX1yZXR1cm4gdC5wcm90b3R5cGUuX2V4aXN0aW5nPWZ1bmN0aW9uKHQpe3JldHVybiB0IGluIHRoaXMuX2RpY3Q/dGhpcy5fZGljdFt0XTpudWxsfSx0LnByb3RvdHlwZS5hZGRfdmFsdWU9ZnVuY3Rpb24odCxlKXt2YXIgcjtpZihudWxsPT09ZSl0aHJvdyBuZXcgRXJyb3IoIkNhbid0IHB1dCBudWxsIGluIHRoaXMgZGljdCIpO2lmKGkuaXNBcnJheShlKSl0aHJvdyBuZXcgRXJyb3IoIkNhbid0IHB1dCBhcnJheXMgaW4gdGhpcyBkaWN0Iik7cmV0dXJuIHI9dGhpcy5fZXhpc3RpbmcodCksbnVsbD09PXI/dGhpcy5fZGljdFt0XT1lOmkuaXNBcnJheShyKT9yLnB1c2goZSk6dGhpcy5fZGljdFt0XT1bcixlXX0sdC5wcm90b3R5cGUucmVtb3ZlX3ZhbHVlPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbjtyZXR1cm4gcj10aGlzLl9leGlzdGluZyh0KSxpLmlzQXJyYXkocik/KG49aS53aXRob3V0KHIsZSksbi5sZW5ndGg+MD90aGlzLl9kaWN0W3RdPW46ZGVsZXRlIHRoaXMuX2RpY3RbdF0pOmkuaXNFcXVhbChyLGUpP2RlbGV0ZSB0aGlzLl9kaWN0W3RdOnZvaWQgMH0sdC5wcm90b3R5cGUuZ2V0X29uZT1mdW5jdGlvbih0LGUpe3ZhciByO2lmKHI9dGhpcy5fZXhpc3RpbmcodCksaS5pc0FycmF5KHIpKXtpZigxPT09ci5sZW5ndGgpcmV0dXJuIHJbMF07dGhyb3cgbmV3IEVycm9yKGUpfXJldHVybiByfSx0fSgpLG89ZnVuY3Rpb24oKXtmdW5jdGlvbiB0KGUpe2lmKGUpe2lmKGUuY29uc3RydWN0b3I9PT10KXJldHVybiBuZXcgdChlLnZhbHVlcyk7ZS5jb25zdHJ1Y3Rvcj09PUFycmF5P3RoaXMudmFsdWVzPXQuY29tcGFjdChlKTp0aGlzLnZhbHVlcz1bZV19ZWxzZSB0aGlzLnZhbHVlcz1bXX1yZXR1cm4gdC5jb21wYWN0PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvO2ZvcihvPVtdLHI9MCxuPXQubGVuZ3RoO3I8bjtyKyspZT10W3JdLG8uaW5kZXhPZihlKT09PS0xJiZvLnB1c2goZSk7cmV0dXJuIG99LHQucHJvdG90eXBlLnB1c2g9ZnVuY3Rpb24odCl7aWYodGhpcy5taXNzaW5nKHQpKXJldHVybiB0aGlzLnZhbHVlcy5wdXNoKHQpfSx0LnByb3RvdHlwZS5yZW1vdmU9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9dGhpcy52YWx1ZXMuaW5kZXhPZih0KSx0aGlzLnZhbHVlcz10aGlzLnZhbHVlcy5zbGljZSgwLGUpLmNvbmNhdCh0aGlzLnZhbHVlcy5zbGljZShlKzEpKX0sdC5wcm90b3R5cGUubGVuZ3RoPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aH0sdC5wcm90b3R5cGUuaW5jbHVkZXM9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMudmFsdWVzLmluZGV4T2YodCkhPT0tMX0sdC5wcm90b3R5cGUubWlzc2luZz1mdW5jdGlvbih0KXtyZXR1cm4hdGhpcy5pbmNsdWRlcyh0KX0sdC5wcm90b3R5cGUuc2xpY2U9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy52YWx1ZXMuc2xpY2UodCxlKX0sdC5wcm90b3R5cGUuam9pbj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy52YWx1ZXMuam9pbih0KX0sdC5wcm90b3R5cGUudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5qb2luKCIsICIpfSx0LnByb3RvdHlwZS5pbmNsdWRlcz1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy52YWx1ZXMuaW5kZXhPZih0KSE9PS0xfSx0LnByb3RvdHlwZS51bmlvbj1mdW5jdGlvbihlKXtyZXR1cm4gZT1uZXcgdChlKSxuZXcgdCh0aGlzLnZhbHVlcy5jb25jYXQoZS52YWx1ZXMpKX0sdC5wcm90b3R5cGUuaW50ZXJzZWN0PWZ1bmN0aW9uKGUpe3ZhciByLG4sbyxpLHM7Zm9yKGU9bmV3IHQoZSksaT1uZXcgdCxzPWUudmFsdWVzLG49MCxvPXMubGVuZ3RoO248bztuKyspcj1zW25dLHRoaXMuaW5jbHVkZXMocikmJmUuaW5jbHVkZXMocikmJmkucHVzaChyKTtyZXR1cm4gaX0sdC5wcm90b3R5cGUuZGlmZj1mdW5jdGlvbihlKXt2YXIgcixuLG8saSxzO2ZvcihlPW5ldyB0KGUpLGk9bmV3IHQscz10aGlzLnZhbHVlcyxuPTAsbz1zLmxlbmd0aDtuPG87bisrKXI9c1tuXSxlLm1pc3NpbmcocikmJmkucHVzaChyKTtyZXR1cm4gaX0sdH0oKSxlLmV4cG9ydHM9e011bHRpRGljdDpuLFNldDpvfX0se3VuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sImNvcmUvdXRpbC9tYXRoIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGg7YT1mdW5jdGlvbih0KXt2YXIgZSxyLG47Zm9yKGU9dC5sZW5ndGgscj0xLzA7ZS0tOyluPXRbZV0sbjxyJiYocj1uKTtyZXR1cm4gcn0scz1mdW5jdGlvbih0KXt2YXIgZSxyLG47Zm9yKGU9dC5sZW5ndGgscj0tKDEvMCk7ZS0tOyluPXRbZV0sbj5yJiYocj1uKTtyZXR1cm4gcn0saT1mdW5jdGlvbih0KXtmb3IoO3Q8MDspdCs9MipNYXRoLlBJO2Zvcig7dD4yKk1hdGguUEk7KXQtPTIqTWF0aC5QSTtyZXR1cm4gdH0sbz1mdW5jdGlvbih0LGUpe3JldHVybiBNYXRoLmFicyhpKHQtZSkpfSxuPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBzO3JldHVybiB0PWkodCkscz1vKGUsciksImFudGljbG9jayI9PT1uP28oZSx0KTw9cyYmbyh0LHIpPD1zOiEobyhlLHQpPD1zJiZvKHQscik8PXMpfSx1PWZ1bmN0aW9uKCl7cmV0dXJuIE1hdGgucmFuZG9tKCl9LGw9ZnVuY3Rpb24odCxlKXtyZXR1cm4gTWF0aC5hdGFuMihlWzFdLXRbMV0sZVswXS10WzBdKX0saD1mdW5jdGlvbih0LGUpe3ZhciByLG4sbztmb3Iocj1udWxsLG49bnVsbDs7KWlmKHI9dSgpLG49dSgpLG49KDIqbi0xKSpNYXRoLnNxcnQoMiooMS9NYXRoLkUpKSwtNCpyKnIqTWF0aC5sb2cocik+PW4qbilicmVhaztyZXR1cm4gbz1uL3Isbz10K2Uqb30sZS5leHBvcnRzPXthcnJheV9taW46YSxhcnJheV9tYXg6cyxhbmdsZV9ub3JtOmksYW5nbGVfZGlzdDpvLGFuZ2xlX2JldHdlZW46bixhdGFuMjpsLHJub3JtOmgscmFuZG9tOnV9fSx7fV0sImNvcmUvdXRpbC9yZWZzIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE7bz10KCJ1bmRlcnNjb3JlIiksbj10KCIuLi9oYXNfcHJvcHMiKSxzPWZ1bmN0aW9uKHQpe3ZhciBlO2lmKCEodCBpbnN0YW5jZW9mIG4uY29uc3RydWN0b3IpKXRocm93IG5ldyBFcnJvcigiY2FuIG9ubHkgY3JlYXRlIHJlZnMgZm9yIEhhc1Byb3BzIHN1YmNsYXNzZXMiKTtyZXR1cm4gZT17dHlwZTp0LnR5cGUsaWQ6dC5pZH0sbnVsbCE9dC5fc3VidHlwZSYmKGUuc3VidHlwZT10Ll9zdWJ0eXBlKSxlfSxhPWZ1bmN0aW9uKHQpe3ZhciBlO2lmKG8uaXNPYmplY3QodCkpe2lmKGU9by5rZXlzKHQpLnNvcnQoKSwyPT09ZS5sZW5ndGgpcmV0dXJuImlkIj09PWVbMF0mJiJ0eXBlIj09PWVbMV07aWYoMz09PWUubGVuZ3RoKXJldHVybiJpZCI9PT1lWzBdJiYic3VidHlwZSI9PT1lWzFdJiYidHlwZSI9PT1lWzJdfXJldHVybiExfSxpPWZ1bmN0aW9uKHQpe3JldHVybiBvLmlzQXJyYXkodCk/by5tYXAodCxpKTp0IGluc3RhbmNlb2Ygbi5jb25zdHJ1Y3Rvcj90LnJlZigpOnZvaWQgMH0sZS5leHBvcnRzPXtjb252ZXJ0X3RvX3JlZjppLGNyZWF0ZV9yZWY6cyxpc19yZWY6YX19LHsiLi4vaGFzX3Byb3BzIjoiY29yZS9oYXNfcHJvcHMiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sImNvcmUvdXRpbC9zdmdfY29sb3JzIjpbZnVuY3Rpb24odCxlLHIpe2UuZXhwb3J0cz17aW5kaWFucmVkOiIjQ0Q1QzVDIixsaWdodGNvcmFsOiIjRjA4MDgwIixzYWxtb246IiNGQTgwNzIiLGRhcmtzYWxtb246IiNFOTk2N0EiLGxpZ2h0c2FsbW9uOiIjRkZBMDdBIixjcmltc29uOiIjREMxNDNDIixyZWQ6IiNGRjAwMDAiLGZpcmVicmljazoiI0IyMjIyMiIsZGFya3JlZDoiIzhCMDAwMCIscGluazoiI0ZGQzBDQiIsbGlnaHRwaW5rOiIjRkZCNkMxIixob3RwaW5rOiIjRkY2OUI0IixkZWVwcGluazoiI0ZGMTQ5MyIsbWVkaXVtdmlvbGV0cmVkOiIjQzcxNTg1IixwYWxldmlvbGV0cmVkOiIjREI3MDkzIixjb3JhbDoiI0ZGN0Y1MCIsdG9tYXRvOiIjRkY2MzQ3IixvcmFuZ2VyZWQ6IiNGRjQ1MDAiLGRhcmtvcmFuZ2U6IiNGRjhDMDAiLG9yYW5nZToiI0ZGQTUwMCIsZ29sZDoiI0ZGRDcwMCIseWVsbG93OiIjRkZGRjAwIixsaWdodHllbGxvdzoiI0ZGRkZFMCIsbGVtb25jaGlmZm9uOiIjRkZGQUNEIixsaWdodGdvbGRlbnJvZHllbGxvdzoiI0ZBRkFEMiIscGFwYXlhd2hpcDoiI0ZGRUZENSIsbW9jY2FzaW46IiNGRkU0QjUiLHBlYWNocHVmZjoiI0ZGREFCOSIscGFsZWdvbGRlbnJvZDoiI0VFRThBQSIsa2hha2k6IiNGMEU2OEMiLGRhcmtraGFraToiI0JEQjc2QiIsbGF2ZW5kZXI6IiNFNkU2RkEiLHRoaXN0bGU6IiNEOEJGRDgiLHBsdW06IiNEREEwREQiLHZpb2xldDoiI0VFODJFRSIsb3JjaGlkOiIjREE3MEQ2IixmdWNoc2lhOiIjRkYwMEZGIixtYWdlbnRhOiIjRkYwMEZGIixtZWRpdW1vcmNoaWQ6IiNCQTU1RDMiLG1lZGl1bXB1cnBsZToiIzkzNzBEQiIsYmx1ZXZpb2xldDoiIzhBMkJFMiIsZGFya3Zpb2xldDoiIzk0MDBEMyIsZGFya29yY2hpZDoiIzk5MzJDQyIsZGFya21hZ2VudGE6IiM4QjAwOEIiLHB1cnBsZToiIzgwMDA4MCIsaW5kaWdvOiIjNEIwMDgyIixzbGF0ZWJsdWU6IiM2QTVBQ0QiLGRhcmtzbGF0ZWJsdWU6IiM0ODNEOEIiLG1lZGl1bXNsYXRlYmx1ZToiIzdCNjhFRSIsZ3JlZW55ZWxsb3c6IiNBREZGMkYiLGNoYXJ0cmV1c2U6IiM3RkZGMDAiLGxhd25ncmVlbjoiIzdDRkMwMCIsbGltZToiIzAwRkYwMCIsbGltZWdyZWVuOiIjMzJDRDMyIixwYWxlZ3JlZW46IiM5OEZCOTgiLGxpZ2h0Z3JlZW46IiM5MEVFOTAiLG1lZGl1bXNwcmluZ2dyZWVuOiIjMDBGQTlBIixzcHJpbmdncmVlbjoiIzAwRkY3RiIsbWVkaXVtc2VhZ3JlZW46IiMzQ0IzNzEiLHNlYWdyZWVuOiIjMkU4QjU3Iixmb3Jlc3RncmVlbjoiIzIyOEIyMiIsZ3JlZW46IiMwMDgwMDAiLGRhcmtncmVlbjoiIzAwNjQwMCIseWVsbG93Z3JlZW46IiM5QUNEMzIiLG9saXZlZHJhYjoiIzZCOEUyMyIsb2xpdmU6IiM4MDgwMDAiLGRhcmtvbGl2ZWdyZWVuOiIjNTU2QjJGIixtZWRpdW1hcXVhbWFyaW5lOiIjNjZDREFBIixkYXJrc2VhZ3JlZW46IiM4RkJDOEYiLGxpZ2h0c2VhZ3JlZW46IiMyMEIyQUEiLGRhcmtjeWFuOiIjMDA4QjhCIix0ZWFsOiIjMDA4MDgwIixhcXVhOiIjMDBGRkZGIixjeWFuOiIjMDBGRkZGIixsaWdodGN5YW46IiNFMEZGRkYiLHBhbGV0dXJxdW9pc2U6IiNBRkVFRUUiLGFxdWFtYXJpbmU6IiM3RkZGRDQiLHR1cnF1b2lzZToiIzQwRTBEMCIsbWVkaXVtdHVycXVvaXNlOiIjNDhEMUNDIixkYXJrdHVycXVvaXNlOiIjMDBDRUQxIixjYWRldGJsdWU6IiM1RjlFQTAiLHN0ZWVsYmx1ZToiIzQ2ODJCNCIsbGlnaHRzdGVlbGJsdWU6IiNCMEM0REUiLHBvd2RlcmJsdWU6IiNCMEUwRTYiLGxpZ2h0Ymx1ZToiI0FERDhFNiIsc2t5Ymx1ZToiIzg3Q0VFQiIsbGlnaHRza3libHVlOiIjODdDRUZBIixkZWVwc2t5Ymx1ZToiIzAwQkZGRiIsZG9kZ2VyYmx1ZToiIzFFOTBGRiIsY29ybmZsb3dlcmJsdWU6IiM2NDk1RUQiLHJveWFsYmx1ZToiIzQxNjlFMSIsYmx1ZToiIzAwMDBGRiIsbWVkaXVtYmx1ZToiIzAwMDBDRCIsZGFya2JsdWU6IiMwMDAwOEIiLG5hdnk6IiMwMDAwODAiLG1pZG5pZ2h0Ymx1ZToiIzE5MTk3MCIsY29ybnNpbGs6IiNGRkY4REMiLGJsYW5jaGVkYWxtb25kOiIjRkZFQkNEIixiaXNxdWU6IiNGRkU0QzQiLG5hdmFqb3doaXRlOiIjRkZERUFEIix3aGVhdDoiI0Y1REVCMyIsYnVybHl3b29kOiIjREVCODg3Iix0YW46IiNEMkI0OEMiLHJvc3licm93bjoiI0JDOEY4RiIsc2FuZHlicm93bjoiI0Y0QTQ2MCIsZ29sZGVucm9kOiIjREFBNTIwIixkYXJrZ29sZGVucm9kOiIjQjg4NjBCIixwZXJ1OiIjQ0Q4NTNGIixjaG9jb2xhdGU6IiNEMjY5MUUiLHNhZGRsZWJyb3duOiIjOEI0NTEzIixzaWVubmE6IiNBMDUyMkQiLGJyb3duOiIjQTUyQTJBIixtYXJvb246IiM4MDAwMDAiLHdoaXRlOiIjRkZGRkZGIixzbm93OiIjRkZGQUZBIixob25leWRldzoiI0YwRkZGMCIsbWludGNyZWFtOiIjRjVGRkZBIixhenVyZToiI0YwRkZGRiIsYWxpY2VibHVlOiIjRjBGOEZGIixnaG9zdHdoaXRlOiIjRjhGOEZGIix3aGl0ZXNtb2tlOiIjRjVGNUY1IixzZWFzaGVsbDoiI0ZGRjVFRSIsYmVpZ2U6IiNGNUY1REMiLG9sZGxhY2U6IiNGREY1RTYiLGZsb3JhbHdoaXRlOiIjRkZGQUYwIixpdm9yeToiI0ZGRkZGMCIsYW50aXF1ZXdoaXRlOiIjRkFFQkQ3IixsaW5lbjoiI0ZBRjBFNiIsbGF2ZW5kZXJibHVzaDoiI0ZGRjBGNSIsbWlzdHlyb3NlOiIjRkZFNEUxIixnYWluc2Jvcm86IiNEQ0RDREMiLGxpZ2h0Z3JheToiI0QzRDNEMyIsbGlnaHRncmV5OiIjRDNEM0QzIixzaWx2ZXI6IiNDMEMwQzAiLGRhcmtncmF5OiIjQTlBOUE5IixkYXJrZ3JleToiI0E5QTlBOSIsZ3JheToiIzgwODA4MCIsZ3JleToiIzgwODA4MCIsZGltZ3JheToiIzY5Njk2OSIsZGltZ3JleToiIzY5Njk2OSIsbGlnaHRzbGF0ZWdyYXk6IiM3Nzg4OTkiLGxpZ2h0c2xhdGVncmV5OiIjNzc4ODk5IixzbGF0ZWdyYXk6IiM3MDgwOTAiLHNsYXRlZ3JleToiIzcwODA5MCIsZGFya3NsYXRlZ3JheToiIzJGNEY0RiIsZGFya3NsYXRlZ3JleToiIzJGNEY0RiIsYmxhY2s6IiMwMDAwMDAifX0se31dLCJjb3JlL3V0aWwvdGV4dCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk7bj10KCJqcXVlcnkiKSxvPXt9LGk9ZnVuY3Rpb24odCl7dmFyIGUscixpLHMsYTtpZihudWxsIT1vW3RdKXJldHVybiBvW3RdO2E9bigiPHNwYW4+SGc8L3NwYW4+IikuY3NzKHtmb250OnR9KSxlPW4oJzxkaXYgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2lkdGg6IDFweDsgaGVpZ2h0OiAwcHg7Ij4gPC9kaXY+JyksaT1uKCI8ZGl2PjwvZGl2PiIpLGkuYXBwZW5kKGEsZSkscj1uKCJib2R5Iiksci5hcHBlbmQoaSk7dHJ5e3M9e30sZS5jc3Moe3ZlcnRpY2FsQWxpZ246ImJhc2VsaW5lIn0pLHMuYXNjZW50PWUub2Zmc2V0KCkudG9wLWEub2Zmc2V0KCkudG9wLGUuY3NzKHt2ZXJ0aWNhbEFsaWduOiJib3R0b20ifSkscy5oZWlnaHQ9ZS5vZmZzZXQoKS50b3AtYS5vZmZzZXQoKS50b3Ascy5kZXNjZW50PXMuaGVpZ2h0LXMuYXNjZW50fWZpbmFsbHl7aS5yZW1vdmUoKX1yZXR1cm4gb1t0XT1zLHN9LGUuZXhwb3J0cz17Z2V0X3RleHRfaGVpZ2h0Oml9fSx7anF1ZXJ5OiJqcXVlcnkifV0sImNvcmUvdXRpbC90aHJvdHRsZSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk7bj1mdW5jdGlvbih0KXtyZXR1cm4gdCgpfSxvPSgidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdyYmbnVsbCE9PXdpbmRvdz93aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lOnZvaWQgMCl8fCgidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdyYmbnVsbCE9PXdpbmRvdz93aW5kb3cubW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lOnZvaWQgMCl8fCgidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdyYmbnVsbCE9PXdpbmRvdz93aW5kb3cud2Via2l0UmVxdWVzdEFuaW1hdGlvbkZyYW1lOnZvaWQgMCl8fCgidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdyYmbnVsbCE9PXdpbmRvdz93aW5kb3cubXNSZXF1ZXN0QW5pbWF0aW9uRnJhbWU6dm9pZCAwKXx8bixpPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixpLHMsYSxsLHUsaDtyZXR1cm4gbD1bbnVsbCxudWxsLG51bGwsbnVsbF0sbj1sWzBdLHI9bFsxXSxoPWxbMl0sdT1sWzNdLGE9MCxzPSExLGk9ZnVuY3Rpb24oKXtyZXR1cm4gYT1uZXcgRGF0ZSxoPW51bGwscz0hMSx1PXQuYXBwbHkobixyKX0sZnVuY3Rpb24oKXt2YXIgdCxsO3JldHVybiB0PW5ldyBEYXRlLGw9ZS0odC1hKSxuPXRoaXMscj1hcmd1bWVudHMsbDw9MCYmIXM/KGNsZWFyVGltZW91dChoKSxzPSEwLG8oaSkpOmh8fHN8fChoPXNldFRpbWVvdXQoZnVuY3Rpb24oKXtyZXR1cm4gbyhpKX0sbCkpLHV9fSxlLmV4cG9ydHM9e3Rocm90dGxlOml9fSx7fV0sImNvcmUvdXRpbC91bmRlcnNjb3JlIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG87bj10KCJ1bmRlcnNjb3JlIiksbz1mdW5jdGlvbigpe3JldHVybiBuLnVuaXF1ZUlkPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGk7Zm9yKG89W10sZT0iMDEyMzQ1Njc4OUFCQ0RFRiIscj1uPTA7bjw9MzE7cj0rK24pb1tyXT1lLnN1YnN0cihNYXRoLmZsb29yKDE2Kk1hdGgucmFuZG9tKCkpLDEpO3JldHVybiBvWzEyXT0iNCIsb1sxNl09ZS5zdWJzdHIoMyZvWzE2XXw4LDEpLGk9by5qb2luKCIiKSx0P3QrIi0iK2k6aX19LG4uaXNOdWxsT3JVbmRlZmluZWQ9ZnVuY3Rpb24odCl7cmV0dXJuIG4uaXNOdWxsKHQpfHxuLmlzVW5kZWZpbmVkKHQpfSxuLnNldGRlZmF1bHQ9ZnVuY3Rpb24odCxlLHIpe3JldHVybiBuLmhhcyh0LGUpP3RbZV06KHRbZV09cixyKX0sZS5leHBvcnRzPXtwYXRjaDpvfX0se3VuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sZG9jdW1lbnQ6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0sayxqPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlULmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LFQ9e30uaGFzT3duUHJvcGVydHksUz1bXS5pbmRleE9mfHxmdW5jdGlvbih0KXtmb3IodmFyIGU9MCxyPXRoaXMubGVuZ3RoO2U8cjtlKyspaWYoZSBpbiB0aGlzJiZ0aGlzW2VdPT09dClyZXR1cm4gZTtyZXR1cm4tMX07dj10KCJ1bmRlcnNjb3JlIiksbj10KCJqcXVlcnkiKSxjPXQoIi4vYmFzZSIpLk1vZGVscyx4PXQoIi4vdmVyc2lvbiIpLE09dCgiLi9jb3JlL2xheW91dC9zb2x2ZXIiKSxsPU0uRVEsbT1NLlNvbHZlcix5PU0uVmFyaWFibGUsdz10KCIuL2NvcmUvbG9nZ2luZyIpLmxvZ2dlcix1PXQoIi4vY29yZS9oYXNfcHJvcHMiKSxiPXQoIi4vY29yZS91dGlsL3JlZnMiKS5pc19yZWYsaz10KCIuL2NvcmUvdXRpbC9kYXRhX3N0cnVjdHVyZXMiKSxwPWsuTXVsdGlEaWN0LGY9ay5TZXQsbz10KCIuL21vZGVscy9zb3VyY2VzL2NvbHVtbl9kYXRhX3NvdXJjZSIpLGE9ZnVuY3Rpb24oKXtmdW5jdGlvbiB0KHQpe3RoaXMuZG9jdW1lbnQ9dH1yZXR1cm4gdH0oKSxoPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUodCxyLG4sbyxpKXt0aGlzLmRvY3VtZW50PXQsdGhpcy5tb2RlbD1yLHRoaXMuYXR0cj1uLHRoaXMub2xkPW8sdGhpcy5uZXdfPWksZS5fX3N1cGVyX18uY29uc3RydWN0b3IuY2FsbCh0aGlzLHRoaXMuZG9jdW1lbnQpfXJldHVybiBqKGUsdCksZS5wcm90b3R5cGUuanNvbj1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbztpZigiaWQiPT09dGhpcy5hdHRyKXRocm93IGNvbnNvbGUubG9nKCInaWQnIGZpZWxkIGlzIGltbXV0YWJsZSBhbmQgc2hvdWxkIG5ldmVyIGJlIGluIGEgTW9kZWxDaGFuZ2VkRXZlbnQgIix0aGlzKSxuZXcgRXJyb3IoIidpZCcgZmllbGQgc2hvdWxkIG5ldmVyIGNoYW5nZSwgd2hhdGV2ZXIgY29kZSBqdXN0IHNldCBpdCBpcyB3cm9uZyIpO3I9dGhpcy5uZXdfLG49dS5fdmFsdWVfdG9fanNvbigibmV3XyIscix0aGlzLm1vZGVsKSxvPXt9LHUuX3ZhbHVlX3JlY29yZF9yZWZlcmVuY2VzKHIsbywhMCksdGhpcy5tb2RlbC5pZCBpbiBvJiZ0aGlzLm1vZGVsIT09ciYmZGVsZXRlIG9bdGhpcy5tb2RlbC5pZF07Zm9yKGUgaW4gbyl0W2VdPW9bZV07cmV0dXJue2tpbmQ6Ik1vZGVsQ2hhbmdlZCIsbW9kZWw6dGhpcy5tb2RlbC5yZWYoKSxhdHRyOnRoaXMuYXR0ciwibmV3IjpufX0sZX0oYSksZz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKHQscil7dGhpcy5kb2N1bWVudD10LHRoaXMudGl0bGU9cixlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5jYWxsKHRoaXMsdGhpcy5kb2N1bWVudCl9cmV0dXJuIGooZSx0KSxlLnByb3RvdHlwZS5qc29uPWZ1bmN0aW9uKHQpe3JldHVybntraW5kOiJUaXRsZUNoYW5nZWQiLHRpdGxlOnRoaXMudGl0bGV9fSxlfShhKSxfPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUodCxyKXt0aGlzLmRvY3VtZW50PXQsdGhpcy5tb2RlbD1yLGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmNhbGwodGhpcyx0aGlzLmRvY3VtZW50KX1yZXR1cm4gaihlLHQpLGUucHJvdG90eXBlLmpzb249ZnVuY3Rpb24odCl7cmV0dXJuIHUuX3ZhbHVlX3JlY29yZF9yZWZlcmVuY2VzKHRoaXMubW9kZWwsdCwhMCkse2tpbmQ6IlJvb3RBZGRlZCIsbW9kZWw6dGhpcy5tb2RlbC5yZWYoKX19LGV9KGEpLGQ9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSh0LHIpe3RoaXMuZG9jdW1lbnQ9dCx0aGlzLm1vZGVsPXIsZS5fX3N1cGVyX18uY29uc3RydWN0b3IuY2FsbCh0aGlzLHRoaXMuZG9jdW1lbnQpfXJldHVybiBqKGUsdCksZS5wcm90b3R5cGUuanNvbj1mdW5jdGlvbih0KXtyZXR1cm57a2luZDoiUm9vdFJlbW92ZWQiLG1vZGVsOnRoaXMubW9kZWwucmVmKCl9fSxlfShhKSxpPSJCb2tlaCBBcHBsaWNhdGlvbiIscz1mdW5jdGlvbigpe2Z1bmN0aW9uIHQoKXt0aGlzLl90aXRsZT1pLHRoaXMuX3Jvb3RzPVtdLHRoaXMuX2FsbF9tb2RlbHM9e30sdGhpcy5fYWxsX21vZGVsc19ieV9uYW1lPW5ldyBwLHRoaXMuX2FsbF9tb2RlbHNfZnJlZXplX2NvdW50PTAsdGhpcy5fY2FsbGJhY2tzPVtdLHRoaXMuX2RvY193aWR0aD1uZXcgeSgiZG9jdW1lbnRfd2lkdGgiKSx0aGlzLl9kb2NfaGVpZ2h0PW5ldyB5KCJkb2N1bWVudF9oZWlnaHQiKSx0aGlzLl9zb2x2ZXI9bmV3IG0sdGhpcy5faW5pdF9zb2x2ZXIoKSxuKHdpbmRvdykub24oInJlc2l6ZSIsbi5wcm94eSh0aGlzLnJlc2l6ZSx0aGlzKSl9cmV0dXJuIHQucHJvdG90eXBlLl9pbml0X3NvbHZlcj1mdW5jdGlvbigpe3ZhciB0LGUscixuLG87Zm9yKHRoaXMuX3NvbHZlci5jbGVhcigpLHRoaXMuX3NvbHZlci5hZGRfZWRpdF92YXJpYWJsZSh0aGlzLl9kb2Nfd2lkdGgpLHRoaXMuX3NvbHZlci5hZGRfZWRpdF92YXJpYWJsZSh0aGlzLl9kb2NfaGVpZ2h0KSxuPXRoaXMuX3Jvb3RzLG89W10sdD0wLGU9bi5sZW5ndGg7dDxlO3QrKylyPW5bdF0sci5sYXlvdXRhYmxlP28ucHVzaCh0aGlzLl9hZGRfbGF5b3V0YWJsZShyKSk6by5wdXNoKHZvaWQgMCk7cmV0dXJuIG99LHQucHJvdG90eXBlLnNvbHZlcj1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9zb2x2ZXJ9LHQucHJvdG90eXBlLnJlc2l6ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9yZXNpemUoKSx0aGlzLl9yZXNpemUoKX0sdC5wcm90b3R5cGUuX3Jlc2l6ZT1mdW5jdGlvbigpe3ZhciB0LGUscixvLGkscyxhLGwsdSxoO2ZvcihpPXRoaXMuX3Jvb3RzLGU9MCxyPWkubGVuZ3RoO2U8cjtlKyspaWYocz1pW2VdLHMubGF5b3V0YWJsZT09PSEwJiYodT1zLmdldF9jb25zdHJhaW5lZF92YXJpYWJsZXMoKSxudWxsIT11LndpZHRofHxudWxsIT11LmhlaWdodCkpe2ZvcihhPW4oIiNtb2RlbGlkXyIrcy5pZCksbD0wLG89YTswPT09bDspbz1vLnBhcmVudCgpLGw9by5oZWlnaHQoKTtoPW8ud2lkdGgoKSx0PWwsbnVsbCE9dS53aWR0aCYmKHcuZGVidWcoIlN1Z2dlc3Qgd2lkdGggb24gRG9jdW1lbnQgLS0gIitoKSx0aGlzLl9zb2x2ZXIuc3VnZ2VzdF92YWx1ZSh0aGlzLl9kb2Nfd2lkdGgsaCkpLG51bGwhPXUuaGVpZ2h0JiYody5kZWJ1ZygiU3VnZ2VzdCBoZWlnaHQgb24gRG9jdW1lbnQgLS0gIit0KSx0aGlzLl9zb2x2ZXIuc3VnZ2VzdF92YWx1ZSh0aGlzLl9kb2NfaGVpZ2h0LHQpKX1yZXR1cm4gdGhpcy5fc29sdmVyLnVwZGF0ZV92YXJpYWJsZXMoITEpLHRoaXMuX3NvbHZlci50cmlnZ2VyKCJyZXNpemUiKX0sdC5wcm90b3R5cGUuY2xlYXI9ZnVuY3Rpb24oKXt2YXIgdDt0aGlzLl9wdXNoX2FsbF9tb2RlbHNfZnJlZXplKCk7dHJ5e2Zvcih0PVtdO3RoaXMuX3Jvb3RzLmxlbmd0aD4wOyl0LnB1c2godGhpcy5yZW1vdmVfcm9vdCh0aGlzLl9yb290c1swXSkpO3JldHVybiB0fWZpbmFsbHl7dGhpcy5fcG9wX2FsbF9tb2RlbHNfZnJlZXplKCl9fSx0LnByb3RvdHlwZS5fZGVzdHJ1Y3RpdmVseV9tb3ZlPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscztpZih0PT09dGhpcyl0aHJvdyBuZXcgRXJyb3IoIkF0dGVtcHRlZCB0byBvdmVyd3JpdGUgYSBkb2N1bWVudCB3aXRoIGl0c2VsZiIpO3QuY2xlYXIoKSxzPVtdLHRoaXMuX3B1c2hfYWxsX21vZGVsc19mcmVlemUoKTt0cnl7Zm9yKDt0aGlzLl9yb290cy5sZW5ndGg+MDspdGhpcy5yZW1vdmVfcm9vdCh0aGlzLl9yb290c1swXSkscy5wdXNoKGkpfWZpbmFsbHl7dGhpcy5fcG9wX2FsbF9tb2RlbHNfZnJlZXplKCl9Zm9yKGU9MCxuPXMubGVuZ3RoO2U8bjtlKyspaWYoaT1zW2VdLG51bGwhPT1pLmRvY3VtZW50KXRocm93IG5ldyBFcnJvcigiU29tZWhvdyB3ZSBkaWRuJ3QgZGV0YWNoICIraSk7aWYoMCE9PV9hbGxfbW9kZWxzLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoIl9hbGxfbW9kZWxzIHN0aWxsIGhhZCBzdHVmZiBpbiBpdDogIit0aGlzLl9hbGxfbW9kZWxzKTtmb3Iocj0wLG89cy5sZW5ndGg7cjxvO3IrKylpPXNbcl0sdC5hZGRfcm9vdChpKTtyZXR1cm4gdC5zZXRfdGl0bGUodGhpcy5fdGl0bGUpfSx0LnByb3RvdHlwZS5fcHVzaF9hbGxfbW9kZWxzX2ZyZWV6ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9hbGxfbW9kZWxzX2ZyZWV6ZV9jb3VudCs9MX0sdC5wcm90b3R5cGUuX3BvcF9hbGxfbW9kZWxzX2ZyZWV6ZT1mdW5jdGlvbigpe2lmKHRoaXMuX2FsbF9tb2RlbHNfZnJlZXplX2NvdW50LT0xLDA9PT10aGlzLl9hbGxfbW9kZWxzX2ZyZWV6ZV9jb3VudClyZXR1cm4gdGhpcy5fcmVjb21wdXRlX2FsbF9tb2RlbHMoKX0sdC5wcm90b3R5cGUuX2ludmFsaWRhdGVfYWxsX21vZGVscz1mdW5jdGlvbigpe2lmKHcuZGVidWcoImludmFsaWRhdGluZyBkb2N1bWVudCBtb2RlbHMiKSwwPT09dGhpcy5fYWxsX21vZGVsc19mcmVlemVfY291bnQpcmV0dXJuIHRoaXMuX3JlY29tcHV0ZV9hbGxfbW9kZWxzKCl9LHQucHJvdG90eXBlLl9yZWNvbXB1dGVfYWxsX21vZGVscz1mdW5jdGlvbigpe3ZhciB0LGUscixuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxtLGcseSxiLHgsdyxNO2ZvcihjPW5ldyBmLGc9dGhpcy5fcm9vdHMscj0wLG89Zy5sZW5ndGg7cjxvO3IrKylkPWdbcl0sYz1jLnVuaW9uKGQucmVmZXJlbmNlcygpKTtmb3IoXz1uZXcgZih2LnZhbHVlcyh0aGlzLl9hbGxfbW9kZWxzKSksTT1fLmRpZmYoYyksdz1jLmRpZmYoXyksbT17fSx5PWMudmFsdWVzLG49MCxpPXkubGVuZ3RoO248aTtuKyspbD15W25dLG1bbC5pZF09bDtmb3IoYj1NLnZhbHVlcyx1PTAscz1iLmxlbmd0aDt1PHM7dSsrKWU9Ylt1XSxlLmRldGFjaF9kb2N1bWVudCgpLGg9ZS5nZXQoIm5hbWUiKSxudWxsIT09aCYmdGhpcy5fYWxsX21vZGVsc19ieV9uYW1lLnJlbW92ZV92YWx1ZShoLGUpO2Zvcih4PXcudmFsdWVzLHA9MCxhPXgubGVuZ3RoO3A8YTtwKyspdD14W3BdLHQuYXR0YWNoX2RvY3VtZW50KHRoaXMpLGg9dC5nZXQoIm5hbWUiKSxudWxsIT09aCYmdGhpcy5fYWxsX21vZGVsc19ieV9uYW1lLmFkZF92YWx1ZShoLHQpO3JldHVybiB0aGlzLl9hbGxfbW9kZWxzPW19LHQucHJvdG90eXBlLnJvb3RzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3Jvb3RzfSx0LnByb3RvdHlwZS5fYWRkX2xheW91dGFibGU9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGEsdSxoLGMscDtpZih0LmxheW91dGFibGUhPT0hMCl0aHJvdyBuZXcgRXJyb3IoIkNhbm5vdCBhZGQgbm9uLWxheW91dGFibGUgLSAiK3QpO2ZvcihvPXQuZ2V0X2VkaXRfdmFyaWFibGVzKCkscj10LmdldF9jb25zdHJhaW50cygpLHA9dC5nZXRfY29uc3RyYWluZWRfdmFyaWFibGVzKCksaT0wLGE9by5sZW5ndGg7aTxhO2krKyloPW9baV0sbj1oLmVkaXRfdmFyaWFibGUsYz1oLnN0cmVuZ3RoLHRoaXMuX3NvbHZlci5hZGRfZWRpdF92YXJpYWJsZShuLGMpO2ZvcihzPTAsdT1yLmxlbmd0aDtzPHU7cysrKWU9cltzXSx0aGlzLl9zb2x2ZXIuYWRkX2NvbnN0cmFpbnQoZSk7cmV0dXJuIG51bGwhPXAud2lkdGgmJnRoaXMuX3NvbHZlci5hZGRfY29uc3RyYWludChsKHAud2lkdGgsdGhpcy5fZG9jX3dpZHRoKSksbnVsbCE9cC5oZWlnaHQmJnRoaXMuX3NvbHZlci5hZGRfY29uc3RyYWludChsKHAuaGVpZ2h0LHRoaXMuX2RvY19oZWlnaHQpKSx0aGlzLl9zb2x2ZXIudXBkYXRlX3ZhcmlhYmxlcygpfSx0LnByb3RvdHlwZS5hZGRfcm9vdD1mdW5jdGlvbih0KXtpZih3LmRlYnVnKCJBZGRpbmcgcm9vdDogIit0KSwhKFMuY2FsbCh0aGlzLl9yb290cyx0KT49MCkpe3RoaXMuX3B1c2hfYWxsX21vZGVsc19mcmVlemUoKTt0cnl7dGhpcy5fcm9vdHMucHVzaCh0KSx0Ll9pc19yb290PSEwfWZpbmFsbHl7dGhpcy5fcG9wX2FsbF9tb2RlbHNfZnJlZXplKCl9cmV0dXJuIHRoaXMuX2luaXRfc29sdmVyKCksdGhpcy5fdHJpZ2dlcl9vbl9jaGFuZ2UobmV3IF8odGhpcyx0KSl9fSx0LnByb3RvdHlwZS5yZW1vdmVfcm9vdD1mdW5jdGlvbih0KXt2YXIgZTtpZihlPXRoaXMuX3Jvb3RzLmluZGV4T2YodCksIShlPDApKXt0aGlzLl9wdXNoX2FsbF9tb2RlbHNfZnJlZXplKCk7dHJ5e3RoaXMuX3Jvb3RzLnNwbGljZShlLDEpLHQuX2lzX3Jvb3Q9ITF9ZmluYWxseXt0aGlzLl9wb3BfYWxsX21vZGVsc19mcmVlemUoKX1yZXR1cm4gdGhpcy5faW5pdF9zb2x2ZXIoKSx0aGlzLl90cmlnZ2VyX29uX2NoYW5nZShuZXcgZCh0aGlzLHQpKX19LHQucHJvdG90eXBlLnRpdGxlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3RpdGxlfSx0LnByb3RvdHlwZS5zZXRfdGl0bGU9ZnVuY3Rpb24odCl7aWYodCE9PXRoaXMuX3RpdGxlKXJldHVybiB0aGlzLl90aXRsZT10LHRoaXMuX3RyaWdnZXJfb25fY2hhbmdlKG5ldyBnKHRoaXMsdCkpfSx0LnByb3RvdHlwZS5nZXRfbW9kZWxfYnlfaWQ9ZnVuY3Rpb24odCl7cmV0dXJuIHQgaW4gdGhpcy5fYWxsX21vZGVscz90aGlzLl9hbGxfbW9kZWxzW3RdOm51bGx9LHQucHJvdG90eXBlLmdldF9tb2RlbF9ieV9uYW1lPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9hbGxfbW9kZWxzX2J5X25hbWUuZ2V0X29uZSh0LCJNdWx0aXBsZSBtb2RlbHMgYXJlIG5hbWVkICciK3QrIiciKX0sdC5wcm90b3R5cGUub25fY2hhbmdlPWZ1bmN0aW9uKHQpe2lmKCEoUy5jYWxsKHRoaXMuX2NhbGxiYWNrcyx0KT49MCkpcmV0dXJuIHRoaXMuX2NhbGxiYWNrcy5wdXNoKHQpfSx0LnByb3RvdHlwZS5yZW1vdmVfb25fY2hhbmdlPWZ1bmN0aW9uKHQpe3ZhciBlO2lmKGU9dGhpcy5fY2FsbGJhY2tzLmluZGV4T2YodCksZT49MClyZXR1cm4gdGhpcy5fY2FsbGJhY2tzLnNwbGljZShlLDEpfSx0LnByb3RvdHlwZS5fdHJpZ2dlcl9vbl9jaGFuZ2U9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saTtmb3Iobz10aGlzLl9jYWxsYmFja3MsaT1bXSxyPTAsbj1vLmxlbmd0aDtyPG47cisrKWU9b1tyXSxpLnB1c2goZSh0KSk7cmV0dXJuIGl9LHQucHJvdG90eXBlLl9ub3RpZnlfY2hhbmdlPWZ1bmN0aW9uKHQsZSxyLG4pe3JldHVybiJuYW1lIj09PWUmJih0aGlzLl9hbGxfbW9kZWxzX2J5X25hbWUucmVtb3ZlX3ZhbHVlKHIsdCksbnVsbCE9PW4mJnRoaXMuX2FsbF9tb2RlbHNfYnlfbmFtZS5hZGRfdmFsdWUobix0KSksdGhpcy5fdHJpZ2dlcl9vbl9jaGFuZ2UobmV3IGgodGhpcyx0LGUscixuKSl9LHQuX3JlZmVyZW5jZXNfanNvbj1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpLHM7Zm9yKG51bGw9PWUmJihlPSEwKSxzPVtdLHI9MCxuPXQubGVuZ3RoO3I8bjtyKyspbz10W3JdLGk9by5yZWYoKSxpLmF0dHJpYnV0ZXM9by5hdHRyaWJ1dGVzX2FzX2pzb24oZSksZGVsZXRlIGkuYXR0cmlidXRlcy5pZCxzLnB1c2goaSk7cmV0dXJuIHN9LHQuX2luc3RhbnRpYXRlX29iamVjdD1mdW5jdGlvbih0LGUscil7dmFyIG4sbztyZXR1cm4gbj12LmV4dGVuZCh7fSxyLHtpZDp0fSksbmV3KG89YyhlKSkobix7c2lsZW50OiEwLGRlZmVyX2luaXRpYWxpemF0aW9uOiEwfSl9LHQuX2luc3RhbnRpYXRlX3JlZmVyZW5jZXNfanNvbj1mdW5jdGlvbihlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGg7Zm9yKGg9e30sbz0wLGk9ZS5sZW5ndGg7bzxpO28rKylzPWVbb10sbD1zLmlkLHU9cy50eXBlLGE9cy5hdHRyaWJ1dGVzLGwgaW4gcj9uPXJbbF06KG49dC5faW5zdGFudGlhdGVfb2JqZWN0KGwsdSxhKSwic3VidHlwZSJpbiBzJiZuLnNldF9zdWJ0eXBlKHMuc3VidHlwZSkpLGhbbi5pZF09bjtyZXR1cm4gaH0sdC5fcmVzb2x2ZV9yZWZzPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk7cmV0dXJuIGk9ZnVuY3Rpb24odCl7aWYoYih0KSl7aWYodC5pZCBpbiBlKXJldHVybiBlW3QuaWRdO2lmKHQuaWQgaW4gcilyZXR1cm4gclt0LmlkXTt0aHJvdyBuZXcgRXJyb3IoInJlZmVyZW5jZSAiK0pTT04uc3RyaW5naWZ5KHQpKyIgaXNuJ3Qga25vd24gKG5vdCBpbiBEb2N1bWVudD8pIil9cmV0dXJuIHYuaXNBcnJheSh0KT9uKHQpOnYuaXNPYmplY3QodCk/byh0KTp0fSxvPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbjtyPXt9O2ZvcihlIGluIHQpbj10W2VdLHJbZV09aShuKTtyZXR1cm4gcn0sbj1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbztmb3Iobj1bXSxlPTAscj10Lmxlbmd0aDtlPHI7ZSsrKW89dFtlXSxuLnB1c2goaShvKSk7cmV0dXJuIG59LGkodCl9LHQuX2luaXRpYWxpemVfcmVmZXJlbmNlc19qc29uPWZ1bmN0aW9uKGUscixuKXt2YXIgbyxpLHMsYSxsLGgsYyxwLF87Zm9yKHA9e30scz0wLGE9ZS5sZW5ndGg7czxhO3MrKylsPWVbc10sYz1sLmlkLGg9bC5hdHRyaWJ1dGVzLF89ITEsaT1jIGluIHI/cltjXTooXz0hMCxuW2NdKSxoPXQuX3Jlc29sdmVfcmVmcyhoLHIsbikscFtpLmlkXT1baSxoLF9dO3JldHVybiBvPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLGkscztyPXt9LG49ZnVuY3Rpb24oZSxvKXt2YXIgaSxzLGEsbCxoLGMscCxkLGYsbTtpZihlIGluc3RhbmNlb2YgdSl7aWYoIShlLmlkIGluIHIpJiZlLmlkIGluIHQpe3JbZS5pZF09ITAscD10W2UuaWRdLG09cFswXSxzPXBbMV0sXz1wWzJdO2ZvcihpIGluIHMpYT1zW2ldLG4oYSxvKTtyZXR1cm4gbyhlLHMsXyl9fWVsc2V7aWYodi5pc0FycmF5KGUpKXtmb3IoZD1bXSxoPTAsYz1lLmxlbmd0aDtoPGM7aCsrKWE9ZVtoXSxkLnB1c2gobihhLG8pKTtyZXR1cm4gZH1pZih2LmlzT2JqZWN0KGUpKXtmPVtdO2ZvcihsIGluIGUpYT1lW2xdLGYucHVzaChuKGEsbykpO3JldHVybiBmfX19LGk9W107Zm9yKG8gaW4gdClzPXRbb10saS5wdXNoKG4oc1swXSxlKSk7cmV0dXJuIGl9LG8ocCxmdW5jdGlvbih0LGUscil7aWYocilyZXR1cm4gdC5zZXQoZSl9KSxvKHAsZnVuY3Rpb24odCxlLHIpe2lmKHIpcmV0dXJuIHQuaW5pdGlhbGl6ZShlKX0pfSx0Ll9ldmVudF9mb3JfYXR0cmlidXRlX2NoYW5nZT1mdW5jdGlvbih0LGUscixuLG8pe3ZhciBpLHM7cmV0dXJuIGk9bi5nZXRfbW9kZWxfYnlfaWQodC5pZCksaS5hdHRyaWJ1dGVfaXNfc2VyaWFsaXphYmxlKGUpPyhzPXtraW5kOiJNb2RlbENoYW5nZWQiLG1vZGVsOntpZDp0LmlkLHR5cGU6dC50eXBlfSxhdHRyOmUsIm5ldyI6cn0sdS5fanNvbl9yZWNvcmRfcmVmZXJlbmNlcyhuLHIsbywhMCkscyk6bnVsbH0sdC5fZXZlbnRzX3RvX3N5bmNfb2JqZWN0cz1mdW5jdGlvbihlLHIsbixvKXt2YXIgaSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LGI7Zm9yKGE9T2JqZWN0LmtleXMoZS5hdHRyaWJ1dGVzKSxiPU9iamVjdC5rZXlzKHIuYXR0cmlidXRlcyksZz12LmRpZmZlcmVuY2UoYSxiKSxpPXYuZGlmZmVyZW5jZShiLGEpLHk9di5pbnRlcnNlY3Rpb24oYSxiKSxzPVtdLGw9MCxjPWcubGVuZ3RoO2w8YztsKyspdT1nW2xdLHcud2FybigiU2VydmVyIHNlbnQga2V5ICIrdSsiIGJ1dCB3ZSBkb24ndCBzZWVtIHRvIGhhdmUgaXQgaW4gb3VyIEpTT04iKTtmb3IoaD0wLHA9aS5sZW5ndGg7aDxwO2grKyl1PWlbaF0sZj1yLmF0dHJpYnV0ZXNbdV0scy5wdXNoKHQuX2V2ZW50X2Zvcl9hdHRyaWJ1dGVfY2hhbmdlKGUsdSxmLG4sbykpO2ZvcihkPTAsXz15Lmxlbmd0aDtkPF87ZCsrKXU9eVtkXSxtPWUuYXR0cmlidXRlc1t1XSxmPXIuYXR0cmlidXRlc1t1XSxudWxsPT09bSYmbnVsbD09PWZ8fChudWxsPT09bXx8bnVsbD09PWY/cy5wdXNoKHQuX2V2ZW50X2Zvcl9hdHRyaWJ1dGVfY2hhbmdlKGUsdSxmLG4sbykpOnYuaXNFcXVhbChtLGYpfHxzLnB1c2godC5fZXZlbnRfZm9yX2F0dHJpYnV0ZV9jaGFuZ2UoZSx1LGYsbixvKSkpO3JldHVybiB2LmZpbHRlcihzLGZ1bmN0aW9uKHQpe3JldHVybiBudWxsIT09dH0pfSx0Ll9jb21wdXRlX3BhdGNoX3NpbmNlX2pzb249ZnVuY3Rpb24oZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSxiLHgsdyxNLGssajtmb3IoYj1yLnRvX2pzb24obD0hMSkseT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpO2ZvcihpPXt9LG89dC5yb290cy5yZWZlcmVuY2VzLGU9MCxyPW8ubGVuZ3RoO2U8cjtlKyspbj1vW2VdLGlbbi5pZF09bjtyZXR1cm4gaX0sbz15KGUpLHM9e30saT1bXSxmPWUucm9vdHMucm9vdF9pZHMsdT0wLGM9Zi5sZW5ndGg7dTxjO3UrKylkPWZbdV0sc1tkXT1vW2RdLGkucHVzaChkKTtmb3IoeD15KGIpLE09e30sdz1bXSxtPWIucm9vdHMucm9vdF9pZHMsaD0wLHA9bS5sZW5ndGg7aDxwO2grKylkPW1baF0sTVtkXT14W2RdLHcucHVzaChkKTtpZihpLnNvcnQoKSx3LnNvcnQoKSx2LmRpZmZlcmVuY2UoaSx3KS5sZW5ndGg+MHx8di5kaWZmZXJlbmNlKHcsaSkubGVuZ3RoPjApdGhyb3cgbmV3IEVycm9yKCJOb3QgaW1wbGVtZW50ZWQ6IGNvbXB1dGluZyBhZGQvcmVtb3ZlIG9mIGRvY3VtZW50IHJvb3RzIik7aj17fSxuPVtdLGc9ci5fYWxsX21vZGVscztmb3IoYSBpbiBnKV89Z1thXSxhIGluIG8mJihrPXQuX2V2ZW50c190b19zeW5jX29iamVjdHMob1thXSx4W2FdLHIsaiksbj1uLmNvbmNhdChrKSk7cmV0dXJue2V2ZW50czpuLHJlZmVyZW5jZXM6dC5fcmVmZXJlbmNlc19qc29uKHYudmFsdWVzKGopLGw9ITEpfX0sdC5wcm90b3R5cGUudG9fanNvbl9zdHJpbmc9ZnVuY3Rpb24odCl7cmV0dXJuIG51bGw9PXQmJih0PSEwKSxKU09OLnN0cmluZ2lmeSh0aGlzLnRvX2pzb24odCkpfSx0LnByb3RvdHlwZS50b19qc29uPWZ1bmN0aW9uKGUpe3ZhciByLG4sbyxpLHMsYTtmb3IobnVsbD09ZSYmKGU9ITApLHM9W10saT10aGlzLl9yb290cyxyPTAsbj1pLmxlbmd0aDtyPG47cisrKW89aVtyXSxzLnB1c2goby5pZCk7cmV0dXJuIGE9di52YWx1ZXModGhpcy5fYWxsX21vZGVscykse3RpdGxlOnRoaXMuX3RpdGxlLHJvb3RzOntyb290X2lkczpzLHJlZmVyZW5jZXM6dC5fcmVmZXJlbmNlc19qc29uKGEsZSl9fX0sdC5mcm9tX2pzb25fc3RyaW5nPWZ1bmN0aW9uKGUpe3ZhciByO2lmKG51bGw9PT1lfHxudWxsPT1lKXRocm93IG5ldyBFcnJvcigiSlNPTiBzdHJpbmcgaXMgIit0eXBlb2YgZSk7cmV0dXJuIHI9SlNPTi5wYXJzZShlKSx0LmZyb21fanNvbihyKX0sdC5mcm9tX2pzb249ZnVuY3Rpb24oZSl7dmFyIHIsbixvLGkscyxhLGwsdSxoLGM7aWYody5kZWJ1ZygiQ3JlYXRpbmcgRG9jdW1lbnQgZnJvbSBKU09OIiksIm9iamVjdCIhPXR5cGVvZiBlKXRocm93IG5ldyBFcnJvcigiSlNPTiBvYmplY3QgaGFzIHdyb25nIHR5cGUgIit0eXBlb2YgZSk7Zm9yKGk9ZS52ZXJzaW9uLGM9IkxpYnJhcnkgdmVyc2lvbnM6IEpTICgiK3grIikgIC8gIFB5dGhvbiAoIitpKyIpIixpLmluZGV4T2YoIi0iKTwwJiZ4IT09aT8ody53YXJuKCJKUy9QeXRob24gdmVyc2lvbiBtaXNtYXRjaCIpLHcud2FybihjKSk6dy5kZWJ1ZyhjKSxoPWUucm9vdHMsdT1oLnJvb3RfaWRzLGw9aC5yZWZlcmVuY2VzLGE9dC5faW5zdGFudGlhdGVfcmVmZXJlbmNlc19qc29uKGwse30pLHQuX2luaXRpYWxpemVfcmVmZXJlbmNlc19qc29uKGwse30sYSkscj1uZXcgdCxuPTAsbz11Lmxlbmd0aDtuPG87bisrKXM9dVtuXSxyLmFkZF9yb290KGFbc10pO3JldHVybiByLnNldF90aXRsZShlLnRpdGxlKSxyfSx0LnByb3RvdHlwZS5yZXBsYWNlX3dpdGhfanNvbj1mdW5jdGlvbihlKXt2YXIgcjtyZXR1cm4gcj10LmZyb21fanNvbihlKSxyLl9kZXN0cnVjdGl2ZWx5X21vdmUodGhpcyl9LHQucHJvdG90eXBlLmNyZWF0ZV9qc29uX3BhdGNoX3N0cmluZz1mdW5jdGlvbih0KXtyZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy5jcmVhdGVfanNvbl9wYXRjaCh0KSl9LHQucHJvdG90eXBlLmNyZWF0ZV9qc29uX3BhdGNoPWZ1bmN0aW9uKGUpe3ZhciByLG4sbyxpLHMsYTtmb3Iocz17fSxvPVtdLG49MCxpPWUubGVuZ3RoO248aTtuKyspe2lmKHI9ZVtuXSxyLmRvY3VtZW50IT09dGhpcyl0aHJvdyBjb25zb2xlLmxvZygiQ2Fubm90IGNyZWF0ZSBhIHBhdGNoIHVzaW5nIGV2ZW50cyBmcm9tIGEgZGlmZmVyZW50IGRvY3VtZW50LCBldmVudCBoYWQgIixyLmRvY3VtZW50LCIgd2UgYXJlICIsdGhpcyksbmV3IEVycm9yKCJDYW5ub3QgY3JlYXRlIGEgcGF0Y2ggdXNpbmcgZXZlbnRzIGZyb20gYSBkaWZmZXJlbnQgZG9jdW1lbnQiKTtvLnB1c2goci5qc29uKHMpKX1yZXR1cm4gYT17ZXZlbnRzOm8scmVmZXJlbmNlczp0Ll9yZWZlcmVuY2VzX2pzb24odi52YWx1ZXMocykpfX0sdC5wcm90b3R5cGUuYXBwbHlfanNvbl9wYXRjaF9zdHJpbmc9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuYXBwbHlfanNvbl9wYXRjaChKU09OLnBhcnNlKHQpKX0sdC5wcm90b3R5cGUuYXBwbHlfanNvbl9wYXRjaD1mdW5jdGlvbihlKXt2YXIgcixuLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0sayxqLFQsUztmb3Iodz1lLnJlZmVyZW5jZXMsbD1lLmV2ZW50cyx4PXQuX2luc3RhbnRpYXRlX3JlZmVyZW5jZXNfanNvbih3LHRoaXMuX2FsbF9tb2RlbHMpLGg9MCxwPWwubGVuZ3RoO2g8cDtoKyspaWYoYT1sW2hdLCJtb2RlbCJpbiBhKWlmKGQ9YS5tb2RlbC5pZCxkIGluIHRoaXMuX2FsbF9tb2RlbHMpeFtkXT10aGlzLl9hbGxfbW9kZWxzW2RdO2Vsc2UgaWYoIShkIGluIHgpKXRocm93IGNvbnNvbGUubG9nKCJHb3QgYW4gZXZlbnQgZm9yIHVua25vd24gbW9kZWwgIixhLm1vZGVsKSxuZXcgRXJyb3IoImV2ZW50IG1vZGVsIHdhc24ndCBrbm93biIpO2c9e30sZj17fTtmb3IodSBpbiB4KVM9eFt1XSx1IGluIHRoaXMuX2FsbF9tb2RlbHM/Z1t1XT1TOmZbdV09Uztmb3IodC5faW5pdGlhbGl6ZV9yZWZlcmVuY2VzX2pzb24odyxnLGYpLE09W10sYz0wLF89bC5sZW5ndGg7YzxfO2MrKylpZihhPWxbY10sIk1vZGVsQ2hhbmdlZCI9PT1hLmtpbmQpe2lmKHk9YS5tb2RlbC5pZCwhKHkgaW4gdGhpcy5fYWxsX21vZGVscykpdGhyb3cgbmV3IEVycm9yKCJDYW5ub3QgYXBwbHkgcGF0Y2ggdG8gIit5KyIgd2hpY2ggaXMgbm90IGluIHRoZSBkb2N1bWVudCIpO3Y9dGhpcy5fYWxsX21vZGVsc1t5XSxyPWEuYXR0cixTPXQuX3Jlc29sdmVfcmVmcyhhWyJuZXciXSxnLGYpLE0ucHVzaCh2LnNldCgobT17fSxtWyIiK3JdPVMsbSkpKX1lbHNlIGlmKCJDb2x1bW5zU3RyZWFtZWQiPT09YS5raW5kKXtpZihpPWEuY29sdW1uX3NvdXJjZS5pZCwhKGkgaW4gdGhpcy5fYWxsX21vZGVscykpdGhyb3cgbmV3IEVycm9yKCJDYW5ub3Qgc3RyZWFtIHRvICIraSsiIHdoaWNoIGlzIG5vdCBpbiB0aGUgZG9jdW1lbnQiKTtpZihuPXRoaXMuX2FsbF9tb2RlbHNbaV0sIShuIGluc3RhbmNlb2Ygby5Nb2RlbCkpdGhyb3cgbmV3IEVycm9yKCJDYW5ub3Qgc3RyZWFtIHRvIG5vbi1Db2x1bW5EYXRhU291cmNlIik7cz1hLmRhdGEsaz1hLnJvbGxvdmVyLE0ucHVzaChuLnN0cmVhbShzLGspKX1lbHNlIGlmKCJDb2x1bW5zUGF0Y2hlZCI9PT1hLmtpbmQpe2lmKGk9YS5jb2x1bW5fc291cmNlLmlkLCEoaSBpbiB0aGlzLl9hbGxfbW9kZWxzKSl0aHJvdyBuZXcgRXJyb3IoIkNhbm5vdCBwYXRjaCAiK2krIiB3aGljaCBpcyBub3QgaW4gdGhlIGRvY3VtZW50Iik7aWYobj10aGlzLl9hbGxfbW9kZWxzW2ldLCEobiBpbnN0YW5jZW9mIG8uTW9kZWwpKXRocm93IG5ldyBFcnJvcigiQ2Fubm90IHBhdGNoIG5vbi1Db2x1bW5EYXRhU291cmNlIik7Yj1hLnBhdGNoZXMsTS5wdXNoKG4ucGF0Y2goYikpfWVsc2UgaWYoIlJvb3RBZGRlZCI9PT1hLmtpbmQpaj1hLm1vZGVsLmlkLFQ9eFtqXSxNLnB1c2godGhpcy5hZGRfcm9vdChUKSk7ZWxzZSBpZigiUm9vdFJlbW92ZWQiPT09YS5raW5kKWo9YS5tb2RlbC5pZCxUPXhbal0sTS5wdXNoKHRoaXMucmVtb3ZlX3Jvb3QoVCkpO2Vsc2V7aWYoIlRpdGxlQ2hhbmdlZCIhPT1hLmtpbmQpdGhyb3cgbmV3IEVycm9yKCJVbmtub3duIHBhdGNoIGV2ZW50ICIrSlNPTi5zdHJpbmdpZnkoYSkpO00ucHVzaCh0aGlzLnNldF90aXRsZShhLnRpdGxlKSl9cmV0dXJuIE19LHR9KCksZS5leHBvcnRzPXtEb2N1bWVudDpzLERvY3VtZW50Q2hhbmdlZEV2ZW50OmEsTW9kZWxDaGFuZ2VkRXZlbnQ6aCxUaXRsZUNoYW5nZWRFdmVudDpnLFJvb3RBZGRlZEV2ZW50Ol8sUm9vdFJlbW92ZWRFdmVudDpkLERFRkFVTFRfVElUTEU6aX19LHsiLi9iYXNlIjoiYmFzZSIsIi4vY29yZS9oYXNfcHJvcHMiOiJjb3JlL2hhc19wcm9wcyIsIi4vY29yZS9sYXlvdXQvc29sdmVyIjoiY29yZS9sYXlvdXQvc29sdmVyIiwiLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuL2NvcmUvdXRpbC9kYXRhX3N0cnVjdHVyZXMiOiJjb3JlL3V0aWwvZGF0YV9zdHJ1Y3R1cmVzIiwiLi9jb3JlL3V0aWwvcmVmcyI6ImNvcmUvdXRpbC9yZWZzIiwiLi9tb2RlbHMvc291cmNlcy9jb2x1bW5fZGF0YV9zb3VyY2UiOiJtb2RlbHMvc291cmNlcy9jb2x1bW5fZGF0YV9zb3VyY2UiLCIuL3ZlcnNpb24iOiJ2ZXJzaW9uIixqcXVlcnk6ImpxdWVyeSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSxlbWJlZDpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTLHosUCxFLEEsQyxOO249dCgianF1ZXJ5IiksYz10KCJ1bmRlcnNjb3JlIiksaT10KCJiYWNrYm9uZSIpLGE9dCgiZXM2LXByb21pc2UiKS5Qcm9taXNlLGs9dCgiLi9iYXNlIiksRT10KCIuL2NsaWVudCIpLnB1bGxfc2Vzc2lvbixBPXQoIi4vY29yZS9sb2dnaW5nIiksUD1BLmxvZ2dlcixOPUEuc2V0X2xvZ19sZXZlbCxDPXQoIi4vZG9jdW1lbnQiKSxzPUMuRG9jdW1lbnQsbD1DLlJvb3RBZGRlZEV2ZW50LHU9Qy5Sb290UmVtb3ZlZEV2ZW50LGg9Qy5UaXRsZUNoYW5nZWRFdmVudCxvPSJiay1yb290IixkPWZ1bmN0aW9uKHQpe3ZhciBlO2lmKFAuZGVidWcoImhhbmRsaW5nIG5vdGVib29rIGNvbW1zIiksZT1KU09OLnBhcnNlKHQuY29udGVudC5kYXRhKSwiZXZlbnRzImluIGUmJiJyZWZlcmVuY2VzImluIGUpcmV0dXJuIHRoaXMuYXBwbHlfanNvbl9wYXRjaChlKTtpZigiZG9jImluIGUpcmV0dXJuIHRoaXMucmVwbGFjZV93aXRoX2pzb24oZS5kb2MpO3Rocm93IG5ldyBFcnJvcigiaGFuZGxpbmcgbm90ZWJvb2sgY29tbXMgbWVzc2FnZTogIix0KX0seT1mdW5jdGlvbih0LGUscil7aWYodD09PXIudGFyZ2V0X25hbWUpcmV0dXJuIHIub25fbXNnKGMuYmluZChkLGUpKX0sZj1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpLHMsYSxsO2lmKCJ1bmRlZmluZWQiPT10eXBlb2YgSnVweXRlcnx8bnVsbD09PUp1cHl0ZXJ8fG51bGw9PUp1cHl0ZXIubm90ZWJvb2sua2VybmVsKXJldHVybiBjb25zb2xlLndhcm4oIkp1cHl0ZXIgbm90ZWJvb2tzIGNvbW1zIG5vdCBhdmFpbGFibGUuIHB1c2hfbm90ZWJvb2soKSB3aWxsIG5vdCBmdW5jdGlvbiIpO1AuaW5mbygiUmVnaXN0ZXJpbmcgSnVweXRlciBjb21tcyBmb3IgdGFyZ2V0ICIrdCkscj1KdXB5dGVyLm5vdGVib29rLmtlcm5lbC5jb21tX21hbmFnZXIsbD1jLnBhcnRpYWwoeSx0LGUpLGE9ci5jb21tcztmb3IoaSBpbiBhKXM9YVtpXSxzLnRoZW4obCk7dHJ5e3JldHVybiByLnJlZ2lzdGVyX3RhcmdldCh0LGZ1bmN0aW9uKHIsbil7cmV0dXJuIFAuaW5mbygiUmVnaXN0ZXJpbmcgSnVweXRlciBjb21tcyBmb3IgdGFyZ2V0ICIrdCksci5vbl9tc2coYy5iaW5kKGQsZSkpfSl9Y2F0Y2gobyl7cmV0dXJuIG49byxQLndhcm4oIkp1cHl0ZXIgY29tbXMgZmFpbGVkIHRvIHJlZ2lzdGVyLiBwdXNoX25vdGVib29rKCkgd2lsbCBub3QgZnVuY3Rpb24uIChleGNlcHRpb24gcmVwb3J0ZWQ6ICIrbisiKSIpfX0scD1mdW5jdGlvbih0KXt2YXIgZTtyZXR1cm4gZT1uZXcgdC5kZWZhdWx0X3ZpZXcoe21vZGVsOnR9KSxrLmluZGV4W3QuaWRdPWUsZX0sbT1mdW5jdGlvbih0LGUscil7CnZhciBvLGkscyxhLGMsXyxkO2Q9e30sYz1mdW5jdGlvbihlKXt2YXIgcjtyZXR1cm4gcj1wKGUpLGRbZS5pZF09cixuKHQpLmFwcGVuZChyLiRlbCl9LF89ZnVuY3Rpb24oZSl7dmFyIHI7aWYoZS5pZCBpbiBkKXJldHVybiByPWRbZS5pZF0sbih0KS5yZW1vdmUoci4kZWwpLGRlbGV0ZSBkW2UuaWRdLGRlbGV0ZSBrLmluZGV4W2UuaWRdfSxhPWUucm9vdHMoKTtmb3Iobz0wLGk9YS5sZW5ndGg7bzxpO28rKylzPWFbb10sYyhzKTtyZXR1cm4gciYmKHdpbmRvdy5kb2N1bWVudC50aXRsZT1lLnRpdGxlKCkpLGUub25fY2hhbmdlKGZ1bmN0aW9uKHQpe3JldHVybiB0IGluc3RhbmNlb2YgbD9jKHQubW9kZWwpOnQgaW5zdGFuY2VvZiB1P18odC5tb2RlbCk6ciYmdCBpbnN0YW5jZW9mIGg/d2luZG93LmRvY3VtZW50LnRpdGxlPXQudGl0bGU6dm9pZCAwfSksZH0sTT1mdW5jdGlvbih0LGUscil7dmFyIG8saTtpZihvPXIuZ2V0X21vZGVsX2J5X2lkKGUpLG51bGw9PW8pdGhyb3cgbmV3IEVycm9yKCJNb2RlbCAiK2UrIiB3YXMgbm90IGluIGRvY3VtZW50ICIrcik7cmV0dXJuIGk9cChvKSxjLmRlbGF5KGZ1bmN0aW9uKCl7cmV0dXJuIG4odCkucmVwbGFjZVdpdGgoaS4kZWwpfSl9LHg9ZnVuY3Rpb24odCxlLHIpe3JldHVybiBjLmRlbGF5KGZ1bmN0aW9uKCl7cmV0dXJuIG0obih0KSxlLHIpfSl9LGI9ZnVuY3Rpb24odCxlLHIpe3JldHVybiBudWxsPT1yJiYocj0hMSksbShuKGUpLHQscil9LGc9e30sXz1mdW5jdGlvbih0LGUpe3ZhciByO2lmKG51bGw9PXR8fG51bGw9PT10KXRocm93IG5ldyBFcnJvcigiTWlzc2luZyB3ZWJzb2NrZXRfdXJsIik7cmV0dXJuIHQgaW4gZ3x8KGdbdF09e30pLHI9Z1t0XSxlIGluIHJ8fChyW2VdPUUodCxlKSkscltlXX0sdj1mdW5jdGlvbih0LGUscixuKXt2YXIgbztyZXR1cm4gbz1fKGUsciksby50aGVuKGZ1bmN0aW9uKGUpe3JldHVybiBtKHQsZS5kb2N1bWVudCxuKX0sZnVuY3Rpb24odCl7dGhyb3cgUC5lcnJvcigiRmFpbGVkIHRvIGxvYWQgQm9rZWggc2Vzc2lvbiAiK3IrIjogIit0KSx0fSl9LHc9ZnVuY3Rpb24odCxlLHIsbyl7dmFyIGk7cmV0dXJuIGk9XyhlLG8pLGkudGhlbihmdW5jdGlvbihlKXt2YXIgbyxpO2lmKG89ZS5kb2N1bWVudC5nZXRfbW9kZWxfYnlfaWQociksbnVsbD09byl0aHJvdyBuZXcgRXJyb3IoIkRpZCBub3QgZmluZCBtb2RlbCAiK3IrIiBpbiBzZXNzaW9uIik7cmV0dXJuIGk9cChvKSxuKHQpLnJlcGxhY2VXaXRoKGkuJGVsKX0sZnVuY3Rpb24odCl7dGhyb3cgUC5lcnJvcigiRmFpbGVkIHRvIGxvYWQgQm9rZWggc2Vzc2lvbiAiK28rIjogIit0KSx0fSl9LFM9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9bigiPGxpbmsgaHJlZj0nIit0KyInIHJlbD0nc3R5bGVzaGVldCcgdHlwZT0ndGV4dC9jc3MnPiIpLG4oImJvZHkiKS5hcHBlbmQoZSl9LHo9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9bigiPHN0eWxlPiIpLmh0bWwodCksbigiYm9keSIpLmFwcGVuZChlKX0sVD1mdW5jdGlvbih0LGUpe3ZhciByO3JldHVybiByPXQuZGF0YSgpLG51bGwhPXIuYm9rZWhMb2dMZXZlbCYmci5ib2tlaExvZ0xldmVsLmxlbmd0aD4wJiZOKHIuYm9rZWhMb2dMZXZlbCksbnVsbCE9ci5ib2tlaERvY0lkJiZyLmJva2VoRG9jSWQubGVuZ3RoPjAmJihlLmRvY2lkPXIuYm9rZWhEb2NJZCksbnVsbCE9ci5ib2tlaE1vZGVsSWQmJnIuYm9rZWhNb2RlbElkLmxlbmd0aD4wJiYoZS5tb2RlbGlkPXIuYm9rZWhNb2RlbElkKSxudWxsIT1yLmJva2VoU2Vzc2lvbklkJiZyLmJva2VoU2Vzc2lvbklkLmxlbmd0aD4wJiYoZS5zZXNzaW9uaWQ9ci5ib2tlaFNlc3Npb25JZCksUC5pbmZvKCJXaWxsIGluamVjdCBCb2tlaCBzY3JpcHQgdGFnIHdpdGggcGFyYW1zICIrSlNPTi5zdHJpbmdpZnkoZSkpfSxqPWZ1bmN0aW9uKHQsZSxyKXt2YXIgaSxhLGwsdSxoLGMscCxfLGQsbSxnO251bGw9PXImJihyPW51bGwpLGw9e307Zm9yKGEgaW4gdClsW2FdPXMuZnJvbV9qc29uKHRbYV0pO2ZvcihtPVtdLGM9MCxfPWUubGVuZ3RoO2M8XztjKyspe2lmKHA9ZVtjXSxudWxsIT1wLm5vdGVib29rX2NvbW1zX3RhcmdldCYmZihwLm5vdGVib29rX2NvbW1zX3RhcmdldCxsW2FdKSxoPXAuZWxlbWVudGlkLHU9bigiIyIraCksMD09PXUubGVuZ3RoKXRocm93IG5ldyBFcnJvcigiRXJyb3IgcmVuZGVyaW5nIEJva2VoIG1vZGVsOiBjb3VsZCBub3QgZmluZCB0YWcgd2l0aCBpZDogIitoKTtpZih1Lmxlbmd0aD4xKXRocm93IG5ldyBFcnJvcigiRXJyb3IgcmVuZGVyaW5nIEJva2VoIG1vZGVsOiBmb3VuZCB0b28gbWFueSB0YWdzIHdpdGggaWQ6ICIraCk7aWYoIWRvY3VtZW50LmJvZHkuY29udGFpbnModVswXSkpdGhyb3cgbmV3IEVycm9yKCJFcnJvciByZW5kZXJpbmcgQm9rZWggbW9kZWw6IGVsZW1lbnQgd2l0aCBpZCAnIitoKyInIG11c3QgYmUgdW5kZXIgPGJvZHk+Iik7aWYoIlNDUklQVCI9PT11LnByb3AoInRhZ05hbWUiKSYmKFQodSxwKSxpPW4oIjxkaXY+Iix7ImNsYXNzIjpvfSksdS5yZXBsYWNlV2l0aChpKSx1PWkpLGc9bnVsbCE9cC51c2VfZm9yX3RpdGxlJiZwLnVzZV9mb3JfdGl0bGUsZD1udWxsLG51bGwhPXAubW9kZWxpZClpZihudWxsIT1wLmRvY2lkKU0odSxwLm1vZGVsaWQsbFtwLmRvY2lkXSk7ZWxzZXtpZihudWxsPT1wLnNlc3Npb25pZCl0aHJvdyBuZXcgRXJyb3IoIkVycm9yIHJlbmRlcmluZyBCb2tlaCBtb2RlbCAiK3AubW9kZWxpZCsiIHRvIGVsZW1lbnQgIitoKyI6IG5vIGRvY3VtZW50IElEIG9yIHNlc3Npb24gSUQgc3BlY2lmaWVkIik7ZD13KHUscixwLm1vZGVsaWQscC5zZXNzaW9uaWQpfWVsc2UgaWYobnVsbCE9cC5kb2NpZCl4KHUsbFtwLmRvY2lkXSxnKTtlbHNle2lmKG51bGw9PXAuc2Vzc2lvbmlkKXRocm93IG5ldyBFcnJvcigiRXJyb3IgcmVuZGVyaW5nIEJva2VoIGRvY3VtZW50IHRvIGVsZW1lbnQgIitoKyI6IG5vIGRvY3VtZW50IElEIG9yIHNlc3Npb24gSUQgc3BlY2lmaWVkIik7ZD12KHUscixwLnNlc3Npb25pZCxnKX1udWxsIT09ZD9tLnB1c2goZC50aGVuKGZ1bmN0aW9uKHQpe3JldHVybiBjb25zb2xlLmxvZygiQm9rZWggaXRlbXMgd2VyZSByZW5kZXJlZCBzdWNjZXNzZnVsbHkiKX0sZnVuY3Rpb24odCl7cmV0dXJuIGNvbnNvbGUubG9nKCJFcnJvciByZW5kZXJpbmcgQm9rZWggaXRlbXMgIix0KX0pKTptLnB1c2godm9pZCAwKX1yZXR1cm4gbX0sZS5leHBvcnRzPXtlbWJlZF9pdGVtczpqLGFkZF9kb2N1bWVudF9zdGF0aWM6eCxhZGRfZG9jdW1lbnRfc3RhbmRhbG9uZTpiLGluamVjdF9jc3M6UyxpbmplY3RfcmF3X2Nzczp6LEJPS0VIX1JPT1Q6b319LHsiLi9iYXNlIjoiYmFzZSIsIi4vY2xpZW50IjoiY2xpZW50IiwiLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuL2RvY3VtZW50IjoiZG9jdW1lbnQiLGJhY2tib25lOiJiYWNrYm9uZSIsImVzNi1wcm9taXNlIjoiZXM2LXByb21pc2UiLGpxdWVyeToianF1ZXJ5Iix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLG1haW46W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk7bz10KCJ1bmRlcnNjb3JlIiksbj17fSxuLnJlcXVpcmU9dCxuLnZlcnNpb249dCgiLi92ZXJzaW9uIiksbi5fPXQoInVuZGVyc2NvcmUiKSxuLiQ9dCgianF1ZXJ5Iiksbi5CYWNrYm9uZT10KCJiYWNrYm9uZSIpLG4uQmFja2JvbmUuJD1uLiQsaT10KCIuL2NvcmUvbG9nZ2luZyIpLG4ubG9nZ2VyPWkubG9nZ2VyLG4uc2V0X2xvZ19sZXZlbD1pLnNldF9sb2dfbGV2ZWwsbi5pbmRleD10KCIuL2Jhc2UiKS5pbmRleCxuLmVtYmVkPXQoIi4vZW1iZWQiKSxuLnNhZmVseT10KCIuL3NhZmVseSIpLG4uTW9kZWxzPXQoIi4vYmFzZSIpLk1vZGVscyxuLkJva2VoPW4sZS5leHBvcnRzPW59LHsiLi9iYXNlIjoiYmFzZSIsIi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi9lbWJlZCI6ImVtYmVkIiwiLi9zYWZlbHkiOiJzYWZlbHkiLCIuL3ZlcnNpb24iOiJ2ZXJzaW9uIixiYWNrYm9uZToiYmFja2JvbmUiLGpxdWVyeToianF1ZXJ5Iix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLG1vZGVsOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpbC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxsPXt9Lmhhc093blByb3BlcnR5O2k9dCgidW5kZXJzY29yZSIpLG49dCgiLi9jb3JlL2hhc19wcm9wcyIpLHM9dCgiLi9jb3JlL3Byb3BlcnRpZXMiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGUudHlwZT0iTW9kZWwiLGUucHJvdG90eXBlLl9jb29yZHM9W10sZS5jb29yZHM9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxhLGw7Zm9yKGU9dGhpcy5wcm90b3R5cGUuX2Nvb3Jkcy5jb25jYXQodCksdGhpcy5wcm90b3R5cGUuX2Nvb3Jkcz1lLGk9e30scj0wLG49dC5sZW5ndGg7cjxuO3IrKylvPXRbcl0sYT1vWzBdLGw9b1sxXSxpW2FdPVtzLk51bWJlclNwZWNdLGlbbF09W3MuTnVtYmVyU3BlY107cmV0dXJuIHRoaXMuZGVmaW5lKGkpfSxlLmRlZmluZSh7dGFnczpbcy5BcnJheSxbXV0sbmFtZTpbcy5TdHJpbmddfSksZS5wcm90b3R5cGUuc2VsZWN0PWZ1bmN0aW9uKHQpe2lmKHQucHJvdG90eXBlIGluc3RhbmNlb2YgZSlyZXR1cm4gdGhpcy5yZWZlcmVuY2VzKCkuZmlsdGVyKGZ1bmN0aW9uKGUpe3JldHVybiBlIGluc3RhbmNlb2YgdH0pO2lmKGkuaXNTdHJpbmcodCkpcmV0dXJuIHRoaXMucmVmZXJlbmNlcygpLmZpbHRlcihmdW5jdGlvbihlKXtyZXR1cm4gZS5uYW1lPT09dH0pO3Rocm93IG5ldyBFcnJvcigiaW52YWxpZCBzZWxlY3RvciIpfSxlLnByb3RvdHlwZS5zZWxlY3Rfb25lPWZ1bmN0aW9uKHQpe3ZhciBlO3N3aXRjaChlPXRoaXMuc2VsZWN0KHQpLGUubGVuZ3RoKXtjYXNlIDA6cmV0dXJuIG51bGw7Y2FzZSAxOnJldHVybiBlWzBdO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKCJmb3VuZCBtb3JlIHRoYW4gb25lIG9iamVjdCBtYXRjaGluZyBnaXZlbiBzZWxlY3RvciIpfX0sZX0obiksZS5leHBvcnRzPW99LHsiLi9jb3JlL2hhc19wcm9wcyI6ImNvcmUvaGFzX3Byb3BzIiwiLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9hbm5vdGF0aW9ucy9hbm5vdGF0aW9uIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1PWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSloLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGg9e30uaGFzT3duUHJvcGVydHk7YT10KCJ1bmRlcnNjb3JlIikscz10KCIuLi8uLi9jb3JlL2xheW91dC9zaWRlX3BhbmVsIiksbD10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxpPXQoIi4uL3JlbmRlcmVycy9yZW5kZXJlciIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHUoZSx0KSxlLnByb3RvdHlwZS5fZ2V0X3BhbmVsX29mZnNldD1mdW5jdGlvbigpe3ZhciB0LGU7cmV0dXJuIHQ9dGhpcy5tb2RlbC5wYW5lbC5fbGVmdC5fdmFsdWUsZT10aGlzLm1vZGVsLnBhbmVsLl9ib3R0b20uX3ZhbHVlLHt4OnQseTotZX19LGUucHJvdG90eXBlLl9nZXRfc2l6ZT1mdW5jdGlvbigpe3JldHVybi0xfSxlfShpLlZpZXcpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHUoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJBbm5vdGF0aW9uIixlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9byxlLmRlZmluZSh7cGxvdDpbbC5JbnN0YW5jZV19KSxlLm92ZXJyaWRlKHtsZXZlbDoiYW5ub3RhdGlvbiJ9KSxlLnByb3RvdHlwZS5hZGRfcGFuZWw9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMucGFuZWw9bmV3IHMuTW9kZWwoe3NpZGU6dH0pLHRoaXMucGFuZWwuYXR0YWNoX2RvY3VtZW50KHRoaXMuZG9jdW1lbnQpLHRoaXMubGV2ZWw9Im92ZXJsYXkifSxlfShpLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm4sVmlldzpvfX0seyIuLi8uLi9jb3JlL2xheW91dC9zaWRlX3BhbmVsIjoiY29yZS9sYXlvdXQvc2lkZV9wYW5lbCIsIi4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4uL3JlbmRlcmVycy9yZW5kZXJlciI6Im1vZGVscy9yZW5kZXJlcnMvcmVuZGVyZXIiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9hbm5vdGF0aW9ucy9hcnJvdyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGM9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXAuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0scD17fS5oYXNPd25Qcm9wZXJ0eTtsPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vYW5ub3RhdGlvbiIpLGE9dCgiLi9hcnJvd19oZWFkIikuT3BlbkhlYWQscz10KCIuLi9zb3VyY2VzL2NvbHVtbl9kYXRhX3NvdXJjZSIpLGg9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksdT10KCIuLi8uLi9jb3JlL3V0aWwvbWF0aCIpLmF0YW4yLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGMoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0KSxudWxsPT10aGlzLm1nZXQoInNvdXJjZSIpJiZ0aGlzLm1zZXQoInNvdXJjZSIsbmV3IHMuTW9kZWwpLHRoaXMuY2FudmFzPXRoaXMucGxvdF9tb2RlbC5nZXQoImNhbnZhcyIpLHRoaXMueG1hcHBlcj10aGlzLnBsb3Rfdmlldy5mcmFtZS5nZXQoInhfbWFwcGVycyIpW3RoaXMubWdldCgieF9yYW5nZV9uYW1lIildLHRoaXMueW1hcHBlcj10aGlzLnBsb3Rfdmlldy5mcmFtZS5nZXQoInlfbWFwcGVycyIpW3RoaXMubWdldCgieV9yYW5nZV9uYW1lIildLHRoaXMuc2V0X2RhdGEoKX0sZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5saXN0ZW5Ubyh0aGlzLm1vZGVsLCJjaGFuZ2UiLHRoaXMucGxvdF92aWV3LnJlcXVlc3RfcmVuZGVyKSx0aGlzLmxpc3RlblRvKHRoaXMubWdldCgic291cmNlIiksImNoYW5nZSIsZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zZXRfZGF0YSgpLHRoaXMucGxvdF92aWV3LnJlcXVlc3RfcmVuZGVyKCl9KX0sZS5wcm90b3R5cGUuc2V0X2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4gZS5fX3N1cGVyX18uc2V0X2RhdGEuY2FsbCh0aGlzLHRoaXMubWdldCgic291cmNlIikpLHRoaXMuc2V0X3Zpc3VhbHModGhpcy5tZ2V0KCJzb3VyY2UiKSl9LGUucHJvdG90eXBlLl9tYXBfZGF0YT1mdW5jdGlvbigpe3ZhciB0LGUscixuO3JldHVybiBlPSJkYXRhIj09PXRoaXMubWdldCgic3RhcnRfdW5pdHMiKT90aGlzLnBsb3Rfdmlldy5tYXBfdG9fc2NyZWVuKHRoaXMuX3hfc3RhcnQsdGhpcy5feV9zdGFydCxyPXRoaXMubWdldCgieF9yYW5nZV9uYW1lIiksbj10aGlzLm1nZXQoInlfcmFuZ2VfbmFtZSIpKTpbdGhpcy5jYW52YXMudl92eF90b19zeCh0aGlzLl94X3N0YXJ0KSx0aGlzLmNhbnZhcy52X3Z5X3RvX3N5KHRoaXMuX3lfc3RhcnQpXSx0PSJkYXRhIj09PXRoaXMubWdldCgiZW5kX3VuaXRzIik/dGhpcy5wbG90X3ZpZXcubWFwX3RvX3NjcmVlbih0aGlzLl94X2VuZCx0aGlzLl95X2VuZCxyPXRoaXMubWdldCgieF9yYW5nZV9uYW1lIiksbj10aGlzLm1nZXQoInlfcmFuZ2VfbmFtZSIpKTpbdGhpcy5jYW52YXMudl92eF90b19zeCh0aGlzLl94X2VuZCksdGhpcy5jYW52YXMudl92eV90b19zeSh0aGlzLl95X2VuZCldLFtlLHRdfSxlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24oKXt2YXIgdDtpZih0PXRoaXMuX21hcF9kYXRhKCksdGhpcy5zdGFydD10WzBdLHRoaXMuZW5kPXRbMV0sdGhpcy5fZHJhd19hcnJvd19ib2R5KCksbnVsbCE9dGhpcy5tZ2V0KCJlbmQiKSYmdGhpcy5fZHJhd19hcnJvd19oZWFkKHRoaXMubWdldCgiZW5kIiksdGhpcy5zdGFydCx0aGlzLmVuZCksbnVsbCE9dGhpcy5tZ2V0KCJzdGFydCIpKXJldHVybiB0aGlzLl9kcmF3X2Fycm93X2hlYWQodGhpcy5tZ2V0KCJzdGFydCIpLHRoaXMuZW5kLHRoaXMuc3RhcnQpfSxlLnByb3RvdHlwZS5fZHJhd19hcnJvd19ib2R5PWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47Zm9yKHQ9dGhpcy5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LHQuc2F2ZSgpLGU9cj0wLG49dGhpcy5feF9zdGFydC5sZW5ndGg7MDw9bj9yPG46cj5uO2U9MDw9bj8rK3I6LS1yKXRoaXMudmlzdWFscy5saW5lLnNldF92ZWN0b3JpemUodCxlKSx0LmJlZ2luUGF0aCgpLHQubW92ZVRvKHRoaXMuc3RhcnRbMF1bZV0sdGhpcy5zdGFydFsxXVtlXSksdC5saW5lVG8odGhpcy5lbmRbMF1bZV0sdGhpcy5lbmRbMV1bZV0pLHRoaXMudmlzdWFscy5saW5lLmRvaXQmJnQuc3Ryb2tlKCk7cmV0dXJuIHQucmVzdG9yZSgpfSxlLnByb3RvdHlwZS5fZHJhd19hcnJvd19oZWFkPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw7Zm9yKG89dGhpcy5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LGw9W10saT1zPTAsYT10aGlzLl94X3N0YXJ0Lmxlbmd0aDswPD1hP3M8YTpzPmE7aT0wPD1hPysrczotLXMpbj1NYXRoLlBJLzIrdShbZVswXVtpXSxlWzFdW2ldXSxbclswXVtpXSxyWzFdW2ldXSksby5zYXZlKCksby50cmFuc2xhdGUoclswXVtpXSxyWzFdW2ldKSxvLnJvdGF0ZShuKSx0LnJlbmRlcihvLGkpLGwucHVzaChvLnJlc3RvcmUoKSk7cmV0dXJuIGx9LGV9KG4uVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gYyhlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLnR5cGU9IkFycm93IixlLm1peGlucyhbImxpbmUiXSksZS5kZWZpbmUoe3hfc3RhcnQ6W2guTnVtYmVyU3BlY10seV9zdGFydDpbaC5OdW1iZXJTcGVjXSxzdGFydF91bml0czpbaC5TdHJpbmcsImRhdGEiXSxzdGFydDpbaC5JbnN0YW5jZSxudWxsXSx4X2VuZDpbaC5OdW1iZXJTcGVjXSx5X2VuZDpbaC5OdW1iZXJTcGVjXSxlbmRfdW5pdHM6W2guU3RyaW5nLCJkYXRhIl0sZW5kOltoLkluc3RhbmNlLG5ldyBhLk1vZGVsKHt9KV0sc291cmNlOltoLkluc3RhbmNlXSx4X3JhbmdlX25hbWU6W2guU3RyaW5nLCJkZWZhdWx0Il0seV9yYW5nZV9uYW1lOltoLlN0cmluZywiZGVmYXVsdCJdfSksZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvLFZpZXc6aX19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vY29yZS91dGlsL21hdGgiOiJjb3JlL3V0aWwvbWF0aCIsIi4uL3NvdXJjZXMvY29sdW1uX2RhdGFfc291cmNlIjoibW9kZWxzL3NvdXJjZXMvY29sdW1uX2RhdGFfc291cmNlIiwiLi9hbm5vdGF0aW9uIjoibW9kZWxzL2Fubm90YXRpb25zL2Fubm90YXRpb24iLCIuL2Fycm93X2hlYWQiOiJtb2RlbHMvYW5ub3RhdGlvbnMvYXJyb3dfaGVhZCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2Fubm90YXRpb25zL2Fycm93X2hlYWQiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxjPXt9Lmhhc093blByb3BlcnR5O249dCgiLi9hbm5vdGF0aW9uIiksYT10KCIuLi9yZW5kZXJlcnMvcmVuZGVyZXIiKSx1PXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJBcnJvd0hlYWQiLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCl7dmFyIHIsbixvLGkscyxsLHUsaDtmb3IoZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy52aXN1YWxzPXt9LHM9dGhpcy5taXhpbnMsdT1bXSxyPTAsbj1zLmxlbmd0aDtyPG47cisrKWg9c1tyXSxsPWguc3BsaXQoIjoiKSxvPWxbMF0saT1sWzFdLG51bGw9PWkmJihpPSIiKSx1LnB1c2godGhpcy52aXN1YWxzW2krb109bmV3IGEuVmlzdWFsc1tvXSh7b2JqOnRoaXMscHJlZml4Oml9KSk7cmV0dXJuIHV9LGUucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbih0LGUpe3JldHVybiBudWxsfSxlfShuLk1vZGVsKSxzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBoKGUsdCksZS5wcm90b3R5cGUudHlwZT0iT3BlbkhlYWQiLGUucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbih0LGUpe2lmKHRoaXMudmlzdWFscy5saW5lLmRvaXQpcmV0dXJuIHRoaXMudmlzdWFscy5saW5lLnNldF92ZWN0b3JpemUodCxlKSx0LmJlZ2luUGF0aCgpLHQubW92ZVRvKC41KnRoaXMuZ2V0KCJzaXplIiksdGhpcy5nZXQoInNpemUiKSksdC5saW5lVG8oMCwwKSx0LmxpbmVUbygtLjUqdGhpcy5nZXQoInNpemUiKSx0aGlzLmdldCgic2l6ZSIpKSx0LnN0cm9rZSgpfSxlLm1peGlucyhbImxpbmUiXSksZS5kZWZpbmUoe3NpemU6W3UuTnVtYmVyLDI1XX0pLGV9KG8pLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJOb3JtYWxIZWFkIixlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24odCxlKXtpZih0aGlzLnZpc3VhbHMuZmlsbC5kb2l0JiYodGhpcy52aXN1YWxzLmZpbGwuc2V0X3ZlY3Rvcml6ZSh0LGUpLHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8oLjUqdGhpcy5nZXQoInNpemUiKSx0aGlzLmdldCgic2l6ZSIpKSx0LmxpbmVUbygwLDApLHQubGluZVRvKC0uNSp0aGlzLmdldCgic2l6ZSIpLHRoaXMuZ2V0KCJzaXplIikpLHQuY2xvc2VQYXRoKCksdC5maWxsKCkpLHRoaXMudmlzdWFscy5saW5lLmRvaXQpcmV0dXJuIHRoaXMudmlzdWFscy5saW5lLnNldF92ZWN0b3JpemUodCxlKSx0LmJlZ2luUGF0aCgpLHQubW92ZVRvKC41KnRoaXMuZ2V0KCJzaXplIiksdGhpcy5nZXQoInNpemUiKSksdC5saW5lVG8oMCwwKSx0LmxpbmVUbygtLjUqdGhpcy5nZXQoInNpemUiKSx0aGlzLmdldCgic2l6ZSIpKSx0LmNsb3NlUGF0aCgpLHQuc3Ryb2tlKCl9LGUubWl4aW5zKFsibGluZSIsImZpbGwiXSksZS5kZWZpbmUoe3NpemU6W3UuTnVtYmVyLDI1XX0pLGUub3ZlcnJpZGUoe2ZpbGxfY29sb3I6ImJsYWNrIn0pLGV9KG8pLGw9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJWZWVIZWFkIixlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24odCxlKXtpZih0aGlzLnZpc3VhbHMuZmlsbC5kb2l0JiYodGhpcy52aXN1YWxzLmZpbGwuc2V0X3ZlY3Rvcml6ZSh0LGUpLHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8oLjUqdGhpcy5nZXQoInNpemUiKSx0aGlzLmdldCgic2l6ZSIpKSx0LmxpbmVUbygwLDApLHQubGluZVRvKC0uNSp0aGlzLmdldCgic2l6ZSIpLHRoaXMuZ2V0KCJzaXplIikpLHQubGluZVRvKDAsLjUqdGhpcy5nZXQoInNpemUiKSksdC5jbG9zZVBhdGgoKSx0LmZpbGwoKSksdGhpcy52aXN1YWxzLmxpbmUuZG9pdClyZXR1cm4gdGhpcy52aXN1YWxzLmxpbmUuc2V0X3ZlY3Rvcml6ZSh0LGUpLHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8oLjUqdGhpcy5nZXQoInNpemUiKSx0aGlzLmdldCgic2l6ZSIpKSx0LmxpbmVUbygwLDApLHQubGluZVRvKC0uNSp0aGlzLmdldCgic2l6ZSIpLHRoaXMuZ2V0KCJzaXplIikpLHQubGluZVRvKDAsLjUqdGhpcy5nZXQoInNpemUiKSksdC5jbG9zZVBhdGgoKSx0LnN0cm9rZSgpfSxlLm1peGlucyhbImxpbmUiLCJmaWxsIl0pLGUuZGVmaW5lKHtzaXplOlt1Lk51bWJlciwyNV19KSxlLm92ZXJyaWRlKHtmaWxsX2NvbG9yOiJibGFjayJ9KSxlfShvKSxlLmV4cG9ydHM9e09wZW5IZWFkOntNb2RlbDpzfSxOb3JtYWxIZWFkOntNb2RlbDppfSxWZWVIZWFkOntNb2RlbDpsfX19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vcmVuZGVyZXJzL3JlbmRlcmVyIjoibW9kZWxzL3JlbmRlcmVycy9yZW5kZXJlciIsIi4vYW5ub3RhdGlvbiI6Im1vZGVscy9hbm5vdGF0aW9ucy9hbm5vdGF0aW9uIn1dLCJtb2RlbHMvYW5ub3RhdGlvbnMvYm94X2Fubm90YXRpb24iOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl1LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHU9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2Fubm90YXRpb24iKSxhPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0KSx0aGlzLiRlbC5hcHBlbmRUbyh0aGlzLnBsb3Rfdmlldy4kZWwuZmluZCgiZGl2LmJrLWNhbnZhcy1vdmVybGF5cyIpKSx0aGlzLiRlbC5hZGRDbGFzcygiYmstc2hhZGluZyIpLHRoaXMuJGVsLmhpZGUoKX0sZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXtyZXR1cm4iY3NzIj09PXRoaXMubWdldCgicmVuZGVyX21vZGUiKT8odGhpcy5saXN0ZW5Ubyh0aGlzLm1vZGVsLCJjaGFuZ2UiLHRoaXMucmVuZGVyKSx0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImRhdGFfdXBkYXRlIix0aGlzLnJlbmRlcikpOih0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZSIsdGhpcy5wbG90X3ZpZXcucmVxdWVzdF9yZW5kZXIpLHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiZGF0YV91cGRhdGUiLHRoaXMucGxvdF92aWV3LnJlcXVlc3RfcmVuZGVyKSl9LGUucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbigpe3ZhciB0LGUscixuO3JldHVybiBudWxsPT10aGlzLm1nZXQoImxlZnQiKSYmbnVsbD09dGhpcy5tZ2V0KCJyaWdodCIpJiZudWxsPT10aGlzLm1nZXQoInRvcCIpJiZudWxsPT10aGlzLm1nZXQoImJvdHRvbSIpPyh0aGlzLiRlbC5oaWRlKCksbnVsbCk6KHRoaXMuZnJhbWU9dGhpcy5wbG90X21vZGVsLmdldCgiZnJhbWUiKSx0aGlzLmNhbnZhcz10aGlzLnBsb3RfbW9kZWwuZ2V0KCJjYW52YXMiKSx0aGlzLnhtYXBwZXI9dGhpcy5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJ4X21hcHBlcnMiKVt0aGlzLm1nZXQoInhfcmFuZ2VfbmFtZSIpXSx0aGlzLnltYXBwZXI9dGhpcy5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJ5X21hcHBlcnMiKVt0aGlzLm1nZXQoInlfcmFuZ2VfbmFtZSIpXSxlPXRoaXMuY2FudmFzLnZ4X3RvX3N4KHRoaXMuX2NhbGNfZGltKCJsZWZ0Iix0aGlzLnhtYXBwZXIsdGhpcy5mcmFtZS5nZXQoImhfcmFuZ2UiKS5nZXQoInN0YXJ0IikpKSxyPXRoaXMuY2FudmFzLnZ4X3RvX3N4KHRoaXMuX2NhbGNfZGltKCJyaWdodCIsdGhpcy54bWFwcGVyLHRoaXMuZnJhbWUuZ2V0KCJoX3JhbmdlIikuZ2V0KCJlbmQiKSkpLHQ9dGhpcy5jYW52YXMudnlfdG9fc3kodGhpcy5fY2FsY19kaW0oImJvdHRvbSIsdGhpcy55bWFwcGVyLHRoaXMuZnJhbWUuZ2V0KCJ2X3JhbmdlIikuZ2V0KCJzdGFydCIpKSksbj10aGlzLmNhbnZhcy52eV90b19zeSh0aGlzLl9jYWxjX2RpbSgidG9wIix0aGlzLnltYXBwZXIsdGhpcy5mcmFtZS5nZXQoInZfcmFuZ2UiKS5nZXQoImVuZCIpKSksImNzcyI9PT10aGlzLm1nZXQoInJlbmRlcl9tb2RlIik/dGhpcy5fY3NzX2JveChlLHIsdCxuKTp0aGlzLl9jYW52YXNfYm94KGUscix0LG4pKX0sZS5wcm90b3R5cGUuX2Nzc19ib3g9ZnVuY3Rpb24odCxlLHIsbil7dmFyIG8saSxhLGwsdSxoLGMscDtyZXR1cm4gcD1NYXRoLmFicyhlLXQpLGg9TWF0aC5hYnMoci1uKSx1PXRoaXMubWdldCgibGluZV93aWR0aCIpLnZhbHVlLGE9dGhpcy5tZ2V0KCJsaW5lX2NvbG9yIikudmFsdWUsaT10aGlzLm1nZXQoImZpbGxfY29sb3IiKS52YWx1ZSxvPXRoaXMubWdldCgiZmlsbF9hbHBoYSIpLnZhbHVlLGM9ImxlZnQ6Iit0KyJweDsgd2lkdGg6IitwKyJweDsgdG9wOiIrbisicHg7IGhlaWdodDoiK2grInB4OyBib3JkZXItd2lkdGg6Iit1KyJweDsgYm9yZGVyLWNvbG9yOiIrYSsiOyBiYWNrZ3JvdW5kLWNvbG9yOiIraSsiOyBvcGFjaXR5OiIrbysiOyIsbD10aGlzLm1nZXQoImxpbmVfZGFzaCIpLHMuaXNBcnJheShsKSYmKGw9bC5sZW5ndGg8Mj8ic29saWQiOiJkYXNoZWQiKSxzLmlzU3RyaW5nKGwpJiYoYys9IiBib3JkZXItc3R5bGU6IitsKyI7IiksdGhpcy4kZWwuYXR0cigic3R5bGUiLGMpLHRoaXMuJGVsLnNob3coKX0sZS5wcm90b3R5cGUuX2NhbnZhc19ib3g9ZnVuY3Rpb24odCxlLHIsbil7dmFyIG87cmV0dXJuIG89dGhpcy5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LG8uc2F2ZSgpLG8uYmVnaW5QYXRoKCksby5yZWN0KHQsbixlLXQsci1uKSx0aGlzLnZpc3VhbHMuZmlsbC5zZXRfdmFsdWUobyksby5maWxsKCksdGhpcy52aXN1YWxzLmxpbmUuc2V0X3ZhbHVlKG8pLG8uc3Ryb2tlKCksby5yZXN0b3JlKCl9LGUucHJvdG90eXBlLl9jYWxjX2RpbT1mdW5jdGlvbih0LGUscil7dmFyIG47cmV0dXJuIG49bnVsbCE9dGhpcy5tZ2V0KHQpPyJkYXRhIj09PXRoaXMubWdldCh0KyJfdW5pdHMiKT9lLm1hcF90b190YXJnZXQodGhpcy5tZ2V0KHQpKTp0aGlzLm1nZXQodCk6cn0sZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWksZS5wcm90b3R5cGUudHlwZT0iQm94QW5ub3RhdGlvbiIsZS5taXhpbnMoWyJsaW5lIiwiZmlsbCJdKSxlLmRlZmluZSh7cmVuZGVyX21vZGU6W2EuUmVuZGVyTW9kZSwiY2FudmFzIl0seF9yYW5nZV9uYW1lOlthLlN0cmluZywiZGVmYXVsdCJdLHlfcmFuZ2VfbmFtZTpbYS5TdHJpbmcsImRlZmF1bHQiXSx0b3A6W2EuTnVtYmVyLG51bGxdLHRvcF91bml0czpbYS5TcGF0aWFsVW5pdHMsImRhdGEiXSxib3R0b206W2EuTnVtYmVyLG51bGxdLGJvdHRvbV91bml0czpbYS5TcGF0aWFsVW5pdHMsImRhdGEiXSxsZWZ0OlthLk51bWJlcixudWxsXSxsZWZ0X3VuaXRzOlthLlNwYXRpYWxVbml0cywiZGF0YSJdLHJpZ2h0OlthLk51bWJlcixudWxsXSxyaWdodF91bml0czpbYS5TcGF0aWFsVW5pdHMsImRhdGEiXX0pLGUub3ZlcnJpZGUoe2ZpbGxfY29sb3I6IiNmZmY5YmEiLGZpbGxfYWxwaGE6LjQsbGluZV9jb2xvcjoiI2NjY2NjYyIsbGluZV9hbHBoYTouM30pLGUucHJvdG90eXBlLnVwZGF0ZT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbztyZXR1cm4gcj10LmxlZnQsbj10LnJpZ2h0LG89dC50b3AsZT10LmJvdHRvbSx0aGlzLnNldCh7bGVmdDpyLHJpZ2h0Om4sdG9wOm8sYm90dG9tOmV9LHtzaWxlbnQ6ITB9KSx0aGlzLnRyaWdnZXIoImRhdGFfdXBkYXRlIil9LGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vYW5ub3RhdGlvbiI6Im1vZGVscy9hbm5vdGF0aW9ucy9hbm5vdGF0aW9uIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvYW5ub3RhdGlvbnMvY29sb3JfYmFyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5PWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl2LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHY9e30uaGFzT3duUHJvcGVydHk7Zj10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2Fubm90YXRpb24iKSxpPXQoIi4uL3RpY2tlcnMvYmFzaWNfdGlja2VyIiksbz10KCIuLi9mb3JtYXR0ZXJzL2Jhc2ljX3RpY2tfZm9ybWF0dGVyIiksaD10KCIuLi9tYXBwZXJzL2xpbmVhcl9jb2xvcl9tYXBwZXIiKSxjPXQoIi4uL21hcHBlcnMvbGluZWFyX21hcHBlciIpLHA9dCgiLi4vbWFwcGVycy9sb2dfbWFwcGVyIiksXz10KCIuLi9yYW5nZXMvcmFuZ2UxZCIpLG09dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksZz10KCIuLi8uLi9jb3JlL3V0aWwvdGV4dCIpLGQ9MjUsdT0uMyxsPS44LGE9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHkoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0KSx0aGlzLl9zZXRfY2FudmFzX2ltYWdlKCl9LGUucHJvdG90eXBlLmJpbmRfYm9rZWhfZXZlbnRzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiY2hhbmdlOnZpc2libGUiLHRoaXMucGxvdF92aWV3LnJlcXVlc3RfcmVuZGVyKSx0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwudGlja2VyLCJjaGFuZ2UiLHRoaXMucGxvdF92aWV3LnJlcXVlc3RfcmVuZGVyKSx0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwuZm9ybWF0dGVyLCJjaGFuZ2UiLHRoaXMucGxvdF92aWV3LnJlcXVlc3RfcmVuZGVyKSx0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwuY29sb3JfbWFwcGVyLCJjaGFuZ2UiLGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3NldF9jYW52YXNfaW1hZ2UoKSx0aGlzLnBsb3Rfdmlldy5yZXF1ZXN0X3JlbmRlcigpfSl9LGUucHJvdG90eXBlLl9nZXRfcGFuZWxfb2Zmc2V0PWZ1bmN0aW9uKCl7dmFyIHQsZTtyZXR1cm4gdD10aGlzLm1vZGVsLnBhbmVsLl9sZWZ0Ll92YWx1ZSxlPXRoaXMubW9kZWwucGFuZWwuX3RvcC5fdmFsdWUse3g6dCx5Oi1lfX0sZS5wcm90b3R5cGUuX2dldF9zaXplPWZ1bmN0aW9uKCl7dmFyIHQsZTtyZXR1cm4gdD10aGlzLmNvbXB1dGVfbGVnZW5kX2RpbWVuc2lvbnMoKSxlPXRoaXMubW9kZWwucGFuZWwuc2lkZSwiYWJvdmUiPT09ZXx8ImJlbG93Ij09PWU/dC5oZWlnaHQ6ImxlZnQiPT09ZXx8InJpZ2h0Ij09PWU/dC53aWR0aDp2b2lkIDB9LGUucHJvdG90eXBlLl9zZXRfY2FudmFzX2ltYWdlPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLHMsYSxsLHUsYyxwLF87c3dpdGNoKGE9dGhpcy5tb2RlbC5jb2xvcl9tYXBwZXIucGFsZXR0ZSwidmVydGljYWwiPT09dGhpcy5tb2RlbC5vcmllbnRhdGlvbiYmKGE9YS5zbGljZSgwKS5yZXZlcnNlKCkpLHRoaXMubW9kZWwub3JpZW50YXRpb24pe2Nhc2UidmVydGljYWwiOmw9WzEsYS5sZW5ndGhdLF89bFswXSxvPWxbMV07YnJlYWs7Y2FzZSJob3Jpem9udGFsIjp1PVthLmxlbmd0aCwxXSxfPXVbMF0sbz11WzFdfXJldHVybiByPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImNhbnZhcyIpLGM9W18sb10sci53aWR0aD1jWzBdLHIuaGVpZ2h0PWNbMV0saT1yLmdldENvbnRleHQoIjJkIikscz1pLmdldEltYWdlRGF0YSgwLDAsXyxvKSxuPW5ldyBoLk1vZGVsKHtwYWxldHRlOmF9KSx0PW4udl9tYXBfc2NyZWVuKGZ1bmN0aW9uKCl7cD1bXTtmb3IodmFyIHQ9MCxlPWEubGVuZ3RoOzA8PWU/dDxlOnQ+ZTswPD1lP3QrKzp0LS0pcC5wdXNoKHQpO3JldHVybiBwfS5hcHBseSh0aGlzKSksZT1uZXcgVWludDhDbGFtcGVkQXJyYXkodCkscy5kYXRhLnNldChlKSxpLnB1dEltYWdlRGF0YShzLDAsMCksdGhpcy5pbWFnZT1yfSxlLnByb3RvdHlwZS5jb21wdXRlX2xlZ2VuZF9kaW1lbnNpb25zPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLHMsYSxsLHU7c3dpdGNoKHQ9dGhpcy5tb2RlbC5fY29tcHV0ZWRfaW1hZ2VfZGltZW5zaW9ucygpLGE9W3QuaGVpZ2h0LHQud2lkdGhdLGU9YVswXSxyPWFbMV0sbj10aGlzLl9nZXRfbGFiZWxfZXh0ZW50KCksdT10aGlzLm1vZGVsLl90aXRsZV9leHRlbnQoKSxsPXRoaXMubW9kZWwuX3RpY2tfZXh0ZW50KCkscz10aGlzLm1vZGVsLnBhZGRpbmcsdGhpcy5tb2RlbC5vcmllbnRhdGlvbil7Y2FzZSJ2ZXJ0aWNhbCI6bz1lK3UrMipzLGk9citsK24rMipzO2JyZWFrO2Nhc2UiaG9yaXpvbnRhbCI6bz1lK3UrbCtuKzIqcyxpPXIrMipzfXJldHVybntoZWlnaHQ6byx3aWR0aDppfX0sZS5wcm90b3R5cGUuY29tcHV0ZV9sZWdlbmRfbG9jYXRpb249ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLGwsdSxoLGM7aWYoZT10aGlzLmNvbXB1dGVfbGVnZW5kX2RpbWVuc2lvbnMoKSxzPVtlLmhlaWdodCxlLndpZHRoXSxyPXNbMF0sbz1zWzFdLG49dGhpcy5tb2RlbC5tYXJnaW4saT10aGlzLm1vZGVsLmxvY2F0aW9uLHQ9dGhpcy5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJoX3JhbmdlIiksdT10aGlzLnBsb3Rfdmlldy5mcmFtZS5nZXQoInZfcmFuZ2UiKSxmLmlzU3RyaW5nKGkpKXN3aXRjaChpKXtjYXNlInRvcF9sZWZ0IjpoPXQuZ2V0KCJzdGFydCIpK24sYz11LmdldCgiZW5kIiktbjticmVhaztjYXNlInRvcF9jZW50ZXIiOmg9KHQuZ2V0KCJlbmQiKSt0LmdldCgic3RhcnQiKSkvMi1vLzIsYz11LmdldCgiZW5kIiktbjticmVhaztjYXNlInRvcF9yaWdodCI6aD10LmdldCgiZW5kIiktbi1vLGM9dS5nZXQoImVuZCIpLW47YnJlYWs7Y2FzZSJyaWdodF9jZW50ZXIiOmg9dC5nZXQoImVuZCIpLW4tbyxjPSh1LmdldCgiZW5kIikrdS5nZXQoInN0YXJ0IikpLzIrci8yO2JyZWFrO2Nhc2UiYm90dG9tX3JpZ2h0IjpoPXQuZ2V0KCJlbmQiKS1uLW8sYz11LmdldCgic3RhcnQiKStuK3I7YnJlYWs7Y2FzZSJib3R0b21fY2VudGVyIjpoPSh0LmdldCgiZW5kIikrdC5nZXQoInN0YXJ0IikpLzItby8yLGM9dS5nZXQoInN0YXJ0IikrbityO2JyZWFrO2Nhc2UiYm90dG9tX2xlZnQiOmg9dC5nZXQoInN0YXJ0IikrbixjPXUuZ2V0KCJzdGFydCIpK24rcjticmVhaztjYXNlImxlZnRfY2VudGVyIjpoPXQuZ2V0KCJzdGFydCIpK24sYz0odS5nZXQoImVuZCIpK3UuZ2V0KCJzdGFydCIpKS8yK3IvMjticmVhaztjYXNlImNlbnRlciI6aD0odC5nZXQoImVuZCIpK3QuZ2V0KCJzdGFydCIpKS8yLW8vMixjPSh1LmdldCgiZW5kIikrdS5nZXQoInN0YXJ0IikpLzIrci8yfWVsc2UgZi5pc0FycmF5KGkpJiYyPT09aS5sZW5ndGgmJihoPWlbMF0sYz1pWzFdKTtyZXR1cm4gYT10aGlzLnBsb3Rfdmlldy5jYW52YXMudnhfdG9fc3goaCksbD10aGlzLnBsb3Rfdmlldy5jYW52YXMudnlfdG9fc3koYykse3N4OmEsc3k6bH19LGUucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbigpe3ZhciB0LGUscixuLG87aWYodGhpcy5tb2RlbC52aXNpYmxlIT09ITEpcmV0dXJuIHQ9dGhpcy5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LHQuc2F2ZSgpLG51bGwhPXRoaXMubW9kZWwucGFuZWwmJihvPXRoaXMuX2dldF9wYW5lbF9vZmZzZXQoKSx0LnRyYW5zbGF0ZShvLngsby55KSxlPXRoaXMuX2dldF9mcmFtZV9vZmZzZXQoKSx0LnRyYW5zbGF0ZShlLngsZS55KSksbj10aGlzLmNvbXB1dGVfbGVnZW5kX2xvY2F0aW9uKCksdC50cmFuc2xhdGUobi5zeCxuLnN5KSx0aGlzLl9kcmF3X2Jib3godCkscj10aGlzLl9nZXRfaW1hZ2Vfb2Zmc2V0KCksdC50cmFuc2xhdGUoci54LHIueSksdGhpcy5fZHJhd19pbWFnZSh0KSxudWxsIT10aGlzLm1vZGVsLmNvbG9yX21hcHBlci5sb3cmJm51bGwhPXRoaXMubW9kZWwuY29sb3JfbWFwcGVyLmhpZ2gmJih0aGlzLl9kcmF3X21ham9yX3RpY2tzKHQpLHRoaXMuX2RyYXdfbWlub3JfdGlja3ModCksdGhpcy5fZHJhd19tYWpvcl9sYWJlbHModCkpLHRoaXMubW9kZWwudGl0bGUmJnRoaXMuX2RyYXdfdGl0bGUodCksdC5yZXN0b3JlKCl9LGUucHJvdG90eXBlLl9kcmF3X2Jib3g9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9dGhpcy5jb21wdXRlX2xlZ2VuZF9kaW1lbnNpb25zKCksdC5zYXZlKCksdGhpcy52aXN1YWxzLmJhY2tncm91bmRfZmlsbC5kb2l0JiYodGhpcy52aXN1YWxzLmJhY2tncm91bmRfZmlsbC5zZXRfdmFsdWUodCksdC5maWxsUmVjdCgwLDAsZS53aWR0aCxlLmhlaWdodCkpLHRoaXMudmlzdWFscy5ib3JkZXJfbGluZS5kb2l0JiYodGhpcy52aXN1YWxzLmJvcmRlcl9saW5lLnNldF92YWx1ZSh0KSx0LnN0cm9rZVJlY3QoMCwwLGUud2lkdGgsZS5oZWlnaHQpKSx0LnJlc3RvcmUoKX0sZS5wcm90b3R5cGUuX2RyYXdfaW1hZ2U9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9dGhpcy5tb2RlbC5fY29tcHV0ZWRfaW1hZ2VfZGltZW5zaW9ucygpLHQuc2F2ZSgpLHQuc2V0SW1hZ2VTbW9vdGhpbmdFbmFibGVkKCExKSx0Lmdsb2JhbEFscGhhPXRoaXMubW9kZWwuc2NhbGVfYWxwaGEsdC5kcmF3SW1hZ2UodGhpcy5pbWFnZSwwLDAsZS53aWR0aCxlLmhlaWdodCksdGhpcy52aXN1YWxzLmJhcl9saW5lLmRvaXQmJih0aGlzLnZpc3VhbHMuYmFyX2xpbmUuc2V0X3ZhbHVlKHQpLHQuc3Ryb2tlUmVjdCgwLDAsZS53aWR0aCxlLmhlaWdodCkpLHQucmVzdG9yZSgpfSxlLnByb3RvdHlwZS5fZHJhd19tYWpvcl90aWNrcz1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGY7aWYodGhpcy52aXN1YWxzLm1ham9yX3RpY2tfbGluZS5kb2l0KXtmb3Iocz10aGlzLm1vZGVsLl9ub3JtYWxzKCksbz1zWzBdLGk9c1sxXSxyPXRoaXMubW9kZWwuX2NvbXB1dGVkX2ltYWdlX2RpbWVuc2lvbnMoKSxhPVtyLndpZHRoKm8sci5oZWlnaHQqaV0sZD1hWzBdLGY9YVsxXSxsPXRoaXMubW9kZWwuX3RpY2tfY29vcmRpbmF0ZXMoKS5tYWpvcixoPWxbMF0sYz1sWzFdLHA9dGhpcy5tb2RlbC5tYWpvcl90aWNrX2luLF89dGhpcy5tb2RlbC5tYWpvcl90aWNrX291dCx0LnNhdmUoKSx0LnRyYW5zbGF0ZShkLGYpLHRoaXMudmlzdWFscy5tYWpvcl90aWNrX2xpbmUuc2V0X3ZhbHVlKHQpLGU9bj0wLHU9aC5sZW5ndGg7MDw9dT9uPHU6bj51O2U9MDw9dT8rK246LS1uKXQuYmVnaW5QYXRoKCksdC5tb3ZlVG8oTWF0aC5yb3VuZChoW2VdK28qXyksTWF0aC5yb3VuZChjW2VdK2kqXykpLHQubGluZVRvKE1hdGgucm91bmQoaFtlXS1vKnApLE1hdGgucm91bmQoY1tlXS1pKnApKSx0LnN0cm9rZSgpO3JldHVybiB0LnJlc3RvcmUoKX19LGUucHJvdG90eXBlLl9kcmF3X21pbm9yX3RpY2tzPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZjtpZih0aGlzLnZpc3VhbHMubWlub3JfdGlja19saW5lLmRvaXQpe2ZvcihzPXRoaXMubW9kZWwuX25vcm1hbHMoKSxvPXNbMF0saT1zWzFdLHI9dGhpcy5tb2RlbC5fY29tcHV0ZWRfaW1hZ2VfZGltZW5zaW9ucygpLGE9W3Iud2lkdGgqbyxyLmhlaWdodCppXSxkPWFbMF0sZj1hWzFdLGw9dGhpcy5tb2RlbC5fdGlja19jb29yZGluYXRlcygpLm1pbm9yLGg9bFswXSxjPWxbMV0scD10aGlzLm1vZGVsLm1pbm9yX3RpY2tfaW4sXz10aGlzLm1vZGVsLm1pbm9yX3RpY2tfb3V0LHQuc2F2ZSgpLHQudHJhbnNsYXRlKGQsZiksdGhpcy52aXN1YWxzLm1pbm9yX3RpY2tfbGluZS5zZXRfdmFsdWUodCksZT1uPTAsdT1oLmxlbmd0aDswPD11P248dTpuPnU7ZT0wPD11PysrbjotLW4pdC5iZWdpblBhdGgoKSx0Lm1vdmVUbyhNYXRoLnJvdW5kKGhbZV0rbypfKSxNYXRoLnJvdW5kKGNbZV0raSpfKSksdC5saW5lVG8oTWF0aC5yb3VuZChoW2VdLW8qcCksTWF0aC5yb3VuZChjW2VdLWkqcCkpLHQuc3Ryb2tlKCk7cmV0dXJuIHQucmVzdG9yZSgpfX0sZS5wcm90b3R5cGUuX2RyYXdfbWFqb3JfbGFiZWxzPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2O2lmKHRoaXMudmlzdWFscy5tYWpvcl9sYWJlbF90ZXh0LmRvaXQpe2ZvcihsPXRoaXMubW9kZWwuX25vcm1hbHMoKSxzPWxbMF0sYT1sWzFdLG49dGhpcy5tb2RlbC5fY29tcHV0ZWRfaW1hZ2VfZGltZW5zaW9ucygpLHU9W24ud2lkdGgqcyxuLmhlaWdodCphXSxtPXVbMF0seT11WzFdLF89dGhpcy5tb2RlbC5sYWJlbF9zdGFuZG9mZit0aGlzLm1vZGVsLl90aWNrX2V4dGVudCgpLGg9W18qcyxfKmFdLGc9aFswXSx2PWhbMV0sYz10aGlzLm1vZGVsLl90aWNrX2Nvb3JkaW5hdGVzKCkubWFqb3IsZD1jWzBdLGY9Y1sxXSxpPXRoaXMubW9kZWwuX3RpY2tfY29vcmRpbmF0ZXMoKS5tYWpvcl9sYWJlbHMsZT10aGlzLm1nZXQoImZvcm1hdHRlciIpLmRvRm9ybWF0KGkpLHRoaXMudmlzdWFscy5tYWpvcl9sYWJlbF90ZXh0LnNldF92YWx1ZSh0KSx0LnNhdmUoKSx0LnRyYW5zbGF0ZShtK2cseSt2KSxyPW89MCxwPWQubGVuZ3RoOzA8PXA/bzxwOm8+cDtyPTA8PXA/KytvOi0tbyl0LmZpbGxUZXh0KGVbcl0sTWF0aC5yb3VuZChkW3JdK3MqdGhpcy5tb2RlbC5sYWJlbF9zdGFuZG9mZiksTWF0aC5yb3VuZChmW3JdK2EqdGhpcy5tb2RlbC5sYWJlbF9zdGFuZG9mZikpO3JldHVybiB0LnJlc3RvcmUoKX19LGUucHJvdG90eXBlLl9kcmF3X3RpdGxlPWZ1bmN0aW9uKHQpe2lmKHRoaXMudmlzdWFscy50aXRsZV90ZXh0LmRvaXQpcmV0dXJuIHQuc2F2ZSgpLHRoaXMudmlzdWFscy50aXRsZV90ZXh0LnNldF92YWx1ZSh0KSx0LmZpbGxUZXh0KHRoaXMubW9kZWwudGl0bGUsMCwtdGhpcy5tb2RlbC50aXRsZV9zdGFuZG9mZiksdC5yZXN0b3JlKCl9LGUucHJvdG90eXBlLl9nZXRfbGFiZWxfZXh0ZW50PWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47aWYobnVsbCE9dGhpcy5tb2RlbC5jb2xvcl9tYXBwZXIubG93JiZudWxsIT10aGlzLm1vZGVsLmNvbG9yX21hcHBlci5oaWdoKXtzd2l0Y2godD10aGlzLnBsb3Rfdmlldy5jYW52YXNfdmlldy5jdHgsdC5zYXZlKCksdGhpcy52aXN1YWxzLm1ham9yX2xhYmVsX3RleHQuc2V0X3ZhbHVlKHQpLHRoaXMubW9kZWwub3JpZW50YXRpb24pe2Nhc2UidmVydGljYWwiOmU9dGhpcy5tb2RlbC5mb3JtYXR0ZXIuZG9Gb3JtYXQodGhpcy5tb2RlbC5fdGlja19jb29yZGluYXRlcygpLm1ham9yX2xhYmVscyksbj1mLm1heChmdW5jdGlvbigpe3ZhciBuLG8saTtmb3IoaT1bXSxuPTAsbz1lLmxlbmd0aDtuPG87bisrKXI9ZVtuXSxpLnB1c2godC5tZWFzdXJlVGV4dChyLnRvU3RyaW5nKCkpLndpZHRoKTtyZXR1cm4gaX0oKSk7YnJlYWs7Y2FzZSJob3Jpem9udGFsIjpuPWcuZ2V0X3RleHRfaGVpZ2h0KHRoaXMudmlzdWFscy5tYWpvcl9sYWJlbF90ZXh0LmZvbnRfdmFsdWUoKSkuaGVpZ2h0fW4rPXRoaXMubW9kZWwubGFiZWxfc3RhbmRvZmYsdC5yZXN0b3JlKCl9ZWxzZSBuPTA7cmV0dXJuIG59LGUucHJvdG90eXBlLl9nZXRfZnJhbWVfb2Zmc2V0PWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbztzd2l0Y2gocj1bMCwwXSxuPXJbMF0sbz1yWzFdLGU9dGhpcy5tb2RlbC5wYW5lbCx0PXRoaXMucGxvdF92aWV3LmZyYW1lLGUuc2lkZSl7Y2FzZSJsZWZ0IjpjYXNlInJpZ2h0IjpvPU1hdGguYWJzKGUuZ2V0KCJ0b3AiKS10LmdldCgidG9wIikpO2JyZWFrO2Nhc2UiYWJvdmUiOmNhc2UiYmVsb3ciOm49TWF0aC5hYnModC5nZXQoImxlZnQiKSl9cmV0dXJue3g6bix5Om99fSxlLnByb3RvdHlwZS5fZ2V0X2ltYWdlX29mZnNldD1mdW5jdGlvbigpe3ZhciB0LGU7cmV0dXJuIHQ9dGhpcy5tb2RlbC5wYWRkaW5nLGU9dGhpcy5tb2RlbC5wYWRkaW5nK3RoaXMubW9kZWwuX3RpdGxlX2V4dGVudCgpLHt4OnQseTplfX0sZX0obi5WaWV3KSxzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB5KGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWEsZS5wcm90b3R5cGUudHlwZT0iQ29sb3JCYXIiLGUubWl4aW5zKFsidGV4dDptYWpvcl9sYWJlbF8iLCJ0ZXh0OnRpdGxlXyIsImxpbmU6bWFqb3JfdGlja18iLCJsaW5lOm1pbm9yX3RpY2tfIiwibGluZTpib3JkZXJfIiwibGluZTpiYXJfIiwiZmlsbDpiYWNrZ3JvdW5kXyJdKSxlLmRlZmluZSh7bG9jYXRpb246W20uQW55LCJ0b3BfcmlnaHQiXSxvcmllbnRhdGlvbjpbbS5PcmllbnRhdGlvbiwidmVydGljYWwiXSx0aXRsZTpbbS5TdHJpbmddLHRpdGxlX3N0YW5kb2ZmOlttLk51bWJlciwyXSxoZWlnaHQ6W20uQW55LCJhdXRvIl0sd2lkdGg6W20uQW55LCJhdXRvIl0sc2NhbGVfYWxwaGE6W20uTnVtYmVyLDFdLHRpY2tlcjpbbS5JbnN0YW5jZSxmdW5jdGlvbigpe3JldHVybiBuZXcgaS5Nb2RlbH1dLGZvcm1hdHRlcjpbbS5JbnN0YW5jZSxmdW5jdGlvbigpe3JldHVybiBuZXcgby5Nb2RlbH1dLGNvbG9yX21hcHBlcjpbbS5JbnN0YW5jZV0sbGFiZWxfc3RhbmRvZmY6W20uTnVtYmVyLDVdLG1hcmdpbjpbbS5OdW1iZXIsMzBdLHBhZGRpbmc6W20uTnVtYmVyLDEwXSxtYWpvcl90aWNrX2luOlttLk51bWJlciw1XSxtYWpvcl90aWNrX291dDpbbS5OdW1iZXIsMF0sbWlub3JfdGlja19pbjpbbS5OdW1iZXIsMF0sbWlub3JfdGlja19vdXQ6W20uTnVtYmVyLDBdfSksZS5vdmVycmlkZSh7YmFja2dyb3VuZF9maWxsX2NvbG9yOiIjZmZmZmZmIixiYWNrZ3JvdW5kX2ZpbGxfYWxwaGE6Ljk1LGJhcl9saW5lX2NvbG9yOm51bGwsYm9yZGVyX2xpbmVfY29sb3I6bnVsbCxtYWpvcl9sYWJlbF90ZXh0X2FsaWduOiJjZW50ZXIiLG1ham9yX2xhYmVsX3RleHRfYmFzZWxpbmU6Im1pZGRsZSIsbWFqb3JfbGFiZWxfdGV4dF9mb250X3NpemU6IjhwdCIsbWFqb3JfdGlja19saW5lX2NvbG9yOiIjZmZmZmZmIixtaW5vcl90aWNrX2xpbmVfY29sb3I6bnVsbCx0aXRsZV90ZXh0X2ZvbnRfc2l6ZToiMTBwdCIsdGl0bGVfdGV4dF9mb250X3N0eWxlOiJpdGFsaWMifSksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0LHIpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0LHIpfSxlLnByb3RvdHlwZS5fbm9ybWFscz1mdW5jdGlvbigpe3ZhciB0LGUscixuO3JldHVybiJ2ZXJ0aWNhbCI9PT10aGlzLm9yaWVudGF0aW9uPyhyPVsxLDBdLHQ9clswXSxlPXJbMV0pOihuPVswLDFdLHQ9blswXSxlPW5bMV0pLFt0LGVdfSxlLnByb3RvdHlwZS5fdGl0bGVfZXh0ZW50PWZ1bmN0aW9uKCl7dmFyIHQsZTtyZXR1cm4gdD10aGlzLnRpdGxlX3RleHRfZm9udCsiICIrdGhpcy50aXRsZV90ZXh0X2ZvbnRfc2l6ZSsiICIrdGhpcy50aXRsZV90ZXh0X2ZvbnRfc3R5bGUsZT10aGlzLnRpdGxlP2cuZ2V0X3RleHRfaGVpZ2h0KHQpLmhlaWdodCt0aGlzLnRpdGxlX3N0YW5kb2ZmOjB9LGUucHJvdG90eXBlLl90aWNrX2V4dGVudD1mdW5jdGlvbigpe3ZhciB0O3JldHVybiB0PW51bGwhPXRoaXMuY29sb3JfbWFwcGVyLmxvdyYmbnVsbCE9dGhpcy5jb2xvcl9tYXBwZXIuaGlnaD9mLm1heChbdGhpcy5tYWpvcl90aWNrX291dCx0aGlzLm1pbm9yX3RpY2tfb3V0XSk6MH0sZS5wcm90b3R5cGUuX2NvbXB1dGVkX2ltYWdlX2RpbWVuc2lvbnM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvO3N3aXRjaCh0PXRoaXMucGxvdC5wbG90X2NhbnZhcy5mcmFtZS5nZXQoImhlaWdodCIpLGU9dGhpcy5wbG90LnBsb3RfY2FudmFzLmZyYW1lLmdldCgid2lkdGgiKSxuPXRoaXMuX3RpdGxlX2V4dGVudCgpLHRoaXMub3JpZW50YXRpb24pe2Nhc2UidmVydGljYWwiOiJhdXRvIj09PXRoaXMuaGVpZ2h0P251bGwhPXRoaXMucGFuZWw/cj10LTIqdGhpcy5wYWRkaW5nLW46KHI9Zi5tYXgoW3RoaXMuY29sb3JfbWFwcGVyLnBhbGV0dGUubGVuZ3RoKmQsdCp1XSkscj1mLm1pbihbcix0KmwtMip0aGlzLnBhZGRpbmctbl0pKTpyPXRoaXMuaGVpZ2h0LG89ImF1dG8iPT09dGhpcy53aWR0aD9kOnRoaXMud2lkdGg7YnJlYWs7Y2FzZSJob3Jpem9udGFsIjpyPSJhdXRvIj09PXRoaXMuaGVpZ2h0P2Q6dGhpcy5oZWlnaHQsImF1dG8iPT09dGhpcy53aWR0aD9udWxsIT10aGlzLnBhbmVsP289ZS0yKnRoaXMucGFkZGluZzoobz1mLm1heChbdGhpcy5jb2xvcl9tYXBwZXIucGFsZXR0ZS5sZW5ndGgqZCxlKnVdKSxvPWYubWluKFtvLGUqbC0yKnRoaXMucGFkZGluZ10pKTpvPXRoaXMud2lkdGh9cmV0dXJue2hlaWdodDpyLHdpZHRoOm99fSxlLnByb3RvdHlwZS5fdGlja19jb29yZGluYXRlX21hcHBlcj1mdW5jdGlvbih0KXt2YXIgZSxyO3N3aXRjaChyPXtzb3VyY2VfcmFuZ2U6bmV3IF8uTW9kZWwoe3N0YXJ0OnRoaXMuY29sb3JfbWFwcGVyLmxvdyxlbmQ6dGhpcy5jb2xvcl9tYXBwZXIuaGlnaH0pLHRhcmdldF9yYW5nZTpuZXcgXy5Nb2RlbCh7c3RhcnQ6MCxlbmQ6dH0pfSx0aGlzLmNvbG9yX21hcHBlci50eXBlKXtjYXNlIkxpbmVhckNvbG9yTWFwcGVyIjplPW5ldyBjLk1vZGVsKHIpO2JyZWFrO2Nhc2UiTG9nQ29sb3JNYXBwZXIiOmU9bmV3IHAuTW9kZWwocil9cmV0dXJuIGV9LGUucHJvdG90eXBlLl90aWNrX2Nvb3JkaW5hdGVzPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiO3N3aXRjaChvPXRoaXMuX2NvbXB1dGVkX2ltYWdlX2RpbWVuc2lvbnMoKSx0aGlzLm9yaWVudGF0aW9uKXtjYXNlInZlcnRpY2FsIjp5PW8uaGVpZ2h0O2JyZWFrO2Nhc2UiaG9yaXpvbnRhbCI6eT1vLndpZHRofWZvcihjPXRoaXMuX3RpY2tfY29vcmRpbmF0ZV9tYXBwZXIoeSksZD10aGlzLl9ub3JtYWxzKCkscj1kWzBdLGk9ZFsxXSxmPVt0aGlzLmNvbG9yX21hcHBlci5sb3csdGhpcy5jb2xvcl9tYXBwZXIuaGlnaF0sdj1mWzBdLGU9ZlsxXSxiPXRoaXMudGlja2VyLmdldF90aWNrcyh2LGUsbnVsbCx0aGlzLnRpY2tlci5kZXNpcmVkX251bV90aWNrcyksaD1iLm1ham9yLF89Yi5taW5vcixsPVtbXSxbXV0scD1bW10sW11dLG49cz0wLG09aC5sZW5ndGg7MDw9bT9zPG06cz5tO249MDw9bT8rK3M6LS1zKWhbbl08dnx8aFtuXT5lfHwobFtyXS5wdXNoKGhbbl0pLGxbaV0ucHVzaCgwKSk7Zm9yKG49YT0wLGc9Xy5sZW5ndGg7MDw9Zz9hPGc6YT5nO249MDw9Zz8rK2E6LS1hKV9bbl08dnx8X1tuXT5lfHwocFtyXS5wdXNoKF9bbl0pLHBbaV0ucHVzaCgwKSk7cmV0dXJuIHU9bFtyXS5zbGljZSgwKSxsW3JdPWMudl9tYXBfdG9fdGFyZ2V0KGxbcl0pLHBbcl09Yy52X21hcF90b190YXJnZXQocFtyXSksInZlcnRpY2FsIj09PXRoaXMub3JpZW50YXRpb24mJihsW3JdPW5ldyBGbG9hdDY0QXJyYXkoZnVuY3Rpb24oKXt2YXIgZSxuLG8saTtmb3Iobz1sW3JdLGk9W10sbj0wLGU9by5sZW5ndGg7bjxlO24rKyl0PW9bbl0saS5wdXNoKHktdCk7cmV0dXJuIGl9KCkpLHBbcl09bmV3IEZsb2F0NjRBcnJheShmdW5jdGlvbigpe3ZhciBlLG4sbyxpO2ZvcihvPXBbcl0saT1bXSxuPTAsZT1vLmxlbmd0aDtuPGU7bisrKXQ9b1tuXSxpLnB1c2goeS10KTtyZXR1cm4gaX0oKSkpLHttYWpvcjpsLG1pbm9yOnAsbWFqb3JfbGFiZWxzOnV9fSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOnMsVmlldzphfX0seyIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi9jb3JlL3V0aWwvdGV4dCI6ImNvcmUvdXRpbC90ZXh0IiwiLi4vZm9ybWF0dGVycy9iYXNpY190aWNrX2Zvcm1hdHRlciI6Im1vZGVscy9mb3JtYXR0ZXJzL2Jhc2ljX3RpY2tfZm9ybWF0dGVyIiwiLi4vbWFwcGVycy9saW5lYXJfY29sb3JfbWFwcGVyIjoibW9kZWxzL21hcHBlcnMvbGluZWFyX2NvbG9yX21hcHBlciIsIi4uL21hcHBlcnMvbGluZWFyX21hcHBlciI6Im1vZGVscy9tYXBwZXJzL2xpbmVhcl9tYXBwZXIiLCIuLi9tYXBwZXJzL2xvZ19tYXBwZXIiOiJtb2RlbHMvbWFwcGVycy9sb2dfbWFwcGVyIiwiLi4vcmFuZ2VzL3JhbmdlMWQiOiJtb2RlbHMvcmFuZ2VzL3JhbmdlMWQiLCIuLi90aWNrZXJzL2Jhc2ljX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL2Jhc2ljX3RpY2tlciIsIi4vYW5ub3RhdGlvbiI6Im1vZGVscy9hbm5vdGF0aW9ucy9hbm5vdGF0aW9uIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvYW5ub3RhdGlvbnMvbGFiZWwiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpbC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxsPXt9Lmhhc093blByb3BlcnR5O2k9dCgiLi90ZXh0X2Fubm90YXRpb24iKSxzPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGEoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3ZhciByLG4sbyxpO2UuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMuY2FudmFzPXRoaXMucGxvdF9tb2RlbC5nZXQoImNhbnZhcyIpLHRoaXMueG1hcHBlcj10aGlzLnBsb3Rfdmlldy5mcmFtZS5nZXQoInhfbWFwcGVycyIpW3RoaXMubWdldCgieF9yYW5nZV9uYW1lIildLHRoaXMueW1hcHBlcj10aGlzLnBsb3Rfdmlldy5mcmFtZS5nZXQoInlfbWFwcGVycyIpW3RoaXMubWdldCgieV9yYW5nZV9uYW1lIildLG89dGhpcy52aXN1YWxzLGk9W107Zm9yKHIgaW4gbyluPW9bcl0saS5wdXNoKG4ud2FybV9jYWNoZShudWxsKSk7cmV0dXJuIGl9LGUucHJvdG90eXBlLl9nZXRfc2l6ZT1mdW5jdGlvbigpe3ZhciB0LGUscixuO3JldHVybiB0PXRoaXMucGxvdF92aWV3LmNhbnZhc192aWV3LmN0eCx0aGlzLnZpc3VhbHMudGV4dC5zZXRfdmFsdWUodCkscj10aGlzLm1vZGVsLnBhbmVsLnNpZGUsImFib3ZlIj09PXJ8fCJiZWxvdyI9PT1yP2U9dC5tZWFzdXJlVGV4dCh0aGlzLm1nZXQoInRleHQiKSkuYXNjZW50OiJsZWZ0Ij09PXJ8fCJyaWdodCI9PT1yP249dC5tZWFzdXJlVGV4dCh0aGlzLm1nZXQoInRleHQiKSkud2lkdGg6dm9pZCAwfSxlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscztzd2l0Y2goZT10aGlzLnBsb3Rfdmlldy5jYW52YXNfdmlldy5jdHgsdGhpcy5tZ2V0KCJhbmdsZV91bml0cyIpKXtjYXNlInJhZCI6dD0tMSp0aGlzLm1nZXQoImFuZ2xlIik7YnJlYWs7Y2FzZSJkZWciOnQ9LTEqdGhpcy5tZ2V0KCJhbmdsZSIpKk1hdGguUEkvMTgwfXJldHVybiBpPSJkYXRhIj09PXRoaXMubWdldCgieF91bml0cyIpP3RoaXMueG1hcHBlci5tYXBfdG9fdGFyZ2V0KHRoaXMubWdldCgieCIpKTp0aGlzLm1nZXQoIngiKSxuPXRoaXMuY2FudmFzLnZ4X3RvX3N4KGkpLHM9ImRhdGEiPT09dGhpcy5tZ2V0KCJ5X3VuaXRzIik/dGhpcy55bWFwcGVyLm1hcF90b190YXJnZXQodGhpcy5tZ2V0KCJ5IikpOnRoaXMubWdldCgieSIpLG89dGhpcy5jYW52YXMudnlfdG9fc3kocyksbnVsbCE9dGhpcy5tb2RlbC5wYW5lbCYmKHI9dGhpcy5fZ2V0X3BhbmVsX29mZnNldCgpLG4rPXIueCxvKz1yLnkpLCJjYW52YXMiPT09dGhpcy5tZ2V0KCJyZW5kZXJfbW9kZSIpP3RoaXMuX2NhbnZhc190ZXh0KGUsdGhpcy5tZ2V0KCJ0ZXh0Iiksbit0aGlzLm1nZXQoInhfb2Zmc2V0Iiksby10aGlzLm1nZXQoInlfb2Zmc2V0IiksdCk6dGhpcy5fY3NzX3RleHQoZSx0aGlzLm1nZXQoInRleHQiKSxuK3RoaXMubWdldCgieF9vZmZzZXQiKSxvLXRoaXMubWdldCgieV9vZmZzZXQiKSx0KX0sZX0oaS5WaWV3KSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PW8sZS5wcm90b3R5cGUudHlwZT0iTGFiZWwiLGUubWl4aW5zKFsidGV4dCIsImxpbmU6Ym9yZGVyXyIsImZpbGw6YmFja2dyb3VuZF8iXSksZS5kZWZpbmUoe3g6W3MuTnVtYmVyXSx4X3VuaXRzOltzLlNwYXRpYWxVbml0cywiZGF0YSJdLHk6W3MuTnVtYmVyXSx5X3VuaXRzOltzLlNwYXRpYWxVbml0cywiZGF0YSJdLHRleHQ6W3MuU3RyaW5nXSxhbmdsZTpbcy5BbmdsZSwwXSxhbmdsZV91bml0czpbcy5BbmdsZVVuaXRzLCJyYWQiXSx4X29mZnNldDpbcy5OdW1iZXIsMF0seV9vZmZzZXQ6W3MuTnVtYmVyLDBdLHhfcmFuZ2VfbmFtZTpbcy5TdHJpbmcsImRlZmF1bHQiXSx5X3JhbmdlX25hbWU6W3MuU3RyaW5nLCJkZWZhdWx0Il0scmVuZGVyX21vZGU6W3MuUmVuZGVyTW9kZSwiY2FudmFzIl19KSxlLm92ZXJyaWRlKHtiYWNrZ3JvdW5kX2ZpbGxfY29sb3I6bnVsbCxib3JkZXJfbGluZV9jb2xvcjpudWxsfSksZX0oaS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpuLFZpZXc6b319LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi90ZXh0X2Fubm90YXRpb24iOiJtb2RlbHMvYW5ub3RhdGlvbnMvdGV4dF9hbm5vdGF0aW9uIn1dLCJtb2RlbHMvYW5ub3RhdGlvbnMvbGFiZWxfc2V0IjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGg9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWMuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sYz17fS5oYXNPd25Qcm9wZXJ0eTtsPXQoInVuZGVyc2NvcmUiKSxuPXQoImpxdWVyeSIpLGE9dCgiLi90ZXh0X2Fubm90YXRpb24iKSxvPXQoIi4uL3NvdXJjZXMvY29sdW1uX2RhdGFfc291cmNlIiksdT10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBoKGUsdCksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXt2YXIgcixvLGkscztpZihlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0KSx0aGlzLnhtYXBwZXI9dGhpcy5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJ4X21hcHBlcnMiKVt0aGlzLm1vZGVsLnhfcmFuZ2VfbmFtZV0sdGhpcy55bWFwcGVyPXRoaXMucGxvdF92aWV3LmZyYW1lLmdldCgieV9tYXBwZXJzIilbdGhpcy5tb2RlbC55X3JhbmdlX25hbWVdLHRoaXMuc2V0X2RhdGEoKSwiY3NzIj09PXRoaXMubW9kZWwucmVuZGVyX21vZGUpe2ZvcihzPVtdLHI9bz0wLGk9dGhpcy5fdGV4dC5sZW5ndGg7MDw9aT9vPGk6bz5pO3I9MDw9aT8rK286LS1vKXRoaXMudGl0bGVfZGl2PW4oIjxkaXY+IikuYWRkQ2xhc3MoImJrLWFubm90YXRpb24tY2hpbGQiKS5oaWRlKCksCnMucHVzaCh0aGlzLnRpdGxlX2Rpdi5hcHBlbmRUbyh0aGlzLiRlbCkpO3JldHVybiBzfX0sZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXtyZXR1cm4iY3NzIj09PXRoaXMubW9kZWwucmVuZGVyX21vZGU/KHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiY2hhbmdlIixmdW5jdGlvbigpe3JldHVybiB0aGlzLnNldF9kYXRhKCksdGhpcy5yZW5kZXIoKX0pLHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbC5zb3VyY2UsImNoYW5nZSIsZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zZXRfZGF0YSgpLHRoaXMucmVuZGVyKCl9KSk6KHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiY2hhbmdlIixmdW5jdGlvbigpe3JldHVybiB0aGlzLnNldF9kYXRhKCksdGhpcy5wbG90X3ZpZXcucmVxdWVzdF9yZW5kZXIoKX0pLHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbC5zb3VyY2UsImNoYW5nZSIsZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zZXRfZGF0YSgpLHRoaXMucGxvdF92aWV3LnJlcXVlc3RfcmVuZGVyKCl9KSl9LGUucHJvdG90eXBlLnNldF9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIGUuX19zdXBlcl9fLnNldF9kYXRhLmNhbGwodGhpcyx0aGlzLm1vZGVsLnNvdXJjZSksdGhpcy5zZXRfdmlzdWFscyh0aGlzLm1vZGVsLnNvdXJjZSl9LGUucHJvdG90eXBlLl9tYXBfZGF0YT1mdW5jdGlvbigpe3ZhciB0LGUscixuO3JldHVybiByPSJkYXRhIj09PXRoaXMubW9kZWwueF91bml0cz90aGlzLnhtYXBwZXIudl9tYXBfdG9fdGFyZ2V0KHRoaXMuX3gpOnRoaXMuX3guc2xpY2UoMCksdD10aGlzLmNhbnZhcy52X3Z4X3RvX3N4KHIpLG49ImRhdGEiPT09dGhpcy5tb2RlbC55X3VuaXRzP3RoaXMueW1hcHBlci52X21hcF90b190YXJnZXQodGhpcy5feSk6dGhpcy5feS5zbGljZSgwKSxlPXRoaXMuY2FudmFzLnZfdnlfdG9fc3kobiksW3QsZV19LGUucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbigpe3ZhciB0LGUscixuLG8saSxzLGEsbCx1LGg7aWYodD10aGlzLnBsb3Rfdmlldy5jYW52YXNfdmlldy5jdHgsbz10aGlzLl9tYXBfZGF0YSgpLHU9b1swXSxoPW9bMV0sImNhbnZhcyI9PT10aGlzLm1vZGVsLnJlbmRlcl9tb2RlKXtmb3IoYT1bXSxlPXI9MCxpPXRoaXMuX3RleHQubGVuZ3RoOzA8PWk/cjxpOnI+aTtlPTA8PWk/KytyOi0tcilhLnB1c2godGhpcy5fdl9jYW52YXNfdGV4dCh0LGUsdGhpcy5fdGV4dFtlXSx1W2VdK3RoaXMuX3hfb2Zmc2V0W2VdLGhbZV0tdGhpcy5feV9vZmZzZXRbZV0sdGhpcy5fYW5nbGVbZV0pKTtyZXR1cm4gYX1mb3IobD1bXSxlPW49MCxzPXRoaXMuX3RleHQubGVuZ3RoOzA8PXM/bjxzOm4+cztlPTA8PXM/KytuOi0tbilsLnB1c2godGhpcy5fdl9jc3NfdGV4dCh0LGUsdGhpcy5fdGV4dFtlXSx1W2VdK3RoaXMuX3hfb2Zmc2V0W2VdLGhbZV0tdGhpcy5feV9vZmZzZXRbZV0sdGhpcy5fYW5nbGVbZV0pKTtyZXR1cm4gbH0sZS5wcm90b3R5cGUuX2dldF9zaXplPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47cmV0dXJuIHQ9dGhpcy5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LHRoaXMudmlzdWFscy50ZXh0LnNldF92YWx1ZSh0KSxyPXRoaXMubW9kZWwucGFuZWwuc2lkZSwiYWJvdmUiPT09cnx8ImJlbG93Ij09PXI/ZT10Lm1lYXN1cmVUZXh0KHRoaXMuX3RleHRbMF0pLmFzY2VudDoibGVmdCI9PT1yfHwicmlnaHQiPT09cj9uPXQubWVhc3VyZVRleHQodGhpcy5fdGV4dFswXSkud2lkdGg6dm9pZCAwfSxlLnByb3RvdHlwZS5fdl9jYW52YXNfdGV4dD1mdW5jdGlvbih0LGUscixuLG8saSl7dmFyIHM7cmV0dXJuIHRoaXMudmlzdWFscy50ZXh0LnNldF92ZWN0b3JpemUodCxlKSxzPXRoaXMuX2NhbGN1bGF0ZV9ib3VuZGluZ19ib3hfZGltZW5zaW9ucyh0LHIpLHQuc2F2ZSgpLHQuYmVnaW5QYXRoKCksdC50cmFuc2xhdGUobixvKSx0LnJvdGF0ZShpKSx0LnJlY3Qoc1swXSxzWzFdLHNbMl0sc1szXSksdGhpcy52aXN1YWxzLmJhY2tncm91bmRfZmlsbC5kb2l0JiYodGhpcy52aXN1YWxzLmJhY2tncm91bmRfZmlsbC5zZXRfdmVjdG9yaXplKHQsZSksdC5maWxsKCkpLHRoaXMudmlzdWFscy5ib3JkZXJfbGluZS5kb2l0JiYodGhpcy52aXN1YWxzLmJvcmRlcl9saW5lLnNldF92ZWN0b3JpemUodCxlKSx0LnN0cm9rZSgpKSx0aGlzLnZpc3VhbHMudGV4dC5kb2l0JiYodGhpcy52aXN1YWxzLnRleHQuc2V0X3ZlY3Rvcml6ZSh0LGUpLHQuZmlsbFRleHQociwwLDApKSx0LnJlc3RvcmUoKX0sZS5wcm90b3R5cGUuX3ZfY3NzX3RleHQ9ZnVuY3Rpb24odCxlLHIsbixvLGkpe3ZhciBzLGEsdSxoO3JldHVybiB0aGlzLnZpc3VhbHMudGV4dC5zZXRfdmVjdG9yaXplKHQsZSkscz10aGlzLl9jYWxjdWxhdGVfYm91bmRpbmdfYm94X2RpbWVuc2lvbnModCxyKSx1PXRoaXMudmlzdWFscy5ib3JkZXJfbGluZS5saW5lX2Rhc2gudmFsdWUoKSxsLmlzQXJyYXkodSkmJihoPXUubGVuZ3RoPDI/InNvbGlkIjoiZGFzaGVkIiksbC5pc1N0cmluZyh1KSYmKGg9dSksdGhpcy52aXN1YWxzLmJvcmRlcl9saW5lLnNldF92ZWN0b3JpemUodCxlKSx0aGlzLnZpc3VhbHMuYmFja2dyb3VuZF9maWxsLnNldF92ZWN0b3JpemUodCxlKSxhPXtwb3NpdGlvbjoiYWJzb2x1dGUiLGxlZnQ6bitzWzBdKyJweCIsdG9wOm8rc1sxXSsicHgiLGNvbG9yOiIiK3RoaXMudmlzdWFscy50ZXh0LnRleHRfY29sb3IudmFsdWUoKSxvcGFjaXR5OiIiK3RoaXMudmlzdWFscy50ZXh0LnRleHRfYWxwaGEudmFsdWUoKSxmb250OiIiK3RoaXMudmlzdWFscy50ZXh0LmZvbnRfdmFsdWUoKSwibGluZS1oZWlnaHQiOiJub3JtYWwifSxpJiZsLmV4dGVuZChhLHt0cmFuc2Zvcm06InJvdGF0ZSgiK2krInJhZCkifSksdGhpcy52aXN1YWxzLmJhY2tncm91bmRfZmlsbC5kb2l0JiZsLmV4dGVuZChhLHsiYmFja2dyb3VuZC1jb2xvciI6IiIrdGhpcy52aXN1YWxzLmJhY2tncm91bmRfZmlsbC5jb2xvcl92YWx1ZSgpfSksdGhpcy52aXN1YWxzLmJvcmRlcl9saW5lLmRvaXQmJmwuZXh0ZW5kKGEseyJib3JkZXItc3R5bGUiOiIiK2gsImJvcmRlci13aWR0aCI6IiIrdGhpcy52aXN1YWxzLmJvcmRlcl9saW5lLmxpbmVfd2lkdGgudmFsdWUoKSwiYm9yZGVyLWNvbG9yIjoiIit0aGlzLnZpc3VhbHMuYm9yZGVyX2xpbmUuY29sb3JfdmFsdWUoKX0pLHRoaXMuJGVsLmNoaWxkcmVuKCkuZXEoZSkuaHRtbChyKS5jc3MoYSkuc2hvdygpfSxlfShhLlZpZXcpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9cyxlLnByb3RvdHlwZS50eXBlPSJMYWJlbCIsZS5taXhpbnMoWyJ0ZXh0IiwibGluZTpib3JkZXJfIiwiZmlsbDpiYWNrZ3JvdW5kXyJdKSxlLmNvb3JkcyhbWyJ4IiwieSJdXSksZS5kZWZpbmUoe3hfdW5pdHM6W3UuU3BhdGlhbFVuaXRzLCJkYXRhIl0seV91bml0czpbdS5TcGF0aWFsVW5pdHMsImRhdGEiXSx0ZXh0Olt1LlN0cmluZ1NwZWMse2ZpZWxkOiJ0ZXh0In1dLGFuZ2xlOlt1LkFuZ2xlU3BlYywwXSx4X29mZnNldDpbdS5OdW1iZXJTcGVjLHt2YWx1ZTowfV0seV9vZmZzZXQ6W3UuTnVtYmVyU3BlYyx7dmFsdWU6MH1dLHNvdXJjZTpbdS5JbnN0YW5jZSxmdW5jdGlvbigpe3JldHVybiBuZXcgby5Nb2RlbH1dLHhfcmFuZ2VfbmFtZTpbdS5TdHJpbmcsImRlZmF1bHQiXSx5X3JhbmdlX25hbWU6W3UuU3RyaW5nLCJkZWZhdWx0Il0scmVuZGVyX21vZGU6W3UuUmVuZGVyTW9kZSwiY2FudmFzIl19KSxlLm92ZXJyaWRlKHtiYWNrZ3JvdW5kX2ZpbGxfY29sb3I6bnVsbCxib3JkZXJfbGluZV9jb2xvcjpudWxsfSksZX0oYS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDppLFZpZXc6c319LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vc291cmNlcy9jb2x1bW5fZGF0YV9zb3VyY2UiOiJtb2RlbHMvc291cmNlcy9jb2x1bW5fZGF0YV9zb3VyY2UiLCIuL3RleHRfYW5ub3RhdGlvbiI6Im1vZGVscy9hbm5vdGF0aW9ucy90ZXh0X2Fubm90YXRpb24iLGpxdWVyeToianF1ZXJ5Iix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvYW5ub3RhdGlvbnMvbGVnZW5kIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1PWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSloLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGg9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2Fubm90YXRpb24iKSxsPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGE9dCgiLi4vLi4vY29yZS91dGlsL3RleHQiKS5nZXRfdGV4dF9oZWlnaHQsaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCl7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpfSxlLnByb3RvdHlwZS5jb21wdXRlX2xlZ2VuZF9iYm94PWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0sayxqLFQ7Zm9yKGQ9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbyxpO2ZvcihyPXRoaXMubWdldCgibGVnZW5kcyIpLGk9W10sdD0wLGU9ci5sZW5ndGg7dDxlO3QrKylvPXJbdF0sXz1vWzBdLG49b1sxXSxpLnB1c2goXyk7cmV0dXJuIGl9LmNhbGwodGhpcyksZT10aGlzLm1nZXQoImdseXBoX2hlaWdodCIpLHI9dGhpcy5tZ2V0KCJnbHlwaF93aWR0aCIpLGw9dGhpcy5tZ2V0KCJsYWJlbF9oZWlnaHQiKSxoPXRoaXMubWdldCgibGFiZWxfd2lkdGgiKSx0aGlzLm1heF9sYWJlbF9oZWlnaHQ9cy5tYXgoW2EodGhpcy52aXN1YWxzLmxhYmVsX3RleHQuZm9udF92YWx1ZSgpKS5oZWlnaHQsbCxlXSksdD10aGlzLnBsb3Rfdmlldy5jYW52YXNfdmlldy5jdHgsdC5zYXZlKCksdGhpcy52aXN1YWxzLmxhYmVsX3RleHQuc2V0X3ZhbHVlKHQpLHRoaXMudGV4dF93aWR0aHM9e30saT0wLHk9ZC5sZW5ndGg7aTx5O2krKyl4PWRbaV0sdGhpcy50ZXh0X3dpZHRoc1t4XT1zLm1heChbdC5tZWFzdXJlVGV4dCh4KS53aWR0aCxoXSk7aWYodC5yZXN0b3JlKCksYj1zLm1heChzLnZhbHVlcyh0aGlzLnRleHRfd2lkdGhzKSkscD10aGlzLm1nZXQoImxlZ2VuZF9tYXJnaW4iKSxmPXRoaXMubWdldCgibGVnZW5kX3BhZGRpbmciKSxtPXRoaXMubWdldCgibGVnZW5kX3NwYWNpbmciKSx1PXRoaXMubWdldCgibGFiZWxfc3RhbmRvZmYiKSwidmVydGljYWwiPT09dGhpcy5tZ2V0KCJvcmllbnRhdGlvbiIpKWM9ZC5sZW5ndGgqdGhpcy5tYXhfbGFiZWxfaGVpZ2h0KyhkLmxlbmd0aC0xKSptKzIqZixnPWIrcit1KzIqZjtlbHNle2c9MipmKyhkLmxlbmd0aC0xKSptLHc9dGhpcy50ZXh0X3dpZHRocztmb3IoeCBpbiB3KWs9d1t4XSxnKz1zLm1heChbayxoXSkrcit1O2M9dGhpcy5tYXhfbGFiZWxfaGVpZ2h0KzIqZn1pZih2PXRoaXMubWdldCgibG9jYXRpb24iKSxvPXRoaXMucGxvdF92aWV3LmZyYW1lLmdldCgiaF9yYW5nZSIpLE09dGhpcy5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJ2X3JhbmdlIikscy5pc1N0cmluZyh2KSlzd2l0Y2godil7Y2FzZSJ0b3BfbGVmdCI6aj1vLmdldCgic3RhcnQiKStwLFQ9TS5nZXQoImVuZCIpLXA7YnJlYWs7Y2FzZSJ0b3BfY2VudGVyIjpqPShvLmdldCgiZW5kIikrby5nZXQoInN0YXJ0IikpLzItZy8yLFQ9TS5nZXQoImVuZCIpLXA7YnJlYWs7Y2FzZSJ0b3BfcmlnaHQiOmo9by5nZXQoImVuZCIpLXAtZyxUPU0uZ2V0KCJlbmQiKS1wO2JyZWFrO2Nhc2UicmlnaHRfY2VudGVyIjpqPW8uZ2V0KCJlbmQiKS1wLWcsVD0oTS5nZXQoImVuZCIpK00uZ2V0KCJzdGFydCIpKS8yK2MvMjticmVhaztjYXNlImJvdHRvbV9yaWdodCI6aj1vLmdldCgiZW5kIiktcC1nLFQ9TS5nZXQoInN0YXJ0IikrcCtjO2JyZWFrO2Nhc2UiYm90dG9tX2NlbnRlciI6aj0oby5nZXQoImVuZCIpK28uZ2V0KCJzdGFydCIpKS8yLWcvMixUPU0uZ2V0KCJzdGFydCIpK3ArYzticmVhaztjYXNlImJvdHRvbV9sZWZ0IjpqPW8uZ2V0KCJzdGFydCIpK3AsVD1NLmdldCgic3RhcnQiKStwK2M7YnJlYWs7Y2FzZSJsZWZ0X2NlbnRlciI6aj1vLmdldCgic3RhcnQiKStwLFQ9KE0uZ2V0KCJlbmQiKStNLmdldCgic3RhcnQiKSkvMitjLzI7YnJlYWs7Y2FzZSJjZW50ZXIiOmo9KG8uZ2V0KCJlbmQiKStvLmdldCgic3RhcnQiKSkvMi1nLzIsVD0oTS5nZXQoImVuZCIpK00uZ2V0KCJzdGFydCIpKS8yK2MvMn1lbHNlIHMuaXNBcnJheSh2KSYmMj09PXYubGVuZ3RoJiYoaj12WzBdLFQ9dlsxXSk7cmV0dXJuIGo9dGhpcy5wbG90X3ZpZXcuY2FudmFzLnZ4X3RvX3N4KGopLFQ9dGhpcy5wbG90X3ZpZXcuY2FudmFzLnZ5X3RvX3N5KFQpLHt4OmoseTpULHdpZHRoOmcsaGVpZ2h0OmN9fSxlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0sayxqO2lmKDAhPT10aGlzLm1vZGVsLmxlZ2VuZHMubGVuZ3RoKXtmb3IoZT10aGlzLmNvbXB1dGVfbGVnZW5kX2Jib3goKSxuPXRoaXMubWdldCgiZ2x5cGhfaGVpZ2h0Iiksbz10aGlzLm1nZXQoImdseXBoX3dpZHRoIiksZD10aGlzLm1nZXQoIm9yaWVudGF0aW9uIikscj10aGlzLnBsb3Rfdmlldy5jYW52YXNfdmlldy5jdHgsci5zYXZlKCksbnVsbCE9dGhpcy5tb2RlbC5wYW5lbCYmKGY9dGhpcy5fZ2V0X3BhbmVsX29mZnNldCgpLHIudHJhbnNsYXRlKGYueCxmLnkpKSxyLmJlZ2luUGF0aCgpLHIucmVjdChlLngsZS55LGUud2lkdGgsZS5oZWlnaHQpLHRoaXMudmlzdWFscy5iYWNrZ3JvdW5kX2ZpbGwuc2V0X3ZhbHVlKHIpLHIuZmlsbCgpLHRoaXMudmlzdWFscy5ib3JkZXJfbGluZS5kb2l0JiYodGhpcy52aXN1YWxzLmJvcmRlcl9saW5lLnNldF92YWx1ZShyKSxyLnN0cm9rZSgpKSx0PXRoaXMubWdldCgibGVnZW5kcyIpLmxlbmd0aCxjPXRoaXMubWdldCgibGVnZW5kX3NwYWNpbmciKSx1PXRoaXMubWdldCgibGFiZWxfc3RhbmRvZmYiKSx3PWo9dGhpcy5tZ2V0KCJsZWdlbmRfcGFkZGluZyIpLG09dGhpcy5tZ2V0KCJsZWdlbmRzIiksYT1zPTAscD1tLmxlbmd0aDtzPHA7YT0rK3MpZm9yKGc9bVthXSxoPWdbMF0saT1nWzFdLGI9ZS54K3csTT1lLnkraix4PWIrbyxrPU0rbiwidmVydGljYWwiPT09ZD9qKz10aGlzLm1heF9sYWJlbF9oZWlnaHQrYzp3Kz10aGlzLnRleHRfd2lkdGhzW2hdK28rdStjLHRoaXMudmlzdWFscy5sYWJlbF90ZXh0LnNldF92YWx1ZShyKSxyLmZpbGxUZXh0KGgseCt1LE0rdGhpcy5tYXhfbGFiZWxfaGVpZ2h0LzIpLGw9MCxfPWkubGVuZ3RoO2w8XztsKyspeT1pW2xdLHY9dGhpcy5wbG90X3ZpZXcucmVuZGVyZXJfdmlld3NbeS5pZF0sdi5kcmF3X2xlZ2VuZChyLGIseCxNLGspO3JldHVybiByLnJlc3RvcmUoKX19LGUucHJvdG90eXBlLl9nZXRfc2l6ZT1mdW5jdGlvbigpe3ZhciB0LGU7cmV0dXJuIHQ9dGhpcy5jb21wdXRlX2xlZ2VuZF9iYm94KCksZT10aGlzLm1vZGVsLnBhbmVsLnNpZGUsImFib3ZlIj09PWV8fCJiZWxvdyI9PT1lP3QuaGVpZ2h0OiJsZWZ0Ij09PWV8fCJyaWdodCI9PT1lP3Qud2lkdGg6dm9pZCAwfSxlLnByb3RvdHlwZS5fZ2V0X3BhbmVsX29mZnNldD1mdW5jdGlvbigpe3ZhciB0LGU7cmV0dXJuIHQ9dGhpcy5tb2RlbC5wYW5lbC5fbGVmdC5fdmFsdWUsZT10aGlzLm1vZGVsLnBhbmVsLl90b3AuX3ZhbHVlLHt4OnQseTotZX19LGV9KG4uVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLnR5cGU9IkxlZ2VuZCIsZS5taXhpbnMoWyJ0ZXh0OmxhYmVsXyIsImxpbmU6Ym9yZGVyXyIsImZpbGw6YmFja2dyb3VuZF8iXSksZS5kZWZpbmUoe2xlZ2VuZHM6W2wuQXJyYXksW11dLG9yaWVudGF0aW9uOltsLk9yaWVudGF0aW9uLCJ2ZXJ0aWNhbCJdLGxvY2F0aW9uOltsLkFueSwidG9wX3JpZ2h0Il0sbGFiZWxfc3RhbmRvZmY6W2wuTnVtYmVyLDVdLGdseXBoX2hlaWdodDpbbC5OdW1iZXIsMjBdLGdseXBoX3dpZHRoOltsLk51bWJlciwyMF0sbGFiZWxfaGVpZ2h0OltsLk51bWJlciwyMF0sbGFiZWxfd2lkdGg6W2wuTnVtYmVyLDIwXSxsZWdlbmRfbWFyZ2luOltsLk51bWJlciwxMF0sbGVnZW5kX3BhZGRpbmc6W2wuTnVtYmVyLDEwXSxsZWdlbmRfc3BhY2luZzpbbC5OdW1iZXIsM119KSxlLm92ZXJyaWRlKHtib3JkZXJfbGluZV9jb2xvcjoiI2U1ZTVlNSIsYm9yZGVyX2xpbmVfYWxwaGE6LjUsYm9yZGVyX2xpbmVfd2lkdGg6MSxiYWNrZ3JvdW5kX2ZpbGxfY29sb3I6IiNmZmZmZmYiLGJhY2tncm91bmRfZmlsbF9hbHBoYTouOTUsbGFiZWxfdGV4dF9mb250X3NpemU6IjEwcHQiLGxhYmVsX3RleHRfYmFzZWxpbmU6Im1pZGRsZSJ9KSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzppfX0seyIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi9jb3JlL3V0aWwvdGV4dCI6ImNvcmUvdXRpbC90ZXh0IiwiLi9hbm5vdGF0aW9uIjoibW9kZWxzL2Fubm90YXRpb25zL2Fubm90YXRpb24iLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9hbm5vdGF0aW9ucy9wb2x5X2Fubm90YXRpb24iOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl1LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHU9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2Fubm90YXRpb24iKSxhPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS5iaW5kX2Jva2VoX2V2ZW50cz1mdW5jdGlvbigpe3JldHVybiB0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZSIsdGhpcy5wbG90X3ZpZXcucmVxdWVzdF9yZW5kZXIpLHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiZGF0YV91cGRhdGUiLHRoaXMucGxvdF92aWV3LnJlcXVlc3RfcmVuZGVyKX0sZS5wcm90b3R5cGUucmVuZGVyPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGwsdSxoO2lmKHU9dGhpcy5tZ2V0KCJ4cyIpLGg9dGhpcy5tZ2V0KCJ5cyIpLHUubGVuZ3RoIT09aC5sZW5ndGgpcmV0dXJuIG51bGw7aWYodS5sZW5ndGg8M3x8aC5sZW5ndGg8MylyZXR1cm4gbnVsbDtmb3IoZT10aGlzLnBsb3Rfdmlldy5jYW52YXMsdD10aGlzLnBsb3Rfdmlldy5jYW52YXNfdmlldy5jdHgscj1uPTAsbz11Lmxlbmd0aDswPD1vP248bzpuPm87cj0wPD1vPysrbjotLW4pInNjcmVlbiI9PT10aGlzLm1nZXQoInhzX3VuaXRzIikmJihhPXVbcl0pLCJzY3JlZW4iPT09dGhpcy5tZ2V0KCJ5c191bml0cyIpJiYobD1oW3JdKSxpPWUudnhfdG9fc3goYSkscz1lLnZ5X3RvX3N5KGwpLDA9PT1yPyh0LmJlZ2luUGF0aCgpLHQubW92ZVRvKGkscykpOnQubGluZVRvKGkscyk7cmV0dXJuIHQuY2xvc2VQYXRoKCksdGhpcy52aXN1YWxzLmxpbmUuZG9pdCYmKHRoaXMudmlzdWFscy5saW5lLnNldF92YWx1ZSh0KSx0LnN0cm9rZSgpKSx0aGlzLnZpc3VhbHMuZmlsbC5kb2l0Pyh0aGlzLnZpc3VhbHMuZmlsbC5zZXRfdmFsdWUodCksdC5maWxsKCkpOnZvaWQgMH0sZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWksZS5wcm90b3R5cGUudHlwZT0iUG9seUFubm90YXRpb24iLGUubWl4aW5zKFsibGluZSIsImZpbGwiXSksZS5kZWZpbmUoe3hzOlthLkFycmF5LFtdXSx4c191bml0czpbYS5TcGF0aWFsVW5pdHMsImRhdGEiXSx5czpbYS5BcnJheSxbXV0seXNfdW5pdHM6W2EuU3BhdGlhbFVuaXRzLCJkYXRhIl0seF9yYW5nZV9uYW1lOlthLlN0cmluZywiZGVmYXVsdCJdLHlfcmFuZ2VfbmFtZTpbYS5TdHJpbmcsImRlZmF1bHQiXX0pLGUub3ZlcnJpZGUoe2ZpbGxfY29sb3I6IiNmZmY5YmEiLGZpbGxfYWxwaGE6LjQsbGluZV9jb2xvcjoiI2NjY2NjYyIsbGluZV9hbHBoYTouM30pLGUucHJvdG90eXBlLnVwZGF0ZT1mdW5jdGlvbih0KXt2YXIgZSxyO3JldHVybiBlPXQueHMscj10LnlzLHRoaXMuc2V0KHt4czplLHlzOnJ9LHtzaWxlbnQ6ITB9KSx0aGlzLnRyaWdnZXIoImRhdGFfdXBkYXRlIil9LGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vYW5ub3RhdGlvbiI6Im1vZGVscy9hbm5vdGF0aW9ucy9hbm5vdGF0aW9uIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvYW5ub3RhdGlvbnMvc3BhbiI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXUuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sdT17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vYW5ub3RhdGlvbiIpLGE9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCl7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMuJGVsLmFwcGVuZFRvKHRoaXMucGxvdF92aWV3LiRlbC5maW5kKCJkaXYuYmstY2FudmFzLW92ZXJsYXlzIikpLHRoaXMuJGVsLmNzcyh7cG9zaXRpb246ImFic29sdXRlIn0pLHRoaXMuJGVsLmhpZGUoKX0sZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tZ2V0KCJmb3JfaG92ZXIiKT90aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZTpjb21wdXRlZF9sb2NhdGlvbiIsdGhpcy5fZHJhd19zcGFuKToiY2FudmFzIj09PXRoaXMubWdldCgicmVuZGVyX21vZGUiKT90aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZTpsb2NhdGlvbiIsdGhpcy5wbG90X3ZpZXcucmVxdWVzdF9yZW5kZXIpOnRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiY2hhbmdlOmxvY2F0aW9uIix0aGlzLl9kcmF3X3NwYW4pfSxlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZHJhd19zcGFuKCl9LGUucHJvdG90eXBlLl9kcmF3X3NwYW49ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLGwsdTtyZXR1cm4gbz10aGlzLm1nZXQoImZvcl9ob3ZlciIpP3RoaXMubWdldCgiY29tcHV0ZWRfbG9jYXRpb24iKTp0aGlzLm1nZXQoImxvY2F0aW9uIiksbnVsbD09bz92b2lkIHRoaXMuJGVsLmhpZGUoKToocj10aGlzLnBsb3RfbW9kZWwuZ2V0KCJmcmFtZSIpLHQ9dGhpcy5wbG90X21vZGVsLmdldCgiY2FudmFzIiksbD10aGlzLnBsb3Rfdmlldy5mcmFtZS5nZXQoInhfbWFwcGVycyIpW3RoaXMubWdldCgieF9yYW5nZV9uYW1lIildLHU9dGhpcy5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJ5X21hcHBlcnMiKVt0aGlzLm1nZXQoInlfcmFuZ2VfbmFtZSIpXSwid2lkdGgiPT09dGhpcy5tZ2V0KCJkaW1lbnNpb24iKT8ocz10LnZ5X3RvX3N5KHRoaXMuX2NhbGNfZGltKG8sdSkpLGk9dC52eF90b19zeChyLmdldCgibGVmdCIpKSxhPXIuZ2V0KCJ3aWR0aCIpLG49dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLmxpbmVfd2lkdGgudmFsdWUoKSk6KHM9dC52eV90b19zeShyLmdldCgidG9wIikpLGk9dC52eF90b19zeCh0aGlzLl9jYWxjX2RpbShvLGwpKSxhPXRoaXMubW9kZWwucHJvcGVydGllcy5saW5lX3dpZHRoLnZhbHVlKCksbj1yLmdldCgiaGVpZ2h0IikpLCJjc3MiPT09dGhpcy5tZ2V0KCJyZW5kZXJfbW9kZSIpPyh0aGlzLiRlbC5jc3Moe3RvcDpzLGxlZnQ6aSx3aWR0aDphKyJweCIsaGVpZ2h0Om4rInB4Iiwiei1pbmRleCI6MWUzLCJiYWNrZ3JvdW5kLWNvbG9yIjp0aGlzLm1vZGVsLnByb3BlcnRpZXMubGluZV9jb2xvci52YWx1ZSgpLG9wYWNpdHk6dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLmxpbmVfYWxwaGEudmFsdWUoKX0pLHRoaXMuJGVsLnNob3coKSk6ImNhbnZhcyI9PT10aGlzLm1nZXQoInJlbmRlcl9tb2RlIik/KGU9dGhpcy5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LGUuc2F2ZSgpLGUuYmVnaW5QYXRoKCksdGhpcy52aXN1YWxzLmxpbmUuc2V0X3ZhbHVlKGUpLGUubW92ZVRvKGkscyksIndpZHRoIj09PXRoaXMubWdldCgiZGltZW5zaW9uIik/ZS5saW5lVG8oaSthLHMpOmUubGluZVRvKGkscytuKSxlLnN0cm9rZSgpLGUucmVzdG9yZSgpKTp2b2lkIDApfSxlLnByb3RvdHlwZS5fY2FsY19kaW09ZnVuY3Rpb24odCxlKXt2YXIgcjtyZXR1cm4gcj0iZGF0YSI9PT10aGlzLm1nZXQoImxvY2F0aW9uX3VuaXRzIik/ZS5tYXBfdG9fdGFyZ2V0KHQpOnR9LGV9KG4uVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLnR5cGU9IlNwYW4iLGUubWl4aW5zKFsibGluZSJdKSxlLmRlZmluZSh7cmVuZGVyX21vZGU6W2EuUmVuZGVyTW9kZSwiY2FudmFzIl0seF9yYW5nZV9uYW1lOlthLlN0cmluZywiZGVmYXVsdCJdLHlfcmFuZ2VfbmFtZTpbYS5TdHJpbmcsImRlZmF1bHQiXSxsb2NhdGlvbjpbYS5OdW1iZXIsbnVsbF0sbG9jYXRpb25fdW5pdHM6W2EuU3BhdGlhbFVuaXRzLCJkYXRhIl0sZGltZW5zaW9uOlthLkRpbWVuc2lvbiwid2lkdGgiXX0pLGUub3ZlcnJpZGUoe2xpbmVfY29sb3I6ImJsYWNrIn0pLGUuaW50ZXJuYWwoe2Zvcl9ob3ZlcjpbYS5Cb29sZWFuLCExXSxjb21wdXRlZF9sb2NhdGlvbjpbYS5OdW1iZXIsbnVsbF19KSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzppfX0seyIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuL2Fubm90YXRpb24iOiJtb2RlbHMvYW5ub3RhdGlvbnMvYW5ub3RhdGlvbiIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2Fubm90YXRpb25zL3RleHRfYW5ub3RhdGlvbiI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpaC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxoPXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLG49dCgiLi9hbm5vdGF0aW9uIiksbD10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxhPXQoIi4uLy4uL2NvcmUvdXRpbC90ZXh0IikuZ2V0X3RleHRfaGVpZ2h0LGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHUoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe2lmKGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMuY2FudmFzPXRoaXMucGxvdF9tb2RlbC5nZXQoImNhbnZhcyIpLHRoaXMuZnJhbWU9dGhpcy5wbG90X21vZGVsLmdldCgiZnJhbWUiKSwiY3NzIj09PXRoaXMubWdldCgicmVuZGVyX21vZGUiKSlyZXR1cm4gdGhpcy4kZWwuYWRkQ2xhc3MoImJrLWFubm90YXRpb24iKSx0aGlzLiRlbC5hcHBlbmRUbyh0aGlzLnBsb3Rfdmlldy4kZWwuZmluZCgiZGl2LmJrLWNhbnZhcy1vdmVybGF5cyIpKX0sZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXtyZXR1cm4iY3NzIj09PXRoaXMubWdldCgicmVuZGVyX21vZGUiKT90aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZSIsdGhpcy5yZW5kZXIpOnRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiY2hhbmdlIix0aGlzLnBsb3Rfdmlldy5yZXF1ZXN0X3JlbmRlcil9LGUucHJvdG90eXBlLl9jYWxjdWxhdGVfdGV4dF9kaW1lbnNpb25zPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbjtyZXR1cm4gbj10Lm1lYXN1cmVUZXh0KGUpLndpZHRoLHI9YSh0aGlzLnZpc3VhbHMudGV4dC5mb250X3ZhbHVlKCkpLmhlaWdodCxbbixyXX0sZS5wcm90b3R5cGUuX2NhbGN1bGF0ZV9ib3VuZGluZ19ib3hfZGltZW5zaW9ucz1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpLHM7c3dpdGNoKG49dGhpcy5fY2FsY3VsYXRlX3RleHRfZGltZW5zaW9ucyh0LGUpLG89blswXSxyPW5bMV0sdC50ZXh0QWxpZ24pe2Nhc2UibGVmdCI6aT0wO2JyZWFrO2Nhc2UiY2VudGVyIjppPS1vLzI7YnJlYWs7Y2FzZSJyaWdodCI6aT0tb31zd2l0Y2godC50ZXh0QmFzZWxpbmUpe2Nhc2UidG9wIjpzPTA7YnJlYWs7Y2FzZSJtaWRkbGUiOnM9LS41KnI7YnJlYWs7Y2FzZSJib3R0b20iOnM9LTEqcjticmVhaztjYXNlImFscGhhYmV0aWMiOnM9LS44KnI7YnJlYWs7Y2FzZSJoYW5naW5nIjpzPS0uMTcqcjticmVhaztjYXNlImlkZW9ncmFwaGljIjpzPS0uODMqcn1yZXR1cm5baSxzLG8scl19LGUucHJvdG90eXBlLl9nZXRfc2l6ZT1mdW5jdGlvbigpe3ZhciB0O3JldHVybiB0PXRoaXMucGxvdF92aWV3LmNhbnZhc192aWV3LmN0eCx0aGlzLnZpc3VhbHMudGV4dC5zZXRfdmFsdWUodCksdC5tZWFzdXJlVGV4dCh0aGlzLm1nZXQoInRleHQiKSkuYXNjZW50fSxlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH0sZS5wcm90b3R5cGUuX2NhbnZhc190ZXh0PWZ1bmN0aW9uKHQsZSxyLG4sbyl7dmFyIGk7cmV0dXJuIHRoaXMudmlzdWFscy50ZXh0LnNldF92YWx1ZSh0KSxpPXRoaXMuX2NhbGN1bGF0ZV9ib3VuZGluZ19ib3hfZGltZW5zaW9ucyh0LGUpLHQuc2F2ZSgpLHQuYmVnaW5QYXRoKCksdC50cmFuc2xhdGUocixuKSxvJiZ0LnJvdGF0ZShvKSx0LnJlY3QoaVswXSxpWzFdLGlbMl0saVszXSksdGhpcy52aXN1YWxzLmJhY2tncm91bmRfZmlsbC5kb2l0JiYodGhpcy52aXN1YWxzLmJhY2tncm91bmRfZmlsbC5zZXRfdmFsdWUodCksdC5maWxsKCkpLHRoaXMudmlzdWFscy5ib3JkZXJfbGluZS5kb2l0JiYodGhpcy52aXN1YWxzLmJvcmRlcl9saW5lLnNldF92YWx1ZSh0KSx0LnN0cm9rZSgpKSx0aGlzLnZpc3VhbHMudGV4dC5kb2l0JiYodGhpcy52aXN1YWxzLnRleHQuc2V0X3ZhbHVlKHQpLHQuZmlsbFRleHQoZSwwLDApKSx0LnJlc3RvcmUoKX0sZS5wcm90b3R5cGUuX2Nzc190ZXh0PWZ1bmN0aW9uKHQsZSxyLG4sbyl7dmFyIGksYSxsLHU7cmV0dXJuIHRoaXMuJGVsLmhpZGUoKSx0aGlzLnZpc3VhbHMudGV4dC5zZXRfdmFsdWUodCksaT10aGlzLl9jYWxjdWxhdGVfYm91bmRpbmdfYm94X2RpbWVuc2lvbnModCxlKSxsPXRoaXMudmlzdWFscy5ib3JkZXJfbGluZS5saW5lX2Rhc2gudmFsdWUoKSxzLmlzQXJyYXkobCkmJih1PWwubGVuZ3RoPDI/InNvbGlkIjoiZGFzaGVkIikscy5pc1N0cmluZyhsKSYmKHU9bCksdGhpcy52aXN1YWxzLmJvcmRlcl9saW5lLnNldF92YWx1ZSh0KSx0aGlzLnZpc3VhbHMuYmFja2dyb3VuZF9maWxsLnNldF92YWx1ZSh0KSxhPXtwb3NpdGlvbjoiYWJzb2x1dGUiLGxlZnQ6citpWzBdKyJweCIsdG9wOm4raVsxXSsicHgiLGNvbG9yOiIiK3RoaXMudmlzdWFscy50ZXh0LnRleHRfY29sb3IudmFsdWUoKSxvcGFjaXR5OiIiK3RoaXMudmlzdWFscy50ZXh0LnRleHRfYWxwaGEudmFsdWUoKSxmb250OiIiK3RoaXMudmlzdWFscy50ZXh0LmZvbnRfdmFsdWUoKSwibGluZS1oZWlnaHQiOiJub3JtYWwifSxvJiZzLmV4dGVuZChhLHt0cmFuc2Zvcm06InJvdGF0ZSgiK28rInJhZCkifSksdGhpcy52aXN1YWxzLmJhY2tncm91bmRfZmlsbC5kb2l0JiZzLmV4dGVuZChhLHsiYmFja2dyb3VuZC1jb2xvciI6IiIrdGhpcy52aXN1YWxzLmJhY2tncm91bmRfZmlsbC5jb2xvcl92YWx1ZSgpfSksdGhpcy52aXN1YWxzLmJvcmRlcl9saW5lLmRvaXQmJnMuZXh0ZW5kKGEseyJib3JkZXItc3R5bGUiOiIiK3UsImJvcmRlci13aWR0aCI6IiIrdGhpcy52aXN1YWxzLmJvcmRlcl9saW5lLmxpbmVfd2lkdGgudmFsdWUoKSwiYm9yZGVyLWNvbG9yIjoiIit0aGlzLnZpc3VhbHMuYm9yZGVyX2xpbmUuY29sb3JfdmFsdWUoKX0pLHRoaXMuJGVsLmh0bWwoZSkuY3NzKGEpLnNob3coKX0sZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5wcm90b3R5cGUudHlwZT0iVGV4dEFubm90YXRpb24iLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4uLy4uL2NvcmUvdXRpbC90ZXh0IjoiY29yZS91dGlsL3RleHQiLCIuL2Fubm90YXRpb24iOiJtb2RlbHMvYW5ub3RhdGlvbnMvYW5ub3RhdGlvbiIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2Fubm90YXRpb25zL3RpdGxlIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpdS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSx1PXt9Lmhhc093blByb3BlcnR5O249dCgiLi90ZXh0X2Fubm90YXRpb24iKSxhPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLHM9dCgiLi4vcmVuZGVyZXJzL3JlbmRlcmVyIikuVmlzdWFscyxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXt2YXIgcjtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy52aXN1YWxzLnRleHQ9bmV3IHMudGV4dCh7b2JqOnRoaXMubW9kZWwscHJlZml4OiIifSkscj10aGlzLnBsb3Rfdmlldy5jYW52YXNfdmlldy5jdHgsci5zYXZlKCksdGhpcy5tb2RlbC5wYW5lbC5hcHBseV9sYWJlbF90ZXh0X2hldXJpc3RpY3MociwianVzdGlmaWVkIiksdGhpcy5tb2RlbC50ZXh0X2Jhc2VsaW5lPXIudGV4dEJhc2VsaW5lLHRoaXMubW9kZWwudGV4dF9hbGlnbj10aGlzLm1vZGVsLmFsaWduLHIucmVzdG9yZSgpfSxlLnByb3RvdHlwZS5fZ2V0X2NvbXB1dGVkX2xvY2F0aW9uPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLHM7c3dpdGNoKGU9dGhpcy5fY2FsY3VsYXRlX3RleHRfZGltZW5zaW9ucyh0aGlzLnBsb3Rfdmlldy5jYW52YXNfdmlldy5jdHgsdGhpcy50ZXh0KSxzPWVbMF0sdD1lWzFdLHRoaXMubW9kZWwucGFuZWwuc2lkZSl7Y2FzZSJsZWZ0IjpvPTAsaT10aGlzLl9nZXRfdGV4dF9sb2NhdGlvbih0aGlzLm1nZXQoImFsaWduIiksdGhpcy5mcmFtZS5nZXQoInZfcmFuZ2UiKSkrdGhpcy5tZ2V0KCJvZmZzZXQiKTticmVhaztjYXNlInJpZ2h0IjpvPXRoaXMuY2FudmFzLmdldCgicmlnaHQiKS0xLGk9dGhpcy5jYW52YXMuZ2V0KCJoZWlnaHQiKS10aGlzLl9nZXRfdGV4dF9sb2NhdGlvbih0aGlzLm1nZXQoImFsaWduIiksdGhpcy5mcmFtZS5nZXQoInZfcmFuZ2UiKSktdGhpcy5tZ2V0KCJvZmZzZXQiKTticmVhaztjYXNlImFib3ZlIjpvPXRoaXMuX2dldF90ZXh0X2xvY2F0aW9uKHRoaXMubWdldCgiYWxpZ24iKSx0aGlzLmZyYW1lLmdldCgiaF9yYW5nZSIpKSt0aGlzLm1nZXQoIm9mZnNldCIpLGk9dGhpcy5jYW52YXMuZ2V0KCJ0b3AiKS0xMDticmVhaztjYXNlImJlbG93IjpvPXRoaXMuX2dldF90ZXh0X2xvY2F0aW9uKHRoaXMubWdldCgiYWxpZ24iKSx0aGlzLmZyYW1lLmdldCgiaF9yYW5nZSIpKSt0aGlzLm1nZXQoIm9mZnNldCIpLGk9MH1yZXR1cm4gcj10aGlzLmNhbnZhcy52eF90b19zeChvKSxuPXRoaXMuY2FudmFzLnZ5X3RvX3N5KGkpLFtyLG5dfSxlLnByb3RvdHlwZS5fZ2V0X3RleHRfbG9jYXRpb249ZnVuY3Rpb24odCxlKXt2YXIgcjtzd2l0Y2godCl7Y2FzZSJsZWZ0IjpyPWUuZ2V0KCJzdGFydCIpO2JyZWFrO2Nhc2UiY2VudGVyIjpyPShlLmdldCgiZW5kIikrZS5nZXQoInN0YXJ0IikpLzI7YnJlYWs7Y2FzZSJyaWdodCI6cj1lLmdldCgiZW5kIil9cmV0dXJuIHJ9LGUucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbigpe3ZhciB0LGUscixuLG87aWYodD10aGlzLm1vZGVsLnBhbmVsLmdldF9sYWJlbF9hbmdsZV9oZXVyaXN0aWMoInBhcmFsbGVsIikscj10aGlzLl9nZXRfY29tcHV0ZWRfbG9jYXRpb24oKSxuPXJbMF0sbz1yWzFdLGU9dGhpcy5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LCIiIT09dGhpcy5tb2RlbC50ZXh0JiZudWxsIT09dGhpcy5tb2RlbC50ZXh0KXJldHVybiJjYW52YXMiPT09dGhpcy5tb2RlbC5yZW5kZXJfbW9kZT90aGlzLl9jYW52YXNfdGV4dChlLHRoaXMubW9kZWwudGV4dCxuLG8sdCk6dGhpcy5fY3NzX3RleHQoZSx0aGlzLm1vZGVsLnRleHQsbixvLHQpfSxlLnByb3RvdHlwZS5fZ2V0X3NpemU9ZnVuY3Rpb24oKXt2YXIgdCxlO3JldHVybiBlPXRoaXMubW9kZWwudGV4dCwiIj09PWV8fG51bGw9PT1lPzA6KHQ9dGhpcy5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LHRoaXMudmlzdWFscy50ZXh0LnNldF92YWx1ZSh0KSx0Lm1lYXN1cmVUZXh0KGUpLmFzY2VudCsxMCl9LGV9KG4uVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLnR5cGU9IlRpdGxlIixlLm1peGlucyhbImxpbmU6Ym9yZGVyXyIsImZpbGw6YmFja2dyb3VuZF8iXSksZS5kZWZpbmUoe3RleHQ6W2EuU3RyaW5nXSx0ZXh0X2ZvbnQ6W2EuRm9udCwiaGVsdmV0aWNhIl0sdGV4dF9mb250X3NpemU6W2EuRm9udFNpemVTcGVjLCIxMHB0Il0sdGV4dF9mb250X3N0eWxlOlthLkZvbnRTdHlsZSwiYm9sZCJdLHRleHRfY29sb3I6W2EuQ29sb3JTcGVjLCIjNDQ0NDQ0Il0sdGV4dF9hbHBoYTpbYS5OdW1iZXJTcGVjLDFdLGFsaWduOlthLlRleHRBbGlnbiwibGVmdCJdLG9mZnNldDpbYS5OdW1iZXIsMF0scmVuZGVyX21vZGU6W2EuUmVuZGVyTW9kZSwiY2FudmFzIl19KSxlLm92ZXJyaWRlKHtiYWNrZ3JvdW5kX2ZpbGxfY29sb3I6bnVsbCxib3JkZXJfbGluZV9jb2xvcjpudWxsfSksZS5pbnRlcm5hbCh7dGV4dF9hbGlnbjpbYS5UZXh0QWxpZ24sImxlZnQiXSx0ZXh0X2Jhc2VsaW5lOlthLlRleHRCYXNlbGluZSwiYm90dG9tIl19KSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzppfX0seyIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi9yZW5kZXJlcnMvcmVuZGVyZXIiOiJtb2RlbHMvcmVuZGVyZXJzL3JlbmRlcmVyIiwiLi90ZXh0X2Fubm90YXRpb24iOiJtb2RlbHMvYW5ub3RhdGlvbnMvdGV4dF9hbm5vdGF0aW9uIn1dLCJtb2RlbHMvYW5ub3RhdGlvbnMvdG9vbHRpcCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7bj10KCJqcXVlcnkiKSxhPXQoInVuZGVyc2NvcmUiKSxvPXQoIi4vYW5ub3RhdGlvbiIpLGw9dCgiLi4vLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLHU9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIikscz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLmNsYXNzTmFtZT0iYmstdG9vbHRpcCIsZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy4kZWwuYXBwZW5kVG8odGhpcy5wbG90X3ZpZXcuJGVsLmZpbmQoImRpdi5iay1jYW52YXMtb3ZlcmxheXMiKSksdGhpcy4kZWwuY3NzKHsiei1pbmRleCI6MTAxMH0pLHRoaXMuJGVsLmhpZGUoKX0sZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5saXN0ZW5Ubyh0aGlzLm1vZGVsLCJjaGFuZ2U6ZGF0YSIsdGhpcy5fZHJhd190aXBzKX0sZS5wcm90b3R5cGUucmVuZGVyPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2RyYXdfdGlwcygpfSxlLnByb3RvdHlwZS5fZHJhd190aXBzPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG8saSxzLGwsdSxoLGMscCxfLGQsZixtLGcseSx2O2lmKGk9dGhpcy5tb2RlbC5kYXRhLHRoaXMuJGVsLmVtcHR5KCksdGhpcy4kZWwuaGlkZSgpLHRoaXMuJGVsLnRvZ2dsZUNsYXNzKCJiay10b29sdGlwLWN1c3RvbSIsdGhpcy5tZ2V0KCJjdXN0b20iKSksIWEuaXNFbXB0eShpKSl7Zm9yKGw9MCxoPWkubGVuZ3RoO2w8aDtsKyspbT1pW2xdLGc9bVswXSx5PW1bMV0sbz1tWzJdLHRoaXMubWdldCgiaW5uZXJfb25seSIpJiYhdGhpcy5wbG90X3ZpZXcuZnJhbWUuY29udGFpbnMoZyx5KXx8KGQ9bigiPGRpdiAvPiIpLmFwcGVuZFRvKHRoaXMuJGVsKSxkLmFwcGVuZChvKSk7c3dpdGNoKHA9dGhpcy5wbG90X3ZpZXcubWdldCgiY2FudmFzIikudnhfdG9fc3goZyksXz10aGlzLnBsb3Rfdmlldy5tZ2V0KCJjYW52YXMiKS52eV90b19zeSh5KSxlPXRoaXMubW9kZWwuYXR0YWNobWVudCl7Y2FzZSJob3Jpem9udGFsIjp2PXRoaXMucGxvdF92aWV3LmZyYW1lLmdldCgid2lkdGgiKSx1PXRoaXMucGxvdF92aWV3LmZyYW1lLmdldCgibGVmdCIpLGM9Zy11PHYvMj8icmlnaHQiOiJsZWZ0IjticmVhaztjYXNlInZlcnRpY2FsIjpzPXRoaXMucGxvdF92aWV3LmZyYW1lLmdldCgiaGVpZ2h0Iikscj10aGlzLnBsb3Rfdmlldy5mcmFtZS5nZXQoImJvdHRvbSIpLGM9eS1yPHMvMj8iYmVsb3ciOiJhYm92ZSI7YnJlYWs7ZGVmYXVsdDpjPWV9c3dpdGNoKHRoaXMuJGVsLnJlbW92ZUNsYXNzKCJiay1yaWdodCBiay1sZWZ0IGJrLWFib3ZlIGJrLWJlbG93IiksdD0xMCxjKXtjYXNlInJpZ2h0Ijp0aGlzLiRlbC5hZGRDbGFzcygiYmstbGVmdCIpLHU9cCsodGhpcy4kZWwub3V0ZXJXaWR0aCgpLXRoaXMuJGVsLmlubmVyV2lkdGgoKSkrdCxmPV8tdGhpcy4kZWwub3V0ZXJIZWlnaHQoKS8yO2JyZWFrO2Nhc2UibGVmdCI6dGhpcy4kZWwuYWRkQ2xhc3MoImJrLXJpZ2h0IiksdT1wLXRoaXMuJGVsLm91dGVyV2lkdGgoKS10LGY9Xy10aGlzLiRlbC5vdXRlckhlaWdodCgpLzI7YnJlYWs7Y2FzZSJhYm92ZSI6dGhpcy4kZWwuYWRkQ2xhc3MoImJrLWFib3ZlIiksZj1fKyh0aGlzLiRlbC5vdXRlckhlaWdodCgpLXRoaXMuJGVsLmlubmVySGVpZ2h0KCkpK3QsdT1NYXRoLnJvdW5kKHAtdGhpcy4kZWwub3V0ZXJXaWR0aCgpLzIpO2JyZWFrO2Nhc2UiYmVsb3ciOnRoaXMuJGVsLmFkZENsYXNzKCJiay1iZWxvdyIpLGY9Xy10aGlzLiRlbC5vdXRlckhlaWdodCgpLXQsdT1NYXRoLnJvdW5kKHAtdGhpcy4kZWwub3V0ZXJXaWR0aCgpLzIpfXJldHVybiB0aGlzLm1vZGVsLnNob3dfYXJyb3cmJnRoaXMuJGVsLmFkZENsYXNzKCJiay10b29sdGlwLWFycm93IiksdGhpcy4kZWwuY2hpbGRyZW4oKS5sZW5ndGg+MD8odGhpcy4kZWwuY3NzKHt0b3A6ZixsZWZ0OnV9KSx0aGlzLiRlbC5zaG93KCkpOnZvaWQgMH19LGV9KG8uVmlldyksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1zLGUucHJvdG90eXBlLnR5cGU9IlRvb2x0aXAiLGUuZGVmaW5lKHthdHRhY2htZW50Olt1LlN0cmluZywiaG9yaXpvbnRhbCJdLGlubmVyX29ubHk6W3UuQm9vbCwhMF0sc2hvd19hcnJvdzpbdS5Cb29sLCEwXX0pLGUub3ZlcnJpZGUoe2xldmVsOiJvdmVybGF5In0pLGUuaW50ZXJuYWwoe2RhdGE6W3UuQW55LFtdXSxjdXN0b206W3UuQW55XX0pLGUucHJvdG90eXBlLmNsZWFyPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZGF0YT1bXX0sZS5wcm90b3R5cGUuYWRkPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbjtyZXR1cm4gbj10aGlzLmRhdGEsbi5wdXNoKFt0LGUscl0pLHRoaXMuZGF0YT1uLHRoaXMudHJpZ2dlcigiY2hhbmdlOmRhdGEiKX0sZX0oby5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDppLFZpZXc6c319LHsiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9hbm5vdGF0aW9uIjoibW9kZWxzL2Fubm90YXRpb25zL2Fubm90YXRpb24iLGpxdWVyeToianF1ZXJ5Iix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvYXhlcy9heGlzIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlfLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LF89e30uaGFzT3duUHJvcGVydHk7dT10KCJ1bmRlcnNjb3JlIiksbD10KCIuLi8uLi9jb3JlL2xheW91dC9zaWRlX3BhbmVsIikscz10KCIuLi9yZW5kZXJlcnMvZ3VpZGVfcmVuZGVyZXIiKSxhPXQoIi4uL3JlbmRlcmVycy9yZW5kZXJlciIpLGk9dCgiLi4vLi4vY29yZS9sYXlvdXQvc29sdmVyIikuR0UsaD10KCIuLi8uLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIsYz10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBwKGUsdCksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy5feF9yYW5nZV9uYW1lPXRoaXMubWdldCgieF9yYW5nZV9uYW1lIiksdGhpcy5feV9yYW5nZV9uYW1lPXRoaXMubWdldCgieV9yYW5nZV9uYW1lIil9LGUucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbigpe3ZhciB0O2lmKHRoaXMubW9kZWwudmlzaWJsZSE9PSExKXJldHVybiB0PXRoaXMucGxvdF92aWV3LmNhbnZhc192aWV3LmN0eCx0LnNhdmUoKSx0aGlzLl9kcmF3X3J1bGUodCksdGhpcy5fZHJhd19tYWpvcl90aWNrcyh0KSx0aGlzLl9kcmF3X21pbm9yX3RpY2tzKHQpLHRoaXMuX2RyYXdfbWFqb3JfbGFiZWxzKHQpLHRoaXMuX2RyYXdfYXhpc19sYWJlbCh0KSx0LnJlc3RvcmUoKX0sZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5saXN0ZW5Ubyh0aGlzLm1vZGVsLCJjaGFuZ2UiLHRoaXMucGxvdF92aWV3LnJlcXVlc3RfcmVuZGVyKX0sZS5wcm90b3R5cGUuX2dldF9zaXplPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3RpY2tfZXh0ZW50KCkrdGhpcy5fdGlja19sYWJlbF9leHRlbnQoKSt0aGlzLl9heGlzX2xhYmVsX2V4dGVudCgpfSxlLnByb3RvdHlwZS5fZHJhd19ydWxlPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtO2lmKHRoaXMudmlzdWFscy5heGlzX2xpbmUuZG9pdCl7Zm9yKHM9ZT10aGlzLm1nZXQoInJ1bGVfY29vcmRzIiksXz1zWzBdLGY9c1sxXSxhPXRoaXMucGxvdF92aWV3Lm1hcF90b19zY3JlZW4oXyxmLHRoaXMuX3hfcmFuZ2VfbmFtZSx0aGlzLl95X3JhbmdlX25hbWUpLGM9YVswXSxwPWFbMV0sbD10aGlzLm1nZXQoIm5vcm1hbHMiKSxvPWxbMF0saT1sWzFdLHU9dGhpcy5tZ2V0KCJvZmZzZXRzIiksZD11WzBdLG09dVsxXSx0aGlzLnZpc3VhbHMuYXhpc19saW5lLnNldF92YWx1ZSh0KSx0LmJlZ2luUGF0aCgpLHQubW92ZVRvKE1hdGgucm91bmQoY1swXStvKmQpLE1hdGgucm91bmQocFswXStpKm0pKSxyPW49MSxoPWMubGVuZ3RoOzE8PWg/bjxoOm4+aDtyPTE8PWg/KytuOi0tbil0LmxpbmVUbyhNYXRoLnJvdW5kKGNbcl0rbypkKSxNYXRoLnJvdW5kKHBbcl0raSptKSk7cmV0dXJuIHQuc3Ryb2tlKCl9fSxlLnByb3RvdHlwZS5fZHJhd19tYWpvcl90aWNrcz1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdjtpZih0aGlzLnZpc3VhbHMubWFqb3JfdGlja19saW5lLmRvaXQpe2ZvcihlPXRoaXMubWdldCgidGlja19jb29yZHMiKSxzPWUubWFqb3IsbT1zWzBdLHk9c1sxXSxhPXRoaXMucGxvdF92aWV3Lm1hcF90b19zY3JlZW4obSx5LHRoaXMuX3hfcmFuZ2VfbmFtZSx0aGlzLl95X3JhbmdlX25hbWUpLHA9YVswXSxfPWFbMV0sbD10aGlzLm1nZXQoIm5vcm1hbHMiKSxvPWxbMF0saT1sWzFdLHU9dGhpcy5tZ2V0KCJvZmZzZXRzIiksZz11WzBdLHY9dVsxXSxkPXRoaXMubWdldCgibWFqb3JfdGlja19pbiIpLGY9dGhpcy5tZ2V0KCJtYWpvcl90aWNrX291dCIpLHRoaXMudmlzdWFscy5tYWpvcl90aWNrX2xpbmUuc2V0X3ZhbHVlKHQpLGM9W10scj1uPTAsaD1wLmxlbmd0aDswPD1oP248aDpuPmg7cj0wPD1oPysrbjotLW4pdC5iZWdpblBhdGgoKSx0Lm1vdmVUbyhNYXRoLnJvdW5kKHBbcl0rbypmK28qZyksTWF0aC5yb3VuZChfW3JdK2kqZitpKnYpKSx0LmxpbmVUbyhNYXRoLnJvdW5kKHBbcl0tbypkK28qZyksTWF0aC5yb3VuZChfW3JdLWkqZCtpKnYpKSxjLnB1c2godC5zdHJva2UoKSk7cmV0dXJuIGN9fSxlLnByb3RvdHlwZS5fZHJhd19taW5vcl90aWNrcz1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdjtpZih0aGlzLnZpc3VhbHMubWlub3JfdGlja19saW5lLmRvaXQpe2ZvcihlPXRoaXMubWdldCgidGlja19jb29yZHMiKSxzPWUubWlub3IsbT1zWzBdLHk9c1sxXSxhPXRoaXMucGxvdF92aWV3Lm1hcF90b19zY3JlZW4obSx5LHRoaXMuX3hfcmFuZ2VfbmFtZSx0aGlzLl95X3JhbmdlX25hbWUpLHA9YVswXSxfPWFbMV0sbD10aGlzLm1nZXQoIm5vcm1hbHMiKSxvPWxbMF0saT1sWzFdLHU9dGhpcy5tZ2V0KCJvZmZzZXRzIiksZz11WzBdLHY9dVsxXSxkPXRoaXMubWdldCgibWlub3JfdGlja19pbiIpLGY9dGhpcy5tZ2V0KCJtaW5vcl90aWNrX291dCIpLHRoaXMudmlzdWFscy5taW5vcl90aWNrX2xpbmUuc2V0X3ZhbHVlKHQpLGM9W10scj1uPTAsaD1wLmxlbmd0aDswPD1oP248aDpuPmg7cj0wPD1oPysrbjotLW4pdC5iZWdpblBhdGgoKSx0Lm1vdmVUbyhNYXRoLnJvdW5kKHBbcl0rbypmK28qZyksTWF0aC5yb3VuZChfW3JdK2kqZitpKnYpKSx0LmxpbmVUbyhNYXRoLnJvdW5kKHBbcl0tbypkK28qZyksTWF0aC5yb3VuZChfW3JdLWkqZCtpKnYpKSxjLnB1c2godC5zdHJva2UoKSk7cmV0dXJuIGN9fSxlLnByb3RvdHlwZS5fZHJhd19tYWpvcl9sYWJlbHM9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGEsbCxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0saztmb3Iocj10aGlzLm1nZXQoInRpY2tfY29vcmRzIiksYz1yLm1ham9yLHg9Y1swXSxNPWNbMV0scD10aGlzLnBsb3Rfdmlldy5tYXBfdG9fc2NyZWVuKHgsTSx0aGlzLl94X3JhbmdlX25hbWUsdGhpcy5feV9yYW5nZV9uYW1lKSx2PXBbMF0sYj1wWzFdLF89dGhpcy5tZ2V0KCJub3JtYWxzIiksYT1fWzBdLGw9X1sxXSxkPXRoaXMubWdldCgib2Zmc2V0cyIpLHc9ZFswXSxrPWRbMV0sbj10aGlzLm1nZXQoImRpbWVuc2lvbiIpLGc9dGhpcy5tZ2V0KCJwYW5lbF9zaWRlIiksaD10aGlzLm1nZXQoIm1ham9yX2xhYmVsX29yaWVudGF0aW9uIiksZT11LmlzU3RyaW5nKGgpP3RoaXMubW9kZWwucGFuZWwuZ2V0X2xhYmVsX2FuZ2xlX2hldXJpc3RpYyhoKTotaCx5PXRoaXMuX3RpY2tfZXh0ZW50KCkrdGhpcy5tZ2V0KCJtYWpvcl9sYWJlbF9zdGFuZG9mZiIpLHM9dGhpcy5tZ2V0KCJmb3JtYXR0ZXIiKS5kb0Zvcm1hdChyLm1ham9yW25dKSx0aGlzLnZpc3VhbHMubWFqb3JfbGFiZWxfdGV4dC5zZXRfdmFsdWUodCksdGhpcy5tb2RlbC5wYW5lbC5hcHBseV9sYWJlbF90ZXh0X2hldXJpc3RpY3ModCxoKSxtPVtdLG89aT0wLGY9di5sZW5ndGg7MDw9Zj9pPGY6aT5mO289MDw9Zj8rK2k6LS1pKWU/KHQudHJhbnNsYXRlKHZbb10rYSp5K2EqdyxiW29dK2wqeStsKmspLHQucm90YXRlKGUpLHQuZmlsbFRleHQoc1tvXSwwLDApLHQucm90YXRlKC1lKSxtLnB1c2godC50cmFuc2xhdGUoLXZbb10tYSp5K2EqdywtYltvXS1sKnkrbCprKSkpOm0ucHVzaCh0LmZpbGxUZXh0KHNbb10sTWF0aC5yb3VuZCh2W29dK2EqeSthKncpLE1hdGgucm91bmQoYltvXStsKnkrbCprKSkpO3JldHVybiBtfSxlLnByb3RvdHlwZS5fZHJhd19heGlzX2xhYmVsPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGc7aWYocj10aGlzLm1nZXQoImF4aXNfbGFiZWwiKSxudWxsIT1yJiYocz10aGlzLm1nZXQoInJ1bGVfY29vcmRzIiksZD1zWzBdLG09c1sxXSxhPXRoaXMucGxvdF92aWV3Lm1hcF90b19zY3JlZW4oZCxtLHRoaXMuX3hfcmFuZ2VfbmFtZSx0aGlzLl95X3JhbmdlX25hbWUpLHA9YVswXSxfPWFbMV0sbD10aGlzLm1nZXQoIm5vcm1hbHMiKSxuPWxbMF0sbz1sWzFdLHU9dGhpcy5tZ2V0KCJvZmZzZXRzIiksZj11WzBdLGc9dVsxXSxoPXRoaXMubWdldCgicGFuZWxfc2lkZSIpLGk9InBhcmFsbGVsIixlPXRoaXMubW9kZWwucGFuZWwuZ2V0X2xhYmVsX2FuZ2xlX2hldXJpc3RpYyhpKSxjPXRoaXMuX3RpY2tfZXh0ZW50KCkrdGhpcy5fdGlja19sYWJlbF9leHRlbnQoKSt0aGlzLm1nZXQoImF4aXNfbGFiZWxfc3RhbmRvZmYiKSxwPShwWzBdK3BbcC5sZW5ndGgtMV0pLzIsXz0oX1swXStfW18ubGVuZ3RoLTFdKS8yLHRoaXMudmlzdWFscy5heGlzX2xhYmVsX3RleHQuc2V0X3ZhbHVlKHQpLHRoaXMubW9kZWwucGFuZWwuYXBwbHlfbGFiZWxfdGV4dF9oZXVyaXN0aWNzKHQsaSksZD1wK24qYytuKmYsbT1fK28qYytvKmcsIWlzTmFOKGQpJiYhaXNOYU4obSkpKXJldHVybiBlPyh0LnRyYW5zbGF0ZShkLG0pLHQucm90YXRlKGUpLHQuZmlsbFRleHQociwwLDApLHQucm90YXRlKC1lKSx0LnRyYW5zbGF0ZSgtZCwtbSkpOnQuZmlsbFRleHQocixkLG0pfSxlLnByb3RvdHlwZS5fdGlja19leHRlbnQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tZ2V0KCJtYWpvcl90aWNrX291dCIpfSxlLnByb3RvdHlwZS5fdGlja19sYWJlbF9leHRlbnQ9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLGwsaCxjLHAsXyxkLGYsbSxnLHksdjtmb3IoaT0wLG49dGhpcy5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LG89dGhpcy5tZ2V0KCJkaW1lbnNpb24iKSxyPXRoaXMubWdldCgidGlja19jb29yZHMiKS5tYWpvcixtPXRoaXMubWdldCgicGFuZWxfc2lkZSIpLF89dGhpcy5tZ2V0KCJtYWpvcl9sYWJlbF9vcmllbnRhdGlvbiIpLHA9dGhpcy5tZ2V0KCJmb3JtYXR0ZXIiKS5kb0Zvcm1hdChyW29dKSx0aGlzLnZpc3VhbHMubWFqb3JfbGFiZWxfdGV4dC5zZXRfdmFsdWUobiksdS5pc1N0cmluZyhfKT8obD0xLHQ9dGhpcy5tb2RlbC5wYW5lbC5nZXRfbGFiZWxfYW5nbGVfaGV1cmlzdGljKF8pKToobD0yLHQ9LV8pLHQ9TWF0aC5hYnModCksZT1NYXRoLmNvcyh0KSxmPU1hdGguc2luKHQpLCJhYm92ZSI9PT1tfHwiYmVsb3ciPT09bT8odj1mLGE9ZSk6KHY9ZSxhPWYpLGg9Yz0wLGQ9cC5sZW5ndGg7MDw9ZD9jPGQ6Yz5kO2g9MDw9ZD8rK2M6LS1jKW51bGwhPXBbaF0mJih5PTEuMSpuLm1lYXN1cmVUZXh0KHBbaF0pLndpZHRoLHM9Ljkqbi5tZWFzdXJlVGV4dChwW2hdKS5hc2NlbnQsZz15KnYrcy9sKmEsZz5pJiYoaT1nKSk7cmV0dXJuIGk+MCYmKGkrPXRoaXMubWdldCgibWFqb3JfbGFiZWxfc3RhbmRvZmYiKSksaX0sZS5wcm90b3R5cGUuX2F4aXNfbGFiZWxfZXh0ZW50PWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLHMsYSxsLHU7cmV0dXJuIG89MCxsPXRoaXMubWdldCgicGFuZWxfc2lkZSIpLGU9dGhpcy5tZ2V0KCJheGlzX2xhYmVsIikscz0icGFyYWxsZWwiLG49dGhpcy5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LHRoaXMudmlzdWFscy5heGlzX2xhYmVsX3RleHQuc2V0X3ZhbHVlKG4pLHQ9TWF0aC5hYnModGhpcy5tb2RlbC5wYW5lbC5nZXRfbGFiZWxfYW5nbGVfaGV1cmlzdGljKHMpKSxyPU1hdGguY29zKHQpLGE9TWF0aC5zaW4odCksZSYmKG8rPXRoaXMubWdldCgiYXhpc19sYWJlbF9zdGFuZG9mZiIpLHRoaXMudmlzdWFscy5heGlzX2xhYmVsX3RleHQuc2V0X3ZhbHVlKG4pLHU9MS4xKm4ubWVhc3VyZVRleHQoZSkud2lkdGgsaT0uOSpuLm1lYXN1cmVUZXh0KGUpLmFzY2VudCxvKz0iYWJvdmUiPT09bHx8ImJlbG93Ij09PWw/dSphK2kqcjp1KnIraSphKSxvfSxlfShhLlZpZXcpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHAoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9byxlLnByb3RvdHlwZS50eXBlPSJBeGlzIixlLm1peGlucyhbImxpbmU6YXhpc18iLCJsaW5lOm1ham9yX3RpY2tfIiwibGluZTptaW5vcl90aWNrXyIsInRleHQ6bWFqb3JfbGFiZWxfIiwidGV4dDpheGlzX2xhYmVsXyJdKSxlLmRlZmluZSh7Ym91bmRzOltjLkFueSwiYXV0byJdLHRpY2tlcjpbYy5JbnN0YW5jZSxudWxsXSxmb3JtYXR0ZXI6W2MuSW5zdGFuY2UsbnVsbF0seF9yYW5nZV9uYW1lOltjLlN0cmluZywiZGVmYXVsdCJdLHlfcmFuZ2VfbmFtZTpbYy5TdHJpbmcsImRlZmF1bHQiXSxheGlzX2xhYmVsOltjLlN0cmluZywiIl0sYXhpc19sYWJlbF9zdGFuZG9mZjpbYy5JbnQsNV0sbWFqb3JfbGFiZWxfc3RhbmRvZmY6W2MuSW50LDVdLG1ham9yX2xhYmVsX29yaWVudGF0aW9uOltjLkFueSwiaG9yaXpvbnRhbCJdLG1ham9yX3RpY2tfaW46W2MuTnVtYmVyLDJdLG1ham9yX3RpY2tfb3V0OltjLk51bWJlciw2XSxtaW5vcl90aWNrX2luOltjLk51bWJlciwwXSxtaW5vcl90aWNrX291dDpbYy5OdW1iZXIsNF19KSxlLm92ZXJyaWRlKHtheGlzX2xpbmVfY29sb3I6ImJsYWNrIixtYWpvcl90aWNrX2xpbmVfY29sb3I6ImJsYWNrIixtaW5vcl90aWNrX2xpbmVfY29sb3I6ImJsYWNrIixtYWpvcl9sYWJlbF90ZXh0X2ZvbnRfc2l6ZToiOHB0IixtYWpvcl9sYWJlbF90ZXh0X2FsaWduOiJjZW50ZXIiLG1ham9yX2xhYmVsX3RleHRfYmFzZWxpbmU6ImFscGhhYmV0aWMiLGF4aXNfbGFiZWxfdGV4dF9mb250X3NpemU6IjEwcHQiLGF4aXNfbGFiZWxfdGV4dF9mb250X3N0eWxlOiJpdGFsaWMifSksZS5pbnRlcm5hbCh7cGFuZWxfc2lkZTpbYy5BbnldfSksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0LHIpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0LHIpLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJjb21wdXRlZF9ib3VuZHMiLHRoaXMuX2NvbXB1dGVkX2JvdW5kcywhMSksdGhpcy5hZGRfZGVwZW5kZW5jaWVzKCJjb21wdXRlZF9ib3VuZHMiLHRoaXMsWyJib3VuZHMiXSksdGhpcy5hZGRfZGVwZW5kZW5jaWVzKCJjb21wdXRlZF9ib3VuZHMiLHRoaXMuZ2V0KCJwbG90IiksWyJ4X3JhbmdlIiwieV9yYW5nZSJdKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgicnVsZV9jb29yZHMiLHRoaXMuX3J1bGVfY29vcmRzLCExKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoInJ1bGVfY29vcmRzIix0aGlzLFsiY29tcHV0ZWRfYm91bmRzIiwic2lkZSJdKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgidGlja19jb29yZHMiLHRoaXMuX3RpY2tfY29vcmRzLCExKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoInRpY2tfY29vcmRzIix0aGlzLFsiY29tcHV0ZWRfYm91bmRzIiwicGFuZWxfc2lkZSJdKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgicmFuZ2VzIix0aGlzLl9yYW5nZXMsITApLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJub3JtYWxzIixmdW5jdGlvbigpe3JldHVybiB0aGlzLnBhbmVsLl9ub3JtYWxzfSwhMCksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoImRpbWVuc2lvbiIsZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5wYW5lbC5fZGltfSwhMCksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoIm9mZnNldHMiLHRoaXMuX29mZnNldHMsITApfSxlLnByb3RvdHlwZS5hZGRfcGFuZWw9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMucGFuZWw9bmV3IGwuTW9kZWwoe3NpZGU6dH0pLHRoaXMucGFuZWwuYXR0YWNoX2RvY3VtZW50KHRoaXMuZG9jdW1lbnQpLHRoaXMuc2V0KCJwYW5lbF9zaWRlIix0KX0sZS5wcm90b3R5cGUuX29mZnNldHM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvO3JldHVybiByPXRoaXMuZ2V0KCJwYW5lbF9zaWRlIiksZT1bMCwwXSxuPWVbMF0sbz1lWzFdLHQ9dGhpcy5wbG90LnBsb3RfY2FudmFzLmdldCgiZnJhbWUiKSwiYmVsb3ciPT09cj9vPU1hdGguYWJzKHRoaXMucGFuZWwuZ2V0KCJ0b3AiKS10LmdldCgiYm90dG9tIikpOiJhYm92ZSI9PT1yP289TWF0aC5hYnModGhpcy5wYW5lbC5nZXQoImJvdHRvbSIpLXQuZ2V0KCJ0b3AiKSk6InJpZ2h0Ij09PXI/bj1NYXRoLmFicyh0aGlzLnBhbmVsLmdldCgibGVmdCIpLXQuZ2V0KCJyaWdodCIpKToibGVmdCI9PT1yJiYobj1NYXRoLmFicyh0aGlzLnBhbmVsLmdldCgicmlnaHQiKS10LmdldCgibGVmdCIpKSksW24sb119LGUucHJvdG90eXBlLl9yYW5nZXM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbjtyZXR1cm4gZT10aGlzLmdldCgiZGltZW5zaW9uIikscj0oZSsxKSUyLHQ9dGhpcy5wbG90LnBsb3RfY2FudmFzLmdldCgiZnJhbWUiKSxuPVt0LmdldCgieF9yYW5nZXMiKVt0aGlzLmdldCgieF9yYW5nZV9uYW1lIildLHQuZ2V0KCJ5X3JhbmdlcyIpW3RoaXMuZ2V0KCJ5X3JhbmdlX25hbWUiKV1dLFtuW2VdLG5bcl1dfSxlLnByb3RvdHlwZS5fY29tcHV0ZWRfYm91bmRzPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLHMsYTtyZXR1cm4gbz10aGlzLmdldCgicmFuZ2VzIikscj1vWzBdLHQ9b1sxXSxhPW51bGwhPShpPXRoaXMuZ2V0KCJib3VuZHMiKSk/aToiYXV0byIsbj1bci5nZXQoIm1pbiIpLHIuZ2V0KCJtYXgiKV0sImF1dG8iPT09YT9uOnUuaXNBcnJheShhKT8oTWF0aC5hYnMoYVswXS1hWzFdKT5NYXRoLmFicyhuWzBdLW5bMV0pPyhzPU1hdGgubWF4KE1hdGgubWluKGFbMF0sYVsxXSksblswXSksZT1NYXRoLm1pbihNYXRoLm1heChhWzBdLGFbMV0pLG5bMV0pKToocz1NYXRoLm1pbihhWzBdLGFbMV0pLAplPU1hdGgubWF4KGFbMF0sYVsxXSkpLFtzLGVdKTooaC5lcnJvcigidXNlciBib3VuZHMgJyIrYSsiJyBub3QgdW5kZXJzdG9vZCIpLG51bGwpfSxlLnByb3RvdHlwZS5fcnVsZV9jb29yZHM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLGwsdSxoLGM7cmV0dXJuIG49dGhpcy5nZXQoImRpbWVuc2lvbiIpLG89KG4rMSklMixhPXRoaXMuZ2V0KCJyYW5nZXMiKSxzPWFbMF0sZT1hWzFdLGw9dGhpcy5nZXQoImNvbXB1dGVkX2JvdW5kcyIpLHU9bFswXSxyPWxbMV0saD1uZXcgQXJyYXkoMiksYz1uZXcgQXJyYXkoMiksdD1baCxjXSxpPXRoaXMuX2dldF9sb2MoZSksdFtuXVswXT1NYXRoLm1heCh1LHMuZ2V0KCJtaW4iKSksdFtuXVsxXT1NYXRoLm1pbihyLHMuZ2V0KCJtYXgiKSksdFtuXVswXT50W25dWzFdJiYodFtuXVswXT10W25dWzFdPU5hTiksdFtvXVswXT1pLHRbb11bMV09aSx0fSxlLnByb3RvdHlwZS5fdGlja19jb29yZHM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0sayxqLFQsUztpZihuPXRoaXMuZ2V0KCJkaW1lbnNpb24iKSxpPShuKzEpJTIseT10aGlzLmdldCgicmFuZ2VzIiksZj15WzBdLGU9eVsxXSx2PXRoaXMuZ2V0KCJjb21wdXRlZF9ib3VuZHMiKSxrPXZbMF0scj12WzFdLGo9dGhpcy5nZXQoInRpY2tlciIpLmdldF90aWNrcyhrLHIsZix7fSksaD1qLm1ham9yLGQ9ai5taW5vcixsPXRoaXMuX2dldF9sb2MoZSksVD1bXSxTPVtdLHQ9W1QsU10scD1bXSxfPVtdLGM9W3AsX10sIkZhY3RvclJhbmdlIj09PWYudHlwZSlmb3Iobz1zPTAsYj1oLmxlbmd0aDswPD1iP3M8YjpzPmI7bz0wPD1iPysrczotLXMpdFtuXS5wdXNoKGhbb10pLHRbaV0ucHVzaChsKTtlbHNle2Zvcih4PVtmLmdldCgibWluIiksZi5nZXQoIm1heCIpXSxnPXhbMF0sbT14WzFdLG89YT0wLHc9aC5sZW5ndGg7MDw9dz9hPHc6YT53O289MDw9dz8rK2E6LS1hKWhbb108Z3x8aFtvXT5tfHwodFtuXS5wdXNoKGhbb10pLHRbaV0ucHVzaChsKSk7Zm9yKG89dT0wLE09ZC5sZW5ndGg7MDw9TT91PE06dT5NO289MDw9TT8rK3U6LS11KWRbb108Z3x8ZFtvXT5tfHwoY1tuXS5wdXNoKGRbb10pLGNbaV0ucHVzaChsKSl9cmV0dXJue21ham9yOnQsbWlub3I6Y319LGUucHJvdG90eXBlLl9nZXRfbG9jPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvO3JldHVybiByPXQuZ2V0KCJzdGFydCIpLGU9dC5nZXQoImVuZCIpLG89dGhpcy5nZXQoInBhbmVsX3NpZGUiKSwibGVmdCI9PT1vfHwiYmVsb3ciPT09bz9uPSJzdGFydCI6InJpZ2h0IiE9PW8mJiJhYm92ZSIhPT1vfHwobj0iZW5kIiksdC5nZXQobil9LGV9KHMuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bixWaWV3Om99fSx7Ii4uLy4uL2NvcmUvbGF5b3V0L3NpZGVfcGFuZWwiOiJjb3JlL2xheW91dC9zaWRlX3BhbmVsIiwiLi4vLi4vY29yZS9sYXlvdXQvc29sdmVyIjoiY29yZS9sYXlvdXQvc29sdmVyIiwiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vcmVuZGVyZXJzL2d1aWRlX3JlbmRlcmVyIjoibW9kZWxzL3JlbmRlcmVycy9ndWlkZV9yZW5kZXJlciIsIi4uL3JlbmRlcmVycy9yZW5kZXJlciI6Im1vZGVscy9yZW5kZXJlcnMvcmVuZGVyZXIiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9heGVzL2NhdGVnb3JpY2FsX2F4aXMiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxjPXt9Lmhhc093blByb3BlcnR5O2w9dCgidW5kZXJzY29yZSIpLG49dCgiLi9heGlzIikscz10KCIuLi9mb3JtYXR0ZXJzL2NhdGVnb3JpY2FsX3RpY2tfZm9ybWF0dGVyIiksYT10KCIuLi90aWNrZXJzL2NhdGVnb3JpY2FsX3RpY2tlciIpLHU9dCgiLi4vLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJDYXRlZ29yaWNhbEF4aXMiLGUub3ZlcnJpZGUoe3RpY2tlcjpmdW5jdGlvbigpe3JldHVybiBuZXcgYS5Nb2RlbH0sZm9ybWF0dGVyOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBzLk1vZGVsfX0pLGUucHJvdG90eXBlLl9jb21wdXRlZF9ib3VuZHM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGk7cmV0dXJuIG49dGhpcy5nZXQoInJhbmdlcyIpLGU9blswXSx0PW5bMV0saT1udWxsIT0obz10aGlzLmdldCgiYm91bmRzIikpP286ImF1dG8iLHI9W2UuZ2V0KCJtaW4iKSxlLmdldCgibWF4IildLCJhdXRvIiE9PWkmJnUud2FybigiQ2F0ZWdvcmljYWwgQXhlcyBvbmx5IHN1cHBvcnQgdXNlcl9ib3VuZHM9J2F1dG8nLCBpZ25vcmluZyIpLHJ9LGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4uLy4uL2NvcmUvbG9nZ2luZyI6ImNvcmUvbG9nZ2luZyIsIi4uL2Zvcm1hdHRlcnMvY2F0ZWdvcmljYWxfdGlja19mb3JtYXR0ZXIiOiJtb2RlbHMvZm9ybWF0dGVycy9jYXRlZ29yaWNhbF90aWNrX2Zvcm1hdHRlciIsIi4uL3RpY2tlcnMvY2F0ZWdvcmljYWxfdGlja2VyIjoibW9kZWxzL3RpY2tlcnMvY2F0ZWdvcmljYWxfdGlja2VyIiwiLi9heGlzIjoibW9kZWxzL2F4ZXMvYXhpcyIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2F4ZXMvY29udGludW91c19heGlzIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpcy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxzPXt9Lmhhc093blByb3BlcnR5O249dCgiLi9heGlzIiksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaShlLHQpLGUucHJvdG90eXBlLnR5cGU9IkNvbnRpbnVvdXNBeGlzIixlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm99fSx7Ii4vYXhpcyI6Im1vZGVscy9heGVzL2F4aXMifV0sIm1vZGVscy9heGVzL2RhdGV0aW1lX2F4aXMiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHU9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWguY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0saD17fS5oYXNPd25Qcm9wZXJ0eTtsPXQoInVuZGVyc2NvcmUiKSxhPXQoIi4vYXhpcyIpLGk9dCgiLi4vZm9ybWF0dGVycy9kYXRldGltZV90aWNrX2Zvcm1hdHRlciIpLHM9dCgiLi4vdGlja2Vycy9kYXRldGltZV90aWNrZXIiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZX0oYS5WaWV3KSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PW8sZS5wcm90b3R5cGUudHlwZT0iRGF0ZXRpbWVBeGlzIixlLm92ZXJyaWRlKHt0aWNrZXI6ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IHMuTW9kZWx9LGZvcm1hdHRlcjpmdW5jdGlvbigpe3JldHVybiBuZXcgaS5Nb2RlbH19KSxlfShhLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm4sVmlldzpvfX0seyIuLi9mb3JtYXR0ZXJzL2RhdGV0aW1lX3RpY2tfZm9ybWF0dGVyIjoibW9kZWxzL2Zvcm1hdHRlcnMvZGF0ZXRpbWVfdGlja19mb3JtYXR0ZXIiLCIuLi90aWNrZXJzL2RhdGV0aW1lX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL2RhdGV0aW1lX3RpY2tlciIsIi4vYXhpcyI6Im1vZGVscy9heGVzL2F4aXMiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9heGVzL2xpbmVhcl9heGlzIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGg9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWMuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sYz17fS5oYXNPd25Qcm9wZXJ0eTt1PXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vYXhpcyIpLHM9dCgiLi9jb250aW51b3VzX2F4aXMiKSxvPXQoIi4uL2Zvcm1hdHRlcnMvYmFzaWNfdGlja19mb3JtYXR0ZXIiKSxpPXQoIi4uL3RpY2tlcnMvYmFzaWNfdGlja2VyIiksbD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGV9KG4uVmlldyksYT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1sLGUucHJvdG90eXBlLnR5cGU9IkxpbmVhckF4aXMiLGUub3ZlcnJpZGUoe3RpY2tlcjpmdW5jdGlvbigpe3JldHVybiBuZXcgaS5Nb2RlbH0sZm9ybWF0dGVyOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBvLk1vZGVsfX0pLGV9KHMuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6YSxWaWV3Omx9fSx7Ii4uL2Zvcm1hdHRlcnMvYmFzaWNfdGlja19mb3JtYXR0ZXIiOiJtb2RlbHMvZm9ybWF0dGVycy9iYXNpY190aWNrX2Zvcm1hdHRlciIsIi4uL3RpY2tlcnMvYmFzaWNfdGlja2VyIjoibW9kZWxzL3RpY2tlcnMvYmFzaWNfdGlja2VyIiwiLi9heGlzIjoibW9kZWxzL2F4ZXMvYXhpcyIsIi4vY29udGludW91c19heGlzIjoibW9kZWxzL2F4ZXMvY29udGludW91c19heGlzIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvYXhlcy9sb2dfYXhpcyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7dT10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2F4aXMiKSxvPXQoIi4vY29udGludW91c19heGlzIiksYT10KCIuLi9mb3JtYXR0ZXJzL2xvZ190aWNrX2Zvcm1hdHRlciIpLGw9dCgiLi4vdGlja2Vycy9sb2dfdGlja2VyIikscz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGV9KG4uVmlldyksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1zLGUucHJvdG90eXBlLnR5cGU9IkxvZ0F4aXMiLGUub3ZlcnJpZGUoe3RpY2tlcjpmdW5jdGlvbigpe3JldHVybiBuZXcgbC5Nb2RlbH0sZm9ybWF0dGVyOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBhLk1vZGVsfX0pLGV9KG8uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6aSxWaWV3OnN9fSx7Ii4uL2Zvcm1hdHRlcnMvbG9nX3RpY2tfZm9ybWF0dGVyIjoibW9kZWxzL2Zvcm1hdHRlcnMvbG9nX3RpY2tfZm9ybWF0dGVyIiwiLi4vdGlja2Vycy9sb2dfdGlja2VyIjoibW9kZWxzL3RpY2tlcnMvbG9nX3RpY2tlciIsIi4vYXhpcyI6Im1vZGVscy9heGVzL2F4aXMiLCIuL2NvbnRpbnVvdXNfYXhpcyI6Im1vZGVscy9heGVzL2NvbnRpbnVvdXNfYXhpcyIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2NhbGxiYWNrcy9jdXN0b21qcyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlsLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGw9e30uaGFzT3duUHJvcGVydHksdT1bXS5zbGljZTtpPXQoInVuZGVyc2NvcmUiKSxzPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89dCgiLi4vLi4vbW9kZWwiKSxuPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIHIoKXtyZXR1cm4gci5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKHIsZSksci5wcm90b3R5cGUudHlwZT0iQ3VzdG9tSlMiLHIuZGVmaW5lKHthcmdzOltzLkFueSx7fV0sY29kZTpbcy5TdHJpbmcsIiJdLGxhbmc6W3MuU3RyaW5nLCJqYXZhc2NyaXB0Il19KSxyLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHIuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsZSksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoInZhbHVlcyIsdGhpcy5fbWFrZV92YWx1ZXMsITApLHRoaXMuYWRkX2RlcGVuZGVuY2llcygidmFsdWVzIix0aGlzLFsiYXJncyJdKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgiZnVuYyIsdGhpcy5fbWFrZV9mdW5jLCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoImZ1bmMiLHRoaXMsWyJhcmdzIiwiY29kZSJdKX0sci5wcm90b3R5cGUuZXhlY3V0ZT1mdW5jdGlvbihlLHIpe3JldHVybiB0aGlzLmdldCgiZnVuYyIpLmFwcGx5KG51bGwsdS5jYWxsKHRoaXMuZ2V0KCJ2YWx1ZXMiKSkuY29uY2F0KFtlXSxbcl0sW3RdKSl9LHIucHJvdG90eXBlLl9tYWtlX3ZhbHVlcz1mdW5jdGlvbigpe3JldHVybiBpLnZhbHVlcyh0aGlzLmdldCgiYXJncyIpKX0sci5wcm90b3R5cGUuX21ha2VfZnVuYz1mdW5jdGlvbigpe3ZhciBlLHI7cmV0dXJuIGU9dGhpcy5nZXQoImNvZGUiKSxlPWZ1bmN0aW9uKCl7c3dpdGNoKHRoaXMuZ2V0KCJsYW5nIikpe2Nhc2UiamF2YXNjcmlwdCI6cmV0dXJuIGU7Y2FzZSJjb2ZmZWVzY3JpcHQiOnJldHVybiByPXQoImNvZmZlZS1zY3JpcHQiKSxyLmNvbXBpbGUoZSx7YmFyZTohMCxzaGlmdExpbmU6ITB9KX19LmNhbGwodGhpcyksZnVuY3Rpb24odCxlLHIpe3IucHJvdG90eXBlPXQucHJvdG90eXBlO3ZhciBuPW5ldyByLG89dC5hcHBseShuLGUpO3JldHVybiBPYmplY3Qobyk9PT1vP286bn0oRnVuY3Rpb24sdS5jYWxsKGkua2V5cyh0aGlzLmdldCgiYXJncyIpKSkuY29uY2F0KFsiY2Jfb2JqIl0sWyJjYl9kYXRhIl0sWyJyZXF1aXJlIl0sW2VdKSxmdW5jdGlvbigpe30pfSxyfShvKSxlLmV4cG9ydHM9e01vZGVsOm59fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4uLy4uL21vZGVsIjoibW9kZWwiLCJjb2ZmZWUtc2NyaXB0Ijp2b2lkIDAsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2NhbGxiYWNrcy9vcGVuX3VybCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXUuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sdT17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxhPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG49dCgiLi4vLi4vbW9kZWwiKSxpPXQoIi4uLy4uL3V0aWwvdXRpbCIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJPcGVuVVJMIixlLmRlZmluZSh7dXJsOlthLlN0cmluZywiaHR0cDovLyJdfSksZS5wcm90b3R5cGUuZXhlY3V0ZT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxzO2ZvcihvPWkuZ2V0X2luZGljZXModCkscj0wLG49by5sZW5ndGg7cjxuO3IrKyllPW9bcl0scz1pLnJlcGxhY2VfcGxhY2Vob2xkZXJzKHRoaXMuZ2V0KCJ1cmwiKSx0LGUpLHdpbmRvdy5vcGVuKHMpO3JldHVybiBudWxsfSxlfShuKSxlLmV4cG9ydHM9e01vZGVsOm99fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4uLy4uL21vZGVsIjoibW9kZWwiLCIuLi8uLi91dGlsL3V0aWwiOiJ1dGlsL3V0aWwiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9jYW52YXMvY2FudmFzIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4PWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl3LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHc9e30uaGFzT3duUHJvcGVydHk7dT10KCJ1bmRlcnNjb3JlIiksaD10KCIuL2NhbnZhc190ZW1wbGF0ZSIpLGw9dCgiLi4vLi4vY29yZS9sYXlvdXQvbGF5b3V0X2NhbnZhcyIpLG49dCgiLi4vLi4vY29yZS9ib2tlaF92aWV3Iiksdj10KCIuLi8uLi9jb3JlL2xheW91dC9zb2x2ZXIiKSxhPXYuR0Uscz12LkVRLGc9dCgiLi4vLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLHk9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksYj10KCIuLi8uLi9jb3JlL3V0aWwvY2FudmFzIikscD1iLmZpeHVwX2ltYWdlX3Ntb290aGluZyxfPWIuZml4dXBfbGluZV9kYXNoLGQ9Yi5maXh1cF9saW5lX2Rhc2hfb2Zmc2V0LGY9Yi5maXh1cF9tZWFzdXJlX3RleHQsbT1iLmdldF9zY2FsZV9yYXRpbyxjPWIuZml4dXBfZWxsaXBzZSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB4KGUsdCksZS5wcm90b3R5cGUuY2xhc3NOYW1lPSJiay1jYW52YXMtd3JhcHBlciIsZS5wcm90b3R5cGUudGVtcGxhdGU9aCxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3ZhciByLG47cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHI9dGhpcy50ZW1wbGF0ZSh7bWFwOnRoaXMubWdldCgibWFwIil9KSx0aGlzLiRlbC5odG1sKHIpLHRoaXMuY3R4PXRoaXMuZ2V0X2N0eCgpLHRoaXMuY3R4LmdsY2FudmFzPW51bGwsXyh0aGlzLmN0eCksZCh0aGlzLmN0eCkscCh0aGlzLmN0eCksZih0aGlzLmN0eCksYyh0aGlzLmN0eCksdGhpcy5tYXBfZGl2PW51bGwhPShuPXRoaXMuJCgiZGl2LmJrLWNhbnZhcy1tYXAiKSk/bjpudWxsLHRoaXMuc2V0X2RpbXMoW3RoaXMubW9kZWwuaW5pdGlhbF93aWR0aCx0aGlzLm1vZGVsLmluaXRpYWxfaGVpZ2h0XSksZy5kZWJ1ZygiQ2FudmFzVmlldyBpbml0aWFsaXplZCIpfSxlLnByb3RvdHlwZS5nZXRfY2FudmFzX2VsZW1lbnQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4kKCJjYW52YXMuYmstY2FudmFzIilbMF19LGUucHJvdG90eXBlLmdldF9jdHg9ZnVuY3Rpb24oKXt2YXIgdCxlO3JldHVybiB0PXRoaXMuJCgiY2FudmFzLmJrLWNhbnZhcyIpLGU9dFswXS5nZXRDb250ZXh0KCIyZCIpfSxlLnByb3RvdHlwZS5wcmVwYXJlX2NhbnZhcz1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpO2lmKG51bGw9PXQmJih0PSExKSxpPXRoaXMubW9kZWwuX3dpZHRoLl92YWx1ZSxuPXRoaXMubW9kZWwuX2hlaWdodC5fdmFsdWUscj13aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbywhdS5pc0VxdWFsKHRoaXMubGFzdF9kaW1zLFtpLG4scl0pfHx0KXJldHVybiB0aGlzLiRlbC5jc3Moe3dpZHRoOmksaGVpZ2h0Om59KSx0aGlzLnBpeGVsX3JhdGlvPW89bSh0aGlzLmN0eCx0aGlzLm1nZXQoInVzZV9oaWRwaSIpKSxlPXRoaXMuJCgiLmJrLWNhbnZhcyIpLGUuY3NzKHt3aWR0aDppLGhlaWdodDpufSksZS5hdHRyKCJ3aWR0aCIsaSpvKSxlLmF0dHIoImhlaWdodCIsbipvKSxnLmRlYnVnKCJSZW5kZXJpbmcgQ2FudmFzVmlldyBbZm9yY2U9Iit0KyJdIHdpdGggd2lkdGg6ICIraSsiLCBoZWlnaHQ6ICIrbisiLCByYXRpbzogIitvKSx0aGlzLm1vZGVsLnBpeGVsX3JhdGlvPXRoaXMucGl4ZWxfcmF0aW8sdGhpcy5sYXN0X2RpbXM9W2ksbixyXX0sZS5wcm90b3R5cGUuc2V0X2RpbXM9ZnVuY3Rpb24odCxlKXtudWxsPT1lJiYoZT0hMCksdGhpcy5yZXF1ZXN0ZWRfd2lkdGg9dFswXSx0aGlzLnJlcXVlc3RlZF9oZWlnaHQ9dFsxXSx0aGlzLnVwZGF0ZV9jb25zdHJhaW50cyhlKX0sZS5wcm90b3R5cGUudXBkYXRlX2NvbnN0cmFpbnRzPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvO2lmKG51bGw9PXQmJih0PSEwKSxuPXRoaXMucmVxdWVzdGVkX3dpZHRoLHI9dGhpcy5yZXF1ZXN0ZWRfaGVpZ2h0LG51bGwhPW4mJm51bGwhPXImJihlPTUwLCEobjxlfHxyPGV8fHUuaXNFcXVhbCh0aGlzLmxhc3RfcmVxdWVzdGVkX2RpbXMsW24scl0pKSkpcmV0dXJuIG89dGhpcy5tb2RlbC5kb2N1bWVudC5zb2x2ZXIoKSxudWxsIT10aGlzLl93aWR0aF9jb25zdHJhaW50JiZvLnJlbW92ZV9jb25zdHJhaW50KHRoaXMuX3dpZHRoX2NvbnN0cmFpbnQpLHRoaXMuX3dpZHRoX2NvbnN0cmFpbnQ9cyh0aGlzLm1vZGVsLl93aWR0aCwtbiksby5hZGRfY29uc3RyYWludCh0aGlzLl93aWR0aF9jb25zdHJhaW50KSxudWxsIT10aGlzLl9oZWlnaHRfY29uc3RyYWludCYmby5yZW1vdmVfY29uc3RyYWludCh0aGlzLl9oZWlnaHRfY29uc3RyYWludCksdGhpcy5faGVpZ2h0X2NvbnN0cmFpbnQ9cyh0aGlzLm1vZGVsLl9oZWlnaHQsLXIpLG8uYWRkX2NvbnN0cmFpbnQodGhpcy5faGVpZ2h0X2NvbnN0cmFpbnQpLHRoaXMubGFzdF9yZXF1ZXN0ZWRfZGltcz1bbixyXSxvLnVwZGF0ZV92YXJpYWJsZXModCl9LGV9KG4pLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHgoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJDYW52YXMiLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUuaW50ZXJuYWwoe21hcDpbeS5Cb29sZWFuLCExXSxpbml0aWFsX3dpZHRoOlt5Lk51bWJlcl0saW5pdGlhbF9oZWlnaHQ6W3kuTnVtYmVyXSx1c2VfaGlkcGk6W3kuQm9vbGVhbiwhMF0scGl4ZWxfcmF0aW86W3kuTnVtYmVyXX0pLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLnBhbmVsPXRoaXN9LGUucHJvdG90eXBlLnZ4X3RvX3N4PWZ1bmN0aW9uKHQpe3JldHVybiB0fSxlLnByb3RvdHlwZS52eV90b19zeT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5faGVpZ2h0Ll92YWx1ZS0odCsxKX0sZS5wcm90b3R5cGUudl92eF90b19zeD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IEZsb2F0NjRBcnJheSh0KX0sZS5wcm90b3R5cGUudl92eV90b19zeT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHM7Zm9yKGU9bmV3IEZsb2F0NjRBcnJheSh0Lmxlbmd0aCkscj10aGlzLl9oZWlnaHQuX3ZhbHVlLG89bj0wLGk9dC5sZW5ndGg7bjxpO289KytuKXM9dFtvXSxlW29dPXItKHMrMSk7cmV0dXJuIGV9LGUucHJvdG90eXBlLnN4X3RvX3Z4PWZ1bmN0aW9uKHQpe3JldHVybiB0fSxlLnByb3RvdHlwZS5zeV90b192eT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5faGVpZ2h0Ll92YWx1ZS0odCsxKX0sZS5wcm90b3R5cGUudl9zeF90b192eD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IEZsb2F0NjRBcnJheSh0KX0sZS5wcm90b3R5cGUudl9zeV90b192eT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHM7Zm9yKGU9bmV3IEZsb2F0NjRBcnJheSh0Lmxlbmd0aCkscj10aGlzLl9oZWlnaHQuX3ZhbHVlLG89bj0wLGk9dC5sZW5ndGg7bjxpO289KytuKXM9dFtvXSxlW29dPXItKHMrMSk7cmV0dXJuIGV9LGUucHJvdG90eXBlLmdldF9jb25zdHJhaW50cz1mdW5jdGlvbigpe3ZhciB0O3JldHVybiB0PWUuX19zdXBlcl9fLmdldF9jb25zdHJhaW50cy5jYWxsKHRoaXMpLHQucHVzaChhKHRoaXMuX3RvcCkpLHQucHVzaChhKHRoaXMuX2JvdHRvbSkpLHQucHVzaChhKHRoaXMuX2xlZnQpKSx0LnB1c2goYSh0aGlzLl9yaWdodCkpLHQucHVzaChhKHRoaXMuX3dpZHRoKSksdC5wdXNoKGEodGhpcy5faGVpZ2h0KSksdC5wdXNoKHModGhpcy5fd2lkdGgsWy0xLHRoaXMuX3JpZ2h0XSkpLHQucHVzaChzKHRoaXMuX2hlaWdodCxbLTEsdGhpcy5fdG9wXSkpLHR9LGV9KGwuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4uLy4uL2NvcmUvYm9rZWhfdmlldyI6ImNvcmUvYm9rZWhfdmlldyIsIi4uLy4uL2NvcmUvbGF5b3V0L2xheW91dF9jYW52YXMiOiJjb3JlL2xheW91dC9sYXlvdXRfY2FudmFzIiwiLi4vLi4vY29yZS9sYXlvdXQvc29sdmVyIjoiY29yZS9sYXlvdXQvc29sdmVyIiwiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vY29yZS91dGlsL2NhbnZhcyI6ImNvcmUvdXRpbC9jYW52YXMiLCIuL2NhbnZhc190ZW1wbGF0ZSI6Im1vZGVscy9jYW52YXMvY2FudmFzX3RlbXBsYXRlIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvY2FudmFzL2NhbnZhc190ZW1wbGF0ZSI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9ZnVuY3Rpb24odCl7dHx8KHQ9e30pO3ZhciBlPVtdO3JldHVybiBmdW5jdGlvbigpeyhmdW5jdGlvbigpe3RoaXMubWFwJiZlLnB1c2goJ1xuPGRpdiBjbGFzcz0iYmstY2FudmFzLW1hcCI+PC9kaXY+XG4nKSxlLnB1c2goJ1xuPGRpdiBjbGFzcz0iYmstY2FudmFzLWV2ZW50cyIgLz5cbjxkaXYgY2xhc3M9ImJrLWNhbnZhcy1vdmVybGF5cyIgLz5cbjxjYW52YXMgY2xhc3M9XCdiay1jYW52YXNcJz48L2NhbnZhcz4nKX0pLmNhbGwodGhpcyl9LmNhbGwodCksZS5qb2luKCIiKX19LHt9XSwibW9kZWxzL2NhbnZhcy9jYXJ0ZXNpYW5fZnJhbWUiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGYsbT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpZy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxnPXt9Lmhhc093blByb3BlcnR5O3A9dCgidW5kZXJzY29yZSIpLG89dCgiLi4vbWFwcGVycy9jYXRlZ29yaWNhbF9tYXBwZXIiKSxhPXQoIi4uL21hcHBlcnMvZ3JpZF9tYXBwZXIiKSx1PXQoIi4uL21hcHBlcnMvbGluZWFyX21hcHBlciIpLGg9dCgiLi4vbWFwcGVycy9sb2dfbWFwcGVyIiksYz10KCIuLi9yYW5nZXMvcmFuZ2UxZCIpLGY9dCgiLi4vLi4vY29yZS9sYXlvdXQvc29sdmVyIiksaT1mLkVRLHM9Zi5HRSxsPXQoIi4uLy4uL2NvcmUvbGF5b3V0L2xheW91dF9jYW52YXMiKSxfPXQoIi4uLy4uL2NvcmUvbG9nZ2luZyIpLmxvZ2dpbmcsZD10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBtKGUsdCksZS5wcm90b3R5cGUudHlwZT0iQ2FydGVzaWFuRnJhbWUiLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLnBhbmVsPXRoaXMsdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoInhfcmFuZ2VzIixmdW5jdGlvbigpe3JldHVybiB0aGlzLl9nZXRfcmFuZ2VzKCJ4Iil9LCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoInhfcmFuZ2VzIix0aGlzLFsieF9yYW5nZSIsImV4dHJhX3hfcmFuZ2VzIl0pLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJ5X3JhbmdlcyIsZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZ2V0X3JhbmdlcygieSIpfSwhMCksdGhpcy5hZGRfZGVwZW5kZW5jaWVzKCJ5X3JhbmdlcyIsdGhpcyxbInlfcmFuZ2UiLCJleHRyYV95X3JhbmdlcyJdKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgieF9tYXBwZXJzIixmdW5jdGlvbigpe3JldHVybiB0aGlzLl9nZXRfbWFwcGVycygieCIsdGhpcy5nZXQoInhfcmFuZ2VzIiksdGhpcy5nZXQoImhfcmFuZ2UiKSl9LCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoInhfcmFuZ2VzIix0aGlzLFsieF9yYW5nZXMiLCJoX3JhbmdlIl0pLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJ5X21hcHBlcnMiLGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2dldF9tYXBwZXJzKCJ5Iix0aGlzLmdldCgieV9yYW5nZXMiKSx0aGlzLmdldCgidl9yYW5nZSIpKX0sITApLHRoaXMuYWRkX2RlcGVuZGVuY2llcygieV9yYW5nZXMiLHRoaXMsWyJ5X3JhbmdlcyIsInZfcmFuZ2UiXSksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoIm1hcHBlciIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IGEuTW9kZWwoe2RvbWFpbl9tYXBwZXI6dGhpcy5nZXQoInhfbWFwcGVyIiksY29kb21haW5fbWFwcGVyOnRoaXMuZ2V0KCJ5X21hcHBlciIpfSl9LCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoIm1hcHBlciIsdGhpcyxbInhfbWFwcGVyIiwieV9tYXBwZXIiXSksdGhpcy5faF9yYW5nZT1uZXcgYy5Nb2RlbCh7c3RhcnQ6dGhpcy5nZXQoImxlZnQiKSxlbmQ6dGhpcy5nZXQoImxlZnQiKSt0aGlzLmdldCgid2lkdGgiKX0pLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJoX3JhbmdlIixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdC5faF9yYW5nZS5zZXQoInN0YXJ0Iix0LmdldCgibGVmdCIpKSx0Ll9oX3JhbmdlLnNldCgiZW5kIix0LmdldCgibGVmdCIpK3QuZ2V0KCJ3aWR0aCIpKSx0Ll9oX3JhbmdlfX0odGhpcyksITEpLHRoaXMuYWRkX2RlcGVuZGVuY2llcygiaF9yYW5nZSIsdGhpcyxbImxlZnQiLCJ3aWR0aCJdKSx0aGlzLl92X3JhbmdlPW5ldyBjLk1vZGVsKHtzdGFydDp0aGlzLmdldCgiYm90dG9tIiksZW5kOnRoaXMuZ2V0KCJib3R0b20iKSt0aGlzLmdldCgiaGVpZ2h0Iil9KSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgidl9yYW5nZSIsZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHQuX3ZfcmFuZ2Uuc2V0KCJzdGFydCIsdC5nZXQoImJvdHRvbSIpKSx0Ll92X3JhbmdlLnNldCgiZW5kIix0LmdldCgiYm90dG9tIikrdC5nZXQoImhlaWdodCIpKSx0Ll92X3JhbmdlfX0odGhpcyksITEpLHRoaXMuYWRkX2RlcGVuZGVuY2llcygidl9yYW5nZSIsdGhpcyxbImJvdHRvbSIsImhlaWdodCJdKSxudWxsfSxlLnByb3RvdHlwZS5fZG9jX2F0dGFjaGVkPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubGlzdGVuVG8odGhpcy5kb2N1bWVudC5zb2x2ZXIoKSwibGF5b3V0X3VwZGF0ZSIsdGhpcy5fdXBkYXRlX21hcHBlcnMpLG51bGx9LGUucHJvdG90eXBlLmNvbnRhaW5zPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQ+PXRoaXMuZ2V0KCJsZWZ0IikmJnQ8PXRoaXMuZ2V0KCJyaWdodCIpJiZlPj10aGlzLmdldCgiYm90dG9tIikmJmU8PXRoaXMuZ2V0KCJ0b3AiKX0sZS5wcm90b3R5cGUubWFwX3RvX3NjcmVlbj1mdW5jdGlvbih0LGUscixuLG8pe3ZhciBpLHMsYSxsO3JldHVybiBudWxsPT1uJiYobj0iZGVmYXVsdCIpLG51bGw9PW8mJihvPSJkZWZhdWx0IiksYT10aGlzLmdldCgieF9tYXBwZXJzIilbbl0udl9tYXBfdG9fdGFyZ2V0KHQpLGk9ci52X3Z4X3RvX3N4KGEpLGw9dGhpcy5nZXQoInlfbWFwcGVycyIpW29dLnZfbWFwX3RvX3RhcmdldChlKSxzPXIudl92eV90b19zeShsKSxbaSxzXX0sZS5wcm90b3R5cGUuX2dldF9yYW5nZXM9ZnVuY3Rpb24odCl7dmFyIGUscixuLG87aWYobz17fSxvWyJkZWZhdWx0Il09dGhpcy5nZXQodCsiX3JhbmdlIiksZT10aGlzLmdldCgiZXh0cmFfIit0KyJfcmFuZ2VzIiksbnVsbCE9ZSlmb3IociBpbiBlKW49ZVtyXSxvW3JdPW47cmV0dXJuIG99LGUucHJvdG90eXBlLl9nZXRfbWFwcGVycz1mdW5jdGlvbih0LGUscil7dmFyIG4saSxzLGE7aT17fTtmb3IocyBpbiBlKXtpZihhPWVbc10sIlJhbmdlMWQiPT09YS50eXBlfHwiRGF0YVJhbmdlMWQiPT09YS50eXBlKW49ImxvZyI9PT10aGlzLmdldCh0KyJfbWFwcGVyX3R5cGUiKT9oLk1vZGVsOnUuTW9kZWw7ZWxzZXtpZigiRmFjdG9yUmFuZ2UiIT09YS50eXBlKXJldHVybiBsb2dnZXIud2FybigidW5rbm93biByYW5nZSB0eXBlIGZvciByYW5nZSAnIitzKyInOiAiK2EpLG51bGw7bj1vLk1vZGVsfWlbc109bmV3IG4oe3NvdXJjZV9yYW5nZTphLHRhcmdldF9yYW5nZTpyfSl9cmV0dXJuIGl9LGUucHJvdG90eXBlLl91cGRhdGVfbWFwcGVycz1mdW5jdGlvbigpe3ZhciB0LGUscixuO3I9dGhpcy5nZXQoInhfbWFwcGVycyIpO2ZvcihlIGluIHIpdD1yW2VdLHQuc2V0KCJ0YXJnZXRfcmFuZ2UiLHRoaXMuZ2V0KCJoX3JhbmdlIikpO249dGhpcy5nZXQoInlfbWFwcGVycyIpO2ZvcihlIGluIG4pdD1uW2VdLHQuc2V0KCJ0YXJnZXRfcmFuZ2UiLHRoaXMuZ2V0KCJ2X3JhbmdlIikpO3JldHVybiBudWxsfSxlLmludGVybmFsKHtleHRyYV94X3JhbmdlczpbZC5Bbnkse31dLGV4dHJhX3lfcmFuZ2VzOltkLkFueSx7fV0seF9yYW5nZTpbZC5JbnN0YW5jZV0seV9yYW5nZTpbZC5JbnN0YW5jZV0seF9tYXBwZXJfdHlwZTpbZC5BbnldLHlfbWFwcGVyX3R5cGU6W2QuQW55XX0pLGUucHJvdG90eXBlLmdldF9jb25zdHJhaW50cz1mdW5jdGlvbigpe3ZhciB0O3JldHVybiB0PVtdLHQucHVzaChzKHRoaXMuX3RvcCkpLHQucHVzaChzKHRoaXMuX2JvdHRvbSkpLHQucHVzaChzKHRoaXMuX2xlZnQpKSx0LnB1c2gocyh0aGlzLl9yaWdodCkpLHQucHVzaChzKHRoaXMuX3dpZHRoKSksdC5wdXNoKHModGhpcy5faGVpZ2h0KSksdC5wdXNoKGkodGhpcy5fbGVmdCx0aGlzLl93aWR0aCxbLTEsdGhpcy5fcmlnaHRdKSksdC5wdXNoKGkodGhpcy5fYm90dG9tLHRoaXMuX2hlaWdodCxbLTEsdGhpcy5fdG9wXSkpLHR9LGV9KGwuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29yZS9sYXlvdXQvbGF5b3V0X2NhbnZhcyI6ImNvcmUvbGF5b3V0L2xheW91dF9jYW52YXMiLCIuLi8uLi9jb3JlL2xheW91dC9zb2x2ZXIiOiJjb3JlL2xheW91dC9zb2x2ZXIiLCIuLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciI6Im1vZGVscy9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciIsIi4uL21hcHBlcnMvZ3JpZF9tYXBwZXIiOiJtb2RlbHMvbWFwcGVycy9ncmlkX21hcHBlciIsIi4uL21hcHBlcnMvbGluZWFyX21hcHBlciI6Im1vZGVscy9tYXBwZXJzL2xpbmVhcl9tYXBwZXIiLCIuLi9tYXBwZXJzL2xvZ19tYXBwZXIiOiJtb2RlbHMvbWFwcGVycy9sb2dfbWFwcGVyIiwiLi4vcmFuZ2VzL3JhbmdlMWQiOiJtb2RlbHMvcmFuZ2VzL3JhbmdlMWQiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9mb3JtYXR0ZXJzL2Jhc2ljX3RpY2tfZm9ybWF0dGVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxvPXQoIi4vdGlja19mb3JtYXR0ZXIiKSxzPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGEoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJCYXNpY1RpY2tGb3JtYXR0ZXIiLGUuZGVmaW5lKHtwcmVjaXNpb246W3MuQW55LCJhdXRvIl0sdXNlX3NjaWVudGlmaWM6W3MuQm9vbCwhMF0scG93ZXJfbGltaXRfaGlnaDpbcy5OdW1iZXIsNV0scG93ZXJfbGltaXRfbG93OltzLk51bWJlciwtM119KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoInNjaWVudGlmaWNfbGltaXRfbG93IixmdW5jdGlvbigpe3JldHVybiBNYXRoLnBvdygxMCx0aGlzLmdldCgicG93ZXJfbGltaXRfbG93IikpfSwhMCksdGhpcy5hZGRfZGVwZW5kZW5jaWVzKCJzY2llbnRpZmljX2xpbWl0X2xvdyIsdGhpcyxbInBvd2VyX2xpbWl0X2xvdyJdKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgic2NpZW50aWZpY19saW1pdF9oaWdoIixmdW5jdGlvbigpe3JldHVybiBNYXRoLnBvdygxMCx0aGlzLmdldCgicG93ZXJfbGltaXRfaGlnaCIpKX0sITApLHRoaXMuYWRkX2RlcGVuZGVuY2llcygic2NpZW50aWZpY19saW1pdF9oaWdoIix0aGlzLFsicG93ZXJfbGltaXRfaGlnaCJdKSx0aGlzLmxhc3RfcHJlY2lzaW9uPTN9LGUucHJvdG90eXBlLmRvRm9ybWF0PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLHMsYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdztpZigwPT09dC5sZW5ndGgpcmV0dXJuW107aWYodz0wLHQubGVuZ3RoPj0yJiYodz1NYXRoLmFicyh0WzFdLXRbMF0pLzFlNCksYz0hMSx0aGlzLmdldCgidXNlX3NjaWVudGlmaWMiKSlmb3Iobj0wLGw9dC5sZW5ndGg7bjxsO24rKylpZih2PXRbbl0sYj1NYXRoLmFicyh2KSxiPncmJihiPj10aGlzLmdldCgic2NpZW50aWZpY19saW1pdF9oaWdoIil8fGI8PXRoaXMuZ2V0KCJzY2llbnRpZmljX2xpbWl0X2xvdyIpKSl7Yz0hMDticmVha31pZihfPXRoaXMuZ2V0KCJwcmVjaXNpb24iKSxudWxsPT1ffHxpLmlzTnVtYmVyKF8pKXtpZihhPW5ldyBBcnJheSh0Lmxlbmd0aCksYylmb3IoZT1vPTAsZD10Lmxlbmd0aDswPD1kP288ZDpvPmQ7ZT0wPD1kPysrbzotLW8pYVtlXT10W2VdLnRvRXhwb25lbnRpYWwoX3x8dm9pZCAwKTtlbHNlIGZvcihlPXM9MCxmPXQubGVuZ3RoOzA8PWY/czxmOnM+ZjtlPTA8PWY/KytzOi0tcylhW2VdPXRbZV0udG9GaXhlZChffHx2b2lkIDApLnJlcGxhY2UoLyhcLlswLTldKj8pMCskLywiJDEiKS5yZXBsYWNlKC9cLiQvLCIiKTtyZXR1cm4gYX1pZigiYXV0byI9PT1fKWZvcihhPW5ldyBBcnJheSh0Lmxlbmd0aCkseD11PW09dGhpcy5sYXN0X3ByZWNpc2lvbjttPD0xNT91PD0xNTp1Pj0xNTt4PW08PTE1PysrdTotLXUpe2lmKHI9ITAsYyl7Zm9yKGU9aD0wLGc9dC5sZW5ndGg7MDw9Zz9oPGc6aD5nO2U9MDw9Zz8rK2g6LS1oKWlmKGFbZV09dFtlXS50b0V4cG9uZW50aWFsKHgpLGU+MCYmYVtlXT09PWFbZS0xXSl7cj0hMTticmVha31pZihyKWJyZWFrfWVsc2V7Zm9yKGU9cD0wLHk9dC5sZW5ndGg7MDw9eT9wPHk6cD55O2U9MDw9eT8rK3A6LS1wKWlmKGFbZV09dFtlXS50b0ZpeGVkKHgpLnJlcGxhY2UoLyhcLlswLTldKj8pMCskLywiJDEiKS5yZXBsYWNlKC9cLiQvLCIiKSxlPjAmJmFbZV09PT1hW2UtMV0pe3I9ITE7YnJlYWt9aWYocilicmVha31pZihyKXJldHVybiB0aGlzLmxhc3RfcHJlY2lzaW9uPXgsYX1yZXR1cm4gYX0sZX0oby5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpufX0seyIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuL3RpY2tfZm9ybWF0dGVyIjoibW9kZWxzL2Zvcm1hdHRlcnMvdGlja19mb3JtYXR0ZXIiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9mb3JtYXR0ZXJzL2NhdGVnb3JpY2FsX3RpY2tfZm9ybWF0dGVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpcy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxzPXt9Lmhhc093blByb3BlcnR5O289dCgiLi4vZm9ybWF0dGVycy90aWNrX2Zvcm1hdHRlciIpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGkoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJDYXRlZ29yaWNhbFRpY2tGb3JtYXR0ZXIiLGUucHJvdG90eXBlLmRvRm9ybWF0PWZ1bmN0aW9uKHQpe3JldHVybiB0fSxlfShvLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm59fSx7Ii4uL2Zvcm1hdHRlcnMvdGlja19mb3JtYXR0ZXIiOiJtb2RlbHMvZm9ybWF0dGVycy90aWNrX2Zvcm1hdHRlciJ9XSwibW9kZWxzL2Zvcm1hdHRlcnMvZGF0ZXRpbWVfdGlja19mb3JtYXR0ZXIiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlmLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGY9e30uaGFzT3duUHJvcGVydHk7YT10KCJ1bmRlcnNjb3JlIiksaT10KCJzcHJpbnRmIiksXz10KCJ0aW1lem9uZSIpLHM9dCgiLi90aWNrX2Zvcm1hdHRlciIpLGM9dCgiLi4vLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLHA9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksaD1mdW5jdGlvbih0KXtyZXR1cm4gTWF0aC5yb3VuZCh0LzFlMyUxKjFlNil9LGw9ZnVuY3Rpb24odCl7cmV0dXJuIF8odCwiJVkgJW0gJWQgJUggJU0gJVMiKS5zcGxpdCgvXHMrLykubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBwYXJzZUludCh0LDEwKX0pfSx1PWZ1bmN0aW9uKHQsZSl7dmFyIHI7cmV0dXJuIGEuaXNGdW5jdGlvbihlKT9lKHQpOihyPWkuc3ByaW50ZigiJDElMDZkIixoKHQpKSxlPWUucmVwbGFjZSgvKChefFteJV0pKCUlKSopJWYvLHIpLGUuaW5kZXhPZigiJSIpPT09LTE/ZTpfKHQsZSkpfSxuPXttaWNyb3NlY29uZHM6WyIlZnVzIl0sbWlsbGlzZWNvbmRzOlsiJTNObXMiLCIlUy4lM05zIl0sc2Vjb25kczpbIiVTcyJdLG1pbnNlYzpbIjolTTolUyJdLG1pbnV0ZXM6WyI6JU0iLCIlTW0iXSxob3VybWluOlsiJUg6JU0iXSxob3VyczpbIiVIaCIsIiVIOiVNIl0sZGF5czpbIiVtLyVkIiwiJWElZCJdLG1vbnRoczpbIiVtLyVZIiwiJWIleSJdLHllYXJzOlsiJVkiXX0sbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gZChlLHQpLGUucHJvdG90eXBlLnR5cGU9IkRhdGV0aW1lVGlja0Zvcm1hdHRlciIsZS5kZWZpbmUoe2Zvcm1hdHM6W3AuQW55LG5dfSksZS5wcm90b3R5cGUuZm9ybWF0X29yZGVyPVsibWljcm9zZWNvbmRzIiwibWlsbGlzZWNvbmRzIiwic2Vjb25kcyIsIm1pbnNlYyIsIm1pbnV0ZXMiLCJob3VybWluIiwiaG91cnMiLCJkYXlzIiwibW9udGhzIiwieWVhcnMiXSxlLnByb3RvdHlwZS5zdHJpcF9sZWFkaW5nX3plcm9zPSEwLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLl91cGRhdGVfd2lkdGhfZm9ybWF0cygpfSxlLnByb3RvdHlwZS5fdXBkYXRlX3dpZHRoX2Zvcm1hdHM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxsO249XyhuZXcgRGF0ZSksdGhpcy5fd2lkdGhfZm9ybWF0cz17fSxvPXRoaXMuZm9ybWF0cyxpPVtdO2Zvcih0IGluIG8pcj1vW3RdLHM9ZnVuY3Rpb24oKXt2YXIgdCxvLGk7Zm9yKGk9W10sdD0wLG89ci5sZW5ndGg7dDxvO3QrKyllPXJbdF0saS5wdXNoKHUobixlKS5sZW5ndGgpO3JldHVybiBpfSgpLGw9YS5zb3J0QnkoYS56aXAocyxyKSxmdW5jdGlvbih0KXt2YXIgZSxyO3JldHVybiByPXRbMF0sZT10WzFdLHJ9KSxpLnB1c2godGhpcy5fd2lkdGhfZm9ybWF0c1t0XT1hLnppcC5hcHBseShhLGwpKTtyZXR1cm4gaX0sZS5wcm90b3R5cGUuX2dldF9yZXNvbHV0aW9uX3N0cj1mdW5jdGlvbih0LGUpe3ZhciByLG47cmV0dXJuIHI9MS4xKnQsbj1yPC4wMDE/Im1pY3Jvc2Vjb25kcyI6cjwxPyJtaWxsaXNlY29uZHMiOnI8NjA/ZT49NjA/Im1pbnNlYyI6InNlY29uZHMiOnI8MzYwMD9lPj0zNjAwPyJob3VybWluIjoibWludXRlcyI6cjw4NjQwMD8iaG91cnMiOnI8MjY3ODQwMD8iZGF5cyI6cjwzMTUzNmUzPyJtb250aHMiOiJ5ZWFycyJ9LGUucHJvdG90eXBlLmRvRm9ybWF0PWZ1bmN0aW9uKHQsZSxyLG4sbyl7dmFyIGkscyxoLHAsXyxkLGYsbSxnLHksdixiLHgsdyxNLGssaixULFMseixQLEUsQSxDLE4sTyxxLEQsSTtpZihudWxsPT1lJiYoZT1udWxsKSxudWxsPT1yJiYocj1udWxsKSxudWxsPT1uJiYobj0uMyksbnVsbD09byYmKG89bnVsbCksMD09PXQubGVuZ3RoKXJldHVybltdO2lmKEM9TWF0aC5hYnModFt0Lmxlbmd0aC0xXS10WzBdKS8xZTMsaj1vP28ucmVzb2x1dGlvbjpDLyh0Lmxlbmd0aC0xKSxQPXRoaXMuX2dldF9yZXNvbHV0aW9uX3N0cihqLEMpLFQ9dGhpcy5fd2lkdGhfZm9ybWF0c1tQXSxJPVRbMF0sXz1UWzFdLHA9X1swXSxyKXtmb3IoZD1bXSxtPWc9MCxTPUkubGVuZ3RoOzA8PVM/ZzxTOmc+UzttPTA8PVM/KytnOi0tZylJW21dKnQubGVuZ3RoPG4qciYmZC5wdXNoKHRoaXMuX3dpZHRoX2Zvcm1hdHNbbV0pO2QubGVuZ3RoPjAmJihwPWEubGFzdChkKSl9Zm9yKGI9W10sRT10aGlzLmZvcm1hdF9vcmRlci5pbmRleE9mKFApLHE9e30sej10aGlzLmZvcm1hdF9vcmRlcix5PTAseD16Lmxlbmd0aDt5PHg7eSsrKWg9elt5XSxxW2hdPTA7Zm9yKHEuc2Vjb25kcz01LHEubWluc2VjPTQscS5taW51dGVzPTQscS5ob3VybWluPTMscS5ob3Vycz0zLHY9MCx3PXQubGVuZ3RoO3Y8dzt2Kyspe089dFt2XTt0cnl7RD1sKE8pLEE9dShPLHApfWNhdGNoKHMpe2k9cyxjLndhcm4oInVuYWJsZSB0byBmb3JtYXQgdGljayBmb3IgdGltZXN0YW1wIHZhbHVlICIrTyksYy53YXJuKCIgLSAiK2kpLGIucHVzaCgiRVJSIik7Y29udGludWV9Zm9yKGY9ITEsaz1FOzA9PT1EW3FbdGhpcy5mb3JtYXRfb3JkZXJba11dXSYmKGsrPTEsayE9PXRoaXMuZm9ybWF0X29yZGVyLmxlbmd0aCk7KXtpZigoIm1pbnNlYyI9PT1QfHwiaG91cm1pbiI9PT1QKSYmIWYpe2lmKCJtaW5zZWMiPT09UCYmMD09PURbNF0mJjAhPT1EWzVdfHwiaG91cm1pbiI9PT1QJiYwPT09RFszXSYmMCE9PURbNF0pe009dGhpcy5fd2lkdGhfZm9ybWF0c1t0aGlzLmZvcm1hdF9vcmRlcltFLTFdXVsxXVswXSxBPXUoTyxNKTticmVha31mPSEwfU09dGhpcy5fd2lkdGhfZm9ybWF0c1t0aGlzLmZvcm1hdF9vcmRlcltrXV1bMV1bMF0sQT11KE8sTSl9dGhpcy5zdHJpcF9sZWFkaW5nX3plcm9zPyhOPUEucmVwbGFjZSgvXjArL2csIiIpLE4hPT1BJiZpc05hTihwYXJzZUludChOKSkmJihOPSIwIitOKSxiLnB1c2goTikpOmIucHVzaChBKX1yZXR1cm4gYn0sZX0ocy5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvfX0seyIuLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuL3RpY2tfZm9ybWF0dGVyIjoibW9kZWxzL2Zvcm1hdHRlcnMvdGlja19mb3JtYXR0ZXIiLHNwcmludGY6InNwcmludGYiLHRpbWV6b25lOiJ0aW1lem9uZS9pbmRleCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2Zvcm1hdHRlcnMvZnVuY190aWNrX2Zvcm1hdHRlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlsLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGw9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIikscz10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxvPXQoIi4uL2Zvcm1hdHRlcnMvdGlja19mb3JtYXR0ZXIiKSxuPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIHIoKXtyZXR1cm4gci5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKHIsZSksci5wcm90b3R5cGUudHlwZT0iRnVuY1RpY2tGb3JtYXR0ZXIiLHIuZGVmaW5lKHtjb2RlOltzLlN0cmluZywiIl0sbGFuZzpbcy5TdHJpbmcsImphdmFzY3JpcHQiXX0pLHIucHJvdG90eXBlLmRvRm9ybWF0PWZ1bmN0aW9uKGUpe3ZhciByLG4sbztyZXR1cm4gcj10aGlzLmdldCgiY29kZSIpLHI9ZnVuY3Rpb24oKXtzd2l0Y2godGhpcy5nZXQoImxhbmciKSl7Y2FzZSJqYXZhc2NyaXB0IjpyZXR1cm4gcjtjYXNlImNvZmZlZXNjcmlwdCI6cmV0dXJuIG49dCgiY29mZmVlLXNjcmlwdCIpLG4uY29tcGlsZShyLHtiYXJlOiEwLHNoaWZ0TGluZTohMH0pfX0uY2FsbCh0aGlzKSxvPW5ldyBGdW5jdGlvbigidGljayIsInZhciBmdW5jID0gIityKyJyZXR1cm4gZnVuYyh0aWNrKSIpLGkubWFwKGUsbyl9LHJ9KG8uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vZm9ybWF0dGVycy90aWNrX2Zvcm1hdHRlciI6Im1vZGVscy9mb3JtYXR0ZXJzL3RpY2tfZm9ybWF0dGVyIiwiY29mZmVlLXNjcmlwdCI6dm9pZCAwLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9mb3JtYXR0ZXJzL2xvZ190aWNrX2Zvcm1hdHRlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpaC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxoPXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLG49dCgiLi9iYXNpY190aWNrX2Zvcm1hdHRlciIpLGk9dCgiLi90aWNrX2Zvcm1hdHRlciIpLGE9dCgiLi4vLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLGw9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLnR5cGU9IkxvZ1RpY2tGb3JtYXR0ZXIiLGUuZGVmaW5lKHt0aWNrZXI6W2wuSW5zdGFuY2UsbnVsbF19KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7aWYoZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLmJhc2ljX2Zvcm1hdHRlcj1uZXcgbi5Nb2RlbCxudWxsPT10aGlzLmdldCgidGlja2VyIikpcmV0dXJuIGEud2FybigiTG9nVGlja0Zvcm1hdHRlciBub3QgY29uZmlndXJlZCB3aXRoIGEgdGlja2VyLCB1c2luZyBkZWZhdWx0IGJhc2Ugb2YgMTAgKGxhYmVscyB3aWxsIGJlIGluY29ycmVjdCBpZiB0aWNrZXIgYmFzZSBpcyBub3QgMTApIil9LGUucHJvdG90eXBlLmRvRm9ybWF0PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscztpZigwPT09dC5sZW5ndGgpcmV0dXJuW107Zm9yKGU9bnVsbCE9dGhpcy5nZXQoInRpY2tlciIpP3RoaXMuZ2V0KCJ0aWNrZXIiKS5nZXQoImJhc2UiKToxMCxzPSExLG89bmV3IEFycmF5KHQubGVuZ3RoKSxyPW49MCxpPXQubGVuZ3RoOzA8PWk/bjxpOm4+aTtyPTA8PWk/KytuOi0tbilpZihvW3JdPWUrIl4iK01hdGgucm91bmQoTWF0aC5sb2codFtyXSkvTWF0aC5sb2coZSkpLHI+MCYmb1tyXT09PW9bci0xXSl7cz0hMDticmVha31yZXR1cm4gcyYmKG89dGhpcy5iYXNpY19mb3JtYXR0ZXIuZG9Gb3JtYXQodCkpLG99LGV9KGkuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9iYXNpY190aWNrX2Zvcm1hdHRlciI6Im1vZGVscy9mb3JtYXR0ZXJzL2Jhc2ljX3RpY2tfZm9ybWF0dGVyIiwiLi90aWNrX2Zvcm1hdHRlciI6Im1vZGVscy9mb3JtYXR0ZXJzL3RpY2tfZm9ybWF0dGVyIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvZm9ybWF0dGVycy9udW1lcmFsX3RpY2tfZm9ybWF0dGVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpdS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSx1PXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLG49dCgibnVtYnJvIiksaT10KCIuL3RpY2tfZm9ybWF0dGVyIiksYT10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUudHlwZT0iTnVtZXJhbFRpY2tGb3JtYXR0ZXIiLGUuZGVmaW5lKHtmb3JtYXQ6W2EuU3RyaW5nLCIwLDAiXSxsYW5ndWFnZTpbYS5TdHJpbmcsImVuIl0scm91bmRpbmc6W2EuU3RyaW5nLCJyb3VuZCJdfSksZS5wcm90b3R5cGUuZG9Gb3JtYXQ9ZnVuY3Rpb24odCl7dmFyIGUscixvLGkscztyZXR1cm4gZT10aGlzLmdldCgiZm9ybWF0Iiksbz10aGlzLmdldCgibGFuZ3VhZ2UiKSxpPWZ1bmN0aW9uKCl7c3dpdGNoKHRoaXMuZ2V0KCJyb3VuZGluZyIpKXtjYXNlInJvdW5kIjpjYXNlIm5lYXJlc3QiOnJldHVybiBNYXRoLnJvdW5kO2Nhc2UiZmxvb3IiOmNhc2Uicm91bmRkb3duIjpyZXR1cm4gTWF0aC5mbG9vcjtjYXNlImNlaWwiOmNhc2Uicm91bmR1cCI6cmV0dXJuIE1hdGguY2VpbH19LmNhbGwodGhpcykscj1mdW5jdGlvbigpe3ZhciByLGEsbDtmb3IobD1bXSxyPTAsYT10Lmxlbmd0aDtyPGE7cisrKXM9dFtyXSxsLnB1c2gobi5mb3JtYXQocyxlLG8saSkpO3JldHVybiBsfSgpfSxlfShpLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm99fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vdGlja19mb3JtYXR0ZXIiOiJtb2RlbHMvZm9ybWF0dGVycy90aWNrX2Zvcm1hdHRlciIsbnVtYnJvOiJudW1icm8vbnVtYnJvIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvZm9ybWF0dGVycy9wcmludGZfdGlja19mb3JtYXR0ZXIiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl1LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHU9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbz10KCJzcHJpbnRmIiksaT10KCIuL3RpY2tfZm9ybWF0dGVyIiksYT10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUudHlwZT0iUHJpbnRmVGlja0Zvcm1hdHRlciIsZS5kZWZpbmUoe2Zvcm1hdDpbYS5TdHJpbmcsIiVzIl19KSxlLnByb3RvdHlwZS5kb0Zvcm1hdD1mdW5jdGlvbih0KXt2YXIgZSxyLG47cmV0dXJuIGU9dGhpcy5nZXQoImZvcm1hdCIpLHI9ZnVuY3Rpb24oKXt2YXIgcixpLHM7Zm9yKHM9W10scj0wLGk9dC5sZW5ndGg7cjxpO3IrKyluPXRbcl0scy5wdXNoKG8uc3ByaW50ZihlLG4pKTtyZXR1cm4gc30oKX0sZX0oaS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpufX0seyIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuL3RpY2tfZm9ybWF0dGVyIjoibW9kZWxzL2Zvcm1hdHRlcnMvdGlja19mb3JtYXR0ZXIiLHNwcmludGY6InNwcmludGYiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9mb3JtYXR0ZXJzL3RpY2tfZm9ybWF0dGVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlhLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGE9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIiksbj10KCIuLi8uLi9tb2RlbCIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHMoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJUaWNrRm9ybWF0dGVyIixlLnByb3RvdHlwZS5kb0Zvcm1hdD1mdW5jdGlvbih0KXt9LGV9KG4pLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi4vLi4vbW9kZWwiOiJtb2RlbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2dseXBocy9hbm51bGFyX3dlZGdlIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGg9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWMuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sYz17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxpPXQoIi4vZ2x5cGgiKSxsPXQoIi4uLy4uL2NvbW1vbi9oaXR0ZXN0IiksdT10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxhPXQoIi4uLy4uL2NvcmUvdXRpbC9tYXRoIikuYW5nbGVfYmV0d2VlbixvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBoKGUsdCksZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5feHlfaW5kZXgoKX0sZS5wcm90b3R5cGUuX21hcF9kYXRhPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47Zm9yKCJkYXRhIj09PXRoaXMubW9kZWwucHJvcGVydGllcy5pbm5lcl9yYWRpdXMudW5pdHM/dGhpcy5zaW5uZXJfcmFkaXVzPXRoaXMuc2Rpc3QodGhpcy5yZW5kZXJlci54bWFwcGVyLHRoaXMuX3gsdGhpcy5faW5uZXJfcmFkaXVzKTp0aGlzLnNpbm5lcl9yYWRpdXM9dGhpcy5faW5uZXJfcmFkaXVzLCJkYXRhIj09PXRoaXMubW9kZWwucHJvcGVydGllcy5vdXRlcl9yYWRpdXMudW5pdHM/dGhpcy5zb3V0ZXJfcmFkaXVzPXRoaXMuc2Rpc3QodGhpcy5yZW5kZXJlci54bWFwcGVyLHRoaXMuX3gsdGhpcy5fb3V0ZXJfcmFkaXVzKTp0aGlzLnNvdXRlcl9yYWRpdXM9dGhpcy5fb3V0ZXJfcmFkaXVzLHRoaXMuX2FuZ2xlPW5ldyBGbG9hdDMyQXJyYXkodGhpcy5fc3RhcnRfYW5nbGUubGVuZ3RoKSxuPVtdLHQ9ZT0wLHI9dGhpcy5fc3RhcnRfYW5nbGUubGVuZ3RoOzA8PXI/ZTxyOmU+cjt0PTA8PXI/KytlOi0tZSluLnB1c2godGhpcy5fYW5nbGVbdF09dGhpcy5fZW5kX2FuZ2xlW3RdLXRoaXMuX3N0YXJ0X2FuZ2xlW3RdKTtyZXR1cm4gbn0sZS5wcm90b3R5cGUuX3JlbmRlcj1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHAsXztmb3IocD1yLnN4LF89ci5zeSxvPXIuX3N0YXJ0X2FuZ2xlLG49ci5fYW5nbGUsaD1yLnNpbm5lcl9yYWRpdXMsYz1yLnNvdXRlcl9yYWRpdXMsaT10aGlzLm1vZGVsLnByb3BlcnRpZXMuZGlyZWN0aW9uLnZhbHVlKCksdT1bXSxhPTAsbD1lLmxlbmd0aDthPGw7YSsrKXM9ZVthXSxpc05hTihwW3NdK19bc10raFtzXStjW3NdK29bc10rbltzXSl8fCh0LnRyYW5zbGF0ZShwW3NdLF9bc10pLHQucm90YXRlKG9bc10pLHQubW92ZVRvKGNbc10sMCksdC5iZWdpblBhdGgoKSx0LmFyYygwLDAsY1tzXSwwLG5bc10saSksdC5yb3RhdGUobltzXSksdC5saW5lVG8oaFtzXSwwKSx0LmFyYygwLDAsaFtzXSwwLC1uW3NdLCFpKSx0LmNsb3NlUGF0aCgpLHQucm90YXRlKC1uW3NdLW9bc10pLHQudHJhbnNsYXRlKC1wW3NdLC1fW3NdKSx0aGlzLnZpc3VhbHMuZmlsbC5kb2l0JiYodGhpcy52aXN1YWxzLmZpbGwuc2V0X3ZlY3Rvcml6ZSh0LHMpLHQuZmlsbCgpKSx0aGlzLnZpc3VhbHMubGluZS5kb2l0Pyh0aGlzLnZpc3VhbHMubGluZS5zZXRfdmVjdG9yaXplKHQscyksdS5wdXNoKHQuc3Ryb2tlKCkpKTp1LnB1c2godm9pZCAwKSk7cmV0dXJuIHV9LGUucHJvdG90eXBlLl9oaXRfcG9pbnQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTLHosUCxFLEEsQyxOLE8scSxELEksUixGLEIsTDtmb3IoeT1bdC52eCx0LnZ5XSxFPXlbMF0sTj15WzFdLEQ9dGhpcy5yZW5kZXJlci54bWFwcGVyLm1hcF9mcm9tX3RhcmdldChFLCEwKSxGPXRoaXMucmVuZGVyZXIueW1hcHBlci5tYXBfZnJvbV90YXJnZXQoTiwhMCksImRhdGEiPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLm91dGVyX3JhZGl1cy51bml0cz8oST1ELXRoaXMubWF4X291dGVyX3JhZGl1cyxSPUQrdGhpcy5tYXhfb3V0ZXJfcmFkaXVzLEI9Ri10aGlzLm1heF9vdXRlcl9yYWRpdXMsTD1GK3RoaXMubWF4X291dGVyX3JhZGl1cyk6KEE9RS10aGlzLm1heF9vdXRlcl9yYWRpdXMsQz1FK3RoaXMubWF4X291dGVyX3JhZGl1cyx2PXRoaXMucmVuZGVyZXIueG1hcHBlci52X21hcF9mcm9tX3RhcmdldChbQSxDXSwhMCksST12WzBdLFI9dlsxXSxPPU4tdGhpcy5tYXhfb3V0ZXJfcmFkaXVzLHE9Tit0aGlzLm1heF9vdXRlcl9yYWRpdXMsYj10aGlzLnJlbmRlcmVyLnltYXBwZXIudl9tYXBfZnJvbV90YXJnZXQoW08scV0sITApLEI9YlswXSxMPWJbMV0pLG49W10scj1sLnZhbGlkYXRlX2Jib3hfY29vcmRzKFtJLFJdLFtCLExdKSx4PWZ1bmN0aW9uKCl7dmFyIHQsZSxuLG87Zm9yKG49dGhpcy5pbmRleC5zZWFyY2gociksbz1bXSx0PTAsZT1uLmxlbmd0aDt0PGU7dCsrKWc9blt0XSxvLnB1c2goZy5pKTtyZXR1cm4gb30uY2FsbCh0aGlzKSxwPTAsZD14Lmxlbmd0aDtwPGQ7cCsrKWg9eFtwXSwKbT1NYXRoLnBvdyh0aGlzLnNvdXRlcl9yYWRpdXNbaF0sMiksYz1NYXRoLnBvdyh0aGlzLnNpbm5lcl9yYWRpdXNbaF0sMiksaj10aGlzLnJlbmRlcmVyLnhtYXBwZXIubWFwX3RvX3RhcmdldChELCEwKSxUPXRoaXMucmVuZGVyZXIueG1hcHBlci5tYXBfdG9fdGFyZ2V0KHRoaXMuX3hbaF0sITApLHo9dGhpcy5yZW5kZXJlci55bWFwcGVyLm1hcF90b190YXJnZXQoRiwhMCksUD10aGlzLnJlbmRlcmVyLnltYXBwZXIubWFwX3RvX3RhcmdldCh0aGlzLl95W2hdLCEwKSxpPU1hdGgucG93KGotVCwyKStNYXRoLnBvdyh6LVAsMiksaTw9bSYmaT49YyYmbi5wdXNoKFtoLGldKTtmb3Iobz10aGlzLm1vZGVsLnByb3BlcnRpZXMuZGlyZWN0aW9uLnZhbHVlKCksdT1bXSxfPTAsZj1uLmxlbmd0aDtfPGY7XysrKXc9bltfXSxoPXdbMF0saT13WzFdLGs9dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcuY2FudmFzLnZ4X3RvX3N4KEUpLFM9dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcuY2FudmFzLnZ5X3RvX3N5KE4pLGU9TWF0aC5hdGFuMihTLXRoaXMuc3lbaF0say10aGlzLnN4W2hdKSxhKC1lLC10aGlzLl9zdGFydF9hbmdsZVtoXSwtdGhpcy5fZW5kX2FuZ2xlW2hdLG8pJiZ1LnB1c2goW2gsaV0pO3JldHVybiBNPWwuY3JlYXRlX2hpdF90ZXN0X3Jlc3VsdCgpLE1bIjFkIl0uaW5kaWNlcz1zLmNoYWluKHUpLnNvcnRCeShmdW5jdGlvbih0KXtyZXR1cm4gdFsxXX0pLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdFswXX0pLnZhbHVlKCksTX0sZS5wcm90b3R5cGUuZHJhd19sZWdlbmQ9ZnVuY3Rpb24odCxlLHIsbixvKXtyZXR1cm4gdGhpcy5fZ2VuZXJpY19hcmVhX2xlZ2VuZCh0LGUscixuLG8pfSxlLnByb3RvdHlwZS5fc2N4eT1mdW5jdGlvbih0KXt2YXIgZSxyO3JldHVybiByPSh0aGlzLnNpbm5lcl9yYWRpdXNbdF0rdGhpcy5zb3V0ZXJfcmFkaXVzW3RdKS8yLGU9KHRoaXMuX3N0YXJ0X2FuZ2xlW3RdK3RoaXMuX2VuZF9hbmdsZVt0XSkvMix7eDp0aGlzLnN4W3RdK3IqTWF0aC5jb3MoZSkseTp0aGlzLnN5W3RdK3IqTWF0aC5zaW4oZSl9fSxlLnByb3RvdHlwZS5zY3g9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX3NjeHkodCkueH0sZS5wcm90b3R5cGUuc2N5PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9zY3h5KHQpLnl9LGV9KGkuVmlldyksbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1vLGUucHJvdG90eXBlLnR5cGU9IkFubnVsYXJXZWRnZSIsZS5jb29yZHMoW1sieCIsInkiXV0pLGUubWl4aW5zKFsibGluZSIsImZpbGwiXSksZS5kZWZpbmUoe2RpcmVjdGlvbjpbdS5EaXJlY3Rpb24sImFudGljbG9jayJdLGlubmVyX3JhZGl1czpbdS5EaXN0YW5jZVNwZWNdLG91dGVyX3JhZGl1czpbdS5EaXN0YW5jZVNwZWNdLHN0YXJ0X2FuZ2xlOlt1LkFuZ2xlU3BlY10sZW5kX2FuZ2xlOlt1LkFuZ2xlU3BlY119KSxlfShpLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm4sVmlldzpvfX0seyIuLi8uLi9jb21tb24vaGl0dGVzdCI6ImNvbW1vbi9oaXR0ZXN0IiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vY29yZS91dGlsL21hdGgiOiJjb3JlL3V0aWwvbWF0aCIsIi4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvZ2x5cGhzL2FubnVsdXMiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHU9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWguY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0saD17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxpPXQoIi4vZ2x5cGgiKSxhPXQoIi4uLy4uL2NvbW1vbi9oaXR0ZXN0IiksbD10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5feHlfaW5kZXgoKX0sZS5wcm90b3R5cGUuX21hcF9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuImRhdGEiPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLmlubmVyX3JhZGl1cy51bml0cz90aGlzLnNpbm5lcl9yYWRpdXM9dGhpcy5zZGlzdCh0aGlzLnJlbmRlcmVyLnhtYXBwZXIsdGhpcy5feCx0aGlzLl9pbm5lcl9yYWRpdXMpOnRoaXMuc2lubmVyX3JhZGl1cz10aGlzLl9pbm5lcl9yYWRpdXMsImRhdGEiPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLm91dGVyX3JhZGl1cy51bml0cz90aGlzLnNvdXRlcl9yYWRpdXM9dGhpcy5zZGlzdCh0aGlzLnJlbmRlcmVyLnhtYXBwZXIsdGhpcy5feCx0aGlzLl9vdXRlcl9yYWRpdXMpOnRoaXMuc291dGVyX3JhZGl1cz10aGlzLl9vdXRlcl9yYWRpdXN9LGUucHJvdG90eXBlLl9yZW5kZXI9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmO2ZvcihkPXIuc3gsZj1yLnN5LHA9ci5zaW5uZXJfcmFkaXVzLF89ci5zb3V0ZXJfcmFkaXVzLGM9W10scz0wLGw9ZS5sZW5ndGg7czxsO3MrKylpZihvPWVbc10sIWlzTmFOKGRbb10rZltvXStwW29dK19bb10pKXtpZihpPW5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZigiTVNJRSIpPj0wfHxuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoIlRyaWRlbnQiKT4wfHxuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoIkVkZ2UiKT4wLHRoaXMudmlzdWFscy5maWxsLmRvaXQpe2lmKHRoaXMudmlzdWFscy5maWxsLnNldF92ZWN0b3JpemUodCxvKSx0LmJlZ2luUGF0aCgpLGkpZm9yKGg9WyExLCEwXSxhPTAsdT1oLmxlbmd0aDthPHU7YSsrKW49aFthXSx0LmFyYyhkW29dLGZbb10scFtvXSwwLE1hdGguUEksbiksdC5hcmMoZFtvXSxmW29dLF9bb10sTWF0aC5QSSwwLCFuKTtlbHNlIHQuYXJjKGRbb10sZltvXSxwW29dLDAsMipNYXRoLlBJLCEwKSx0LmFyYyhkW29dLGZbb10sX1tvXSwyKk1hdGguUEksMCwhMSk7dC5maWxsKCl9dGhpcy52aXN1YWxzLmxpbmUuZG9pdD8odGhpcy52aXN1YWxzLmxpbmUuc2V0X3ZlY3Rvcml6ZSh0LG8pLHQuYmVnaW5QYXRoKCksdC5hcmMoZFtvXSxmW29dLHBbb10sMCwyKk1hdGguUEkpLHQubW92ZVRvKGRbb10rX1tvXSxmW29dKSx0LmFyYyhkW29dLGZbb10sX1tvXSwwLDIqTWF0aC5QSSksYy5wdXNoKHQuc3Ryb2tlKCkpKTpjLnB1c2godm9pZCAwKX1yZXR1cm4gY30sZS5wcm90b3R5cGUuX2hpdF9wb2ludD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0sayxqLFQ7Zm9yKHA9W3QudngsdC52eV0sdj1wWzBdLGI9cFsxXSx4PXRoaXMucmVuZGVyZXIueG1hcHBlci5tYXBfZnJvbV90YXJnZXQodiwhMCksdz14LXRoaXMubWF4X3JhZGl1cyxNPXgrdGhpcy5tYXhfcmFkaXVzLGs9dGhpcy5yZW5kZXJlci55bWFwcGVyLm1hcF9mcm9tX3RhcmdldChiLCEwKSxqPWstdGhpcy5tYXhfcmFkaXVzLFQ9ayt0aGlzLm1heF9yYWRpdXMsbj1bXSxlPWEudmFsaWRhdGVfYmJveF9jb29yZHMoW3csTV0sW2osVF0pLF89ZnVuY3Rpb24oKXt2YXIgdCxyLG4sbztmb3Iobj10aGlzLmluZGV4LnNlYXJjaChlKSxvPVtdLHQ9MCxyPW4ubGVuZ3RoO3Q8cjt0KyspYz1uW3RdLG8ucHVzaChjLmkpO3JldHVybiBvfS5jYWxsKHRoaXMpLGw9MCx1PV8ubGVuZ3RoO2w8dTtsKyspbz1fW2xdLGg9TWF0aC5wb3codGhpcy5zb3V0ZXJfcmFkaXVzW29dLDIpLGk9TWF0aC5wb3codGhpcy5zaW5uZXJfcmFkaXVzW29dLDIpLGY9dGhpcy5yZW5kZXJlci54bWFwcGVyLm1hcF90b190YXJnZXQoeCksbT10aGlzLnJlbmRlcmVyLnhtYXBwZXIubWFwX3RvX3RhcmdldCh0aGlzLl94W29dKSxnPXRoaXMucmVuZGVyZXIueW1hcHBlci5tYXBfdG9fdGFyZ2V0KGspLHk9dGhpcy5yZW5kZXJlci55bWFwcGVyLm1hcF90b190YXJnZXQodGhpcy5feVtvXSkscj1NYXRoLnBvdyhmLW0sMikrTWF0aC5wb3coZy15LDIpLHI8PWgmJnI+PWkmJm4ucHVzaChbbyxyXSk7cmV0dXJuIGQ9YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksZFsiMWQiXS5pbmRpY2VzPXMuY2hhaW4obikuc29ydEJ5KGZ1bmN0aW9uKHQpe3JldHVybiB0WzFdfSkubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0WzBdfSkudmFsdWUoKSxkfSxlLnByb3RvdHlwZS5kcmF3X2xlZ2VuZD1mdW5jdGlvbih0LGUscixuLG8pe3ZhciBpLHMsYSxsLHUsaCxjLHAsXztyZXR1cm4gdT1udWxsIT0obD10aGlzLmdldF9yZWZlcmVuY2VfcG9pbnQoKSk/bDowLHM9W3VdLHA9e30scFt1XT0oZStyKS8yLF89e30sX1t1XT0obitvKS8yLGE9LjUqTWF0aC5taW4oTWF0aC5hYnMoci1lKSxNYXRoLmFicyhvLW4pKSxoPXt9LGhbdV09LjQqYSxjPXt9LGNbdV09LjgqYSxpPXtzeDpwLHN5Ol8sc2lubmVyX3JhZGl1czpoLHNvdXRlcl9yYWRpdXM6Y30sdGhpcy5fcmVuZGVyKHQscyxpKX0sZX0oaS5WaWV3KSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PW8sZS5wcm90b3R5cGUudHlwZT0iQW5udWx1cyIsZS5jb29yZHMoW1sieCIsInkiXV0pLGUubWl4aW5zKFsibGluZSIsImZpbGwiXSksZS5kZWZpbmUoe2lubmVyX3JhZGl1czpbbC5EaXN0YW5jZVNwZWNdLG91dGVyX3JhZGl1czpbbC5EaXN0YW5jZVNwZWNdfSksZX0oaS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpuLFZpZXc6b319LHsiLi4vLi4vY29tbW9uL2hpdHRlc3QiOiJjb21tb24vaGl0dGVzdCIsIi4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvZ2x5cGhzL2FyYyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXUuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sdT17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxpPXQoIi4vZ2x5cGgiKSxhPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS5faW5kZXhfZGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl94eV9pbmRleCgpfSxlLnByb3RvdHlwZS5fbWFwX2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4iZGF0YSI9PT10aGlzLm1vZGVsLnByb3BlcnRpZXMucmFkaXVzLnVuaXRzP3RoaXMuc3JhZGl1cz10aGlzLnNkaXN0KHRoaXMucmVuZGVyZXIueG1hcHBlcix0aGlzLl94LHRoaXMuX3JhZGl1cyk6dGhpcy5zcmFkaXVzPXRoaXMuX3JhZGl1c30sZS5wcm90b3R5cGUuX3JlbmRlcj1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHA7aWYoYz1yLnN4LHA9ci5zeSxoPXIuc3JhZGl1cyxvPXIuX3N0YXJ0X2FuZ2xlLG49ci5fZW5kX2FuZ2xlLHRoaXMudmlzdWFscy5saW5lLmRvaXQpe2ZvcihpPXRoaXMubW9kZWwucHJvcGVydGllcy5kaXJlY3Rpb24udmFsdWUoKSx1PVtdLGE9MCxsPWUubGVuZ3RoO2E8bDthKyspcz1lW2FdLGlzTmFOKGNbc10rcFtzXStoW3NdK29bc10rbltzXSl8fCh0LmJlZ2luUGF0aCgpLHQuYXJjKGNbc10scFtzXSxoW3NdLG9bc10sbltzXSxpKSx0aGlzLnZpc3VhbHMubGluZS5zZXRfdmVjdG9yaXplKHQscyksdS5wdXNoKHQuc3Ryb2tlKCkpKTtyZXR1cm4gdX19LGUucHJvdG90eXBlLmRyYXdfbGVnZW5kPWZ1bmN0aW9uKHQsZSxyLG4sbyl7cmV0dXJuIHRoaXMuX2dlbmVyaWNfbGluZV9sZWdlbmQodCxlLHIsbixvKX0sZX0oaS5WaWV3KSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PW8sZS5wcm90b3R5cGUudHlwZT0iQXJjIixlLmNvb3JkcyhbWyJ4IiwieSJdXSksZS5taXhpbnMoWyJsaW5lIl0pLGUuZGVmaW5lKHtkaXJlY3Rpb246W2EuRGlyZWN0aW9uLCJhbnRpY2xvY2siXSxyYWRpdXM6W2EuRGlzdGFuY2VTcGVjXSxzdGFydF9hbmdsZTpbYS5BbmdsZVNwZWNdLGVuZF9hbmdsZTpbYS5BbmdsZVNwZWNdfSksZX0oaS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpuLFZpZXc6b319LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9nbHlwaCI6Im1vZGVscy9nbHlwaHMvZ2x5cGgiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvYmV6aWVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1PWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSloLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGg9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbD10KCJyYnVzaCIpLGk9dCgiLi9nbHlwaCIpLGE9ZnVuY3Rpb24odCxlLHIsbixvLGkscyxhKXt2YXIgbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrO2Zvcih3PVtdLGM9W1tdLFtdXSxfPW09MDttPD0yO189KyttKWlmKDA9PT1fPyh1PTYqdC0xMipyKzYqbyxsPS0zKnQrOSpyLTkqbyszKnMscD0zKnItMyp0KToodT02KmUtMTIqbis2KmksbD0tMyplKzkqbi05KmkrMyphLHA9MypuLTMqZSksTWF0aC5hYnMobCk8MWUtMTIpe2lmKE1hdGguYWJzKHUpPDFlLTEyKWNvbnRpbnVlO3Y9LXAvdSwwPHYmJnY8MSYmdy5wdXNoKHYpfWVsc2UgaD11KnUtNCpwKmwseT1NYXRoLnNxcnQoaCksaDwwfHwoYj0oLXUreSkvKDIqbCksMDxiJiZiPDEmJncucHVzaChiKSx4PSgtdS15KS8oMipsKSwwPHgmJng8MSYmdy5wdXNoKHgpKTtmb3IoZD13Lmxlbmd0aCxmPWQ7ZC0tOyl2PXdbZF0sZz0xLXYsTT1nKmcqZyp0KzMqZypnKnYqciszKmcqdip2Km8rdip2KnYqcyxjWzBdW2RdPU0saz1nKmcqZyplKzMqZypnKnYqbiszKmcqdip2Kmkrdip2KnYqYSxjWzFdW2RdPWs7cmV0dXJuIGNbMF1bZl09dCxjWzFdW2ZdPWUsY1swXVtmKzFdPXMsY1sxXVtmKzFdPWEsW01hdGgubWluLmFwcGx5KG51bGwsY1swXSksTWF0aC5tYXguYXBwbHkobnVsbCxjWzFdKSxNYXRoLm1heC5hcHBseShudWxsLGNbMF0pLE1hdGgubWluLmFwcGx5KG51bGwsY1sxXSldfSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyx1LGgsYztmb3IoZT1sKCksbj1bXSx0PXI9MCxvPXRoaXMuX3gwLmxlbmd0aDswPD1vP3I8bzpyPm87dD0wPD1vPysrcjotLXIpaXNOYU4odGhpcy5feDBbdF0rdGhpcy5feDFbdF0rdGhpcy5feTBbdF0rdGhpcy5feTFbdF0rdGhpcy5fY3gwW3RdK3RoaXMuX2N5MFt0XSt0aGlzLl9jeDFbdF0rdGhpcy5fY3kxW3RdKXx8KGk9YSh0aGlzLl94MFt0XSx0aGlzLl95MFt0XSx0aGlzLl94MVt0XSx0aGlzLl95MVt0XSx0aGlzLl9jeDBbdF0sdGhpcy5fY3kwW3RdLHRoaXMuX2N4MVt0XSx0aGlzLl9jeTFbdF0pLHM9aVswXSxoPWlbMV0sdT1pWzJdLGM9aVszXSxuLnB1c2goe21pblg6cyxtaW5ZOmgsbWF4WDp1LG1heFk6YyxpOnR9KSk7cmV0dXJuIGUubG9hZChuKSxlfSxlLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZjtpZihwPXIuc3gwLGQ9ci5zeTAsXz1yLnN4MSxmPXIuc3kxLGE9ci5zY3gsbD1yLnNjeDAsaD1yLnNjeTAsdT1yLnNjeDEsYz1yLnNjeTEsdGhpcy52aXN1YWxzLmxpbmUuZG9pdCl7Zm9yKHM9W10sbz0wLGk9ZS5sZW5ndGg7bzxpO28rKyluPWVbb10saXNOYU4ocFtuXStkW25dK19bbl0rZltuXStsW25dK2hbbl0rdVtuXStjW25dKXx8KHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8ocFtuXSxkW25dKSx0LmJlemllckN1cnZlVG8obFtuXSxoW25dLHVbbl0sY1tuXSxfW25dLGZbbl0pLHRoaXMudmlzdWFscy5saW5lLnNldF92ZWN0b3JpemUodCxuKSxzLnB1c2godC5zdHJva2UoKSkpO3JldHVybiBzfX0sZS5wcm90b3R5cGUuZHJhd19sZWdlbmQ9ZnVuY3Rpb24odCxlLHIsbixvKXtyZXR1cm4gdGhpcy5fZ2VuZXJpY19saW5lX2xlZ2VuZCh0LGUscixuLG8pfSxlfShpLlZpZXcpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHUoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9byxlLnByb3RvdHlwZS50eXBlPSJCZXppZXIiLGUuY29vcmRzKFtbIngwIiwieTAiXSxbIngxIiwieTEiXSxbImN4MCIsImN5MCJdLFsiY3gxIiwiY3kxIl1dKSxlLm1peGlucyhbImxpbmUiXSksZX0oaS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpuLFZpZXc6b319LHsiLi9nbHlwaCI6Im1vZGVscy9nbHlwaHMvZ2x5cGgiLHJidXNoOiJyYnVzaCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2dseXBocy9jaXJjbGUiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHU9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWguY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0saD17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxpPXQoIi4vZ2x5cGgiKSxhPXQoIi4uLy4uL2NvbW1vbi9oaXR0ZXN0IiksbD10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5feHlfaW5kZXgoKX0sZS5wcm90b3R5cGUuX21hcF9kYXRhPWZ1bmN0aW9uKCl7dmFyIHQsZTtyZXR1cm4gbnVsbCE9dGhpcy5fcmFkaXVzPyJkYXRhIj09PXRoaXMubW9kZWwucHJvcGVydGllcy5yYWRpdXMuc3BlYy51bml0cz8odD10aGlzLm1vZGVsLnByb3BlcnRpZXMucmFkaXVzX2RpbWVuc2lvbi5zcGVjLnZhbHVlLHRoaXMuc3JhZGl1cz10aGlzLnNkaXN0KHRoaXMucmVuZGVyZXJbdCsibWFwcGVyIl0sdGhpc1siXyIrdF0sdGhpcy5fcmFkaXVzKSk6KHRoaXMuc3JhZGl1cz10aGlzLl9yYWRpdXMsdGhpcy5tYXhfc2l6ZT0yKnRoaXMubWF4X3JhZGl1cyk6dGhpcy5zcmFkaXVzPWZ1bmN0aW9uKCl7dmFyIHQscixuLG87Zm9yKG49dGhpcy5fc2l6ZSxvPVtdLHQ9MCxyPW4ubGVuZ3RoO3Q8cjt0KyspZT1uW3RdLG8ucHVzaChlLzIpO3JldHVybiBvfS5jYWxsKHRoaXMpfSxlLnByb3RvdHlwZS5fbWFza19kYXRhPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxsLHUsaCxjLHAsXyxkLGYsbSxnO3JldHVybiByPXRoaXMucmVuZGVyZXIucGxvdF92aWV3LmZyYW1lLmdldCgiaF9yYW5nZSIpLHA9dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJ2X3JhbmdlIiksbnVsbCE9dGhpcy5fcmFkaXVzJiYiZGF0YSI9PT10aGlzLm1vZGVsLnByb3BlcnRpZXMucmFkaXVzLnVuaXRzPyhsPXIuZ2V0KCJzdGFydCIpLHU9ci5nZXQoImVuZCIpLG49dGhpcy5yZW5kZXJlci54bWFwcGVyLnZfbWFwX2Zyb21fdGFyZ2V0KFtsLHVdLCEwKSxkPW5bMF0sZj1uWzFdLGQtPXRoaXMubWF4X3JhZGl1cyxmKz10aGlzLm1heF9yYWRpdXMsaD1wLmdldCgic3RhcnQiKSxjPXAuZ2V0KCJlbmQiKSxvPXRoaXMucmVuZGVyZXIueW1hcHBlci52X21hcF9mcm9tX3RhcmdldChbaCxjXSwhMCksbT1vWzBdLGc9b1sxXSxtLT10aGlzLm1heF9yYWRpdXMsZys9dGhpcy5tYXhfcmFkaXVzKToobD1yLmdldCgic3RhcnQiKS10aGlzLm1heF9zaXplLHU9ci5nZXQoImVuZCIpK3RoaXMubWF4X3NpemUsaT10aGlzLnJlbmRlcmVyLnhtYXBwZXIudl9tYXBfZnJvbV90YXJnZXQoW2wsdV0sITApLGQ9aVswXSxmPWlbMV0saD1wLmdldCgic3RhcnQiKS10aGlzLm1heF9zaXplLGM9cC5nZXQoImVuZCIpK3RoaXMubWF4X3NpemUscz10aGlzLnJlbmRlcmVyLnltYXBwZXIudl9tYXBfZnJvbV90YXJnZXQoW2gsY10sITApLG09c1swXSxnPXNbMV0pLGU9YS52YWxpZGF0ZV9iYm94X2Nvb3JkcyhbZCxmXSxbbSxnXSksZnVuY3Rpb24oKXt2YXIgdCxyLG4sbztmb3Iobj10aGlzLmluZGV4LnNlYXJjaChlKSxvPVtdLHQ9MCxyPW4ubGVuZ3RoO3Q8cjt0KyspXz1uW3RdLG8ucHVzaChfLmkpO3JldHVybiBvfS5jYWxsKHRoaXMpfSxlLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdTtmb3IobD1yLnN4LHU9ci5zeSxhPXIuc3JhZGl1cyxzPVtdLG89MCxpPWUubGVuZ3RoO288aTtvKyspbj1lW29dLGlzTmFOKGxbbl0rdVtuXSthW25dKXx8KHQuYmVnaW5QYXRoKCksdC5hcmMobFtuXSx1W25dLGFbbl0sMCwyKk1hdGguUEksITEpLHRoaXMudmlzdWFscy5maWxsLmRvaXQmJih0aGlzLnZpc3VhbHMuZmlsbC5zZXRfdmVjdG9yaXplKHQsbiksdC5maWxsKCkpLHRoaXMudmlzdWFscy5saW5lLmRvaXQ/KHRoaXMudmlzdWFscy5saW5lLnNldF92ZWN0b3JpemUodCxuKSxzLnB1c2godC5zdHJva2UoKSkpOnMucHVzaCh2b2lkIDApKTtyZXR1cm4gc30sZS5wcm90b3R5cGUuX2hpdF9wb2ludD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0sayxqLFQsUyx6LFAsRSxBLEMsTixPLHEsRCxJO2lmKGQ9W3QudngsdC52eV0sVD1kWzBdLFA9ZFsxXSxDPXRoaXMucmVuZGVyZXIueG1hcHBlci5tYXBfZnJvbV90YXJnZXQoVCwhMCkscT10aGlzLnJlbmRlcmVyLnltYXBwZXIubWFwX2Zyb21fdGFyZ2V0KFAsITApLG51bGwhPXRoaXMuX3JhZGl1cyYmImRhdGEiPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLnJhZGl1cy51bml0cz8oTj1DLXRoaXMubWF4X3JhZGl1cyxPPUMrdGhpcy5tYXhfcmFkaXVzLEQ9cS10aGlzLm1heF9yYWRpdXMsST1xK3RoaXMubWF4X3JhZGl1cyk6KFM9VC10aGlzLm1heF9zaXplLHo9VCt0aGlzLm1heF9zaXplLGY9dGhpcy5yZW5kZXJlci54bWFwcGVyLnZfbWFwX2Zyb21fdGFyZ2V0KFtTLHpdLCEwKSxOPWZbMF0sTz1mWzFdLG09W01hdGgubWluKE4sTyksTWF0aC5tYXgoTixPKV0sTj1tWzBdLE89bVsxXSxFPVAtdGhpcy5tYXhfc2l6ZSxBPVArdGhpcy5tYXhfc2l6ZSxnPXRoaXMucmVuZGVyZXIueW1hcHBlci52X21hcF9mcm9tX3RhcmdldChbRSxBXSwhMCksRD1nWzBdLEk9Z1sxXSx5PVtNYXRoLm1pbihELEkpLE1hdGgubWF4KEQsSSldLEQ9eVswXSxJPXlbMV0pLGU9YS52YWxpZGF0ZV9iYm94X2Nvb3JkcyhbTixPXSxbRCxJXSkscj1mdW5jdGlvbigpe3ZhciB0LHIsbixvO2ZvcihuPXRoaXMuaW5kZXguc2VhcmNoKGUpLG89W10sdD0wLHI9bi5sZW5ndGg7dDxyO3QrKylwPW5bdF0sby5wdXNoKHAuaSk7cmV0dXJuIG99LmNhbGwodGhpcyksbz1bXSxudWxsIT10aGlzLl9yYWRpdXMmJiJkYXRhIj09PXRoaXMubW9kZWwucHJvcGVydGllcy5yYWRpdXMudW5pdHMpZm9yKGw9MCxoPXIubGVuZ3RoO2w8aDtsKyspaT1yW2xdLF89TWF0aC5wb3codGhpcy5zcmFkaXVzW2ldLDIpLHg9dGhpcy5yZW5kZXJlci54bWFwcGVyLm1hcF90b190YXJnZXQoQywhMCksdz10aGlzLnJlbmRlcmVyLnhtYXBwZXIubWFwX3RvX3RhcmdldCh0aGlzLl94W2ldLCEwKSxrPXRoaXMucmVuZGVyZXIueW1hcHBlci5tYXBfdG9fdGFyZ2V0KHEsITApLGo9dGhpcy5yZW5kZXJlci55bWFwcGVyLm1hcF90b190YXJnZXQodGhpcy5feVtpXSwhMCksbj1NYXRoLnBvdyh4LXcsMikrTWF0aC5wb3coay1qLDIpLG48PV8mJm8ucHVzaChbaSxuXSk7ZWxzZSBmb3IoYj10aGlzLnJlbmRlcmVyLnBsb3Rfdmlldy5jYW52YXMudnhfdG9fc3goVCksTT10aGlzLnJlbmRlcmVyLnBsb3Rfdmlldy5jYW52YXMudnlfdG9fc3koUCksdT0wLGM9ci5sZW5ndGg7dTxjO3UrKylpPXJbdV0sXz1NYXRoLnBvdyh0aGlzLnNyYWRpdXNbaV0sMiksbj1NYXRoLnBvdyh0aGlzLnN4W2ldLWIsMikrTWF0aC5wb3codGhpcy5zeVtpXS1NLDIpLG48PV8mJm8ucHVzaChbaSxuXSk7cmV0dXJuIG89cy5jaGFpbihvKS5zb3J0QnkoZnVuY3Rpb24odCl7cmV0dXJuIHRbMV19KS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHRbMF19KS52YWx1ZSgpLHY9YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksdlsiMWQiXS5pbmRpY2VzPW8sdn0sZS5wcm90b3R5cGUuX2hpdF9zcGFuPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdyxNLGssaixUO3JldHVybiB1PVt0LnZ4LHQudnldLG09dVswXSx2PXVbMV0saD10aGlzLmJvdW5kcygpLGk9aC5taW5YLHM9aC5taW5ZLG49aC5tYXhYLG89aC5tYXhZLGY9YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksImgiPT09dC5kaXJlY3Rpb24/KGo9cyxUPW8sbnVsbCE9dGhpcy5fcmFkaXVzJiYiZGF0YSI9PT10aGlzLm1vZGVsLnByb3BlcnRpZXMucmFkaXVzLnVuaXRzPyhnPW0tdGhpcy5tYXhfcmFkaXVzLHk9bSt0aGlzLm1heF9yYWRpdXMsYz10aGlzLnJlbmRlcmVyLnhtYXBwZXIudl9tYXBfZnJvbV90YXJnZXQoW2cseV0pLHc9Y1swXSxNPWNbMV0pOihsPXRoaXMubWF4X3NpemUvMixnPW0tbCx5PW0rbCxwPXRoaXMucmVuZGVyZXIueG1hcHBlci52X21hcF9mcm9tX3RhcmdldChbZyx5XSwhMCksdz1wWzBdLE09cFsxXSkpOih3PWksTT1uLG51bGwhPXRoaXMuX3JhZGl1cyYmImRhdGEiPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLnJhZGl1cy51bml0cz8oYj12LXRoaXMubWF4X3JhZGl1cyx4PXYrdGhpcy5tYXhfcmFkaXVzLF89dGhpcy5yZW5kZXJlci55bWFwcGVyLnZfbWFwX2Zyb21fdGFyZ2V0KFtiLHhdKSxqPV9bMF0sVD1fWzFdKToobD10aGlzLm1heF9zaXplLzIsYj12LWwseD12K2wsZD10aGlzLnJlbmRlcmVyLnltYXBwZXIudl9tYXBfZnJvbV90YXJnZXQoW2IseF0sITApLGo9ZFswXSxUPWRbMV0pKSxlPWEudmFsaWRhdGVfYmJveF9jb29yZHMoW3csTV0sW2osVF0pLHI9ZnVuY3Rpb24oKXt2YXIgdCxyLG4sbztmb3Iobj10aGlzLmluZGV4LnNlYXJjaChlKSxvPVtdLHQ9MCxyPW4ubGVuZ3RoO3Q8cjt0Kyspaz1uW3RdLG8ucHVzaChrLmkpO3JldHVybiBvfS5jYWxsKHRoaXMpLGZbIjFkIl0uaW5kaWNlcz1yLGZ9LGUucHJvdG90eXBlLl9oaXRfcmVjdD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsbCx1LGg7cmV0dXJuIHI9dGhpcy5yZW5kZXJlci54bWFwcGVyLnZfbWFwX2Zyb21fdGFyZ2V0KFt0LnZ4MCx0LnZ4MV0sITApLHM9clswXSxsPXJbMV0sbj10aGlzLnJlbmRlcmVyLnltYXBwZXIudl9tYXBfZnJvbV90YXJnZXQoW3QudnkwLHQudnkxXSwhMCksdT1uWzBdLGg9blsxXSxlPWEudmFsaWRhdGVfYmJveF9jb29yZHMoW3MsbF0sW3UsaF0pLG89YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksb1siMWQiXS5pbmRpY2VzPWZ1bmN0aW9uKCl7dmFyIHQscixuLG87Zm9yKG49dGhpcy5pbmRleC5zZWFyY2goZSksbz1bXSx0PTAscj1uLmxlbmd0aDt0PHI7dCsrKWk9blt0XSxvLnB1c2goaS5pKTtyZXR1cm4gb30uY2FsbCh0aGlzKSxvfSxlLnByb3RvdHlwZS5faGl0X3BvbHk9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGwsdSxoLGMscCxfLGQ7Zm9yKHM9W3QudngsdC52eV0sXz1zWzBdLGQ9c1sxXSxjPXRoaXMucmVuZGVyZXIucGxvdF92aWV3LmNhbnZhcy52X3Z4X3RvX3N4KF8pLHA9dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcuY2FudmFzLnZfdnlfdG9fc3koZCksZT1mdW5jdGlvbigpe2g9W107Zm9yKHZhciB0PTAsZT10aGlzLnN4Lmxlbmd0aDswPD1lP3Q8ZTp0PmU7MDw9ZT90Kys6dC0tKWgucHVzaCh0KTtyZXR1cm4gaH0uYXBwbHkodGhpcykscj1bXSxuPWk9MCxsPWUubGVuZ3RoOzA8PWw/aTxsOmk+bDtuPTA8PWw/KytpOi0taSlvPWVbbl0sYS5wb2ludF9pbl9wb2x5KHRoaXMuc3hbbl0sdGhpcy5zeVtuXSxjLHApJiZyLnB1c2gobyk7cmV0dXJuIHU9YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksdVsiMWQiXS5pbmRpY2VzPXIsdX0sZS5wcm90b3R5cGUuZHJhd19sZWdlbmQ9ZnVuY3Rpb24odCxlLHIsbixvKXt2YXIgaSxzLGEsbCx1LGgsYztyZXR1cm4gbD1udWxsIT0oYT10aGlzLmdldF9yZWZlcmVuY2VfcG9pbnQoKSk/YTowLHM9W2xdLGg9e30saFtsXT0oZStyKS8yLGM9e30sY1tsXT0obitvKS8yLHU9e30sdVtsXT0uMipNYXRoLm1pbihNYXRoLmFicyhyLWUpLE1hdGguYWJzKG8tbikpLGk9e3N4Omgsc3k6YyxzcmFkaXVzOnV9LHRoaXMuX3JlbmRlcih0LHMsaSl9LGV9KGkuVmlldyksbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1vLGUucHJvdG90eXBlLnR5cGU9IkNpcmNsZSIsZS5jb29yZHMoW1sieCIsInkiXV0pLGUubWl4aW5zKFsibGluZSIsImZpbGwiXSksZS5kZWZpbmUoe2FuZ2xlOltsLkFuZ2xlU3BlYywwXSxzaXplOltsLkRpc3RhbmNlU3BlYyx7dW5pdHM6InNjcmVlbiIsdmFsdWU6NH1dLHJhZGl1czpbbC5EaXN0YW5jZVNwZWMsbnVsbF0scmFkaXVzX2RpbWVuc2lvbjpbbC5TdHJpbmcsIngiXX0pLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLnByb3BlcnRpZXMucmFkaXVzLm9wdGlvbmFsPSEwfSxlfShpLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm4sVmlldzpvfX0seyIuLi8uLi9jb21tb24vaGl0dGVzdCI6ImNvbW1vbi9oaXR0ZXN0IiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9nbHlwaCI6Im1vZGVscy9nbHlwaHMvZ2x5cGgiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvZWxsaXBzZSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXUuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sdT17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxpPXQoIi4vZ2x5cGgiKSxhPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS5fc2V0X2RhdGE9ZnVuY3Rpb24oKXtpZih0aGlzLm1heF93Mj0wLCJkYXRhIj09PXRoaXMubW9kZWwucHJvcGVydGllcy53aWR0aC51bml0cyYmKHRoaXMubWF4X3cyPXRoaXMubWF4X3dpZHRoLzIpLHRoaXMubWF4X2gyPTAsImRhdGEiPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLmhlaWdodC51bml0cylyZXR1cm4gdGhpcy5tYXhfaDI9dGhpcy5tYXhfaGVpZ2h0LzJ9LGUucHJvdG90eXBlLl9pbmRleF9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3h5X2luZGV4KCl9LGUucHJvdG90eXBlLl9tYXBfZGF0YT1mdW5jdGlvbigpe3JldHVybiJkYXRhIj09PXRoaXMubW9kZWwucHJvcGVydGllcy53aWR0aC51bml0cz90aGlzLnN3PXRoaXMuc2Rpc3QodGhpcy5yZW5kZXJlci54bWFwcGVyLHRoaXMuX3gsdGhpcy5fd2lkdGgsImNlbnRlciIpOnRoaXMuc3c9dGhpcy5fd2lkdGgsImRhdGEiPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLmhlaWdodC51bml0cz90aGlzLnNoPXRoaXMuc2Rpc3QodGhpcy5yZW5kZXJlci55bWFwcGVyLHRoaXMuX3ksdGhpcy5faGVpZ2h0LCJjZW50ZXIiKTp0aGlzLnNoPXRoaXMuX2hlaWdodH0sZS5wcm90b3R5cGUuX3JlbmRlcj1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaDtmb3IodT1yLnN4LGg9ci5zeSxsPXIuc3csYT1yLnNoLHM9W10sbz0wLGk9ZS5sZW5ndGg7bzxpO28rKyluPWVbb10saXNOYU4odVtuXStoW25dK2xbbl0rYVtuXSt0aGlzLl9hbmdsZVtuXSl8fCh0LmJlZ2luUGF0aCgpLHQuZWxsaXBzZSh1W25dLGhbbl0sbFtuXS8yLGFbbl0vMix0aGlzLl9hbmdsZVtuXSwwLDIqTWF0aC5QSSksdGhpcy52aXN1YWxzLmZpbGwuZG9pdCYmKHRoaXMudmlzdWFscy5maWxsLnNldF92ZWN0b3JpemUodCxuKSx0LmZpbGwoKSksdGhpcy52aXN1YWxzLmxpbmUuZG9pdD8odGhpcy52aXN1YWxzLmxpbmUuc2V0X3ZlY3Rvcml6ZSh0LG4pLHMucHVzaCh0LnN0cm9rZSgpKSk6cy5wdXNoKHZvaWQgMCkpO3JldHVybiBzfSxlLnByb3RvdHlwZS5kcmF3X2xlZ2VuZD1mdW5jdGlvbih0LGUscixuLG8pe3ZhciBpLHMsYSxsLHUsaCxjLHAsXyxkO3JldHVybiB1PW51bGwhPShsPXRoaXMuZ2V0X3JlZmVyZW5jZV9wb2ludCgpKT9sOjAsYT1bdV0sXz17fSxfW3VdPShlK3IpLzIsZD17fSxkW3VdPShuK28pLzIsaD10aGlzLnN3W3VdL3RoaXMuc2hbdV0saT0uOCpNYXRoLm1pbihNYXRoLmFicyhyLWUpLE1hdGguYWJzKG8tbikpLHA9e30sYz17fSxoPjE/KHBbdV09aSxjW3VdPWkvaCk6KHBbdV09aSpoLGNbdV09aSkscz17c3g6XyxzeTpkLHN3OnAsc2g6Y30sdGhpcy5fcmVuZGVyKHQsYSxzKX0sZS5wcm90b3R5cGUuX2JvdW5kcz1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5tYXhfd2gyX2JvdW5kcyh0KX0sZX0oaS5WaWV3KSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PW8sZS5wcm90b3R5cGUudHlwZT0iRWxsaXBzZSIsZS5jb29yZHMoW1sieCIsInkiXV0pLGUubWl4aW5zKFsibGluZSIsImZpbGwiXSksZS5kZWZpbmUoe2FuZ2xlOlthLkFuZ2xlU3BlYywwXSx3aWR0aDpbYS5EaXN0YW5jZVNwZWNdLGhlaWdodDpbYS5EaXN0YW5jZVNwZWNdfSksZX0oaS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpuLFZpZXc6b319LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9nbHlwaCI6Im1vZGVscy9nbHlwaHMvZ2x5cGgiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvZ2VhciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7bD10KCJ1bmRlcnNjb3JlIiksYT10KCIuL2dseXBoIiksaT10KCJnZWFyX3V0aWxzIiksdT10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxuPXQoIi4uLy4uL3V0aWwvYmV6aWVyIikscz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLl9pbmRleF9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3h5X2luZGV4KCl9LGUucHJvdG90eXBlLl9tYXBfZGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLnNtb2R1bGU9dGhpcy5zZGlzdCh0aGlzLnJlbmRlcmVyLnhtYXBwZXIsdGhpcy5feCx0aGlzLl9tb2R1bGUsImVkZ2UiKX0sZS5wcm90b3R5cGUuX3JlbmRlcj1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTLHo7Zm9yKGo9ci5zeCxUPXIuc3ksaz1yLnNtb2R1bGUsbz1yLl9hbmdsZSx1PXIuX3RlZXRoLGE9ci5fcHJlc3N1cmVfYW5nbGUsbD1yLl9zaGFmdF9zaXplLHM9ci5faW50ZXJuYWwsXz0wLGY9ZS5sZW5ndGg7XzxmO18rKylpZihjPWVbX10sIWlzTmFOKGpbY10rVFtjXStvW2NdK2tbY10rdVtjXSthW2NdK2xbY10rc1tjXSkpe2ZvcihtPWtbY10qdVtjXS8yLGg9c1tjXT9pLmNyZWF0ZV9pbnRlcm5hbF9nZWFyX3Rvb3RoOmkuY3JlYXRlX2dlYXJfdG9vdGgsdz1oKGtbY10sdVtjXSxhW2NdKSxnPXcuc2xpY2UoMCwzKSxuPWdbMF0sUz1nWzFdLHo9Z1syXSx4PXcuc2xpY2UoMyksdC5zYXZlKCksdC50cmFuc2xhdGUoaltjXSxUW2NdKSx0LnJvdGF0ZShvW2NdKSx0LmJlZ2luUGF0aCgpLGI9MipNYXRoLlBJL3VbY10sdC5tb3ZlVG8oUyx6KSxwPWQ9MCx5PXVbY107MDw9eT9kPHk6ZD55O3A9MDw9eT8rK2Q6LS1kKXRoaXMuX3JlbmRlcl9zZXEodCx4KSx0LnJvdGF0ZShiKTt0LmNsb3NlUGF0aCgpLHNbY10/KHY9bSsyLjc1KmtbY10sdC5tb3ZlVG8odiwwKSx0LmFyYygwLDAsdiwwLDIqTWF0aC5QSSwhMCkpOmxbY10+MCYmKE09bSpsW2NdLHQubW92ZVRvKE0sMCksdC5hcmMoMCwwLE0sMCwyKk1hdGguUEksITApKSx0aGlzLnZpc3VhbHMuZmlsbC5kb2l0JiYodGhpcy52aXN1YWxzLmZpbGwuc2V0X3ZlY3Rvcml6ZSh0LGMpLHQuZmlsbCgpKSx0aGlzLnZpc3VhbHMubGluZS5kb2l0JiYodGhpcy52aXN1YWxzLmxpbmUuc2V0X3ZlY3Rvcml6ZSh0LGMpLHQuc3Ryb2tlKCkpLHQucmVzdG9yZSgpfX0sZS5wcm90b3R5cGUuX3JlbmRlcl9zZXE9ZnVuY3Rpb24odCxlKXt2YXIgcixvLGkscyxhLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdyxNLGssaixULFMseixQLEUsQSxDO2Zvcih1PTA7dTxlLmxlbmd0aDspc3dpdGNoKGwuaXNTdHJpbmcoZVt1XSkmJihyPWVbdV0sdSs9MSkscil7Y2FzZSJNIjpmPWUuc2xpY2UodSx1KzIpLEU9ZlswXSxDPWZbMV0sdC5tb3ZlVG8oRSxDKSxtPVtFLENdLF89bVswXSxkPW1bMV0sdSs9MjticmVhaztjYXNlIkwiOnk9ZS5zbGljZSh1LHUrMiksRT15WzBdLEM9eVsxXSx0LmxpbmVUbyhFLEMpLHY9W0UsQ10sXz12WzBdLGQ9dlsxXSx1Kz0yO2JyZWFrO2Nhc2UiQyI6Yj1lLnNsaWNlKHUsdSs2KSxvPWJbMF0scz1iWzFdLGk9YlsyXSxhPWJbM10sRT1iWzRdLEM9Yls1XSx0LmJlemllckN1cnZlVG8obyxzLGksYSxFLEMpLHg9W0UsQ10sXz14WzBdLGQ9eFsxXSx1Kz02O2JyZWFrO2Nhc2UiUSI6dz1lLnNsaWNlKHUsdSs0KSxvPXdbMF0scz13WzFdLEU9d1syXSxDPXdbM10sdC5xdWFkcmF0aWNDdXJ2ZVRvKG8scyxFLEMpLE09W0UsQ10sXz1NWzBdLGQ9TVsxXSx1Kz00O2JyZWFrO2Nhc2UiQSI6Zm9yKGs9ZS5zbGljZSh1LHUrNyksVD1rWzBdLFM9a1sxXSxBPWtbMl0sYz1rWzNdLFA9a1s0XSxFPWtbNV0sQz1rWzZdLHo9bi5hcmNfdG9fYmV6aWVyKF8sZCxULFMsLUEsYywxLVAsRSxDKSxoPTAscD16Lmxlbmd0aDtoPHA7aCsrKWo9eltoXSxvPWpbMF0scz1qWzFdLGk9alsyXSxhPWpbM10sRT1qWzRdLEM9als1XSx0LmJlemllckN1cnZlVG8obyxzLGksYSxFLEMpO2c9W0UsQ10sXz1nWzBdLGQ9Z1sxXSx1Kz03O2JyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKCJ1bmV4cGVjdGVkIGNvbW1hbmQ6ICIrcil9fSxlLnByb3RvdHlwZS5kcmF3X2xlZ2VuZD1mdW5jdGlvbih0LGUscixuLG8pe3JldHVybiB0aGlzLl9nZW5lcmljX2FyZWFfbGVnZW5kKHQsZSxyLG4sbyl9LGV9KGEuVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1zLGUucHJvdG90eXBlLnR5cGU9IkdlYXIiLGUuY29vcmRzKFtbIngiLCJ5Il1dKSxlLm1peGlucyhbImxpbmUiLCJmaWxsIl0pLGUuZGVmaW5lKHthbmdsZTpbdS5BbmdsZVNwZWMsMF0sbW9kdWxlOlt1Lk51bWJlclNwZWMsbnVsbF0scHJlc3N1cmVfYW5nbGU6W3UuTnVtYmVyU3BlYywyMF0sc2hhZnRfc2l6ZTpbdS5OdW1iZXJTcGVjLC4zXSx0ZWV0aDpbdS5OdW1iZXJTcGVjLG51bGxdLGludGVybmFsOlt1Lk51bWJlclNwZWMsITFdfSksZX0oYS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvLFZpZXc6c319LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vdXRpbC9iZXppZXIiOiJ1dGlsL2JlemllciIsIi4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIixnZWFyX3V0aWxzOiJnZWFyX3V0aWxzIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvZ2x5cGhzL2dseXBoIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF89ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWQuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sZD17fS5oYXNPd25Qcm9wZXJ0eTtsPXQoInVuZGVyc2NvcmUiKSxwPXQoInJidXNoIiksbj10KCIuLi9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciIpLGE9dCgiLi4vcmVuZGVyZXJzL3JlbmRlcmVyIiksYz10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSx1PXQoIi4uLy4uL2NvcmUvdXRpbC9iYm94Iikscz10KCIuLi8uLi9tb2RlbCIpLGg9dCgiLi93ZWJnbC9tYWluIiksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gXyhlLHQpLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCl7dmFyIHIsbixvO2lmKGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMucmVuZGVyZXI9dC5yZW5kZXJlcixudWxsIT0obnVsbCE9KG89dGhpcy5yZW5kZXJlcik/by5wbG90X3ZpZXc6dm9pZCAwKSYmKG49dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LG51bGwhPW4uZ2xjYW52YXMmJihyPWhbdGhpcy5tb2RlbC50eXBlKyJHTEdseXBoIl0pKSlyZXR1cm4gdGhpcy5nbGdseXBoPW5ldyByKG4uZ2xjYW52YXMuZ2wsdGhpcyl9LGUucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbih0LGUscil7aWYodGhpcy5tZ2V0KCJ2aXNpYmxlIikpe2lmKHQuYmVnaW5QYXRoKCksbnVsbCE9dGhpcy5nbGdseXBoJiZ0aGlzLl9yZW5kZXJfZ2wodCxlLHIpKXJldHVybjt0aGlzLl9yZW5kZXIodCxlLHIpfX0sZS5wcm90b3R5cGUuX3JlbmRlcl9nbD1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHA7cmV0dXJuIGM9cD0xLGk9dGhpcy5yZW5kZXJlci5tYXBfdG9fc2NyZWVuKFswKmMsMSpjLDIqY10sWzAqcCwxKnAsMipwXSksbj1pWzBdLG89aVsxXSxjPTEwMC9NYXRoLm1pbihNYXRoLm1heChNYXRoLmFicyhuWzFdLW5bMF0pLDFlLTEyKSwxZTEyKSxwPTEwMC9NYXRoLm1pbihNYXRoLm1heChNYXRoLmFicyhvWzFdLW9bMF0pLDFlLTEyKSwxZTEyKSxzPXRoaXMucmVuZGVyZXIubWFwX3RvX3NjcmVlbihbMCpjLDEqYywyKmNdLFswKnAsMSpwLDIqcF0pLG49c1swXSxvPXNbMV0sIShNYXRoLmFicyhuWzFdLW5bMF0tKG5bMl0tblsxXSkpPjFlLTZ8fE1hdGguYWJzKG9bMV0tb1swXS0ob1syXS1vWzFdKSk+MWUtNikmJihhPVsoblsxXS1uWzBdKS9jLChvWzFdLW9bMF0pL3BdLGw9YVswXSx1PWFbMV0saD17cGl4ZWxfcmF0aW86dC5waXhlbF9yYXRpbyx3aWR0aDp0LmdsY2FudmFzLndpZHRoLGhlaWdodDp0LmdsY2FudmFzLmhlaWdodCxkeDpuWzBdL2wsZHk6b1swXS91LHN4Omwsc3k6dX0sdGhpcy5nbGdseXBoLmRyYXcoZSxyLGgpLCEwKX0sZS5wcm90b3R5cGUuYm91bmRzPWZ1bmN0aW9uKCl7dmFyIHQsZTtyZXR1cm4gbnVsbD09dGhpcy5pbmRleD91LmVtcHR5KCk6KGU9dGhpcy5pbmRleC5kYXRhLHQ9e21pblg6ZS5taW5YLG1pblk6ZS5taW5ZLG1heFg6ZS5tYXhYLG1heFk6ZS5tYXhZfSx0aGlzLl9ib3VuZHModCkpfSxlLnByb3RvdHlwZS5tYXhfd2gyX2JvdW5kcz1mdW5jdGlvbih0KXtyZXR1cm57bWluWDp0Lm1pblgtdGhpcy5tYXhfdzIsbWF4WDp0Lm1heFgrdGhpcy5tYXhfdzIsbWluWTp0Lm1pblktdGhpcy5tYXhfaDIsbWF4WTp0Lm1heFkrdGhpcy5tYXhfaDJ9fSxlLnByb3RvdHlwZS5nZXRfYW5jaG9yX3BvaW50PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvO3N3aXRjaChuPXJbMF0sbz1yWzFdLHQpe2Nhc2UiY2VudGVyIjpyZXR1cm57eDp0aGlzLnNjeChlLG4sbykseTp0aGlzLnNjeShlLG4sbyl9O2RlZmF1bHQ6cmV0dXJuIG51bGx9fSxlLnByb3RvdHlwZS5zY3g9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuc3hbdF19LGUucHJvdG90eXBlLnNjeT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5zeVt0XX0sZS5wcm90b3R5cGUuX3h5X2luZGV4PWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG8saSxzLGEsbCx1O2ZvcihlPXAoKSxvPVtdLGE9dGhpcy5yZW5kZXJlci54bWFwcGVyIGluc3RhbmNlb2Ygbi5Nb2RlbD90aGlzLnJlbmRlcmVyLnhtYXBwZXIudl9tYXBfdG9fdGFyZ2V0KHRoaXMuX3gsITApOnRoaXMuX3gsdT10aGlzLnJlbmRlcmVyLnltYXBwZXIgaW5zdGFuY2VvZiBuLk1vZGVsP3RoaXMucmVuZGVyZXIueW1hcHBlci52X21hcF90b190YXJnZXQodGhpcy5feSwhMCk6dGhpcy5feSx0PXI9MCxpPWEubGVuZ3RoOzA8PWk/cjxpOnI+aTt0PTA8PWk/KytyOi0tcilzPWFbdF0sIWlzTmFOKHMpJiZpc0Zpbml0ZShzKSYmKGw9dVt0XSwhaXNOYU4obCkmJmlzRmluaXRlKGwpJiZvLnB1c2goe21pblg6cyxtaW5ZOmwsbWF4WDpzLG1heFk6bCxpOnR9KSk7cmV0dXJuIGUubG9hZChvKSxlfSxlLnByb3RvdHlwZS5zZGlzdD1mdW5jdGlvbih0LGUscixuLG8pe3ZhciBpLHMsYSx1LGgsYyxwO3JldHVybiBudWxsPT1uJiYobj0iZWRnZSIpLG51bGw9PW8mJihvPSExKSxsLmlzU3RyaW5nKGVbMF0pJiYoZT10LnZfbWFwX3RvX3RhcmdldChlKSksImNlbnRlciI9PT1uPyhzPWZ1bmN0aW9uKCl7dmFyIHQsZSxuO2ZvcihuPVtdLHQ9MCxlPXIubGVuZ3RoO3Q8ZTt0KyspaT1yW3RdLG4ucHVzaChpLzIpO3JldHVybiBufSgpLHU9ZnVuY3Rpb24oKXt2YXIgdCxyLG47Zm9yKG49W10sYT10PTAscj1lLmxlbmd0aDswPD1yP3Q8cjp0PnI7YT0wPD1yPysrdDotLXQpbi5wdXNoKGVbYV0tc1thXSk7cmV0dXJuIG59KCksaD1mdW5jdGlvbigpe3ZhciB0LHIsbjtmb3Iobj1bXSxhPXQ9MCxyPWUubGVuZ3RoOzA8PXI/dDxyOnQ+cjthPTA8PXI/Kyt0Oi0tdCluLnB1c2goZVthXStzW2FdKTtyZXR1cm4gbn0oKSk6KHU9ZSxoPWZ1bmN0aW9uKCl7dmFyIHQsZSxuO2ZvcihuPVtdLGE9dD0wLGU9dS5sZW5ndGg7MDw9ZT90PGU6dD5lO2E9MDw9ZT8rK3Q6LS10KW4ucHVzaCh1W2FdK3JbYV0pO3JldHVybiBufSgpKSxjPXQudl9tYXBfdG9fdGFyZ2V0KHUpLHA9dC52X21hcF90b190YXJnZXQoaCksbz9mdW5jdGlvbigpe3ZhciB0LGUscjtmb3Iocj1bXSxhPXQ9MCxlPWMubGVuZ3RoOzA8PWU/dDxlOnQ+ZTthPTA8PWU/Kyt0Oi0tdClyLnB1c2goTWF0aC5jZWlsKE1hdGguYWJzKHBbYV0tY1thXSkpKTtyZXR1cm4gcn0oKTpmdW5jdGlvbigpe3ZhciB0LGUscjtmb3Iocj1bXSxhPXQ9MCxlPWMubGVuZ3RoOzA8PWU/dDxlOnQ+ZTthPTA8PWU/Kyt0Oi0tdClyLnB1c2goTWF0aC5hYnMocFthXS1jW2FdKSk7cmV0dXJuIHJ9KCl9LGUucHJvdG90eXBlLmdldF9yZWZlcmVuY2VfcG9pbnQ9ZnVuY3Rpb24oKXt9LGUucHJvdG90eXBlLmRyYXdfbGVnZW5kPWZ1bmN0aW9uKHQsZSxyLG4sbyl7cmV0dXJuIG51bGx9LGUucHJvdG90eXBlLl9nZW5lcmljX2xpbmVfbGVnZW5kPWZ1bmN0aW9uKHQsZSxyLG4sbyl7dmFyIGkscztyZXR1cm4gcz1udWxsIT0oaT10aGlzLmdldF9yZWZlcmVuY2VfcG9pbnQoKSk/aTowLHQuc2F2ZSgpLHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8oZSwobitvKS8yKSx0LmxpbmVUbyhyLChuK28pLzIpLHRoaXMudmlzdWFscy5saW5lLmRvaXQmJih0aGlzLnZpc3VhbHMubGluZS5zZXRfdmVjdG9yaXplKHQscyksdC5zdHJva2UoKSksdC5yZXN0b3JlKCl9LGUucHJvdG90eXBlLl9nZW5lcmljX2FyZWFfbGVnZW5kPWZ1bmN0aW9uKHQsZSxyLG4sbyl7dmFyIGkscyxhLGwsdSxoLGMscCxfLGQsZjtpZihoPW51bGwhPSh1PXRoaXMuZ2V0X3JlZmVyZW5jZV9wb2ludCgpKT91OjAsbD1baF0sZj1NYXRoLmFicyhyLWUpLHM9LjEqZixhPU1hdGguYWJzKG8tbiksaT0uMSphLGM9ZStzLHA9ci1zLF89bitpLGQ9by1pLHRoaXMudmlzdWFscy5maWxsLmRvaXQmJih0aGlzLnZpc3VhbHMuZmlsbC5zZXRfdmVjdG9yaXplKHQsaCksdC5maWxsUmVjdChjLF8scC1jLGQtXykpLHRoaXMudmlzdWFscy5saW5lLmRvaXQpcmV0dXJuIHQuYmVnaW5QYXRoKCksdC5yZWN0KGMsXyxwLWMsZC1fKSx0aGlzLnZpc3VhbHMubGluZS5zZXRfdmVjdG9yaXplKHQsaCksdC5zdHJva2UoKX0sZX0oYS5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBfKGUsdCksZS5kZWZpbmUoe3Zpc2libGU6W2MuQm9vbCwhMF19KSxlLmludGVybmFsKHt4X3JhbmdlX25hbWU6W2MuU3RyaW5nLCJkZWZhdWx0Il0seV9yYW5nZV9uYW1lOltjLlN0cmluZywiZGVmYXVsdCJdfSksZX0ocyksZS5leHBvcnRzPXtNb2RlbDpvLFZpZXc6aX19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vY29yZS91dGlsL2Jib3giOiJjb3JlL3V0aWwvYmJveCIsIi4uLy4uL21vZGVsIjoibW9kZWwiLCIuLi9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciI6Im1vZGVscy9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciIsIi4uL3JlbmRlcmVycy9yZW5kZXJlciI6Im1vZGVscy9yZW5kZXJlcnMvcmVuZGVyZXIiLCIuL3dlYmdsL21haW4iOiJtb2RlbHMvZ2x5cGhzL3dlYmdsL21haW4iLHJidXNoOiJyYnVzaCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2dseXBocy9oYmFyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlfLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LF89e30uaGFzT3duUHJvcGVydHk7bD10KCJ1bmRlcnNjb3JlIiksYz10KCJyYnVzaCIpLGE9dCgiLi9xdWFkIiksbz10KCIuL2dseXBoIiksbj10KCIuLi9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciIpLHU9dCgiLi4vLi4vY29tbW9uL2hpdHRlc3QiKSxoPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLHM9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHAoZSx0KSxlLnByb3RvdHlwZS5fbWFwX2RhdGE9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGk7Zm9yKGk9dGhpcy5yZW5kZXJlci55bWFwcGVyLnZfbWFwX3RvX3RhcmdldCh0aGlzLl95KSx0aGlzLnN5PXRoaXMucGxvdF92aWV3LmNhbnZhcy52X3Z5X3RvX3N5KGkpLG89dGhpcy5yZW5kZXJlci54bWFwcGVyLnZfbWFwX3RvX3RhcmdldCh0aGlzLl9yaWdodCksbj10aGlzLnJlbmRlcmVyLnhtYXBwZXIudl9tYXBfdG9fdGFyZ2V0KHRoaXMuX2xlZnQpLHRoaXMuc3JpZ2h0PXRoaXMucGxvdF92aWV3LmNhbnZhcy52X3Z4X3RvX3N4KG8pLHRoaXMuc2xlZnQ9dGhpcy5wbG90X3ZpZXcuY2FudmFzLnZfdnhfdG9fc3gobiksdGhpcy5zdG9wPVtdLHRoaXMuc2JvdHRvbT1bXSx0aGlzLnNoPXRoaXMuc2Rpc3QodGhpcy5yZW5kZXJlci55bWFwcGVyLHRoaXMuX3ksdGhpcy5faGVpZ2h0LCJjZW50ZXIiKSx0PWU9MCxyPXRoaXMuc3kubGVuZ3RoOzA8PXI/ZTxyOmU+cjt0PTA8PXI/KytlOi0tZSl0aGlzLnN0b3AucHVzaCh0aGlzLnN5W3RdLXRoaXMuc2hbdF0vMiksdGhpcy5zYm90dG9tLnB1c2godGhpcy5zeVt0XSt0aGlzLnNoW3RdLzIpO3JldHVybiBudWxsfSxlLnByb3RvdHlwZS5faW5kZXhfZGF0YT1mdW5jdGlvbigpe3ZhciB0LGUscixvLGkscyxhLGwsdSxoLHAsXyxkLGY7Zm9yKGw9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdCBpbnN0YW5jZW9mIG4uTW9kZWw/dC52X21hcF90b190YXJnZXQoZSwhMCk6ZX0sYT1sKHRoaXMucmVuZGVyZXIueG1hcHBlcix0aGlzLl9sZWZ0KSxfPWwodGhpcy5yZW5kZXJlci54bWFwcGVyLHRoaXMuX3JpZ2h0KSxmPWwodGhpcy5yZW5kZXJlci55bWFwcGVyLHRoaXMuX3kpLGU9bCh0aGlzLnJlbmRlcmVyLnltYXBwZXIsdGhpcy5faGVpZ2h0KSxvPWMoKSx1PVtdLHI9aT0wLHA9Zi5sZW5ndGg7MDw9cD9pPHA6aT5wO3I9MDw9cD8rK2k6LS1pKXM9YVtyXSxoPV9bcl0sZD1mW3JdKy41KmVbcl0sdD1mW3JdLS41KmVbcl0sIWlzTmFOKHMraCtkK3QpJiZpc0Zpbml0ZShzK2grZCt0KSYmdS5wdXNoKHttaW5YOnMsbWluWTp0LG1heFg6aCxtYXhZOmQsaTpyfSk7cmV0dXJuIG8ubG9hZCh1KSxvfSxlLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoO2ZvcihsPXIuc2xlZnQsdT1yLnNyaWdodCxoPXIuc3RvcCxhPXIuc2JvdHRvbSxzPVtdLG89MCxpPWUubGVuZ3RoO288aTtvKyspbj1lW29dLGlzTmFOKGxbbl0raFtuXSt1W25dK2Fbbl0pfHwodGhpcy52aXN1YWxzLmZpbGwuZG9pdCYmKHRoaXMudmlzdWFscy5maWxsLnNldF92ZWN0b3JpemUodCxuKSx0LmZpbGxSZWN0KGxbbl0saFtuXSx1W25dLWxbbl0sYVtuXS1oW25dKSksdGhpcy52aXN1YWxzLmxpbmUuZG9pdD8odC5iZWdpblBhdGgoKSx0LnJlY3QobFtuXSxoW25dLHVbbl0tbFtuXSxhW25dLWhbbl0pLHRoaXMudmlzdWFscy5saW5lLnNldF92ZWN0b3JpemUodCxuKSxzLnB1c2godC5zdHJva2UoKSkpOnMucHVzaCh2b2lkIDApKTtyZXR1cm4gc30sZS5wcm90b3R5cGUuX2hpdF9wb2ludD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYTtyZXR1cm4gcj1bdC52eCx0LnZ5XSxvPXJbMF0saT1yWzFdLHM9dGhpcy5yZW5kZXJlci54bWFwcGVyLm1hcF9mcm9tX3RhcmdldChvLCEwKSxhPXRoaXMucmVuZGVyZXIueW1hcHBlci5tYXBfZnJvbV90YXJnZXQoaSwhMCksZT1mdW5jdGlvbigpe3ZhciB0LGUscixuO2ZvcihyPXRoaXMuaW5kZXguc2VhcmNoKHttaW5YOnMsbWluWTphLG1heFg6cyxtYXhZOmF9KSxuPVtdLHQ9MCxlPXIubGVuZ3RoO3Q8ZTt0Kyspcz1yW3RdLG4ucHVzaChzLmkpO3JldHVybiBufS5jYWxsKHRoaXMpLG49dS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksblsiMWQiXS5pbmRpY2VzPWUsbn0sZS5wcm90b3R5cGUuc2N4PWZ1bmN0aW9uKHQpe3JldHVybih0aGlzLnNsZWZ0W3RdK3RoaXMuc3JpZ2h0W3RdKS8yfSxlfShvLlZpZXcpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHAoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9cyxlLnByb3RvdHlwZS50eXBlPSJIQmFyIixlLm1peGlucyhbImxpbmUiLCJmaWxsIl0pLGUuZGVmaW5lKHt5OltoLk51bWJlclNwZWNdLGhlaWdodDpbaC5EaXN0YW5jZVNwZWNdLGxlZnQ6W2guTnVtYmVyU3BlYywwXSxyaWdodDpbaC5OdW1iZXJTcGVjXX0pLGV9KG8uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6aSxWaWV3OnN9fSx7Ii4uLy4uL2NvbW1vbi9oaXR0ZXN0IjoiY29tbW9uL2hpdHRlc3QiLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciI6Im1vZGVscy9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciIsIi4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIiwiLi9xdWFkIjoibW9kZWxzL2dseXBocy9xdWFkIixyYnVzaDoicmJ1c2giLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvaW1hZ2UiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxjPXt9Lmhhc093blByb3BlcnR5O2w9dCgidW5kZXJzY29yZSIpLG49dCgiLi4vZ2x5cGhzL2dseXBoIiksYT10KCIuLi9tYXBwZXJzL2xpbmVhcl9jb2xvcl9tYXBwZXIiKSx1PXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89dCgiLi4vLi4vcGFsZXR0ZXMvcGFsZXR0ZXMiKS5HcmV5cyxzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBoKGUsdCksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy5saXN0ZW5Ubyh0aGlzLm1vZGVsLmNvbG9yX21hcHBlciwiY2hhbmdlIix0aGlzLl91cGRhdGVfaW1hZ2UpfSxlLnByb3RvdHlwZS5fdXBkYXRlX2ltYWdlPWZ1bmN0aW9uKCl7aWYobnVsbCE9dGhpcy5pbWFnZV9kYXRhKXJldHVybiB0aGlzLl9zZXRfZGF0YSgpLHRoaXMucGxvdF92aWV3LnJlcXVlc3RfcmVuZGVyKCl9LGUucHJvdG90eXBlLl9pbmRleF9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3h5X2luZGV4KCl9LGUucHJvdG90eXBlLl9zZXRfZGF0YT1mdW5jdGlvbigpe3ZhciB0LGUscixuLG8saSxzLGEsdSxoLGM7Zm9yKG51bGwhPXRoaXMuaW1hZ2VfZGF0YSYmdGhpcy5pbWFnZV9kYXRhLmxlbmd0aD09PXRoaXMuX2ltYWdlLmxlbmd0aHx8KHRoaXMuaW1hZ2VfZGF0YT1uZXcgQXJyYXkodGhpcy5faW1hZ2UubGVuZ3RoKSksbnVsbCE9dGhpcy5fd2lkdGgmJnRoaXMuX3dpZHRoLmxlbmd0aD09PXRoaXMuX2ltYWdlLmxlbmd0aHx8KHRoaXMuX3dpZHRoPW5ldyBBcnJheSh0aGlzLl9pbWFnZS5sZW5ndGgpKSxudWxsIT10aGlzLl9oZWlnaHQmJnRoaXMuX2hlaWdodC5sZW5ndGg9PT10aGlzLl9pbWFnZS5sZW5ndGh8fCh0aGlzLl9oZWlnaHQ9bmV3IEFycmF5KHRoaXMuX2ltYWdlLmxlbmd0aCkpLGM9W10saT11PTAsaD10aGlzLl9pbWFnZS5sZW5ndGg7MDw9aD91PGg6dT5oO2k9MDw9aD8rK3U6LS11KW51bGwhPXRoaXMuX3Jvd3M/KHRoaXMuX2hlaWdodFtpXT10aGlzLl9yb3dzW2ldLHRoaXMuX3dpZHRoW2ldPXRoaXMuX2NvbHNbaV0pOih0aGlzLl9oZWlnaHRbaV09dGhpcy5faW1hZ2VbaV0ubGVuZ3RoLHRoaXMuX3dpZHRoW2ldPXRoaXMuX2ltYWdlW2ldWzBdLmxlbmd0aCkscj1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJjYW52YXMiKSxyLndpZHRoPXRoaXMuX3dpZHRoW2ldLHIuaGVpZ2h0PXRoaXMuX2hlaWdodFtpXSxvPXIuZ2V0Q29udGV4dCgiMmQiKSxzPW8uZ2V0SW1hZ2VEYXRhKDAsMCx0aGlzLl93aWR0aFtpXSx0aGlzLl9oZWlnaHRbaV0pLG49dGhpcy5tZ2V0KCJjb2xvcl9tYXBwZXIiKSxhPW51bGwhPXRoaXMuX3Jvd3M/dGhpcy5faW1hZ2VbaV06bC5mbGF0dGVuKHRoaXMuX2ltYWdlW2ldKSx0PW4udl9tYXBfc2NyZWVuKGEpLGU9bmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHQpLHMuZGF0YS5zZXQoZSksby5wdXRJbWFnZURhdGEocywwLDApLHRoaXMuaW1hZ2VfZGF0YVtpXT1yLHRoaXMubWF4X2R3PTAsImRhdGEiPT09dGhpcy5fZHcudW5pdHMmJih0aGlzLm1heF9kdz1sLm1heCh0aGlzLl9kdykpLHRoaXMubWF4X2RoPTAsImRhdGEiPT09dGhpcy5fZGgudW5pdHMmJih0aGlzLm1heF9kaD1sLm1heCh0aGlzLl9kaCkpLGMucHVzaCh0aGlzLl94eV9pbmRleCgpKTtyZXR1cm4gY30sZS5wcm90b3R5cGUuX21hcF9kYXRhPWZ1bmN0aW9uKCl7c3dpdGNoKHRoaXMubW9kZWwucHJvcGVydGllcy5kdy51bml0cyl7Y2FzZSJkYXRhIjp0aGlzLnN3PXRoaXMuc2Rpc3QodGhpcy5yZW5kZXJlci54bWFwcGVyLHRoaXMuX3gsdGhpcy5fZHcsImVkZ2UiLHRoaXMubWdldCgiZGlsYXRlIikpO2JyZWFrO2Nhc2Uic2NyZWVuIjp0aGlzLnN3PXRoaXMuX2R3fXN3aXRjaCh0aGlzLm1vZGVsLnByb3BlcnRpZXMuZGgudW5pdHMpe2Nhc2UiZGF0YSI6cmV0dXJuIHRoaXMuc2g9dGhpcy5zZGlzdCh0aGlzLnJlbmRlcmVyLnltYXBwZXIsdGhpcy5feSx0aGlzLl9kaCwiZWRnZSIsdGhpcy5tZ2V0KCJkaWxhdGUiKSk7Y2FzZSJzY3JlZW4iOnJldHVybiB0aGlzLnNoPXRoaXMuX2RofX0sZS5wcm90b3R5cGUuX3JlbmRlcj1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHA7Zm9yKG89ci5pbWFnZV9kYXRhLGg9ci5zeCxjPXIuc3ksdT1yLnN3LGw9ci5zaCxhPXQuZ2V0SW1hZ2VTbW9vdGhpbmdFbmFibGVkKCksdC5zZXRJbWFnZVNtb290aGluZ0VuYWJsZWQoITEpLGk9MCxzPWUubGVuZ3RoO2k8cztpKyspbj1lW2ldLG51bGwhPW9bbl0mJihpc05hTihoW25dK2Nbbl0rdVtuXStsW25dKXx8KHA9Y1tuXSx0LnRyYW5zbGF0ZSgwLHApLHQuc2NhbGUoMSwtMSksdC50cmFuc2xhdGUoMCwtcCksdC5kcmF3SW1hZ2Uob1tuXSwwfGhbbl0sMHxjW25dLHVbbl0sbFtuXSksdC50cmFuc2xhdGUoMCxwKSx0LnNjYWxlKDEsLTEpLHQudHJhbnNsYXRlKDAsLXApKSk7cmV0dXJuIHQuc2V0SW1hZ2VTbW9vdGhpbmdFbmFibGVkKGEpfSxlLnByb3RvdHlwZS5ib3VuZHM9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gdD10aGlzLmluZGV4LmRhdGEse21pblg6dC5taW5YLG1pblk6dC5taW5ZLG1heFg6dC5tYXhYK3RoaXMubWF4X2R3LG1heFk6dC5tYXhZK3RoaXMubWF4X2RofX0sZX0obi5WaWV3KSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBoKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PXMsZS5wcm90b3R5cGUudHlwZT0iSW1hZ2UiLGUuY29vcmRzKFtbIngiLCJ5Il1dKSxlLm1peGlucyhbXSksZS5kZWZpbmUoe2ltYWdlOlt1Lk51bWJlclNwZWNdLGR3Olt1LkRpc3RhbmNlU3BlY10sZGg6W3UuRGlzdGFuY2VTcGVjXSxkaWxhdGU6W3UuQm9vbCwhMV0sY29sb3JfbWFwcGVyOlt1Lkluc3RhbmNlLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBhLk1vZGVsKHtwYWxldHRlOm8uR3JleXM5fSl9XX0pLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6aSxWaWV3OnN9fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4uLy4uL3BhbGV0dGVzL3BhbGV0dGVzIjoicGFsZXR0ZXMvcGFsZXR0ZXMiLCIuLi9nbHlwaHMvZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIiwiLi4vbWFwcGVycy9saW5lYXJfY29sb3JfbWFwcGVyIjoibW9kZWxzL21hcHBlcnMvbGluZWFyX2NvbG9yX21hcHBlciIsCnVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvaW1hZ2VfcmdiYSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXUuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sdT17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vZ2x5cGgiKSxhPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS5faW5kZXhfZGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl94eV9pbmRleCgpfSxlLnByb3RvdHlwZS5fc2V0X2RhdGE9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saSxhLGwsdSxoLGMscCxfLGQsZixtO2ZvcihudWxsIT10aGlzLmltYWdlX2RhdGEmJnRoaXMuaW1hZ2VfZGF0YS5sZW5ndGg9PT10aGlzLl9pbWFnZS5sZW5ndGh8fCh0aGlzLmltYWdlX2RhdGE9bmV3IEFycmF5KHRoaXMuX2ltYWdlLmxlbmd0aCkpLG51bGwhPXRoaXMuX3dpZHRoJiZ0aGlzLl93aWR0aC5sZW5ndGg9PT10aGlzLl9pbWFnZS5sZW5ndGh8fCh0aGlzLl93aWR0aD1uZXcgQXJyYXkodGhpcy5faW1hZ2UubGVuZ3RoKSksbnVsbCE9dGhpcy5faGVpZ2h0JiZ0aGlzLl9oZWlnaHQubGVuZ3RoPT09dGhpcy5faW1hZ2UubGVuZ3RofHwodGhpcy5faGVpZ2h0PW5ldyBBcnJheSh0aGlzLl9pbWFnZS5sZW5ndGgpKSxtPVtdLHU9cD0wLGQ9dGhpcy5faW1hZ2UubGVuZ3RoOzA8PWQ/cDxkOnA+ZDt1PTA8PWQ/KytwOi0tcClpZihudWxsPT1lfHx1PT09ZSl7aWYobnVsbCE9dGhpcy5fcm93cz8odGhpcy5faGVpZ2h0W3VdPXRoaXMuX3Jvd3NbdV0sdGhpcy5fd2lkdGhbdV09dGhpcy5fY29sc1t1XSk6KHRoaXMuX2hlaWdodFt1XT10aGlzLl9pbWFnZVt1XS5sZW5ndGgsdGhpcy5fd2lkdGhbdV09dGhpcy5faW1hZ2VbdV1bMF0ubGVuZ3RoKSxvPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImNhbnZhcyIpLG8ud2lkdGg9dGhpcy5fd2lkdGhbdV0sby5oZWlnaHQ9dGhpcy5faGVpZ2h0W3VdLGE9by5nZXRDb250ZXh0KCIyZCIpLGg9YS5nZXRJbWFnZURhdGEoMCwwLHRoaXMuX3dpZHRoW3VdLHRoaXMuX2hlaWdodFt1XSksbnVsbCE9dGhpcy5fcm93cyloLmRhdGEuc2V0KG5ldyBVaW50OENsYW1wZWRBcnJheSh0aGlzLl9pbWFnZVt1XSkpO2Vsc2V7Zm9yKGw9cy5mbGF0dGVuKHRoaXMuX2ltYWdlW3VdKSxyPW5ldyBBcnJheUJ1ZmZlcig0KmwubGVuZ3RoKSxpPW5ldyBVaW50MzJBcnJheShyKSxjPV89MCxmPWwubGVuZ3RoOzA8PWY/XzxmOl8+ZjtjPTA8PWY/KytfOi0tXylpW2NdPWxbY107bj1uZXcgVWludDhDbGFtcGVkQXJyYXkociksaC5kYXRhLnNldChuKX1hLnB1dEltYWdlRGF0YShoLDAsMCksdGhpcy5pbWFnZV9kYXRhW3VdPW8sdGhpcy5tYXhfZHc9MCwiZGF0YSI9PT10aGlzLl9kdy51bml0cyYmKHRoaXMubWF4X2R3PXMubWF4KHRoaXMuX2R3KSksdGhpcy5tYXhfZGg9MCwiZGF0YSI9PT10aGlzLl9kaC51bml0cz9tLnB1c2godGhpcy5tYXhfZGg9cy5tYXgodGhpcy5fZGgpKTptLnB1c2godm9pZCAwKX1yZXR1cm4gbX0sZS5wcm90b3R5cGUuX21hcF9kYXRhPWZ1bmN0aW9uKCl7c3dpdGNoKHRoaXMubW9kZWwucHJvcGVydGllcy5kdy51bml0cyl7Y2FzZSJkYXRhIjp0aGlzLnN3PXRoaXMuc2Rpc3QodGhpcy5yZW5kZXJlci54bWFwcGVyLHRoaXMuX3gsdGhpcy5fZHcsImVkZ2UiLHRoaXMubWdldCgiZGlsYXRlIikpO2JyZWFrO2Nhc2Uic2NyZWVuIjp0aGlzLnN3PXRoaXMuX2R3fXN3aXRjaCh0aGlzLm1vZGVsLnByb3BlcnRpZXMuZGgudW5pdHMpe2Nhc2UiZGF0YSI6cmV0dXJuIHRoaXMuc2g9dGhpcy5zZGlzdCh0aGlzLnJlbmRlcmVyLnltYXBwZXIsdGhpcy5feSx0aGlzLl9kaCwiZWRnZSIsdGhpcy5tZ2V0KCJkaWxhdGUiKSk7Y2FzZSJzY3JlZW4iOnJldHVybiB0aGlzLnNoPXRoaXMuX2RofX0sZS5wcm90b3R5cGUuX3JlbmRlcj1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHA7Zm9yKG89ci5pbWFnZV9kYXRhLGg9ci5zeCxjPXIuc3ksdT1yLnN3LGw9ci5zaCxhPXQuZ2V0SW1hZ2VTbW9vdGhpbmdFbmFibGVkKCksdC5zZXRJbWFnZVNtb290aGluZ0VuYWJsZWQoITEpLGk9MCxzPWUubGVuZ3RoO2k8cztpKyspbj1lW2ldLGlzTmFOKGhbbl0rY1tuXSt1W25dK2xbbl0pfHwocD1jW25dLHQudHJhbnNsYXRlKDAscCksdC5zY2FsZSgxLC0xKSx0LnRyYW5zbGF0ZSgwLC1wKSx0LmRyYXdJbWFnZShvW25dLDB8aFtuXSwwfGNbbl0sdVtuXSxsW25dKSx0LnRyYW5zbGF0ZSgwLHApLHQuc2NhbGUoMSwtMSksdC50cmFuc2xhdGUoMCwtcCkpO3JldHVybiB0LnNldEltYWdlU21vb3RoaW5nRW5hYmxlZChhKX0sZS5wcm90b3R5cGUuYm91bmRzPWZ1bmN0aW9uKCl7dmFyIHQ7cmV0dXJuIHQ9dGhpcy5pbmRleC5kYXRhLHttaW5YOnQubWluWCxtaW5ZOnQubWluWSxtYXhYOnQubWF4WCt0aGlzLm1heF9kdyxtYXhZOnQubWF4WSt0aGlzLm1heF9kaH19LGV9KG4uVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLnR5cGU9IkltYWdlUkdCQSIsZS5jb29yZHMoW1sieCIsInkiXV0pLGUubWl4aW5zKFtdKSxlLmRlZmluZSh7aW1hZ2U6W2EuTnVtYmVyU3BlY10scm93czpbYS5OdW1iZXJTcGVjXSxjb2xzOlthLk51bWJlclNwZWNdLGR3OlthLkRpc3RhbmNlU3BlY10sZGg6W2EuRGlzdGFuY2VTcGVjXSxkaWxhdGU6W2EuQm9vbCwhMV19KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5wcm9wZXJ0aWVzLnJvd3Mub3B0aW9uYWw9ITAsdGhpcy5wcm9wZXJ0aWVzLmNvbHMub3B0aW9uYWw9ITB9LGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvZ2x5cGhzL2ltYWdlX3VybCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpaC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxoPXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLG49dCgiLi9nbHlwaCIpLGE9dCgiLi4vLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLGw9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCl7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiY2hhbmdlOmdsb2JhbF9hbHBoYSIsdGhpcy5yZW5kZXJlci5yZXF1ZXN0X3JlbmRlcil9LGUucHJvdG90eXBlLl9pbmRleF9kYXRhPWZ1bmN0aW9uKCl7fSxlLnByb3RvdHlwZS5fc2V0X2RhdGE9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscztmb3IobnVsbCE9dGhpcy5pbWFnZSYmdGhpcy5pbWFnZS5sZW5ndGg9PT10aGlzLl91cmwubGVuZ3RofHwodGhpcy5pbWFnZT1mdW5jdGlvbigpe3ZhciB0LHIsbixvO2ZvcihuPXRoaXMuX3VybCxvPVtdLHQ9MCxyPW4ubGVuZ3RoO3Q8cjt0KyspZT1uW3RdLG8ucHVzaChudWxsKTtyZXR1cm4gb30uY2FsbCh0aGlzKSksaT10aGlzLm1vZGVsLnJldHJ5X2F0dGVtcHRzLHM9dGhpcy5tb2RlbC5yZXRyeV90aW1lb3V0LHRoaXMucmV0cmllcz1mdW5jdGlvbigpe3ZhciB0LHIsbixvO2ZvcihuPXRoaXMuX3VybCxvPVtdLHQ9MCxyPW4ubGVuZ3RoO3Q8cjt0KyspZT1uW3RdLG8ucHVzaChpKTtyZXR1cm4gb30uY2FsbCh0aGlzKSxvPVtdLHQ9cj0wLG49dGhpcy5fdXJsLmxlbmd0aDswPD1uP3I8bjpyPm47dD0wPD1uPysrcjotLXIpbnVsbCE9dGhpcy5fdXJsW3RdJiYoZT1uZXcgSW1hZ2UsZS5vbmVycm9yPWZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihlLHIpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiB0LnJldHJpZXNbZV0+MD8oYS50cmFjZSgiSW1hZ2VVUkwgZmFpbGVkIHRvIGxvYWQgIit0Ll91cmxbZV0rIiBpbWFnZSwgcmV0cnlpbmcgaW4gIitzKyIgbXMiKSxzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7cmV0dXJuIHIuc3JjPXQuX3VybFtlXX0scykpOmEud2FybigiSW1hZ2VVUkwgdW5hYmxlIHRvIGxvYWQgIit0Ll91cmxbZV0rIiBpbWFnZSBhZnRlciAiK2krIiByZXRyaWVzIiksdC5yZXRyaWVzW2VdLT0xfX19KHRoaXMpKHQsZSksZS5vbmxvYWQ9ZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKGUscil7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHQuaW1hZ2Vbcl09ZSx0LnJlbmRlcmVyLnJlcXVlc3RfcmVuZGVyKCl9fX0odGhpcykoZSx0KSxvLnB1c2goZS5zcmM9dGhpcy5fdXJsW3RdKSk7cmV0dXJuIG99LGUucHJvdG90eXBlLl9tYXBfZGF0YT1mdW5jdGlvbigpe3ZhciB0LGUscjtzd2l0Y2goZT1mdW5jdGlvbigpe3ZhciB0LGUsbixvO2lmKG51bGwhPXRoaXMuX3cpcmV0dXJuIHRoaXMuX3c7Zm9yKG49dGhpcy5feCxvPVtdLHQ9MCxlPW4ubGVuZ3RoO3Q8ZTt0Kyspcj1uW3RdLG8ucHVzaChOYU4pO3JldHVybiBvfS5jYWxsKHRoaXMpLHQ9ZnVuY3Rpb24oKXt2YXIgdCxlLG4sbztpZihudWxsIT10aGlzLl9oKXJldHVybiB0aGlzLl9oO2ZvcihuPXRoaXMuX3gsbz1bXSx0PTAsZT1uLmxlbmd0aDt0PGU7dCsrKXI9blt0XSxvLnB1c2goTmFOKTtyZXR1cm4gb30uY2FsbCh0aGlzKSx0aGlzLm1vZGVsLnByb3BlcnRpZXMudy51bml0cyl7Y2FzZSJkYXRhIjp0aGlzLnN3PXRoaXMuc2Rpc3QodGhpcy5yZW5kZXJlci54bWFwcGVyLHRoaXMuX3gsZSwiZWRnZSIsdGhpcy5tb2RlbC5kaWxhdGUpO2JyZWFrO2Nhc2Uic2NyZWVuIjp0aGlzLnN3PWV9c3dpdGNoKHRoaXMubW9kZWwucHJvcGVydGllcy5oLnVuaXRzKXtjYXNlImRhdGEiOnJldHVybiB0aGlzLnNoPXRoaXMuc2Rpc3QodGhpcy5yZW5kZXJlci55bWFwcGVyLHRoaXMuX3ksdCwiZWRnZSIsdGhpcy5tb2RlbC5kaWxhdGUpO2Nhc2Uic2NyZWVuIjpyZXR1cm4gdGhpcy5zaD10fX0sZS5wcm90b3R5cGUuX3JlbmRlcj1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkO2ZvcihvPXIuX3VybCxhPXIuaW1hZ2UsXz1yLnN4LGQ9ci5zeSxwPXIuc3csYz1yLnNoLG49ci5fYW5nbGUsaT10aGlzLnJlbmRlcmVyLnBsb3Rfdmlldy5mcmFtZSx0LnJlY3QoaS5nZXQoImxlZnQiKSsxLGkuZ2V0KCJib3R0b20iKSsxLGkuZ2V0KCJ3aWR0aCIpLTIsaS5nZXQoImhlaWdodCIpLTIpLHQuY2xpcCgpLGg9W10sbD0wLHU9ZS5sZW5ndGg7bDx1O2wrKylzPWVbbF0saXNOYU4oX1tzXStkW3NdK25bc10pfHx0aGlzLnJldHJpZXNbc10hPT0tMSYmbnVsbCE9YVtzXSYmaC5wdXNoKHRoaXMuX3JlbmRlcl9pbWFnZSh0LHMsYVtzXSxfLGQscCxjLG4pKTtyZXR1cm4gaH0sZS5wcm90b3R5cGUuX2ZpbmFsX3N4X3N5PWZ1bmN0aW9uKHQsZSxyLG4sbyl7c3dpdGNoKHQpe2Nhc2UidG9wX2xlZnQiOnJldHVybltlLHJdO2Nhc2UidG9wX2NlbnRlciI6cmV0dXJuW2Utbi8yLHJdO2Nhc2UidG9wX3JpZ2h0IjpyZXR1cm5bZS1uLHJdO2Nhc2UicmlnaHRfY2VudGVyIjpyZXR1cm5bZS1uLHItby8yXTtjYXNlImJvdHRvbV9yaWdodCI6cmV0dXJuW2UtbixyLW9dO2Nhc2UiYm90dG9tX2NlbnRlciI6cmV0dXJuW2Utbi8yLHItb107Y2FzZSJib3R0b21fbGVmdCI6cmV0dXJuW2Usci1vXTtjYXNlImxlZnRfY2VudGVyIjpyZXR1cm5bZSxyLW8vMl07Y2FzZSJjZW50ZXIiOnJldHVybltlLW4vMixyLW8vMl19fSxlLnByb3RvdHlwZS5fcmVuZGVyX2ltYWdlPWZ1bmN0aW9uKHQsZSxyLG4sbyxpLHMsYSl7dmFyIGwsdTtyZXR1cm4gaXNOYU4oaVtlXSkmJihpW2VdPXIud2lkdGgpLGlzTmFOKHNbZV0pJiYoc1tlXT1yLmhlaWdodCksbD10aGlzLm1vZGVsLmFuY2hvcix1PXRoaXMuX2ZpbmFsX3N4X3N5KGwsbltlXSxvW2VdLGlbZV0sc1tlXSksbj11WzBdLG89dVsxXSx0LnNhdmUoKSx0Lmdsb2JhbEFscGhhPXRoaXMubW9kZWwuZ2xvYmFsX2FscGhhLGFbZV0/KHQudHJhbnNsYXRlKG4sbyksdC5yb3RhdGUoYVtlXSksdC5kcmF3SW1hZ2UociwwLDAsaVtlXSxzW2VdKSx0LnJvdGF0ZSgtYVtlXSksdC50cmFuc2xhdGUoLW4sLW8pKTp0LmRyYXdJbWFnZShyLG4sbyxpW2VdLHNbZV0pLHQucmVzdG9yZSgpfSxlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHUoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJJbWFnZVVSTCIsZS5jb29yZHMoW1sieCIsInkiXV0pLGUubWl4aW5zKFtdKSxlLmRlZmluZSh7dXJsOltsLlN0cmluZ1NwZWNdLGFuY2hvcjpbbC5BbmNob3IsInRvcF9sZWZ0Il0sZ2xvYmFsX2FscGhhOltsLk51bWJlciwxXSxhbmdsZTpbbC5BbmdsZVNwZWMsMF0sdzpbbC5EaXN0YW5jZVNwZWNdLGg6W2wuRGlzdGFuY2VTcGVjXSxkaWxhdGU6W2wuQm9vbCwhMV0scmV0cnlfYXR0ZW1wdHM6W2wuTnVtYmVyLDBdLHJldHJ5X3RpbWVvdXQ6W2wuTnVtYmVyLDBdfSksZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvLFZpZXc6aX19LHsiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9nbHlwaCI6Im1vZGVscy9nbHlwaHMvZ2x5cGgiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvbGluZSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXUuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sdT17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vZ2x5cGgiKSxhPXQoIi4uLy4uL2NvbW1vbi9oaXR0ZXN0IiksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUucHJvdG90eXBlLl9pbmRleF9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3h5X2luZGV4KCl9LGUucHJvdG90eXBlLl9yZW5kZXI9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbDtmb3IoYT1yLnN4LGw9ci5zeSxuPSExLHRoaXMudmlzdWFscy5saW5lLnNldF92YWx1ZSh0KSxpPTAscz1lLmxlbmd0aDtpPHM7aSsrKW89ZVtpXSxpc0Zpbml0ZShhW29dK2xbb10pfHwhbj9uP3QubGluZVRvKGFbb10sbFtvXSk6KHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8oYVtvXSxsW29dKSxuPSEwKToodC5zdHJva2UoKSx0LmJlZ2luUGF0aCgpLG49ITEpO2lmKG4pcmV0dXJuIHQuc3Ryb2tlKCl9LGUucHJvdG90eXBlLl9oaXRfcG9pbnQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGwsdSxoLGMscDtmb3IoaD1hLmNyZWF0ZV9oaXRfdGVzdF9yZXN1bHQoKSxzPXt4OnRoaXMucmVuZGVyZXIucGxvdF92aWV3LmNhbnZhcy52eF90b19zeCh0LnZ4KSx5OnRoaXMucmVuZGVyZXIucGxvdF92aWV3LmNhbnZhcy52eV90b19zeSh0LnZ5KX0sYz05OTk5LHA9TWF0aC5tYXgoMix0aGlzLnZpc3VhbHMubGluZS5saW5lX3dpZHRoLnZhbHVlKCkvMikscj1uPTAsbD10aGlzLnN4Lmxlbmd0aC0xOzA8PWw/bjxsOm4+bDtyPTA8PWw/KytuOi0tbil1PVt7eDp0aGlzLnN4W3JdLHk6dGhpcy5zeVtyXX0se3g6dGhpcy5zeFtyKzFdLHk6dGhpcy5zeVtyKzFdfV0sbz11WzBdLGk9dVsxXSxlPWEuZGlzdF90b19zZWdtZW50KHMsbyxpKSxlPHAmJmU8YyYmKGM9ZSxoWyIwZCJdLmdseXBoPXRoaXMubW9kZWwsaFsiMGQiXS5nZXRfdmlldz1mdW5jdGlvbigpe3JldHVybiB0aGlzfS5iaW5kKHRoaXMpLGhbIjBkIl0uZmxhZz0hMCxoWyIwZCJdLmluZGljZXM9W3JdKTtyZXR1cm4gaH0sZS5wcm90b3R5cGUuX2hpdF9zcGFuPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxsLHUsaDtmb3Iobj1bdC52eCx0LnZ5XSx1PW5bMF0saD1uWzFdLGk9YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksInYiPT09dC5kaXJlY3Rpb24/KHM9dGhpcy5yZW5kZXJlci55bWFwcGVyLm1hcF9mcm9tX3RhcmdldChoKSxsPXRoaXMuX3kpOihzPXRoaXMucmVuZGVyZXIueG1hcHBlci5tYXBfZnJvbV90YXJnZXQodSksbD10aGlzLl94KSxlPXI9MCxvPWwubGVuZ3RoLTE7MDw9bz9yPG86cj5vO2U9MDw9bz8rK3I6LS1yKWxbZV08PXMmJnM8PWxbZSsxXSYmKGlbIjBkIl0uZ2x5cGg9dGhpcy5tb2RlbCxpWyIwZCJdLmdldF92aWV3PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9LmJpbmQodGhpcyksaVsiMGQiXS5mbGFnPSEwLGlbIjBkIl0uaW5kaWNlcy5wdXNoKGUpKTtyZXR1cm4gaX0sZS5wcm90b3R5cGUuZ2V0X2ludGVycG9sYXRpb25faGl0PWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLGkscyxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHg7cmV0dXJuIHI9W2UudngsZS52eV0scD1yWzBdLF89clsxXSxuPVt0aGlzLl94W3RdLHRoaXMuX3lbdF0sdGhpcy5feFt0KzFdLHRoaXMuX3lbdCsxXV0sbT1uWzBdLGI9blsxXSxnPW5bMl0seD1uWzNdLCJwb2ludCI9PT1lLnR5cGU/KG89dGhpcy5yZW5kZXJlci55bWFwcGVyLnZfbWFwX2Zyb21fdGFyZ2V0KFtfLTEsXysxXSkseT1vWzBdLHY9b1sxXSxpPXRoaXMucmVuZGVyZXIueG1hcHBlci52X21hcF9mcm9tX3RhcmdldChbcC0xLHArMV0pLGQ9aVswXSxmPWlbMV0pOiJ2Ij09PWUuZGlyZWN0aW9uPyhzPXRoaXMucmVuZGVyZXIueW1hcHBlci52X21hcF9mcm9tX3RhcmdldChbXyxfXSkseT1zWzBdLHY9c1sxXSxsPVttLGddLGQ9bFswXSxmPWxbMV0pOih1PXRoaXMucmVuZGVyZXIueG1hcHBlci52X21hcF9mcm9tX3RhcmdldChbcCxwXSksZD11WzBdLGY9dVsxXSxoPVtiLHhdLHk9aFswXSx2PWhbMV0pLGM9YS5jaGVja18yX3NlZ21lbnRzX2ludGVyc2VjdChkLHksZix2LG0sYixnLHgpLFtjLngsYy55XX0sZS5wcm90b3R5cGUuZHJhd19sZWdlbmQ9ZnVuY3Rpb24odCxlLHIsbixvKXtyZXR1cm4gdGhpcy5fZ2VuZXJpY19saW5lX2xlZ2VuZCh0LGUscixuLG8pfSxlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJMaW5lIixlLmNvb3JkcyhbWyJ4IiwieSJdXSksZS5taXhpbnMoWyJsaW5lIl0pLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4uLy4uL2NvbW1vbi9oaXR0ZXN0IjoiY29tbW9uL2hpdHRlc3QiLCIuL2dseXBoIjoibW9kZWxzL2dseXBocy9nbHlwaCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2dseXBocy9tdWx0aV9saW5lIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1PWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSloLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGg9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbD10KCJyYnVzaCIpLGE9dCgiLi4vLi4vY29tbW9uL2hpdHRlc3QiKSxuPXQoIi4vZ2x5cGgiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGksYSx1LGg7Zm9yKGU9bCgpLG49W10sdD1yPTAsbz10aGlzLl94cy5sZW5ndGg7MDw9bz9yPG86cj5vO3Q9MDw9bz8rK3I6LS1yKWE9ZnVuY3Rpb24oKXt2YXIgZSxyLG4sbztmb3Iobj10aGlzLl94c1t0XSxvPVtdLGU9MCxyPW4ubGVuZ3RoO2U8cjtlKyspaT1uW2VdLHMuaXNOYU4oaSl8fG8ucHVzaChpKTtyZXR1cm4gb30uY2FsbCh0aGlzKSxoPWZ1bmN0aW9uKCl7dmFyIGUscixuLG87Zm9yKG49dGhpcy5feXNbdF0sbz1bXSxlPTAscj1uLmxlbmd0aDtlPHI7ZSsrKXU9bltlXSxzLmlzTmFOKHUpfHxvLnB1c2godSk7cmV0dXJuIG99LmNhbGwodGhpcyksMCE9PWEubGVuZ3RoJiZuLnB1c2goe21pblg6cy5taW4oYSksbWluWTpzLm1pbihoKSxtYXhYOnMubWF4KGEpLG1heFk6cy5tYXgoaCksaTp0fSk7cmV0dXJuIGUubG9hZChuKSxlfSxlLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQ7Zm9yKHA9ci5zeHMsZD1yLnN5cyxoPVtdLGk9MCxhPWUubGVuZ3RoO2k8YTtpKyspe2ZvcihuPWVbaV0sbD1bcFtuXSxkW25dXSxjPWxbMF0sXz1sWzFdLHRoaXMudmlzdWFscy5saW5lLnNldF92ZWN0b3JpemUodCxuKSxvPXM9MCx1PWMubGVuZ3RoOzA8PXU/czx1OnM+dTtvPTA8PXU/KytzOi0tcykwIT09bz9pc05hTihjW29dKXx8aXNOYU4oX1tvXSk/KHQuc3Ryb2tlKCksdC5iZWdpblBhdGgoKSk6dC5saW5lVG8oY1tvXSxfW29dKToodC5iZWdpblBhdGgoKSx0Lm1vdmVUbyhjW29dLF9bb10pKTtoLnB1c2godC5zdHJva2UoKSl9cmV0dXJuIGh9LGUucHJvdG90eXBlLl9oaXRfcG9pbnQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxsLHUsaCxjLHAsXyxkLGYsbSxnLHk7Zm9yKG09YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksYz17eDp0aGlzLnJlbmRlcmVyLnBsb3Rfdmlldy5jYW52YXMudnhfdG9fc3godC52eCkseTp0aGlzLnJlbmRlcmVyLnBsb3Rfdmlldy5jYW52YXMudnlfdG9fc3kodC52eSl9LGc9OTk5OSx5PU1hdGgubWF4KDIsdGhpcy52aXN1YWxzLmxpbmUubGluZV93aWR0aC52YWx1ZSgpLzIpLHI9e30sbj1pPTAsXz10aGlzLnN4cy5sZW5ndGg7MDw9Xz9pPF86aT5fO249MDw9Xz8rK2k6LS1pKXtmb3IocD1udWxsLG89bD0wLGQ9dGhpcy5zeHNbbl0ubGVuZ3RoLTE7MDw9ZD9sPGQ6bD5kO289MDw9ZD8rK2w6LS1sKWY9W3t4OnRoaXMuc3hzW25dW29dLHk6dGhpcy5zeXNbbl1bb119LHt4OnRoaXMuc3hzW25dW28rMV0seTp0aGlzLnN5c1tuXVtvKzFdfV0sdT1mWzBdLGg9ZlsxXSxlPWEuZGlzdF90b19zZWdtZW50KGMsdSxoKSxlPHkmJmU8ZyYmKGc9ZSxwPVtvXSk7cCYmKHJbbl09cCl9cmV0dXJuIG1bIjFkIl0uaW5kaWNlcz1zLmtleXMociksbVsiMmQiXT1yLG19LGUucHJvdG90eXBlLl9oaXRfc3Bhbj1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLGwsdSxoLGMscCxfLGQsZixtO2Zvcih1PVt0LnZ4LHQudnldLGY9dVswXSxtPXVbMV0scD1hLmNyZWF0ZV9oaXRfdGVzdF9yZXN1bHQoKSwidiI9PT10LmRpcmVjdGlvbj8oXz10aGlzLnJlbmRlcmVyLnltYXBwZXIubWFwX2Zyb21fdGFyZ2V0KG0pLGQ9dGhpcy5feXMpOihfPXRoaXMucmVuZGVyZXIueG1hcHBlci5tYXBfZnJvbV90YXJnZXQoZiksZD10aGlzLl94cyksZT17fSxyPW89MCxoPWQubGVuZ3RoOzA8PWg/bzxoOm8+aDtyPTA8PWg/KytvOi0tbyl7Zm9yKGw9W10sbj1pPTAsYz1kW3JdLmxlbmd0aC0xOzA8PWM/aTxjOmk+YztuPTA8PWM/KytpOi0taSlkW3JdW25dPD1fJiZfPD1kW3JdW24rMV0mJmwucHVzaChuKTtsLmxlbmd0aD4wJiYoZVtyXT1sKX1yZXR1cm4gcFsiMWQiXS5pbmRpY2VzPXMua2V5cyhlKSxwWyIyZCJdPWUscH0sZS5wcm90b3R5cGUuZ2V0X2ludGVycG9sYXRpb25faGl0PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdztyZXR1cm4gbj1bci52eCxyLnZ5XSxfPW5bMF0sZD1uWzFdLG89W3RoaXMuX3hzW3RdW2VdLHRoaXMuX3lzW3RdW2VdLHRoaXMuX3hzW3RdW2UrMV0sdGhpcy5feXNbdF1bZSsxXV0sZz1vWzBdLHg9b1sxXSx5PW9bMl0sdz1vWzNdLCJwb2ludCI9PT1yLnR5cGU/KGk9dGhpcy5yZW5kZXJlci55bWFwcGVyLnZfbWFwX2Zyb21fdGFyZ2V0KFtkLTEsZCsxXSksdj1pWzBdLGI9aVsxXSxzPXRoaXMucmVuZGVyZXIueG1hcHBlci52X21hcF9mcm9tX3RhcmdldChbXy0xLF8rMV0pLGY9c1swXSxtPXNbMV0pOiJ2Ij09PXIuZGlyZWN0aW9uPyhsPXRoaXMucmVuZGVyZXIueW1hcHBlci52X21hcF9mcm9tX3RhcmdldChbZCxkXSksdj1sWzBdLGI9bFsxXSx1PVtnLHldLGY9dVswXSxtPXVbMV0pOihoPXRoaXMucmVuZGVyZXIueG1hcHBlci52X21hcF9mcm9tX3RhcmdldChbXyxfXSksZj1oWzBdLG09aFsxXSxjPVt4LHddLHY9Y1swXSxiPWNbMV0pLHA9YS5jaGVja18yX3NlZ21lbnRzX2ludGVyc2VjdChmLHYsbSxiLGcseCx5LHcpLFtwLngscC55XX0sZS5wcm90b3R5cGUuZHJhd19sZWdlbmQ9ZnVuY3Rpb24odCxlLHIsbixvKXtyZXR1cm4gdGhpcy5fZ2VuZXJpY19saW5lX2xlZ2VuZCh0LGUscixuLG8pfSxlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHUoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJNdWx0aUxpbmUiLGUuY29vcmRzKFtbInhzIiwieXMiXV0pLGUubWl4aW5zKFsibGluZSJdKSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzppfX0seyIuLi8uLi9jb21tb24vaGl0dGVzdCI6ImNvbW1vbi9oaXR0ZXN0IiwiLi9nbHlwaCI6Im1vZGVscy9nbHlwaHMvZ2x5cGgiLHJidXNoOiJyYnVzaCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2dseXBocy9vdmFsIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpdS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSx1PXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLG49dCgiLi9nbHlwaCIpLGE9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUucHJvdG90eXBlLl9zZXRfZGF0YT1mdW5jdGlvbigpe2lmKHRoaXMubWF4X3cyPTAsImRhdGEiPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLndpZHRoLnVuaXRzJiYodGhpcy5tYXhfdzI9dGhpcy5tYXhfd2lkdGgvMiksdGhpcy5tYXhfaDI9MCwiZGF0YSI9PT10aGlzLm1vZGVsLnByb3BlcnRpZXMuaGVpZ2h0LnVuaXRzKXJldHVybiB0aGlzLm1heF9oMj10aGlzLm1heF9oZWlnaHQvMn0sZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5feHlfaW5kZXgoKX0sZS5wcm90b3R5cGUuX21hcF9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuImRhdGEiPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLndpZHRoLnVuaXRzP3RoaXMuc3c9dGhpcy5zZGlzdCh0aGlzLnJlbmRlcmVyLnhtYXBwZXIsdGhpcy5feCx0aGlzLl93aWR0aCwiY2VudGVyIik6dGhpcy5zdz10aGlzLl93aWR0aCwiZGF0YSI9PT10aGlzLm1vZGVsLnByb3BlcnRpZXMuaGVpZ2h0LnVuaXRzP3RoaXMuc2g9dGhpcy5zZGlzdCh0aGlzLnJlbmRlcmVyLnltYXBwZXIsdGhpcy5feSx0aGlzLl9oZWlnaHQsImNlbnRlciIpOnRoaXMuc2g9dGhpcy5faGVpZ2h0fSxlLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoO2Zvcih1PXIuc3gsaD1yLnN5LGw9ci5zdyxhPXIuc2gscz1bXSxvPTAsaT1lLmxlbmd0aDtvPGk7bysrKW49ZVtvXSxpc05hTih1W25dK2hbbl0rbFtuXSthW25dK3RoaXMuX2FuZ2xlW25dKXx8KHQudHJhbnNsYXRlKHVbbl0saFtuXSksdC5yb3RhdGUodGhpcy5fYW5nbGVbbl0pLHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8oMCwtYVtuXS8yKSx0LmJlemllckN1cnZlVG8obFtuXS8yLC1hW25dLzIsbFtuXS8yLGFbbl0vMiwwLGFbbl0vMiksdC5iZXppZXJDdXJ2ZVRvKC1sW25dLzIsYVtuXS8yLC1sW25dLzIsLWFbbl0vMiwwLC1hW25dLzIpLHQuY2xvc2VQYXRoKCksdGhpcy52aXN1YWxzLmZpbGwuZG9pdCYmKHRoaXMudmlzdWFscy5maWxsLnNldF92ZWN0b3JpemUodCxuKSx0LmZpbGwoKSksdGhpcy52aXN1YWxzLmxpbmUuZG9pdCYmKHRoaXMudmlzdWFscy5saW5lLnNldF92ZWN0b3JpemUodCxuKSx0LnN0cm9rZSgpKSx0LnJvdGF0ZSgtdGhpcy5fYW5nbGVbbl0pLHMucHVzaCh0LnRyYW5zbGF0ZSgtdVtuXSwtaFtuXSkpKTtyZXR1cm4gc30sZS5wcm90b3R5cGUuZHJhd19sZWdlbmQ9ZnVuY3Rpb24odCxlLHIsbixvKXt2YXIgaSxzLGEsbCx1LGgsYyxwLF8sZDtyZXR1cm4gdT1udWxsIT0obD10aGlzLmdldF9yZWZlcmVuY2VfcG9pbnQoKSk/bDowLGE9W3VdLF89e30sX1t1XT0oZStyKS8yLGQ9e30sZFt1XT0obitvKS8yLGg9dGhpcy5zd1t1XS90aGlzLnNoW3VdLGk9LjgqTWF0aC5taW4oTWF0aC5hYnMoci1lKSxNYXRoLmFicyhvLW4pKSxwPXt9LGM9e30saD4xPyhwW3VdPWksY1t1XT1pL2gpOihwW3VdPWkqaCxjW3VdPWkpLHM9e3N4Ol8sc3k6ZCxzdzpwLHNoOmN9LHRoaXMuX3JlbmRlcih0LGEscyl9LGUucHJvdG90eXBlLl9ib3VuZHM9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMubWF4X3doMl9ib3VuZHModCl9LGV9KG4uVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLnR5cGU9Ik92YWwiLGUuY29vcmRzKFtbIngiLCJ5Il1dKSxlLm1peGlucyhbImxpbmUiLCJmaWxsIl0pLGUuZGVmaW5lKHthbmdsZTpbYS5BbmdsZVNwZWMsMF0sd2lkdGg6W2EuRGlzdGFuY2VTcGVjXSxoZWlnaHQ6W2EuRGlzdGFuY2VTcGVjXX0pLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvZ2x5cGhzL3BhdGNoIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vZ2x5cGgiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5feHlfaW5kZXgoKX0sZS5wcm90b3R5cGUuX3JlbmRlcj1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHU7aWYobD1yLnN4LHU9ci5zeSx0aGlzLnZpc3VhbHMuZmlsbC5kb2l0KXtmb3IodGhpcy52aXN1YWxzLmZpbGwuc2V0X3ZhbHVlKHQpLG89MCxzPWUubGVuZ3RoO288cztvKyspbj1lW29dLDAhPT1uP2lzTmFOKGxbbl0rdVtuXSk/KHQuY2xvc2VQYXRoKCksdC5maWxsKCksdC5iZWdpblBhdGgoKSk6dC5saW5lVG8obFtuXSx1W25dKToodC5iZWdpblBhdGgoKSx0Lm1vdmVUbyhsW25dLHVbbl0pKTt0LmNsb3NlUGF0aCgpLHQuZmlsbCgpfWlmKHRoaXMudmlzdWFscy5saW5lLmRvaXQpe2Zvcih0aGlzLnZpc3VhbHMubGluZS5zZXRfdmFsdWUodCksaT0wLGE9ZS5sZW5ndGg7aTxhO2krKyluPWVbaV0sMCE9PW4/aXNOYU4obFtuXSt1W25dKT8odC5jbG9zZVBhdGgoKSx0LnN0cm9rZSgpLHQuYmVnaW5QYXRoKCkpOnQubGluZVRvKGxbbl0sdVtuXSk6KHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8obFtuXSx1W25dKSk7cmV0dXJuIHQuY2xvc2VQYXRoKCksdC5zdHJva2UoKX19LGUucHJvdG90eXBlLmRyYXdfbGVnZW5kPWZ1bmN0aW9uKHQsZSxyLG4sbyl7cmV0dXJuIHRoaXMuX2dlbmVyaWNfYXJlYV9sZWdlbmQodCxlLHIsbixvKX0sZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWksZS5wcm90b3R5cGUudHlwZT0iUGF0Y2giLGUuY29vcmRzKFtbIngiLCJ5Il1dKSxlLm1peGlucyhbImxpbmUiLCJmaWxsIl0pLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvZ2x5cGhzL3BhdGNoZXMiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHU9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWguY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0saD17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxsPXQoInJidXNoIiksbj10KCIuL2dseXBoIiksYT10KCIuLi8uLi9jb21tb24vaGl0dGVzdCIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHUoZSx0KSxlLnByb3RvdHlwZS5fYnVpbGRfZGlzY29udGludW91c19vYmplY3Q9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxhLGwsdSxoO2ZvcihyPXt9LG49bz0wLGg9dC5sZW5ndGg7MDw9aD9vPGg6bz5oO249MDw9aD8rK286LS1vKWZvcihyW25dPVtdLGw9cy50b0FycmF5KHRbbl0pO2wubGVuZ3RoPjA7KWk9cy5maW5kTGFzdEluZGV4KGwsZnVuY3Rpb24odCl7cmV0dXJuIHMuaXNOYU4odCl9KSxpPj0wP3U9bC5zcGxpY2UoaSk6KHU9bCxsPVtdKSxlPWZ1bmN0aW9uKCl7dmFyIHQsZSxyO2ZvcihyPVtdLHQ9MCxlPXUubGVuZ3RoO3Q8ZTt0KyspYT11W3RdLHMuaXNOYU4oYSl8fHIucHVzaChhKTtyZXR1cm4gcn0oKSxyW25dLnB1c2goZSk7cmV0dXJuIHJ9LGUucHJvdG90eXBlLl9pbmRleF9kYXRhPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLGEsdSxoLGMscCxfO2ZvcihlPWwoKSxpPVtdLGM9dGhpcy5fYnVpbGRfZGlzY29udGludW91c19vYmplY3QodGhpcy5feHMpLF89dGhpcy5fYnVpbGRfZGlzY29udGludW91c19vYmplY3QodGhpcy5feXMpLHQ9bj0wLGE9dGhpcy5feHMubGVuZ3RoOzA8PWE/bjxhOm4+YTt0PTA8PWE/KytuOi0tbilmb3Iocj1vPTAsdT1jW3RdLmxlbmd0aDswPD11P288dTpvPnU7cj0wPD11PysrbzotLW8paD1jW3RdW3JdLHA9X1t0XVtyXSwwIT09aC5sZW5ndGgmJmkucHVzaCh7bWluWDpzLm1pbihoKSxtaW5ZOnMubWluKHApLG1heFg6cy5tYXgoaCksbWF4WTpzLm1heChwKSxpOnR9KTtyZXR1cm4gZS5sb2FkKGkpLGV9LGUucHJvdG90eXBlLl9tYXNrX2RhdGE9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGwsdSxoLGM7cmV0dXJuIGw9dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcueF9yYW5nZSxyPVtsLmdldCgibWluIiksbC5nZXQoIm1heCIpXSxpPXJbMF0scz1yWzFdLGM9dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcueV9yYW5nZSxuPVtjLmdldCgibWluIiksYy5nZXQoIm1heCIpXSx1PW5bMF0saD1uWzFdLGU9YS52YWxpZGF0ZV9iYm94X2Nvb3JkcyhbaSxzXSxbdSxoXSksZnVuY3Rpb24oKXt2YXIgdCxyLG4saTtmb3Iobj10aGlzLmluZGV4LnNlYXJjaChlKSxpPVtdLHQ9MCxyPW4ubGVuZ3RoO3Q8cjt0Kyspbz1uW3RdLGkucHVzaChvLmkpO3JldHVybiBpfS5jYWxsKHRoaXMpfSxlLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtO2ZvcihkPXIuc3hzLG09ci5zeXMsdGhpcy5yZW5kZXJlci5zeHNzPXRoaXMuX2J1aWxkX2Rpc2NvbnRpbnVvdXNfb2JqZWN0KGQpLHRoaXMucmVuZGVyZXIuc3lzcz10aGlzLl9idWlsZF9kaXNjb250aW51b3VzX29iamVjdChtKSxwPVtdLGk9MCxhPWUubGVuZ3RoO2k8YTtpKyspe2lmKG49ZVtpXSx1PVtkW25dLG1bbl1dLF89dVswXSxmPXVbMV0sdGhpcy52aXN1YWxzLmZpbGwuZG9pdCl7Zm9yKHRoaXMudmlzdWFscy5maWxsLnNldF92ZWN0b3JpemUodCxuKSxvPXM9MCxoPV8ubGVuZ3RoOzA8PWg/czxoOnM+aDtvPTA8PWg/KytzOi0tcykwIT09bz9pc05hTihfW29dK2Zbb10pPyh0LmNsb3NlUGF0aCgpLHQuZmlsbCgpLHQuYmVnaW5QYXRoKCkpOnQubGluZVRvKF9bb10sZltvXSk6KHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8oX1tvXSxmW29dKSk7dC5jbG9zZVBhdGgoKSx0LmZpbGwoKX1pZih0aGlzLnZpc3VhbHMubGluZS5kb2l0KXtmb3IodGhpcy52aXN1YWxzLmxpbmUuc2V0X3ZlY3Rvcml6ZSh0LG4pLG89bD0wLGM9Xy5sZW5ndGg7MDw9Yz9sPGM6bD5jO289MDw9Yz8rK2w6LS1sKTAhPT1vP2lzTmFOKF9bb10rZltvXSk/KHQuY2xvc2VQYXRoKCksdC5zdHJva2UoKSx0LmJlZ2luUGF0aCgpKTp0LmxpbmVUbyhfW29dLGZbb10pOih0LmJlZ2luUGF0aCgpLHQubW92ZVRvKF9bb10sZltvXSkpO3QuY2xvc2VQYXRoKCkscC5wdXNoKHQuc3Ryb2tlKCkpfWVsc2UgcC5wdXNoKHZvaWQgMCl9cmV0dXJuIHB9LGUucHJvdG90eXBlLl9oaXRfcG9pbnQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGI7Zm9yKHU9W3QudngsdC52eV0sZz11WzBdLHk9dVsxXSxfPXRoaXMucmVuZGVyZXIucGxvdF92aWV3LmNhbnZhcy52eF90b19zeChnKSxmPXRoaXMucmVuZGVyZXIucGxvdF92aWV3LmNhbnZhcy52eV90b19zeSh5KSx2PXRoaXMucmVuZGVyZXIueG1hcHBlci5tYXBfZnJvbV90YXJnZXQoZywhMCksYj10aGlzLnJlbmRlcmVyLnltYXBwZXIubWFwX2Zyb21fdGFyZ2V0KHksITApLGU9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbjtmb3Iocj10aGlzLmluZGV4LnNlYXJjaCh7bWluWDp2LG1pblk6YixtYXhYOnYsbWF4WTpifSksbj1bXSx0PTAsZT1yLmxlbmd0aDt0PGU7dCsrKXY9clt0XSxuLnB1c2godi5pKTtyZXR1cm4gbn0uY2FsbCh0aGlzKSxyPVtdLG49cz0wLGg9ZS5sZW5ndGg7MDw9aD9zPGg6cz5oO249MDw9aD8rK3M6LS1zKWZvcihvPWVbbl0sZD10aGlzLnJlbmRlcmVyLnN4c3Nbb10sbT10aGlzLnJlbmRlcmVyLnN5c3Nbb10saT1sPTAsYz1kLmxlbmd0aDswPD1jP2w8YzpsPmM7aT0wPD1jPysrbDotLWwpYS5wb2ludF9pbl9wb2x5KF8sZixkW2ldLG1baV0pJiZyLnB1c2gobyk7cmV0dXJuIHA9YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCkscFsiMWQiXS5pbmRpY2VzPXIscH0sZS5wcm90b3R5cGUuX2dldF9zbmFwX2Nvb3JkPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvO2ZvcihvPTAsZT0wLHI9dC5sZW5ndGg7ZTxyO2UrKyluPXRbZV0sbys9bjtyZXR1cm4gby90Lmxlbmd0aH0sZS5wcm90b3R5cGUuc2N4PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxsO2lmKDE9PT10aGlzLnJlbmRlcmVyLnN4c3NbdF0ubGVuZ3RoKXJldHVybiB0aGlzLl9nZXRfc25hcF9jb29yZCh0aGlzLnN4c1t0XSk7Zm9yKHM9dGhpcy5yZW5kZXJlci5zeHNzW3RdLGw9dGhpcy5yZW5kZXJlci5zeXNzW3RdLG49bz0wLGk9cy5sZW5ndGg7MDw9aT9vPGk6bz5pO249MDw9aT8rK286LS1vKWlmKGEucG9pbnRfaW5fcG9seShlLHIsc1tuXSxsW25dKSlyZXR1cm4gdGhpcy5fZ2V0X3NuYXBfY29vcmQoc1tuXSk7cmV0dXJuIG51bGx9LGUucHJvdG90eXBlLnNjeT1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsbDtpZigxPT09dGhpcy5yZW5kZXJlci5zeXNzW3RdLmxlbmd0aClyZXR1cm4gdGhpcy5fZ2V0X3NuYXBfY29vcmQodGhpcy5zeXNbdF0pO2ZvcihzPXRoaXMucmVuZGVyZXIuc3hzc1t0XSxsPXRoaXMucmVuZGVyZXIuc3lzc1t0XSxuPW89MCxpPXMubGVuZ3RoOzA8PWk/bzxpOm8+aTtuPTA8PWk/KytvOi0tbylpZihhLnBvaW50X2luX3BvbHkoZSxyLHNbbl0sbFtuXSkpcmV0dXJuIHRoaXMuX2dldF9zbmFwX2Nvb3JkKGxbbl0pfSxlLnByb3RvdHlwZS5kcmF3X2xlZ2VuZD1mdW5jdGlvbih0LGUscixuLG8pe3JldHVybiB0aGlzLl9nZW5lcmljX2FyZWFfbGVnZW5kKHQsZSxyLG4sbyl9LGV9KG4uVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLnR5cGU9IlBhdGNoZXMiLGUuY29vcmRzKFtbInhzIiwieXMiXV0pLGUubWl4aW5zKFsibGluZSIsImZpbGwiXSksZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvLFZpZXc6aX19LHsiLi4vLi4vY29tbW9uL2hpdHRlc3QiOiJjb21tb24vaGl0dGVzdCIsIi4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIixyYnVzaDoicmJ1c2giLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvcXVhZCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7YT10KCJ1bmRlcnNjb3JlIiksdT10KCJyYnVzaCIpLG89dCgiLi9nbHlwaCIpLG49dCgiLi4vbWFwcGVycy9jYXRlZ29yaWNhbF9tYXBwZXIiKSxsPXQoIi4uLy4uL2NvbW1vbi9oaXR0ZXN0Iikscz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLl9pbmRleF9kYXRhPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG8saSxzLGEsbCxoLGMscCxfLGQsZjtmb3IobD1mdW5jdGlvbih0LGUpe3JldHVybiB0IGluc3RhbmNlb2Ygbi5Nb2RlbD90LnZfbWFwX3RvX3RhcmdldChlLCEwKTplfSxhPWwodGhpcy5yZW5kZXJlci54bWFwcGVyLHRoaXMuX2xlZnQpLF89bCh0aGlzLnJlbmRlcmVyLnhtYXBwZXIsdGhpcy5fcmlnaHQpLGY9bCh0aGlzLnJlbmRlcmVyLnltYXBwZXIsdGhpcy5fdG9wKSxlPWwodGhpcy5yZW5kZXJlci55bWFwcGVyLHRoaXMuX2JvdHRvbSksbz11KCksaD1bXSxyPWk9MCxwPWEubGVuZ3RoOzA8PXA/aTxwOmk+cDtyPTA8PXA/KytpOi0taSlzPWFbcl0sYz1fW3JdLGQ9ZltyXSx0PWVbcl0sIWlzTmFOKHMrYytkK3QpJiZpc0Zpbml0ZShzK2MrZCt0KSYmaC5wdXNoKHttaW5YOnMsbWluWTp0LG1heFg6YyxtYXhZOmQsaTpyfSk7cmV0dXJuIG8ubG9hZChoKSxvfSxlLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoO2ZvcihsPXIuc2xlZnQsdT1yLnNyaWdodCxoPXIuc3RvcCxhPXIuc2JvdHRvbSxzPVtdLG89MCxpPWUubGVuZ3RoO288aTtvKyspbj1lW29dLGlzTmFOKGxbbl0raFtuXSt1W25dK2Fbbl0pfHwodGhpcy52aXN1YWxzLmZpbGwuZG9pdCYmKHRoaXMudmlzdWFscy5maWxsLnNldF92ZWN0b3JpemUodCxuKSx0LmZpbGxSZWN0KGxbbl0saFtuXSx1W25dLWxbbl0sYVtuXS1oW25dKSksdGhpcy52aXN1YWxzLmxpbmUuZG9pdD8odC5iZWdpblBhdGgoKSx0LnJlY3QobFtuXSxoW25dLHVbbl0tbFtuXSxhW25dLWhbbl0pLHRoaXMudmlzdWFscy5saW5lLnNldF92ZWN0b3JpemUodCxuKSxzLnB1c2godC5zdHJva2UoKSkpOnMucHVzaCh2b2lkIDApKTtyZXR1cm4gc30sZS5wcm90b3R5cGUuX2hpdF9wb2ludD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYTtyZXR1cm4gcj1bdC52eCx0LnZ5XSxvPXJbMF0saT1yWzFdLHM9dGhpcy5yZW5kZXJlci54bWFwcGVyLm1hcF9mcm9tX3RhcmdldChvLCEwKSxhPXRoaXMucmVuZGVyZXIueW1hcHBlci5tYXBfZnJvbV90YXJnZXQoaSwhMCksZT1mdW5jdGlvbigpe3ZhciB0LGUscixuO2ZvcihyPXRoaXMuaW5kZXguc2VhcmNoKHttaW5YOnMsbWluWTphLG1heFg6cyxtYXhZOmF9KSxuPVtdLHQ9MCxlPXIubGVuZ3RoO3Q8ZTt0Kyspcz1yW3RdLG4ucHVzaChzLmkpO3JldHVybiBufS5jYWxsKHRoaXMpLG49bC5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksblsiMWQiXS5pbmRpY2VzPWUsbn0sZS5wcm90b3R5cGUuZ2V0X2FuY2hvcl9wb2ludD1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHM7c3dpdGNoKG89TWF0aC5taW4odGhpcy5zbGVmdFtlXSx0aGlzLnNyaWdodFtlXSksaT1NYXRoLm1heCh0aGlzLnNyaWdodFtlXSx0aGlzLnNsZWZ0W2VdKSxzPU1hdGgubWluKHRoaXMuc3RvcFtlXSx0aGlzLnNib3R0b21bZV0pLG49TWF0aC5tYXgodGhpcy5zYm90dG9tW2VdLHRoaXMuc3RvcFtlXSksdCl7Y2FzZSJ0b3BfbGVmdCI6cmV0dXJue3g6byx5OnN9O2Nhc2UidG9wX2NlbnRlciI6cmV0dXJue3g6KG8raSkvMix5OnN9O2Nhc2UidG9wX3JpZ2h0IjpyZXR1cm57eDppLHk6c307Y2FzZSJyaWdodF9jZW50ZXIiOnJldHVybnt4OmkseToocytuKS8yfTtjYXNlImJvdHRvbV9yaWdodCI6cmV0dXJue3g6aSx5Om59O2Nhc2UiYm90dG9tX2NlbnRlciI6cmV0dXJue3g6KG8raSkvMix5Om59O2Nhc2UiYm90dG9tX2xlZnQiOnJldHVybnt4Om8seTpufTtjYXNlImxlZnRfY2VudGVyIjpyZXR1cm57eDpvLHk6KHMrbikvMn07Y2FzZSJjZW50ZXIiOnJldHVybnt4OihvK2kpLzIseToocytuKS8yfX19LGUucHJvdG90eXBlLnNjeD1mdW5jdGlvbih0KXtyZXR1cm4odGhpcy5zbGVmdFt0XSt0aGlzLnNyaWdodFt0XSkvMn0sZS5wcm90b3R5cGUuc2N5PWZ1bmN0aW9uKHQpe3JldHVybih0aGlzLnN0b3BbdF0rdGhpcy5zYm90dG9tW3RdKS8yfSxlLnByb3RvdHlwZS5kcmF3X2xlZ2VuZD1mdW5jdGlvbih0LGUscixuLG8pe3JldHVybiB0aGlzLl9nZW5lcmljX2FyZWFfbGVnZW5kKHQsZSxyLG4sbyl9LGV9KG8uVmlldyksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1zLGUucHJvdG90eXBlLnR5cGU9IlF1YWQiLGUuY29vcmRzKFtbInJpZ2h0IiwiYm90dG9tIl0sWyJsZWZ0IiwidG9wIl1dKSxlLm1peGlucyhbImxpbmUiLCJmaWxsIl0pLGV9KG8uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6aSxWaWV3OnN9fSx7Ii4uLy4uL2NvbW1vbi9oaXR0ZXN0IjoiY29tbW9uL2hpdHRlc3QiLCIuLi9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciI6Im1vZGVscy9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciIsIi4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIixyYnVzaDoicmJ1c2giLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvcXVhZHJhdGljIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1PWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSloLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGg9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbD10KCJyYnVzaCIpLG49dCgiLi9nbHlwaCIpLGE9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG87cmV0dXJuIGU9PT0odCtyKS8yP1t0LHJdOihvPSh0LWUpLyh0LTIqZStyKSxuPXQqTWF0aC5wb3coMS1vLDIpKzIqZSooMS1vKSpvK3IqTWF0aC5wb3cobywyKSxbTWF0aC5taW4odCxyLG4pLE1hdGgubWF4KHQscixuKV0pfSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyx1LGgsYyxwO2ZvcihlPWwoKSxuPVtdLHQ9cj0wLG89dGhpcy5feDAubGVuZ3RoOzA8PW8/cjxvOnI+bzt0PTA8PW8/KytyOi0tcilpc05hTih0aGlzLl94MFt0XSt0aGlzLl94MVt0XSt0aGlzLl95MFt0XSt0aGlzLl95MVt0XSt0aGlzLl9jeFt0XSt0aGlzLl9jeVt0XSl8fChpPWEodGhpcy5feDBbdF0sdGhpcy5fY3hbdF0sdGhpcy5feDFbdF0pLHU9aVswXSxoPWlbMV0scz1hKHRoaXMuX3kwW3RdLHRoaXMuX2N5W3RdLHRoaXMuX3kxW3RdKSxjPXNbMF0scD1zWzFdLG4ucHVzaCh7bWluWDp1LG1pblk6YyxtYXhYOmgsbWF4WTpwLGk6dH0pKTtyZXR1cm4gZS5sb2FkKG4pLGV9LGUucHJvdG90eXBlLl9yZW5kZXI9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwO2lmKHU9ci5zeDAsYz1yLnN5MCxoPXIuc3gxLHA9ci5zeTEsYT1yLnNjeCxsPXIuc2N5LHRoaXMudmlzdWFscy5saW5lLmRvaXQpe2ZvcihzPVtdLG89MCxpPWUubGVuZ3RoO288aTtvKyspbj1lW29dLGlzTmFOKHVbbl0rY1tuXStoW25dK3Bbbl0rYVtuXStsW25dKXx8KHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8odVtuXSxjW25dKSx0LnF1YWRyYXRpY0N1cnZlVG8oYVtuXSxsW25dLGhbbl0scFtuXSksdGhpcy52aXN1YWxzLmxpbmUuc2V0X3ZlY3Rvcml6ZSh0LG4pLHMucHVzaCh0LnN0cm9rZSgpKSk7cmV0dXJuIHN9fSxlLnByb3RvdHlwZS5kcmF3X2xlZ2VuZD1mdW5jdGlvbih0LGUscixuLG8pe3JldHVybiB0aGlzLl9nZW5lcmljX2xpbmVfbGVnZW5kKHQsZSxyLG4sbyl9LGV9KG4uVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLnR5cGU9IlF1YWRyYXRpYyIsZS5jb29yZHMoW1sieDAiLCJ5MCJdLFsieDEiLCJ5MSJdLFsiY3giLCJjeSJdXSksZS5taXhpbnMoWyJsaW5lIl0pLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIixyYnVzaDoicmJ1c2giLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvcmF5IjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpdS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSx1PXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLG49dCgiLi9nbHlwaCIpLGE9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUucHJvdG90eXBlLl9pbmRleF9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3h5X2luZGV4KCl9LGUucHJvdG90eXBlLl9tYXBfZGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLnNsZW5ndGg9dGhpcy5zZGlzdCh0aGlzLnJlbmRlcmVyLnhtYXBwZXIsdGhpcy5feCx0aGlzLl9sZW5ndGgpfSxlLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZjtpZihfPXIuc3gsZD1yLnN5LHA9ci5zbGVuZ3RoLG49ci5fYW5nbGUsdGhpcy52aXN1YWxzLmxpbmUuZG9pdCl7Zm9yKGY9dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJ3aWR0aCIpLG89dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJoZWlnaHQiKSxzPTIqKGYrbyksaT1hPTAsaD1wLmxlbmd0aDswPD1oP2E8aDphPmg7aT0wPD1oPysrYTotLWEpMD09PXBbaV0mJihwW2ldPXMpO2ZvcihjPVtdLGw9MCx1PWUubGVuZ3RoO2w8dTtsKyspaT1lW2xdLGlzTmFOKF9baV0rZFtpXStuW2ldK3BbaV0pfHwodC50cmFuc2xhdGUoX1tpXSxkW2ldKSx0LnJvdGF0ZShuW2ldKSx0LmJlZ2luUGF0aCgpLHQubW92ZVRvKDAsMCksdC5saW5lVG8ocFtpXSwwKSx0aGlzLnZpc3VhbHMubGluZS5zZXRfdmVjdG9yaXplKHQsaSksdC5zdHJva2UoKSx0LnJvdGF0ZSgtbltpXSksYy5wdXNoKHQudHJhbnNsYXRlKC1fW2ldLC1kW2ldKSkpO3JldHVybiBjfX0sZS5wcm90b3R5cGUuZHJhd19sZWdlbmQ9ZnVuY3Rpb24odCxlLHIsbixvKXtyZXR1cm4gdGhpcy5fZ2VuZXJpY19saW5lX2xlZ2VuZCh0LGUscixuLG8pfSxlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJSYXkiLGUuY29vcmRzKFtbIngiLCJ5Il1dKSxlLm1peGlucyhbImxpbmUiXSksZS5kZWZpbmUoe2xlbmd0aDpbYS5EaXN0YW5jZVNwZWNdLGFuZ2xlOlthLkFuZ2xlU3BlY119KSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzppfX0seyIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuL2dseXBoIjoibW9kZWxzL2dseXBocy9nbHlwaCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2dseXBocy9yZWN0IjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1PWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSloLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGg9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2dseXBoIiksYT10KCIuLi8uLi9jb21tb24vaGl0dGVzdCIpLGw9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLl9zZXRfZGF0YT1mdW5jdGlvbigpe2lmKHRoaXMubWF4X3cyPTAsImRhdGEiPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLndpZHRoLnVuaXRzJiYodGhpcy5tYXhfdzI9dGhpcy5tYXhfd2lkdGgvMiksdGhpcy5tYXhfaDI9MCwiZGF0YSI9PT10aGlzLm1vZGVsLnByb3BlcnRpZXMuaGVpZ2h0LnVuaXRzKXJldHVybiB0aGlzLm1heF9oMj10aGlzLm1heF9oZWlnaHQvMn0sZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5feHlfaW5kZXgoKX0sZS5wcm90b3R5cGUuX21hcF9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuImRhdGEiPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLndpZHRoLnVuaXRzP3RoaXMuc3c9dGhpcy5zZGlzdCh0aGlzLnJlbmRlcmVyLnhtYXBwZXIsdGhpcy5feCx0aGlzLl93aWR0aCwiY2VudGVyIix0aGlzLm1nZXQoImRpbGF0ZSIpKTp0aGlzLnN3PXRoaXMuX3dpZHRoLCJkYXRhIj09PXRoaXMubW9kZWwucHJvcGVydGllcy5oZWlnaHQudW5pdHM/dGhpcy5zaD10aGlzLnNkaXN0KHRoaXMucmVuZGVyZXIueW1hcHBlcix0aGlzLl95LHRoaXMuX2hlaWdodCwiY2VudGVyIix0aGlzLm1nZXQoImRpbGF0ZSIpKTp0aGlzLnNoPXRoaXMuX2hlaWdodH0sZS5wcm90b3R5cGUuX3JlbmRlcj1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHA7aWYoYz1yLnN4LHA9ci5zeSxoPXIuc3csdT1yLnNoLG49ci5fYW5nbGUsdGhpcy52aXN1YWxzLmZpbGwuZG9pdClmb3IoaT0wLGE9ZS5sZW5ndGg7aTxhO2krKylvPWVbaV0saXNOYU4oY1tvXStwW29dK2hbb10rdVtvXStuW29dKXx8KHRoaXMudmlzdWFscy5maWxsLnNldF92ZWN0b3JpemUodCxvKSxuW29dPyh0LnRyYW5zbGF0ZShjW29dLHBbb10pLHQucm90YXRlKG5bb10pLHQuZmlsbFJlY3QoLWhbb10vMiwtdVtvXS8yLGhbb10sdVtvXSksdC5yb3RhdGUoLW5bb10pLHQudHJhbnNsYXRlKC1jW29dLC1wW29dKSk6dC5maWxsUmVjdChjW29dLWhbb10vMixwW29dLXVbb10vMixoW29dLHVbb10pKTtpZih0aGlzLnZpc3VhbHMubGluZS5kb2l0KXtmb3IodC5iZWdpblBhdGgoKSxzPTAsbD1lLmxlbmd0aDtzPGw7cysrKW89ZVtzXSxpc05hTihjW29dK3Bbb10raFtvXSt1W29dK25bb10pfHwwIT09aFtvXSYmMCE9PXVbb10mJihuW29dPyh0LnRyYW5zbGF0ZShjW29dLHBbb10pLHQucm90YXRlKG5bb10pLHQucmVjdCgtaFtvXS8yLC11W29dLzIsaFtvXSx1W29dKSx0LnJvdGF0ZSgtbltvXSksdC50cmFuc2xhdGUoLWNbb10sLXBbb10pKTp0LnJlY3QoY1tvXS1oW29dLzIscFtvXS11W29dLzIsaFtvXSx1W29dKSx0aGlzLnZpc3VhbHMubGluZS5zZXRfdmVjdG9yaXplKHQsbyksdC5zdHJva2UoKSx0LmJlZ2luUGF0aCgpKTtyZXR1cm4gdC5zdHJva2UoKX19LGUucHJvdG90eXBlLl9oaXRfcmVjdD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsbCx1LGg7cmV0dXJuIHI9dGhpcy5yZW5kZXJlci54bWFwcGVyLnZfbWFwX2Zyb21fdGFyZ2V0KFt0LnZ4MCx0LnZ4MV0sITApLHM9clswXSxsPXJbMV0sbj10aGlzLnJlbmRlcmVyLnltYXBwZXIudl9tYXBfZnJvbV90YXJnZXQoW3QudnkwLHQudnkxXSwhMCksdT1uWzBdLGg9blsxXSxlPWEudmFsaWRhdGVfYmJveF9jb29yZHMoW3MsbF0sW3UsaF0pLG89YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksb1siMWQiXS5pbmRpY2VzPWZ1bmN0aW9uKCl7dmFyIHQscixuLG87Zm9yKG49dGhpcy5pbmRleC5zZWFyY2goZSksbz1bXSx0PTAscj1uLmxlbmd0aDt0PHI7dCsrKWk9blt0XSxvLnB1c2goaS5pKTtyZXR1cm4gb30uY2FsbCh0aGlzKSxvfSxlLnByb3RvdHlwZS5faGl0X3BvaW50PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdyxNLGssaixULFMseixQLEUsQSxDLE47Zm9yKF89W3QudngsdC52eV0seD1fWzBdLGs9X1sxXSx6PXRoaXMucmVuZGVyZXIueG1hcHBlci5tYXBfZnJvbV90YXJnZXQoeCwhMCksQT10aGlzLnJlbmRlcmVyLnltYXBwZXIubWFwX2Zyb21fdGFyZ2V0KGssITApLCJzY3JlZW4iPT09dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLndpZHRoLnVuaXRzPyh3PXgtMip0aGlzLm1heF93aWR0aCxNPXgrMip0aGlzLm1heF93aWR0aCxkPXRoaXMucmVuZGVyZXIueG1hcHBlci52X21hcF9mcm9tX3RhcmdldChbdyxNXSwhMCksUD1kWzBdLEU9ZFsxXSk6KFA9ei0yKnRoaXMubWF4X3dpZHRoLEU9eisyKnRoaXMubWF4X3dpZHRoKSwic2NyZWVuIj09PXRoaXMubW9kZWwucHJvcGVydGllcy5oZWlnaHQudW5pdHM/KGo9ay0yKnRoaXMubWF4X2hlaWdodCxUPWsrMip0aGlzLm1heF9oZWlnaHQsZj10aGlzLnJlbmRlcmVyLnltYXBwZXIudl9tYXBfZnJvbV90YXJnZXQoW2osVF0sITApLEM9ZlswXSxOPWZbMV0pOihDPUEtMip0aGlzLm1heF9oZWlnaHQsTj1BKzIqdGhpcy5tYXhfaGVpZ2h0KSxpPVtdLGU9YS52YWxpZGF0ZV9iYm94X2Nvb3JkcyhbUCxFXSxbQyxOXSksbT1mdW5jdGlvbigpe3ZhciB0LHIsbixvO2ZvcihuPXRoaXMuaW5kZXguc2VhcmNoKGUpLG89W10sdD0wLHI9bi5sZW5ndGg7dDxyO3QrKyloPW5bdF0sby5wdXNoKGguaSk7cmV0dXJuIG99LmNhbGwodGhpcyksbD0wLHU9bS5sZW5ndGg7bDx1O2wrKylzPW1bbF0sdj10aGlzLnJlbmRlcmVyLnBsb3Rfdmlldy5jYW52YXMudnhfdG9fc3goeCksYj10aGlzLnJlbmRlcmVyLnBsb3Rfdmlldy5jYW52YXMudnlfdG9fc3koayksdGhpcy5fYW5nbGVbc10mJihuPU1hdGguc3FydChNYXRoLnBvdyh2LXRoaXMuc3hbc10sMikrTWF0aC5wb3coYi10aGlzLnN5W3NdLDIpKSx5PU1hdGguc2luKC10aGlzLl9hbmdsZVtzXSkscj1NYXRoLmNvcygtdGhpcy5fYW5nbGVbc10pLGM9cioodi10aGlzLnN4W3NdKS15KihiLXRoaXMuc3lbc10pK3RoaXMuc3hbc10scD15Kih2LXRoaXMuc3hbc10pK3IqKGItdGhpcy5zeVtzXSkrdGhpcy5zeVtzXSx2PWMsYj1wKSxTPU1hdGguYWJzKHRoaXMuc3hbc10tdik8PXRoaXMuc3dbc10vMixvPU1hdGguYWJzKHRoaXMuc3lbc10tYik8PXRoaXMuc2hbc10vMixvJiZTJiZpLnB1c2gocyk7cmV0dXJuIGc9YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksZ1siMWQiXS5pbmRpY2VzPWksZ30sZS5wcm90b3R5cGUuZHJhd19sZWdlbmQ9ZnVuY3Rpb24odCxlLHIsbixvKXtyZXR1cm4gdGhpcy5fZ2VuZXJpY19hcmVhX2xlZ2VuZCh0LGUscixuLG8pfSxlLnByb3RvdHlwZS5fYm91bmRzPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLm1heF93aDJfYm91bmRzKHQpfSxlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHUoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJSZWN0IixlLmNvb3JkcyhbWyJ4IiwieSJdXSksZS5taXhpbnMoWyJsaW5lIiwiZmlsbCJdKSxlLmRlZmluZSh7YW5nbGU6W2wuQW5nbGVTcGVjLDBdLHdpZHRoOltsLkRpc3RhbmNlU3BlY10saGVpZ2h0OltsLkRpc3RhbmNlU3BlY10sZGlsYXRlOltsLkJvb2wsITFdfSksZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvLFZpZXc6aX19LHsiLi4vLi4vY29tbW9uL2hpdHRlc3QiOiJjb21tb24vaGl0dGVzdCIsIi4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvZ2x5cGhzL3NlZ21lbnQiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl1LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLAp0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSx1PXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLGE9dCgicmJ1c2giKSxuPXQoIi4vZ2x5cGgiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvO2ZvcihlPWEoKSxuPVtdLHQ9cj0wLG89dGhpcy5feDAubGVuZ3RoOzA8PW8/cjxvOnI+bzt0PTA8PW8/KytyOi0tcilpc05hTih0aGlzLl94MFt0XSt0aGlzLl94MVt0XSt0aGlzLl95MFt0XSt0aGlzLl95MVt0XSl8fG4ucHVzaCh7bWluWDpNYXRoLm1pbih0aGlzLl94MFt0XSx0aGlzLl94MVt0XSksbWluWTpNYXRoLm1pbih0aGlzLl95MFt0XSx0aGlzLl95MVt0XSksbWF4WDpNYXRoLm1heCh0aGlzLl94MFt0XSx0aGlzLl94MVt0XSksbWF4WTpNYXRoLm1heCh0aGlzLl95MFt0XSx0aGlzLl95MVt0XSksaTp0fSk7cmV0dXJuIGUubG9hZChuKSxlfSxlLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoO2lmKGE9ci5zeDAsdT1yLnN5MCxsPXIuc3gxLGg9ci5zeTEsdGhpcy52aXN1YWxzLmxpbmUuZG9pdCl7Zm9yKHM9W10sbz0wLGk9ZS5sZW5ndGg7bzxpO28rKyluPWVbb10saXNOYU4oYVtuXSt1W25dK2xbbl0raFtuXSl8fCh0LmJlZ2luUGF0aCgpLHQubW92ZVRvKGFbbl0sdVtuXSksdC5saW5lVG8obFtuXSxoW25dKSx0aGlzLnZpc3VhbHMubGluZS5zZXRfdmVjdG9yaXplKHQsbikscy5wdXNoKHQuc3Ryb2tlKCkpKTtyZXR1cm4gc319LGUucHJvdG90eXBlLmRyYXdfbGVnZW5kPWZ1bmN0aW9uKHQsZSxyLG4sbyl7cmV0dXJuIHRoaXMuX2dlbmVyaWNfbGluZV9sZWdlbmQodCxlLHIsbixvKX0sZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWksZS5wcm90b3R5cGUudHlwZT0iU2VnbWVudCIsZS5jb29yZHMoW1sieDAiLCJ5MCJdLFsieDEiLCJ5MSJdXSksZS5taXhpbnMoWyJsaW5lIl0pLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIixyYnVzaDoicmJ1c2giLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvdGV4dCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXUuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sdT17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vZ2x5cGgiKSxhPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS5faW5kZXhfZGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl94eV9pbmRleCgpfSxlLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscDtmb3IoYz1yLnN4LHA9ci5zeSxpPXIuX3hfb2Zmc2V0LHM9ci5feV9vZmZzZXQsbj1yLl9hbmdsZSxvPXIuX3RleHQsaD1bXSxsPTAsdT1lLmxlbmd0aDtsPHU7bCsrKWE9ZVtsXSxpc05hTihjW2FdK3BbYV0raVthXStzW2FdK25bYV0pfHxudWxsPT1vW2FdfHwodGhpcy52aXN1YWxzLnRleHQuZG9pdD8odC5zYXZlKCksdC50cmFuc2xhdGUoY1thXStpW2FdLHBbYV0rc1thXSksdC5yb3RhdGUoblthXSksdGhpcy52aXN1YWxzLnRleHQuc2V0X3ZlY3Rvcml6ZSh0LGEpLHQuZmlsbFRleHQob1thXSwwLDApLGgucHVzaCh0LnJlc3RvcmUoKSkpOmgucHVzaCh2b2lkIDApKTtyZXR1cm4gaH0sZS5wcm90b3R5cGUuZHJhd19sZWdlbmQ9ZnVuY3Rpb24odCxlLHIsbixvKXtyZXR1cm4gdC5zYXZlKCksdGhpcy50ZXh0X3Byb3BzLnNldF92YWx1ZSh0KSx0LmZvbnQ9dGhpcy50ZXh0X3Byb3BzLmZvbnRfdmFsdWUoKSx0LmZvbnQ9dC5mb250LnJlcGxhY2UoL1xiW1xkXC5dK1tcd10rXGIvLCIxMHB0IiksdC50ZXh0QWxpZ249InJpZ2h0Iix0LnRleHRCYXNlbGluZT0ibWlkZGxlIix0LmZpbGxUZXh0KCJ0ZXh0IixyLChuK28pLzIpLHQucmVzdG9yZSgpfSxlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJUZXh0IixlLmNvb3JkcyhbWyJ4IiwieSJdXSksZS5taXhpbnMoWyJ0ZXh0Il0pLGUuZGVmaW5lKHt0ZXh0OlthLlN0cmluZ1NwZWMse2ZpZWxkOiJ0ZXh0In1dLGFuZ2xlOlthLkFuZ2xlU3BlYywwXSx4X29mZnNldDpbYS5OdW1iZXJTcGVjLDBdLHlfb2Zmc2V0OlthLk51bWJlclNwZWMsMF19KSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzppfX0seyIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuL2dseXBoIjoibW9kZWxzL2dseXBocy9nbHlwaCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2dseXBocy92YmFyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlfLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LF89e30uaGFzT3duUHJvcGVydHk7bD10KCJ1bmRlcnNjb3JlIiksYz10KCJyYnVzaCIpLGk9dCgiLi9xdWFkIiksbz10KCIuL2dseXBoIiksbj10KCIuLi9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciIpLHU9dCgiLi4vLi4vY29tbW9uL2hpdHRlc3QiKSxoPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGE9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHAoZSx0KSxlLnByb3RvdHlwZS5fbWFwX2RhdGE9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvO2Zvcih0aGlzLnN4PXRoaXMucmVuZGVyZXIueG1hcHBlci52X21hcF90b190YXJnZXQodGhpcy5feCksbz10aGlzLnJlbmRlcmVyLnltYXBwZXIudl9tYXBfdG9fdGFyZ2V0KHRoaXMuX3RvcCksbj10aGlzLnJlbmRlcmVyLnltYXBwZXIudl9tYXBfdG9fdGFyZ2V0KHRoaXMuX2JvdHRvbSksdGhpcy5zdG9wPXRoaXMucGxvdF92aWV3LmNhbnZhcy52X3Z5X3RvX3N5KG8pLHRoaXMuc2JvdHRvbT10aGlzLnBsb3Rfdmlldy5jYW52YXMudl92eV90b19zeShuKSx0aGlzLnNsZWZ0PVtdLHRoaXMuc3JpZ2h0PVtdLHRoaXMuc3c9dGhpcy5zZGlzdCh0aGlzLnJlbmRlcmVyLnhtYXBwZXIsdGhpcy5feCx0aGlzLl93aWR0aCwiY2VudGVyIiksdD1lPTAscj10aGlzLnN4Lmxlbmd0aDswPD1yP2U8cjplPnI7dD0wPD1yPysrZTotLWUpdGhpcy5zbGVmdC5wdXNoKHRoaXMuc3hbdF0tdGhpcy5zd1t0XS8yKSx0aGlzLnNyaWdodC5wdXNoKHRoaXMuc3hbdF0rdGhpcy5zd1t0XS8yKTtyZXR1cm4gbnVsbH0sZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbyxpLHMsYSxsLHUsaCxwLF8sZCxmO2ZvcihhPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQgaW5zdGFuY2VvZiBuLk1vZGVsP3Qudl9tYXBfdG9fdGFyZ2V0KGUsITApOmV9LGY9YSh0aGlzLnJlbmRlcmVyLnhtYXBwZXIsdGhpcy5feCksZD1hKHRoaXMucmVuZGVyZXIueG1hcHBlcix0aGlzLl93aWR0aCksXz1hKHRoaXMucmVuZGVyZXIueW1hcHBlcix0aGlzLl90b3ApLGU9YSh0aGlzLnJlbmRlcmVyLnltYXBwZXIsdGhpcy5fYm90dG9tKSxvPWMoKSxsPVtdLHI9aT0wLGg9Zi5sZW5ndGg7MDw9aD9pPGg6aT5oO3I9MDw9aD8rK2k6LS1pKXM9ZltyXS1kW3JdLzIsdT1mW3JdK2Rbcl0vMixwPV9bcl0sdD1lW3JdLCFpc05hTihzK3UrcCt0KSYmaXNGaW5pdGUocyt1K3ArdCkmJmwucHVzaCh7bWluWDpzLG1pblk6dCxtYXhYOnUsbWF4WTpwLGk6cn0pO3JldHVybiBvLmxvYWQobCksb30sZS5wcm90b3R5cGUuX3JlbmRlcj1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaDtmb3IobD1yLnNsZWZ0LHU9ci5zcmlnaHQsaD1yLnN0b3AsYT1yLnNib3R0b20scz1bXSxvPTAsaT1lLmxlbmd0aDtvPGk7bysrKW49ZVtvXSxpc05hTihsW25dK2hbbl0rdVtuXSthW25dKXx8KHRoaXMudmlzdWFscy5maWxsLmRvaXQmJih0aGlzLnZpc3VhbHMuZmlsbC5zZXRfdmVjdG9yaXplKHQsbiksdC5maWxsUmVjdChsW25dLGhbbl0sdVtuXS1sW25dLGFbbl0taFtuXSkpLHRoaXMudmlzdWFscy5saW5lLmRvaXQ/KHQuYmVnaW5QYXRoKCksdC5yZWN0KGxbbl0saFtuXSx1W25dLWxbbl0sYVtuXS1oW25dKSx0aGlzLnZpc3VhbHMubGluZS5zZXRfdmVjdG9yaXplKHQsbikscy5wdXNoKHQuc3Ryb2tlKCkpKTpzLnB1c2godm9pZCAwKSk7cmV0dXJuIHN9LGUucHJvdG90eXBlLl9oaXRfcG9pbnQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGE7cmV0dXJuIHI9W3QudngsdC52eV0sbz1yWzBdLGk9clsxXSxzPXRoaXMucmVuZGVyZXIueG1hcHBlci5tYXBfZnJvbV90YXJnZXQobywhMCksYT10aGlzLnJlbmRlcmVyLnltYXBwZXIubWFwX2Zyb21fdGFyZ2V0KGksITApLGU9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbjtmb3Iocj10aGlzLmluZGV4LnNlYXJjaCh7bWluWDpzLG1pblk6YSxtYXhYOnMsbWF4WTphfSksbj1bXSx0PTAsZT1yLmxlbmd0aDt0PGU7dCsrKXM9clt0XSxuLnB1c2gocy5pKTtyZXR1cm4gbn0uY2FsbCh0aGlzKSxuPXUuY3JlYXRlX2hpdF90ZXN0X3Jlc3VsdCgpLG5bIjFkIl0uaW5kaWNlcz1lLG59LGUucHJvdG90eXBlLnNjeT1mdW5jdGlvbih0KXtyZXR1cm4odGhpcy5zdG9wW3RdK3RoaXMuc2JvdHRvbVt0XSkvMn0sZX0oby5WaWV3KSxzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBwKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWEsZS5wcm90b3R5cGUudHlwZT0iVkJhciIsZS5taXhpbnMoWyJsaW5lIiwiZmlsbCJdKSxlLmRlZmluZSh7eDpbaC5OdW1iZXJTcGVjXSx3aWR0aDpbaC5EaXN0YW5jZVNwZWNdLHRvcDpbaC5OdW1iZXJTcGVjXSxib3R0b206W2guTnVtYmVyU3BlYywwXX0pLGV9KG8uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6cyxWaWV3OmF9fSx7Ii4uLy4uL2NvbW1vbi9oaXR0ZXN0IjoiY29tbW9uL2hpdHRlc3QiLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciI6Im1vZGVscy9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciIsIi4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIiwiLi9xdWFkIjoibW9kZWxzL2dseXBocy9xdWFkIixyYnVzaDoicmJ1c2giLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvd2ViZ2wvYmFzZSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscDtvPXQoInVuZGVyc2NvcmUiKSxhPXQoIi4uLy4uLy4uL2NvcmUvdXRpbC9jb2xvciIpLGw9YS5jb2xvcjJyZ2JhLG49ZnVuY3Rpb24oKXtmdW5jdGlvbiB0KHQsZSl7dGhpcy5nbD10LHRoaXMuZ2x5cGg9ZSx0aGlzLm52ZXJ0aWNlcz0wLHRoaXMuc2l6ZV9jaGFuZ2VkPSExLHRoaXMuZGF0YV9jaGFuZ2VkPSExLHRoaXMudmlzdWFsc19jaGFuZ2VkPSExLHRoaXMuaW5pdCgpfXJldHVybiB0LnByb3RvdHlwZS5HTFlQSD0iIix0LnByb3RvdHlwZS5WRVJUPSIiLHQucHJvdG90eXBlLkZSQUc9IiIsdC5wcm90b3R5cGUuc2V0X2RhdGFfY2hhbmdlZD1mdW5jdGlvbih0KXtyZXR1cm4gdCE9PXRoaXMubnZlcnRpY2VzJiYodGhpcy5udmVydGljZXM9dCx0aGlzLnNpemVfY2hhbmdlZD0hMCksdGhpcy5kYXRhX2NoYW5nZWQ9ITB9LHQucHJvdG90eXBlLnNldF92aXN1YWxzX2NoYW5nZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy52aXN1YWxzX2NoYW5nZWQ9ITB9LHR9KCksYz1mdW5jdGlvbih0KXtyZXR1cm4gdDwyJiYodD1NYXRoLnNxcnQoMip0KSksdH0sdT1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpO2ZvcihyPW5ldyBGbG9hdDMyQXJyYXkodCksbj1vPTAsaT10OzA8PWk/bzxpOm8+aTtuPTA8PWk/KytvOi0tbylyW25dPWU7cmV0dXJuIHJ9LGg9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1O2ZvcihuPW5ldyBGbG9hdDMyQXJyYXkodCplKSxvPXM9MCxsPXQ7MDw9bD9zPGw6cz5sO289MDw9bD8rK3M6LS1zKWZvcihpPWE9MCx1PWU7MDw9dT9hPHU6YT51O2k9MDw9dT8rK2E6LS1hKW5bbyplK2ldPXJbaV07cmV0dXJuIG59LHA9ZnVuY3Rpb24odCxlKXtyZXR1cm4hby5pc1VuZGVmaW5lZCh0W2VdLnNwZWMudmFsdWUpfSxzPWZ1bmN0aW9uKHQsZSxyLG4sbyxpKXt2YXIgcztyZXR1cm4gby5kb2l0P3AobyxpKT8oZS51c2VkPSExLHQuc2V0X2F0dHJpYnV0ZShyLCJmbG9hdCIsb1tpXS52YWx1ZSgpKSk6KGUudXNlZD0hMCxzPW5ldyBGbG9hdDMyQXJyYXkoby5jYWNoZVtpKyJfYXJyYXkiXSksZS5zZXRfc2l6ZSg0Km4pLGUuc2V0X2RhdGEoMCxzKSx0LnNldF9hdHRyaWJ1dGUociwiZmxvYXQiLGUpKTooZS51c2VkPSExLHQuc2V0X2F0dHJpYnV0ZShyLCJmbG9hdCIsWzBdKSl9LGk9ZnVuY3Rpb24odCxlLHIsbixvLGkpe3ZhciBzLGEsaCxjLF8sZCxmLG0sZyx5LHYsYix4O2lmKHk9NCxjPWkrIl9jb2xvciIsYT1pKyJfYWxwaGEiLG8uZG9pdCl7aWYocChvLGMpJiZwKG8sYSkpcmV0dXJuIGUudXNlZD0hMSx4PWwob1tjXS52YWx1ZSgpLG9bYV0udmFsdWUoKSksdC5zZXRfYXR0cmlidXRlKHIsInZlYzQiLHgpO2ZvcihlLnVzZWQ9ITAsXz1wKG8sYyk/ZnVuY3Rpb24oKXt2YXIgdCxlLHI7Zm9yKHI9W10sZD10PTAsZT1uOzA8PWU/dDxlOnQ+ZTtkPTA8PWU/Kyt0Oi0tdClyLnB1c2gob1tjXS52YWx1ZSgpKTtyZXR1cm4gcn0oKTpvLmNhY2hlW2MrIl9hcnJheSJdLGg9cChvLGEpP3UobixvW2FdLnZhbHVlKCkpOm8uY2FjaGVbYSsiX2FycmF5Il0scz1uZXcgRmxvYXQzMkFycmF5KG4qeSksZD1tPTAsdj1uOzA8PXY/bTx2Om0+djtkPTA8PXY/KyttOi0tbSlmb3IoeD1sKF9bZF0saFtkXSksZj1nPTAsYj15OzA8PWI/ZzxiOmc+YjtmPTA8PWI/KytnOi0tZylzW2QqeStmXT14W2ZdO3JldHVybiBlLnNldF9zaXplKG4qeSo0KSxlLnNldF9kYXRhKDAscyksdC5zZXRfYXR0cmlidXRlKHIsInZlYzQiLGUpfXJldHVybiBlLnVzZWQ9ITEsdC5zZXRfYXR0cmlidXRlKHIsInZlYzQiLFswLDAsMCwwXSl9LGUuZXhwb3J0cz17QmFzZUdMR2x5cGg6bixsaW5lX3dpZHRoOmMsYXR0YWNoX2Zsb2F0OnMsYXR0YWNoX2NvbG9yOmksY29sb3IycmdiYTpsfX0seyIuLi8uLi8uLi9jb3JlL3V0aWwvY29sb3IiOiJjb3JlL3V0aWwvY29sb3IiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9nbHlwaHMvd2ViZ2wvbGluZSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlkLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGQ9e30uaGFzT3duUHJvcGVydHk7dT10KCJnbG9vMiIpLGM9dCgiLi4vLi4vLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLHA9dCgiLi9iYXNlIiksbj1wLkJhc2VHTEdseXBoLGg9cC5saW5lX3dpZHRoLGE9cC5hdHRhY2hfZmxvYXQscz1wLmF0dGFjaF9jb2xvcixsPXAuY29sb3IycmdiYSxvPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCh0KXt0aGlzLl9hdGxhcz17fSx0aGlzLl9pbmRleD0wLHRoaXMuX3dpZHRoPTI1Nix0aGlzLl9oZWlnaHQ9MjU2LHRoaXMudGV4PW5ldyB1LlRleHR1cmUyRCh0KSx0aGlzLnRleC5zZXRfd3JhcHBpbmcodC5SRVBFQVQsdC5SRVBFQVQpLHRoaXMudGV4LnNldF9pbnRlcnBvbGF0aW9uKHQuTkVBUkVTVCx0Lk5FQVJFU1QpLHRoaXMudGV4LnNldF9zaXplKFt0aGlzLl9oZWlnaHQsdGhpcy5fd2lkdGhdLHQuUkdCQSksdGhpcy50ZXguc2V0X2RhdGEoWzAsMF0sW3RoaXMuX2hlaWdodCx0aGlzLl93aWR0aF0sbmV3IFVpbnQ4QXJyYXkodGhpcy5faGVpZ2h0KnRoaXMuX3dpZHRoKjQpKSx0aGlzLmdldF9hdGxhc19kYXRhKFsxXSl9cmV0dXJuIHQucHJvdG90eXBlLmdldF9hdGxhc19kYXRhPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscztyZXR1cm4gbj10LmpvaW4oIi0iKSxyPXRoaXMuX2F0bGFzW25dLHZvaWQgMD09PXImJihpPXRoaXMubWFrZV9wYXR0ZXJuKHQpLGU9aVswXSxvPWlbMV0sdGhpcy50ZXguc2V0X2RhdGEoW3RoaXMuX2luZGV4LDBdLFsxLHRoaXMuX3dpZHRoXSxuZXcgVWludDhBcnJheShmdW5jdGlvbigpe3ZhciB0LHIsbjtmb3Iobj1bXSx0PTAscj1lLmxlbmd0aDt0PHI7dCsrKXM9ZVt0XSxuLnB1c2gocysxMCk7cmV0dXJuIG59KCkpKSx0aGlzLl9hdGxhc1tuXT1bdGhpcy5faW5kZXgvdGhpcy5faGVpZ2h0LG9dLHRoaXMuX2luZGV4Kz0xKSx0aGlzLl9hdGxhc1tuXX0sdC5wcm90b3R5cGUubWFrZV9wYXR0ZXJuPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0sayxqO2Zvcih0Lmxlbmd0aD4xJiZ0Lmxlbmd0aCUyJiYodD10LmNvbmNhdCh0KSksbT0wLHA9MCxfPXQubGVuZ3RoO3A8XztwKyspdz10W3BdLG0rPXc7Zm9yKGU9W10saT0wLHU9Zj0wLHY9dC5sZW5ndGgrMjtmPHY7dT1mKz0yKW49TWF0aC5tYXgoMWUtNCx0W3UldC5sZW5ndGhdKSxvPU1hdGgubWF4KDFlLTQsdFsodSsxKSV0Lmxlbmd0aF0pLGUucHVzaC5hcHBseShlLFtpLGkrbl0pLGkrPW4rbztmb3IoZD10aGlzLl93aWR0aCxyPW5ldyBGbG9hdDMyQXJyYXkoNCpkKSx1PWc9MCxiPWQ7MDw9Yj9nPGI6Zz5iO3U9MDw9Yj8rK2c6LS1nKXtmb3Ioaj1tKnUvKGQtMSksaD0wLGs9MWUxNixjPXk9MCx4PWUubGVuZ3RoOzA8PXg/eTx4Onk+eDtjPTA8PXg/Kyt5Oi0teSlNPU1hdGguYWJzKGVbY10taiksTTxrJiYoaD1jLGs9TSk7aCUyPT09MD8obD1qPD1lW2hdPzE6MCxhPWVbaF0scz1lW2grMV0pOihsPWo+ZVtoXT8tMTowLGE9ZVtoLTFdLHM9ZVtoXSkscls0KnUrMF09ZVtoXSxyWzQqdSsxXT1sLHJbNCp1KzJdPWEscls0KnUrM109c31yZXR1cm5bcixtXX0sdH0oKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBfKGUsdCksZS5wcm90b3R5cGUuR0xZUEg9ImxpbmUiLGUucHJvdG90eXBlLkpPSU5TPXttaXRlcjowLHJvdW5kOjEsYmV2ZWw6Mn0sZS5wcm90b3R5cGUuQ0FQUz17IiI6MCxub25lOjAsIi4iOjAscm91bmQ6MSwiKSI6MSwiKCI6MSxvOjEsInRyaWFuZ2xlIGluIjoyLCI8IjoyLCJ0cmlhbmdsZSBvdXQiOjMsIj4iOjMsc3F1YXJlOjQsIlsiOjQsIl0iOjQsIj0iOjQsYnV0dDo1LCJ8Ijo1fSxlLnByb3RvdHlwZS5WRVJUPSJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcblxuY29uc3QgZmxvYXQgUEkgPSAzLjE0MTU5MjY1MzU4OTc5MzIzODQ2MjY0O1xuY29uc3QgZmxvYXQgVEhFVEEgPSAxNS4wICogMy4xNDE1OTI2NTM1ODk3OTMyMzg0NjI2NC8xODAuMDtcblxudW5pZm9ybSBmbG9hdCB1X3BpeGVsX3JhdGlvO1xudW5pZm9ybSB2ZWMyIHVfY2FudmFzX3NpemUsIHVfb2Zmc2V0O1xudW5pZm9ybSB2ZWMyIHVfc2NhbGVfYXNwZWN0O1xudW5pZm9ybSBmbG9hdCB1X3NjYWxlX2xlbmd0aDtcblxudW5pZm9ybSB2ZWM0IHVfY29sb3I7XG51bmlmb3JtIGZsb2F0IHVfYW50aWFsaWFzO1xudW5pZm9ybSBmbG9hdCB1X2xlbmd0aDtcbnVuaWZvcm0gZmxvYXQgdV9saW5ld2lkdGg7XG51bmlmb3JtIGZsb2F0IHVfZGFzaF9pbmRleDtcbnVuaWZvcm0gZmxvYXQgdV9jbG9zZWQ7XG5cbmF0dHJpYnV0ZSB2ZWMyIGFfcG9zaXRpb247XG5hdHRyaWJ1dGUgdmVjNCBhX3RhbmdlbnRzO1xuYXR0cmlidXRlIHZlYzIgYV9zZWdtZW50O1xuYXR0cmlidXRlIHZlYzIgYV9hbmdsZXM7XG5hdHRyaWJ1dGUgdmVjMiBhX3RleGNvb3JkO1xuXG52YXJ5aW5nIHZlYzQgIHZfY29sb3I7XG52YXJ5aW5nIHZlYzIgIHZfc2VnbWVudDtcbnZhcnlpbmcgdmVjMiAgdl9hbmdsZXM7XG52YXJ5aW5nIHZlYzIgIHZfdGV4Y29vcmQ7XG52YXJ5aW5nIHZlYzIgIHZfbWl0ZXI7XG52YXJ5aW5nIGZsb2F0IHZfbGVuZ3RoO1xudmFyeWluZyBmbG9hdCB2X2xpbmV3aWR0aDtcblxuZmxvYXQgY3Jvc3MoaW4gdmVjMiB2MSwgaW4gdmVjMiB2MilcbntcbiAgICByZXR1cm4gdjEueCp2Mi55IC0gdjEueSp2Mi54O1xufVxuXG5mbG9hdCBzaWduZWRfZGlzdGFuY2UoaW4gdmVjMiB2MSwgaW4gdmVjMiB2MiwgaW4gdmVjMiB2MylcbntcbiAgICByZXR1cm4gY3Jvc3ModjItdjEsdjEtdjMpIC8gbGVuZ3RoKHYyLXYxKTtcbn1cblxudm9pZCByb3RhdGUoIGluIHZlYzIgdiwgaW4gZmxvYXQgYWxwaGEsIG91dCB2ZWMyIHJlc3VsdCApXG57XG4gICAgZmxvYXQgYyA9IGNvcyhhbHBoYSk7XG4gICAgZmxvYXQgcyA9IHNpbihhbHBoYSk7XG4gICAgcmVzdWx0ID0gdmVjMiggYyp2LnggLSBzKnYueSxcbiAgICAgICAgICAgICAgICAgICBzKnYueCArIGMqdi55ICk7XG59XG5cbnZvaWQgbWFpbigpXG57XG4gICAgYm9vbCBjbG9zZWQgPSAodV9jbG9zZWQgPiAwLjApO1xuXG4gICAgLy8gQXR0cmlidXRlcyBhbmQgdW5pZm9ybXMgdG8gdmFyeWluZ3NcbiAgICB2X2NvbG9yID0gdV9jb2xvcjtcbiAgICB2X2xpbmV3aWR0aCA9IHVfbGluZXdpZHRoO1xuICAgIHZfc2VnbWVudCA9IGFfc2VnbWVudCAqIHVfc2NhbGVfbGVuZ3RoO1xuICAgIHZfbGVuZ3RoID0gdV9sZW5ndGggKiB1X3NjYWxlX2xlbmd0aDtcblxuICAgIC8vIFNjYWxlIHRvIG1hcCB0byBwaXhlbCBjb29yZGluYXRlcy4gVGhlIG9yaWdpbmFsIGFsZ29yaXRobSBmcm9tIHRoZSBwYXBlclxuICAgIC8vIGFzc3VtZWQgaXNvdHJvcGljIHNjYWxlLiBXZSBvYnZpb3VzbHkgZG8gbm90IGhhdmUgdGhpcy5cbiAgICB2ZWMyIGFic19zY2FsZV9hc3BlY3QgPSBhYnModV9zY2FsZV9hc3BlY3QpO1xuICAgIHZlYzIgYWJzX3NjYWxlID0gdV9zY2FsZV9sZW5ndGggKiBhYnNfc2NhbGVfYXNwZWN0O1xuXG4gICAgLy8gQ29ycmVjdCBhbmdsZXMgZm9yIGFzcGVjdCByYXRpb1xuICAgIHZlYzIgYXY7XG4gICAgYXYgPSB2ZWMyKDEuMCwgdGFuKGFfYW5nbGVzLngpKSAvIGFic19zY2FsZV9hc3BlY3Q7XG4gICAgdl9hbmdsZXMueCA9IGF0YW4oYXYueSwgYXYueCk7XG4gICAgYXYgPSB2ZWMyKDEuMCwgdGFuKGFfYW5nbGVzLnkpKSAvIGFic19zY2FsZV9hc3BlY3Q7XG4gICAgdl9hbmdsZXMueSA9IGF0YW4oYXYueSwgYXYueCk7XG5cbiAgICAvLyBUaGlja25lc3MgYmVsb3cgMSBwaXhlbCBhcmUgcmVwcmVzZW50ZWQgdXNpbmcgYSAxIHBpeGVsIHRoaWNrbmVzc1xuICAgIC8vIGFuZCBhIG1vZGlmaWVkIGFscGhhXG4gICAgdl9jb2xvci5hID0gbWluKHZfbGluZXdpZHRoLCB2X2NvbG9yLmEpO1xuICAgIHZfbGluZXdpZHRoID0gbWF4KHZfbGluZXdpZHRoLCAxLjApO1xuXG4gICAgLy8gSWYgY29sb3IgaXMgZnVsbHkgdHJhbnNwYXJlbnQgd2UganVzdCB3aWxsIGRpc2NhcmQgdGhlIGZyYWdtZW50IGFueXdheVxuICAgIGlmKCB2X2NvbG9yLmEgPD0gMC4wICkge1xuICAgICAgICBnbF9Qb3NpdGlvbiA9IHZlYzQoMC4wLDAuMCwwLjAsMS4wKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFRoaXMgaXMgdGhlIGFjdHVhbCBoYWxmIHdpZHRoIG9mIHRoZSBsaW5lXG4gICAgZmxvYXQgdyA9IGNlaWwodV9hbnRpYWxpYXMrdl9saW5ld2lkdGgpLzIuMDtcblxuICAgIHZlYzIgcG9zaXRpb24gPSAoYV9wb3NpdGlvbiArIHVfb2Zmc2V0KSAqIGFic19zY2FsZTtcblxuICAgIHZlYzIgdDEgPSBub3JtYWxpemUoYV90YW5nZW50cy54eSAqIGFic19zY2FsZV9hc3BlY3QpOyAgLy8gbm90ZSB0aGUgc2NhbGluZyBmb3IgYXNwZWN0IHJhdGlvIGhlcmVcbiAgICB2ZWMyIHQyID0gbm9ybWFsaXplKGFfdGFuZ2VudHMuencgKiBhYnNfc2NhbGVfYXNwZWN0KTtcbiAgICBmbG9hdCB1ID0gYV90ZXhjb29yZC54O1xuICAgIGZsb2F0IHYgPSBhX3RleGNvb3JkLnk7XG4gICAgdmVjMiBvMSA9IHZlYzIoICt0MS55LCAtdDEueCk7XG4gICAgdmVjMiBvMiA9IHZlYzIoICt0Mi55LCAtdDIueCk7XG5cbiAgICAvLyBUaGlzIGlzIGEgam9pblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBpZiggdDEgIT0gdDIgKSB7XG4gICAgICAgIGZsb2F0IGFuZ2xlID0gYXRhbiAodDEueCp0Mi55LXQxLnkqdDIueCwgdDEueCp0Mi54K3QxLnkqdDIueSk7ICAvLyBBbmdsZSBuZWVkcyByZWNhbGN1bGF0aW9uIGZvciBzb21lIHJlYXNvblxuICAgICAgICB2ZWMyIHQgID0gbm9ybWFsaXplKHQxK3QyKTtcbiAgICAgICAgdmVjMiBvICA9IHZlYzIoICsgdC55LCAtIHQueCk7XG5cbiAgICAgICAgaWYgKCB1X2Rhc2hfaW5kZXggPiAwLjAgKVxuICAgICAgICB7XG4gICAgICAgICAgICAvLyBCcm9rZW4gYW5nbGVcbiAgICAgICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgICAgIGlmKCAoYWJzKGFuZ2xlKSA+IFRIRVRBKSApIHtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbiArPSB2ICogdyAqIG8gLyBjb3MoYW5nbGUvMi4wKTtcbiAgICAgICAgICAgICAgICBmbG9hdCBzID0gc2lnbihhbmdsZSk7XG4gICAgICAgICAgICAgICAgaWYoIGFuZ2xlIDwgMC4wICkge1xuICAgICAgICAgICAgICAgICAgICBpZiggdSA9PSArMS4wICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdSA9IHZfc2VnbWVudC55ICsgdiAqIHcgKiB0YW4oYW5nbGUvMi4wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCB2ID09IDEuMCApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiAtPSAyLjAgKiB3ICogdDEgLyBzaW4oYW5nbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHUgLT0gMi4wICogdyAvIHNpbihhbmdsZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB1ID0gdl9zZWdtZW50LnggLSB2ICogdyAqIHRhbihhbmdsZS8yLjApO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYoIHYgPT0gMS4wICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uICs9IDIuMCAqIHcgKiB0MiAvIHNpbihhbmdsZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdSArPSAyLjAqdyAvIHNpbihhbmdsZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiggdSA9PSArMS4wICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdSA9IHZfc2VnbWVudC55ICsgdiAqIHcgKiB0YW4oYW5nbGUvMi4wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCB2ID09IC0xLjAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gKz0gMi4wICogdyAqIHQxIC8gc2luKGFuZ2xlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1ICs9IDIuMCAqIHcgLyBzaW4oYW5nbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdSA9IHZfc2VnbWVudC54IC0gdiAqIHcgKiB0YW4oYW5nbGUvMi4wKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCB2ID09IC0xLjAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gLT0gMi4wICogdyAqIHQyIC8gc2luKGFuZ2xlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1IC09IDIuMCp3IC8gc2luKGFuZ2xlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBDb250aW51b3VzIGFuZ2xlXG4gICAgICAgICAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uICs9IHYgKiB3ICogbyAvIGNvcyhhbmdsZS8yLjApO1xuICAgICAgICAgICAgICAgIGlmKCB1ID09ICsxLjAgKSB1ID0gdl9zZWdtZW50Lnk7XG4gICAgICAgICAgICAgICAgZWxzZSAgICAgICAgICAgIHUgPSB2X3NlZ21lbnQueDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvbGlkIGxpbmVcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgZWxzZVxuICAgICAgICB7XG4gICAgICAgICAgICBwb3NpdGlvbi54eSArPSB2ICogdyAqIG8gLyBjb3MoYW5nbGUvMi4wKTtcbiAgICAgICAgICAgIGlmKCBhbmdsZSA8IDAuMCApIHtcbiAgICAgICAgICAgICAgICBpZiggdSA9PSArMS4wICkge1xuICAgICAgICAgICAgICAgICAgICB1ID0gdl9zZWdtZW50LnkgKyB2ICogdyAqIHRhbihhbmdsZS8yLjApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHUgPSB2X3NlZ21lbnQueCAtIHYgKiB3ICogdGFuKGFuZ2xlLzIuMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiggdSA9PSArMS4wICkge1xuICAgICAgICAgICAgICAgICAgICB1ID0gdl9zZWdtZW50LnkgKyB2ICogdyAqIHRhbihhbmdsZS8yLjApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHUgPSB2X3NlZ21lbnQueCAtIHYgKiB3ICogdGFuKGFuZ2xlLzIuMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAvLyBUaGlzIGlzIGEgbGluZSBzdGFydCBvciBlbmQgKHQxID09IHQyKVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHBvc2l0aW9uICs9IHYgKiB3ICogbzE7XG4gICAgICAgIGlmKCB1ID09IC0xLjAgKSB7XG4gICAgICAgICAgICB1ID0gdl9zZWdtZW50LnggLSB3O1xuICAgICAgICAgICAgcG9zaXRpb24gLT0gdyAqIHQxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdSA9IHZfc2VnbWVudC55ICsgdztcbiAgICAgICAgICAgIHBvc2l0aW9uICs9IHcgKiB0MjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIE1pdGVyIGRpc3RhbmNlXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgdmVjMiB0O1xuICAgIHZlYzIgY3VyciA9IGFfcG9zaXRpb24gKiBhYnNfc2NhbGU7XG4gICAgaWYoIGFfdGV4Y29vcmQueCA8IDAuMCApIHtcbiAgICAgICAgdmVjMiBuZXh0ID0gY3VyciArIHQyKih2X3NlZ21lbnQueS12X3NlZ21lbnQueCk7XG5cbiAgICAgICAgcm90YXRlKCB0MSwgK3ZfYW5nbGVzLngvMi4wLCB0KTtcbiAgICAgICAgdl9taXRlci54ID0gc2lnbmVkX2Rpc3RhbmNlKGN1cnIsIGN1cnIrdCwgcG9zaXRpb24pO1xuXG4gICAgICAgIHJvdGF0ZSggdDIsICt2X2FuZ2xlcy55LzIuMCwgdCk7XG4gICAgICAgIHZfbWl0ZXIueSA9IHNpZ25lZF9kaXN0YW5jZShuZXh0LCBuZXh0K3QsIHBvc2l0aW9uKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2ZWMyIHByZXYgPSBjdXJyIC0gdDEqKHZfc2VnbWVudC55LXZfc2VnbWVudC54KTtcblxuICAgICAgICByb3RhdGUoIHQxLCAtdl9hbmdsZXMueC8yLjAsdCk7XG4gICAgICAgIHZfbWl0ZXIueCA9IHNpZ25lZF9kaXN0YW5jZShwcmV2LCBwcmV2K3QsIHBvc2l0aW9uKTtcblxuICAgICAgICByb3RhdGUoIHQyLCAtdl9hbmdsZXMueS8yLjAsdCk7XG4gICAgICAgIHZfbWl0ZXIueSA9IHNpZ25lZF9kaXN0YW5jZShjdXJyLCBjdXJyK3QsIHBvc2l0aW9uKTtcbiAgICB9XG5cbiAgICBpZiAoIWNsb3NlZCAmJiB2X3NlZ21lbnQueCA8PSAwLjApIHtcbiAgICAgICAgdl9taXRlci54ID0gMWUxMDtcbiAgICB9XG4gICAgaWYgKCFjbG9zZWQgJiYgdl9zZWdtZW50LnkgPj0gdl9sZW5ndGgpXG4gICAge1xuICAgICAgICB2X21pdGVyLnkgPSAxZTEwO1xuICAgIH1cblxuICAgIHZfdGV4Y29vcmQgPSB2ZWMyKCB1LCB2KncgKTtcblxuICAgIC8vIENhbGN1bGF0ZSBwb3NpdGlvbiBpbiBkZXZpY2UgY29vcmRpbmF0ZXMuIE5vdGUgdGhhdCB3ZVxuICAgIC8vIGFscmVhZHkgc2NhbGVkIHdpdGggYWJzIHNjYWxlIGFib3ZlLlxuICAgIHZlYzIgbm9ybXBvcyA9IHBvc2l0aW9uICogc2lnbih1X3NjYWxlX2FzcGVjdCk7XG4gICAgbm9ybXBvcyArPSAwLjU7ICAvLyBtYWtlIHVwIGZvciBCb2tlaCdzIG9mZnNldFxuICAgIG5vcm1wb3MgLz0gdV9jYW52YXNfc2l6ZSAvIHVfcGl4ZWxfcmF0aW87ICAvLyBpbiAwLi4xXG4gICAgZ2xfUG9zaXRpb24gPSB2ZWM0KG5vcm1wb3MqMi4wLTEuMCwgMC4wLCAxLjApO1xuICAgIGdsX1Bvc2l0aW9uLnkgKj0gLTEuMDtcbn1cbiIsZS5wcm90b3R5cGUuRlJBR189Ii8vIEZyYWdtZW50IHNoYWRlciB0aGF0IGNhbiBiZSBjb252ZW5pZW50IGR1cmluZyBkZWJ1Z2dpbmcgdG8gc2hvdyB0aGUgbGluZSBza2VsZXRvbi5cbnByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xudW5pZm9ybSB2ZWM0ICB1X2NvbG9yO1xudm9pZCBtYWluICgpIHtcbiAgZ2xfRnJhZ0NvbG9yID0gdV9jb2xvcjtcbn0iLGUucHJvdG90eXBlLkZSQUc9InByZWNpc2lvbiBtZWRpdW1wIGZsb2F0O1xuXG5jb25zdCBmbG9hdCBQSSA9IDMuMTQxNTkyNjUzNTg5NzkzMjM4NDYyNjQ7XG5jb25zdCBmbG9hdCBUSEVUQSA9IDE1LjAgKiAzLjE0MTU5MjY1MzU4OTc5MzIzODQ2MjY0LzE4MC4wO1xuXG51bmlmb3JtIHNhbXBsZXIyRCB1X2Rhc2hfYXRsYXM7XG5cbnVuaWZvcm0gdmVjMiB1X2xpbmVjYXBzO1xudW5pZm9ybSBmbG9hdCB1X21pdGVyX2xpbWl0O1xudW5pZm9ybSBmbG9hdCB1X2xpbmVqb2luO1xudW5pZm9ybSBmbG9hdCB1X2FudGlhbGlhcztcbnVuaWZvcm0gZmxvYXQgdV9kYXNoX3BoYXNlO1xudW5pZm9ybSBmbG9hdCB1X2Rhc2hfcGVyaW9kO1xudW5pZm9ybSBmbG9hdCB1X2Rhc2hfaW5kZXg7XG51bmlmb3JtIHZlYzIgdV9kYXNoX2NhcHM7XG51bmlmb3JtIGZsb2F0IHVfY2xvc2VkO1xuXG52YXJ5aW5nIHZlYzQgIHZfY29sb3I7XG52YXJ5aW5nIHZlYzIgIHZfc2VnbWVudDtcbnZhcnlpbmcgdmVjMiAgdl9hbmdsZXM7XG52YXJ5aW5nIHZlYzIgIHZfdGV4Y29vcmQ7XG52YXJ5aW5nIHZlYzIgIHZfbWl0ZXI7XG52YXJ5aW5nIGZsb2F0IHZfbGVuZ3RoO1xudmFyeWluZyBmbG9hdCB2X2xpbmV3aWR0aDtcblxuLy8gQ29tcHV0ZSBkaXN0YW5jZSB0byBjYXAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZmxvYXQgY2FwKCBpbnQgdHlwZSwgZmxvYXQgZHgsIGZsb2F0IGR5LCBmbG9hdCB0LCBmbG9hdCBsaW5ld2lkdGggKVxue1xuICAgIGZsb2F0IGQgPSAwLjA7XG4gICAgZHggPSBhYnMoZHgpO1xuICAgIGR5ID0gYWJzKGR5KTtcbiAgICBpZiAgICAgICh0eXBlID09IDApICBkaXNjYXJkOyAgLy8gTm9uZVxuICAgIGVsc2UgaWYgKHR5cGUgPT0gMSkgIGQgPSBzcXJ0KGR4KmR4K2R5KmR5KTsgIC8vIFJvdW5kXG4gICAgZWxzZSBpZiAodHlwZSA9PSAzKSAgZCA9IChkeCthYnMoZHkpKTsgIC8vIFRyaWFuZ2xlIGluXG4gICAgZWxzZSBpZiAodHlwZSA9PSAyKSAgZCA9IG1heChhYnMoZHkpLCh0K2R4LWFicyhkeSkpKTsgIC8vIFRyaWFuZ2xlIG91dFxuICAgIGVsc2UgaWYgKHR5cGUgPT0gNCkgIGQgPSBtYXgoZHgsZHkpOyAgLy8gU3F1YXJlXG4gICAgZWxzZSBpZiAodHlwZSA9PSA1KSAgZCA9IG1heChkeCt0LGR5KTsgIC8vIEJ1dHRcbiAgICByZXR1cm4gZDtcbn1cblxuLy8gQ29tcHV0ZSBkaXN0YW5jZSB0byBqb2luIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmZsb2F0IGpvaW4oIGluIGludCB0eXBlLCBpbiBmbG9hdCBkLCBpbiB2ZWMyIHNlZ21lbnQsIGluIHZlYzIgdGV4Y29vcmQsIGluIHZlYzIgbWl0ZXIsXG4gICAgICAgICAgIGluIGZsb2F0IGxpbmV3aWR0aCApXG57XG4gICAgLy8gdGV4Y29vcmQueCBpcyBkaXN0YW5jZSBmcm9tIHN0YXJ0XG4gICAgLy8gdGV4Y29vcmQueSBpcyBkaXN0YW5jZSBmcm9tIGNlbnRlcmxpbmVcbiAgICAvLyBzZWdtZW50LnggYW5kIHkgaW5kaWNhdGUgdGhlIGxpbWl0cyAoYXMgZm9yIHRleGNvb3JkLngpIGZvciB0aGlzIHNlZ21lbnRcblxuICAgIGZsb2F0IGR4ID0gdGV4Y29vcmQueDtcblxuICAgIC8vIFJvdW5kIGpvaW5cbiAgICBpZiggdHlwZSA9PSAxICkge1xuICAgICAgICBpZiAoZHggPCBzZWdtZW50LngpIHtcbiAgICAgICAgICAgIGQgPSBtYXgoZCxsZW5ndGgoIHRleGNvb3JkIC0gdmVjMihzZWdtZW50LngsMC4wKSkpO1xuICAgICAgICAgICAgLy9kID0gbGVuZ3RoKCB0ZXhjb29yZCAtIHZlYzIoc2VnbWVudC54LDAuMCkpO1xuICAgICAgICB9IGVsc2UgaWYgKGR4ID4gc2VnbWVudC55KSB7XG4gICAgICAgICAgICBkID0gbWF4KGQsbGVuZ3RoKCB0ZXhjb29yZCAtIHZlYzIoc2VnbWVudC55LDAuMCkpKTtcbiAgICAgICAgICAgIC8vZCA9IGxlbmd0aCggdGV4Y29vcmQgLSB2ZWMyKHNlZ21lbnQueSwwLjApKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBCZXZlbCBqb2luXG4gICAgZWxzZSBpZiAoIHR5cGUgPT0gMiApIHtcbiAgICAgICAgaWYgKGR4IDwgc2VnbWVudC54KSB7XG4gICAgICAgICAgICB2ZWMyIHggPSB0ZXhjb29yZCAtIHZlYzIoc2VnbWVudC54LDAuMCk7XG4gICAgICAgICAgICBkID0gbWF4KGQsIG1heChhYnMoeC54KSwgYWJzKHgueSkpKTtcblxuICAgICAgICB9IGVsc2UgaWYgKGR4ID4gc2VnbWVudC55KSB7XG4gICAgICAgICAgICB2ZWMyIHggPSB0ZXhjb29yZCAtIHZlYzIoc2VnbWVudC55LDAuMCk7XG4gICAgICAgICAgICBkID0gbWF4KGQsIG1heChhYnMoeC54KSwgYWJzKHgueSkpKTtcbiAgICAgICAgfVxuICAgICAgICAvKiAgT3JpZ2luYWwgY29kZSBmb3IgYmV2ZWwgd2hpY2ggZG9lcyBub3Qgd29yayBmb3IgdXNcbiAgICAgICAgaWYoIChkeCA8IHNlZ21lbnQueCkgfHwgIChkeCA+IHNlZ21lbnQueSkgKVxuICAgICAgICAgICAgZCA9IG1heChkLCBtaW4oYWJzKHgueCksYWJzKHgueSkpKTtcbiAgICAgICAgKi9cbiAgICB9XG5cbiAgICByZXR1cm4gZDtcbn1cblxudm9pZCBtYWluKClcbntcbiAgICAvLyBJZiBjb2xvciBpcyBmdWxseSB0cmFuc3BhcmVudCB3ZSBqdXN0IGRpc2NhcmQgdGhlIGZyYWdtZW50XG4gICAgaWYoIHZfY29sb3IuYSA8PSAwLjAgKSB7XG4gICAgICAgIGRpc2NhcmQ7XG4gICAgfVxuXG4gICAgLy8gVGVzdCBpZiBkYXNoIHBhdHRlcm4gaXMgdGhlIHNvbGlkIG9uZSAoMClcbiAgICBib29sIHNvbGlkID0gICh1X2Rhc2hfaW5kZXggPT0gMC4wKTtcblxuICAgIC8vIFRlc3QgaWYgcGF0aCBpcyBjbG9zZWRcbiAgICBib29sIGNsb3NlZCA9ICh1X2Nsb3NlZCA+IDAuMCk7XG5cbiAgICB2ZWM0IGNvbG9yID0gdl9jb2xvcjtcbiAgICBmbG9hdCBkeCA9IHZfdGV4Y29vcmQueDtcbiAgICBmbG9hdCBkeSA9IHZfdGV4Y29vcmQueTtcbiAgICBmbG9hdCB0ID0gdl9saW5ld2lkdGgvMi4wLXVfYW50aWFsaWFzO1xuICAgIGZsb2F0IHdpZHRoID0gMS4wOyAgLy92X2xpbmV3aWR0aDsgb3JpZ2luYWwgY29kZSBoYWQgZGFzaGVzIHNjYWxlIHdpdGggbGluZSB3aWR0aCwgd2UgZG8gbm90XG4gICAgZmxvYXQgZCA9IDAuMDtcblxuICAgIHZlYzIgbGluZWNhcHMgPSB1X2xpbmVjYXBzO1xuICAgIHZlYzIgZGFzaF9jYXBzID0gdV9kYXNoX2NhcHM7XG4gICAgZmxvYXQgbGluZV9zdGFydCA9IDAuMDtcbiAgICBmbG9hdCBsaW5lX3N0b3AgPSB2X2xlbmd0aDtcblxuICAgIC8vIEFwcGx5IG1pdGVyIGxpbWl0OyBmcmFnbWVudHMgdG9vIGZhciBpbnRvIHRoZSBtaXRlciBhcmUgc2ltcGx5IGRpc2NhcmRlZFxuICAgIGlmKCAoZHggPCB2X3NlZ21lbnQueCkgfHwgKGR4ID4gdl9zZWdtZW50LnkpICkge1xuICAgICAgICBmbG9hdCBpbnRvX21pdGVyID0gbWF4KHZfc2VnbWVudC54IC0gZHgsIGR4IC0gdl9zZWdtZW50LnkpO1xuICAgICAgICBpZiAoaW50b19taXRlciA+IHVfbWl0ZXJfbGltaXQqdl9saW5ld2lkdGgvMi4wKVxuICAgICAgICAgIGRpc2NhcmQ7XG4gICAgfVxuXG4gICAgLy8gU29saWQgbGluZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGlmKCBzb2xpZCApIHtcbiAgICAgICAgZCA9IGFicyhkeSk7XG4gICAgICAgIGlmKCAoIWNsb3NlZCkgJiYgKGR4IDwgbGluZV9zdGFydCkgKSB7XG4gICAgICAgICAgICBkID0gY2FwKCBpbnQodV9saW5lY2Fwcy54KSwgYWJzKGR4KSwgYWJzKGR5KSwgdCwgdl9saW5ld2lkdGggKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKCAoIWNsb3NlZCkgJiYgIChkeCA+IGxpbmVfc3RvcCkgKSB7XG4gICAgICAgICAgICBkID0gY2FwKCBpbnQodV9saW5lY2Fwcy55KSwgYWJzKGR4KS1saW5lX3N0b3AsIGFicyhkeSksIHQsIHZfbGluZXdpZHRoICk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBkID0gam9pbiggaW50KHVfbGluZWpvaW4pLCBhYnMoZHkpLCB2X3NlZ21lbnQsIHZfdGV4Y29vcmQsIHZfbWl0ZXIsIHZfbGluZXdpZHRoICk7XG4gICAgICAgIH1cblxuICAgIC8vIERhc2ggbGluZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGZsb2F0IHNlZ21lbnRfc3RhcnQgPSB2X3NlZ21lbnQueDtcbiAgICAgICAgZmxvYXQgc2VnbWVudF9zdG9wICA9IHZfc2VnbWVudC55O1xuICAgICAgICBmbG9hdCBzZWdtZW50X2NlbnRlcj0gKHNlZ21lbnRfc3RhcnQrc2VnbWVudF9zdG9wKS8yLjA7XG4gICAgICAgIGZsb2F0IGZyZXEgICAgICAgICAgPSB1X2Rhc2hfcGVyaW9kKndpZHRoO1xuICAgICAgICBmbG9hdCB1ID0gbW9kKCBkeCArIHVfZGFzaF9waGFzZSp3aWR0aCwgZnJlcSk7XG4gICAgICAgIHZlYzQgdGV4ID0gdGV4dHVyZTJEKHVfZGFzaF9hdGxhcywgdmVjMih1L2ZyZXEsIHVfZGFzaF9pbmRleCkpICogMjU1LjAgLTEwLjA7ICAvLyBjb252ZXJzaW9uIHRvIGludC1saWtlXG4gICAgICAgIGZsb2F0IGRhc2hfY2VudGVyPSB0ZXgueCAqIHdpZHRoO1xuICAgICAgICBmbG9hdCBkYXNoX3R5cGUgID0gdGV4Lnk7XG4gICAgICAgIGZsb2F0IF9zdGFydCA9IHRleC56ICogd2lkdGg7XG4gICAgICAgIGZsb2F0IF9zdG9wICA9IHRleC5hICogd2lkdGg7XG4gICAgICAgIGZsb2F0IGRhc2hfc3RhcnQgPSBkeCAtIHUgKyBfc3RhcnQ7XG4gICAgICAgIGZsb2F0IGRhc2hfc3RvcCAgPSBkeCAtIHUgKyBfc3RvcDtcblxuICAgICAgICAvLyBDb21wdXRlIGV4dGVudHMgb2YgdGhlIGZpcnN0IGRhc2ggKHRoZSBvbmUgcmVsYXRpdmUgdG8gdl9zZWdtZW50LngpXG4gICAgICAgIC8vIE5vdGU6IHRoaXMgY291bGQgYmUgY29tcHV0ZWQgaW4gdGhlIHZlcnRleCBzaGFkZXJcbiAgICAgICAgaWYoIChkYXNoX3N0b3AgPCBzZWdtZW50X3N0YXJ0KSAmJiAoZGFzaF9jYXBzLnggIT0gNS4wKSApIHtcbiAgICAgICAgICAgIGZsb2F0IHUgPSBtb2Qoc2VnbWVudF9zdGFydCArIHVfZGFzaF9waGFzZSp3aWR0aCwgZnJlcSk7XG4gICAgICAgICAgICB2ZWM0IHRleCA9IHRleHR1cmUyRCh1X2Rhc2hfYXRsYXMsIHZlYzIodS9mcmVxLCB1X2Rhc2hfaW5kZXgpKSAqIDI1NS4wIC0xMC4wOyAgLy8gY29udmVyc2lvbiB0byBpbnQtbGlrZVxuICAgICAgICAgICAgZGFzaF9jZW50ZXI9IHRleC54ICogd2lkdGg7XG4gICAgICAgICAgICAvL2Rhc2hfdHlwZSAgPSB0ZXgueTtcbiAgICAgICAgICAgIGZsb2F0IF9zdGFydCA9IHRleC56ICogd2lkdGg7XG4gICAgICAgICAgICBmbG9hdCBfc3RvcCAgPSB0ZXguYSAqIHdpZHRoO1xuICAgICAgICAgICAgZGFzaF9zdGFydCA9IHNlZ21lbnRfc3RhcnQgLSB1ICsgX3N0YXJ0O1xuICAgICAgICAgICAgZGFzaF9zdG9wID0gc2VnbWVudF9zdGFydCAtIHUgKyBfc3RvcDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbXB1dGUgZXh0ZW50cyBvZiB0aGUgbGFzdCBkYXNoICh0aGUgb25lIHJlbGF0aXZlcyB0byB2X3NlZ21lbnQueSlcbiAgICAgICAgLy8gTm90ZTogVGhpcyBjb3VsZCBiZSBjb21wdXRlZCBpbiB0aGUgdmVydGV4IHNoYWRlclxuICAgICAgICBlbHNlIGlmKCAoZGFzaF9zdGFydCA+IHNlZ21lbnRfc3RvcCkgICYmIChkYXNoX2NhcHMueSAhPSA1LjApICkge1xuICAgICAgICAgICAgZmxvYXQgdSA9IG1vZChzZWdtZW50X3N0b3AgKyB1X2Rhc2hfcGhhc2Uqd2lkdGgsIGZyZXEpO1xuICAgICAgICAgICAgdmVjNCB0ZXggPSB0ZXh0dXJlMkQodV9kYXNoX2F0bGFzLCB2ZWMyKHUvZnJlcSwgdV9kYXNoX2luZGV4KSkgKiAyNTUuMCAtMTAuMDsgIC8vIGNvbnZlcnNpb24gdG8gaW50LWxpa2VcbiAgICAgICAgICAgIGRhc2hfY2VudGVyPSB0ZXgueCAqIHdpZHRoO1xuICAgICAgICAgICAgLy9kYXNoX3R5cGUgID0gdGV4Lnk7XG4gICAgICAgICAgICBmbG9hdCBfc3RhcnQgPSB0ZXgueiAqIHdpZHRoO1xuICAgICAgICAgICAgZmxvYXQgX3N0b3AgID0gdGV4LmEgKiB3aWR0aDtcbiAgICAgICAgICAgIGRhc2hfc3RhcnQgPSBzZWdtZW50X3N0b3AgLSB1ICsgX3N0YXJ0O1xuICAgICAgICAgICAgZGFzaF9zdG9wICA9IHNlZ21lbnRfc3RvcCAtIHUgKyBfc3RvcDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoaXMgdGVzdCBpZiB0aGUgd2UgYXJlIGRlYWxpbmcgd2l0aCBhIGRpc2NvbnRpbnVvdXMgYW5nbGVcbiAgICAgICAgYm9vbCBkaXNjb250aW51b3VzID0gKChkeCA8ICBzZWdtZW50X2NlbnRlcikgJiYgYWJzKHZfYW5nbGVzLngpID4gVEhFVEEpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICgoZHggPj0gc2VnbWVudF9jZW50ZXIpICYmIGFicyh2X2FuZ2xlcy55KSA+IFRIRVRBKTtcbiAgICAgICAgLy9pZiggZHggPCBsaW5lX3N0YXJ0KSBkaXNjb250aW51b3VzID0gZmFsc2U7XG4gICAgICAgIC8vaWYoIGR4ID4gbGluZV9zdG9wKSAgZGlzY29udGludW91cyA9IGZhbHNlO1xuXG4gICAgICAgIGZsb2F0IGRfam9pbiA9IGpvaW4oIGludCh1X2xpbmVqb2luKSwgYWJzKGR5KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2X3NlZ21lbnQsIHZfdGV4Y29vcmQsIHZfbWl0ZXIsIHZfbGluZXdpZHRoICk7XG5cbiAgICAgICAgLy8gV2hlbiBwYXRoIGlzIGNsb3NlZCwgd2UgZG8gbm90IGhhdmUgcm9vbSBmb3IgbGluZWNhcHMsIHNvIHdlIG1ha2Ugcm9vbVxuICAgICAgICAvLyBieSBzaG9ydGVuaW5nIHRoZSB0b3RhbCBsZW5ndGhcbiAgICAgICAgaWYgKGNsb3NlZCkge1xuICAgICAgICAgICAgIGxpbmVfc3RhcnQgKz0gdl9saW5ld2lkdGgvMi4wO1xuICAgICAgICAgICAgIGxpbmVfc3RvcCAgLT0gdl9saW5ld2lkdGgvMi4wO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2UgYWxzbyBuZWVkIHRvIHRha2UgYW50aWFsaWFzIGFyZWEgaW50byBhY2NvdW50XG4gICAgICAgIC8vbGluZV9zdGFydCArPSB1X2FudGlhbGlhcztcbiAgICAgICAgLy9saW5lX3N0b3AgIC09IHVfYW50aWFsaWFzO1xuXG4gICAgICAgIC8vIENoZWNrIGlzIGRhc2ggc3RvcCBpcyBiZWZvcmUgbGluZSBzdGFydFxuICAgICAgICBpZiggZGFzaF9zdG9wIDw9IGxpbmVfc3RhcnQgKSB7XG4gICAgICAgICAgICBkaXNjYXJkO1xuICAgICAgICB9XG4gICAgICAgIC8vIENoZWNrIGlzIGRhc2ggc3RhcnQgaXMgYmV5b25kIGxpbmUgc3RvcFxuICAgICAgICBpZiggZGFzaF9zdGFydCA+PSBsaW5lX3N0b3AgKSB7XG4gICAgICAgICAgICBkaXNjYXJkO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgY3VycmVudCBkYXNoIHN0YXJ0IGlzIGJleW9uZCBzZWdtZW50IHN0b3BcbiAgICAgICAgaWYoIGRpc2NvbnRpbnVvdXMgKSB7XG4gICAgICAgICAgICAvLyBEYXNoIHN0YXJ0IGlzIGJleW9uZCBzZWdtZW50LCB3ZSBkaXNjYXJkXG4gICAgICAgICAgICBpZiggKGRhc2hfc3RhcnQgPiBzZWdtZW50X3N0b3ApICkge1xuICAgICAgICAgICAgICAgIGRpc2NhcmQ7XG4gICAgICAgICAgICAgICAgLy9nbF9GcmFnQ29sb3IgPSB2ZWM0KDEuMCwwLjAsMC4wLC4yNSk7IHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRGFzaCBzdG9wIGlzIGJlZm9yZSBzZWdtZW50LCB3ZSBkaXNjYXJkXG4gICAgICAgICAgICBpZiggKGRhc2hfc3RvcCA8IHNlZ21lbnRfc3RhcnQpICkge1xuICAgICAgICAgICAgICAgIGRpc2NhcmQ7ICAvL2dsX0ZyYWdDb2xvciA9IHZlYzQoMC4wLDEuMCwwLjAsLjI1KTsgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgZm9yIHJvdW5kIGNhcHMgKG5pY2VyIHdpdGggdGhpcylcbiAgICAgICAgICAgIGlmKCBkYXNoX2NhcHMueCA9PSAxLjAgKSB7XG4gICAgICAgICAgICAgICAgaWYoICh1ID4gX3N0b3ApICYmIChkYXNoX3N0b3AgPiBzZWdtZW50X3N0b3AgKSAgJiYgKGFicyh2X2FuZ2xlcy55KSA8IFBJLzIuMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGlzY2FyZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSBmb3Igcm91bmQgY2FwcyAgKG5pY2VyIHdpdGggdGhpcylcbiAgICAgICAgICAgIGlmKCBkYXNoX2NhcHMueSA9PSAxLjAgKSB7XG4gICAgICAgICAgICAgICAgaWYoICh1IDwgX3N0YXJ0KSAmJiAoZGFzaF9zdGFydCA8IHNlZ21lbnRfc3RhcnQgKSAgJiYgKGFicyh2X2FuZ2xlcy54KSA8IFBJLzIuMCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGlzY2FyZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSBmb3IgdHJpYW5nbGUgY2FwcyAoaW4gJiBvdXQpIGFuZCBzcXVhcmVcbiAgICAgICAgICAgIC8vIFdlIG1ha2Ugc3VyZSB0aGUgY2FwIHN0b3AgYXQgY3Jvc3NpbmcgZnJvbnRpZXJcbiAgICAgICAgICAgIGlmKCAoZGFzaF9jYXBzLnggIT0gMS4wKSAmJiAoZGFzaF9jYXBzLnggIT0gNS4wKSApIHtcbiAgICAgICAgICAgICAgICBpZiggKGRhc2hfc3RhcnQgPCBzZWdtZW50X3N0YXJ0ICkgICYmIChhYnModl9hbmdsZXMueCkgPCBQSS8yLjApICkge1xuICAgICAgICAgICAgICAgICAgICBmbG9hdCBhID0gdl9hbmdsZXMueC8yLjA7XG4gICAgICAgICAgICAgICAgICAgIGZsb2F0IHggPSAoc2VnbWVudF9zdGFydC1keCkqY29zKGEpIC0gZHkqc2luKGEpO1xuICAgICAgICAgICAgICAgICAgICBmbG9hdCB5ID0gKHNlZ21lbnRfc3RhcnQtZHgpKnNpbihhKSArIGR5KmNvcyhhKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoIHggPiAwLjAgKSBkaXNjYXJkO1xuICAgICAgICAgICAgICAgICAgICAvLyBXZSB0cmFuc2Zvcm0gdGhlIGNhcCBpbnRvIHNxdWFyZSB0byBhdm9pZCBob2xlc1xuICAgICAgICAgICAgICAgICAgICBkYXNoX2NhcHMueCA9IDQuMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSBmb3IgdHJpYW5nbGUgY2FwcyAoaW4gJiBvdXQpIGFuZCBzcXVhcmVcbiAgICAgICAgICAgIC8vIFdlIG1ha2Ugc3VyZSB0aGUgY2FwIHN0b3AgYXQgY3Jvc3NpbmcgZnJvbnRpZXJcbiAgICAgICAgICAgIGlmKCAoZGFzaF9jYXBzLnkgIT0gMS4wKSAmJiAoZGFzaF9jYXBzLnkgIT0gNS4wKSApIHtcbiAgICAgICAgICAgICAgICBpZiggKGRhc2hfc3RvcCA+IHNlZ21lbnRfc3RvcCApICAmJiAoYWJzKHZfYW5nbGVzLnkpIDwgUEkvMi4wKSApIHtcbiAgICAgICAgICAgICAgICAgICAgZmxvYXQgYSA9IHZfYW5nbGVzLnkvMi4wO1xuICAgICAgICAgICAgICAgICAgICBmbG9hdCB4ID0gKGR4LXNlZ21lbnRfc3RvcCkqY29zKGEpIC0gZHkqc2luKGEpO1xuICAgICAgICAgICAgICAgICAgICBmbG9hdCB5ID0gKGR4LXNlZ21lbnRfc3RvcCkqc2luKGEpICsgZHkqY29zKGEpO1xuICAgICAgICAgICAgICAgICAgICBpZiggeCA+IDAuMCApIGRpc2NhcmQ7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdlIHRyYW5zZm9ybSB0aGUgY2FwcyBpbnRvIHNxdWFyZSB0byBhdm9pZCBob2xlc1xuICAgICAgICAgICAgICAgICAgICBkYXNoX2NhcHMueSA9IDQuMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBMaW5lIGNhcCBhdCBzdGFydFxuICAgICAgICBpZiggKGR4IDwgbGluZV9zdGFydCkgJiYgKGRhc2hfc3RhcnQgPCBsaW5lX3N0YXJ0KSAmJiAoZGFzaF9zdG9wID4gbGluZV9zdGFydCkgKSB7XG4gICAgICAgICAgICBkID0gY2FwKCBpbnQobGluZWNhcHMueCksIGR4LWxpbmVfc3RhcnQsIGR5LCB0LCB2X2xpbmV3aWR0aCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTGluZSBjYXAgYXQgc3RvcFxuICAgICAgICBlbHNlIGlmKCAoZHggPiBsaW5lX3N0b3ApICYmIChkYXNoX3N0b3AgPiBsaW5lX3N0b3ApICYmIChkYXNoX3N0YXJ0IDwgbGluZV9zdG9wKSApIHtcbiAgICAgICAgICAgIGQgPSBjYXAoIGludChsaW5lY2Fwcy55KSwgZHgtbGluZV9zdG9wLCBkeSwgdCwgdl9saW5ld2lkdGgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIERhc2ggY2FwIGxlZnQgLSBkYXNoX3R5cGUgPSAtMSwgMCBvciAxLCBidXQgdGhlcmUgbWF5IGJlIHJvdW5kb2ZmIGVycm9yc1xuICAgICAgICBlbHNlIGlmKCBkYXNoX3R5cGUgPCAtMC41ICkge1xuICAgICAgICAgICAgZCA9IGNhcCggaW50KGRhc2hfY2Fwcy55KSwgYWJzKHUtZGFzaF9jZW50ZXIpLCBkeSwgdCwgdl9saW5ld2lkdGgpO1xuICAgICAgICAgICAgaWYoIChkeCA+IGxpbmVfc3RhcnQpICYmIChkeCA8IGxpbmVfc3RvcCkgKVxuICAgICAgICAgICAgICAgIGQgPSBtYXgoZCxkX2pvaW4pO1xuICAgICAgICB9XG4gICAgICAgIC8vIERhc2ggY2FwIHJpZ2h0XG4gICAgICAgIGVsc2UgaWYoIGRhc2hfdHlwZSA+IDAuNSApIHtcbiAgICAgICAgICAgIGQgPSBjYXAoIGludChkYXNoX2NhcHMueCksIGFicyhkYXNoX2NlbnRlci11KSwgZHksIHQsIHZfbGluZXdpZHRoKTtcbiAgICAgICAgICAgIGlmKCAoZHggPiBsaW5lX3N0YXJ0KSAmJiAoZHggPCBsaW5lX3N0b3ApIClcbiAgICAgICAgICAgICAgICBkID0gbWF4KGQsZF9qb2luKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBEYXNoIGJvZHkgKHBsYWluKVxuICAgICAgICBlbHNlIHsvLyBpZiggZGFzaF90eXBlID4gLTAuNSAmJiAgZGFzaF90eXBlIDwgMC41KSB7XG4gICAgICAgICAgICBkID0gYWJzKGR5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIExpbmUgam9pblxuICAgICAgICBpZiggKGR4ID4gbGluZV9zdGFydCkgJiYgKGR4IDwgbGluZV9zdG9wKSkge1xuICAgICAgICAgICAgaWYoIChkeCA8PSBzZWdtZW50X3N0YXJ0KSAmJiAoZGFzaF9zdGFydCA8PSBzZWdtZW50X3N0YXJ0KVxuICAgICAgICAgICAgICAgICYmIChkYXNoX3N0b3AgPj0gc2VnbWVudF9zdGFydCkgKSB7XG4gICAgICAgICAgICAgICAgZCA9IGRfam9pbjtcbiAgICAgICAgICAgICAgICAvLyBBbnRpYWxpYXMgYXQgb3V0ZXIgYm9yZGVyXG4gICAgICAgICAgICAgICAgZmxvYXQgYW5nbGUgPSBQSS8yLit2X2FuZ2xlcy54O1xuICAgICAgICAgICAgICAgIGZsb2F0IGYgPSBhYnMoIChzZWdtZW50X3N0YXJ0IC0gZHgpKmNvcyhhbmdsZSkgLSBkeSpzaW4oYW5nbGUpKTtcbiAgICAgICAgICAgICAgICBkID0gbWF4KGYsZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKCAoZHggPiBzZWdtZW50X3N0b3ApICYmIChkYXNoX3N0YXJ0IDw9IHNlZ21lbnRfc3RvcClcbiAgICAgICAgICAgICAgICAgICAgICYmIChkYXNoX3N0b3AgPj0gc2VnbWVudF9zdG9wKSApIHtcbiAgICAgICAgICAgICAgICBkID0gZF9qb2luO1xuICAgICAgICAgICAgICAgIC8vIEFudGlhbGlhcyBhdCBvdXRlciBib3JkZXJcbiAgICAgICAgICAgICAgICBmbG9hdCBhbmdsZSA9IFBJLzIuK3ZfYW5nbGVzLnk7XG4gICAgICAgICAgICAgICAgZmxvYXQgZiA9IGFicygoZHggLSBzZWdtZW50X3N0b3ApKmNvcyhhbmdsZSkgLSBkeSpzaW4oYW5nbGUpKTtcbiAgICAgICAgICAgICAgICBkID0gbWF4KGYsZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKCBkeCA8IChzZWdtZW50X3N0YXJ0IC0gdl9saW5ld2lkdGgvMi4pKSB7XG4gICAgICAgICAgICAgICAgZGlzY2FyZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoIGR4ID4gKHNlZ21lbnRfc3RvcCArIHZfbGluZXdpZHRoLzIuKSkge1xuICAgICAgICAgICAgICAgIGRpc2NhcmQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiggZHggPCAoc2VnbWVudF9zdGFydCAtIHZfbGluZXdpZHRoLzIuKSkge1xuICAgICAgICAgICAgZGlzY2FyZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKCBkeCA+IChzZWdtZW50X3N0b3AgKyB2X2xpbmV3aWR0aC8yLikpIHtcbiAgICAgICAgICAgIGRpc2NhcmQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEaXN0YW5jZSB0byBib3JkZXIgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgZCA9IGQgLSB0O1xuICAgIGlmKCBkIDwgMC4wICkge1xuICAgICAgICBnbF9GcmFnQ29sb3IgPSBjb2xvcjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkIC89IHVfYW50aWFsaWFzO1xuICAgICAgICBnbF9GcmFnQ29sb3IgPSB2ZWM0KGNvbG9yLnJnYiwgZXhwKC1kKmQpKmNvbG9yLmEpO1xuICAgIH1cbn0iLGUucHJvdG90eXBlLmluaXQ9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gdD10aGlzLmdsLHRoaXMuX3NjYWxlX2FzcGVjdD0wLHRoaXMucHJvZz1uZXcgdS5Qcm9ncmFtKHQpLHRoaXMucHJvZy5zZXRfc2hhZGVycyh0aGlzLlZFUlQsdGhpcy5GUkFHKSx0aGlzLmluZGV4X2J1ZmZlcj1uZXcgdS5JbmRleEJ1ZmZlcih0KSx0aGlzLnZib19wb3NpdGlvbj1uZXcgdS5WZXJ0ZXhCdWZmZXIodCksdGhpcy52Ym9fdGFuZ2VudHM9bmV3IHUuVmVydGV4QnVmZmVyKHQpLHRoaXMudmJvX3NlZ21lbnQ9bmV3IHUuVmVydGV4QnVmZmVyKHQpLHRoaXMudmJvX2FuZ2xlcz1uZXcgdS5WZXJ0ZXhCdWZmZXIodCksdGhpcy52Ym9fdGV4Y29vcmQ9bmV3IHUuVmVydGV4QnVmZmVyKHQpLHRoaXMuZGFzaF9hdGxhcz1uZXcgbyh0KX0sZS5wcm90b3R5cGUuZHJhdz1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdztpZih1PWUuZ2xnbHlwaCx1LmRhdGFfY2hhbmdlZCl7aWYoIWlzRmluaXRlKHIuZHgpfHwhaXNGaW5pdGUoci5keSkpcmV0dXJuO3UuX2Jha2VkX29mZnNldD1bci5keCxyLmR5XSx1Ll9zZXRfZGF0YSgpLHUuZGF0YV9jaGFuZ2VkPSExfWlmKHRoaXMudmlzdWFsc19jaGFuZ2VkJiYodGhpcy5fc2V0X3Zpc3VhbHMoKSx0aGlzLnZpc3VhbHNfY2hhbmdlZD0hMSksdj1yLnN4LGI9ci5zeSx5PU1hdGguc3FydCh2KnYrYipiKSx2Lz15LGIvPXksTWF0aC5hYnModGhpcy5fc2NhbGVfYXNwZWN0LWIvdik+TWF0aC5hYnMoLjAwMSp0aGlzLl9zY2FsZV9hc3BlY3QpJiYodS5fdXBkYXRlX3NjYWxlKHYsYiksdGhpcy5fc2NhbGVfYXNwZWN0PWIvdiksdGhpcy5wcm9nLnNldF9hdHRyaWJ1dGUoImFfcG9zaXRpb24iLCJ2ZWMyIix1LnZib19wb3NpdGlvbiksdGhpcy5wcm9nLnNldF9hdHRyaWJ1dGUoImFfdGFuZ2VudHMiLCJ2ZWM0Iix1LnZib190YW5nZW50cyksdGhpcy5wcm9nLnNldF9hdHRyaWJ1dGUoImFfc2VnbWVudCIsInZlYzIiLHUudmJvX3NlZ21lbnQpLHRoaXMucHJvZy5zZXRfYXR0cmlidXRlKCJhX2FuZ2xlcyIsInZlYzIiLHUudmJvX2FuZ2xlcyksdGhpcy5wcm9nLnNldF9hdHRyaWJ1dGUoImFfdGV4Y29vcmQiLCJ2ZWMyIix1LnZib190ZXhjb29yZCksdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X2xlbmd0aCIsImZsb2F0IixbdS5jdW1zdW1dKSx0aGlzLnByb2cuc2V0X3RleHR1cmUoInVfZGFzaF9hdGxhcyIsdGhpcy5kYXNoX2F0bGFzLnRleCksbj11Ll9iYWtlZF9vZmZzZXQsdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X3BpeGVsX3JhdGlvIiwiZmxvYXQiLFtyLnBpeGVsX3JhdGlvXSksdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X2NhbnZhc19zaXplIiwidmVjMiIsW3Iud2lkdGgsci5oZWlnaHRdKSx0aGlzLnByb2cuc2V0X3VuaWZvcm0oInVfb2Zmc2V0IiwidmVjMiIsW3IuZHgtblswXSxyLmR5LW5bMV1dKSx0aGlzLnByb2cuc2V0X3VuaWZvcm0oInVfc2NhbGVfYXNwZWN0IiwidmVjMiIsW3YsYl0pLHRoaXMucHJvZy5zZXRfdW5pZm9ybSgidV9zY2FsZV9sZW5ndGgiLCJmbG9hdCIsW3ldKSx0aGlzLklfdHJpYW5nbGVzPXUuSV90cmlhbmdsZXMsdGhpcy5JX3RyaWFuZ2xlcy5sZW5ndGg8NjU1MzUpcmV0dXJuIHRoaXMuaW5kZXhfYnVmZmVyLnNldF9zaXplKDIqdGhpcy5JX3RyaWFuZ2xlcy5sZW5ndGgpLHRoaXMuaW5kZXhfYnVmZmVyLnNldF9kYXRhKDAsbmV3IFVpbnQxNkFycmF5KHRoaXMuSV90cmlhbmdsZXMpKSx0aGlzLnByb2cuZHJhdyh0aGlzLmdsLlRSSUFOR0xFUyx0aGlzLmluZGV4X2J1ZmZlcik7Zm9yKHQ9dGhpcy5JX3RyaWFuZ2xlcyxoPXRoaXMuSV90cmlhbmdsZXMubGVuZ3RoLHM9NjQwMDgsaT1bXSxhPWw9MCxkPU1hdGguY2VpbChoL3MpOzA8PWQ/bDxkOmw+ZDthPTA8PWQ/KytsOi0tbClpLnB1c2goW10pO2ZvcihhPXA9MCxmPXQubGVuZ3RoOzA8PWY/cDxmOnA+ZjthPTA8PWY/KytwOi0tcCl3PXRbYV0lcyxvPU1hdGguZmxvb3IodFthXS9zKSxpW29dLnB1c2godyk7Zm9yKGc9W10sbz1fPTAsbT1pLmxlbmd0aDswPD1tP188bTpfPm07bz0wPD1tPysrXzotLV8peD1uZXcgVWludDE2QXJyYXkoaVtvXSksYz1vKnMqNCwwIT09eC5sZW5ndGgmJih0aGlzLnByb2cuc2V0X2F0dHJpYnV0ZSgiYV9wb3NpdGlvbiIsInZlYzIiLHUudmJvX3Bvc2l0aW9uLDAsMipjKSx0aGlzLnByb2cuc2V0X2F0dHJpYnV0ZSgiYV90YW5nZW50cyIsInZlYzQiLHUudmJvX3RhbmdlbnRzLDAsNCpjKSx0aGlzLnByb2cuc2V0X2F0dHJpYnV0ZSgiYV9zZWdtZW50IiwidmVjMiIsdS52Ym9fc2VnbWVudCwwLDIqYyksCnRoaXMucHJvZy5zZXRfYXR0cmlidXRlKCJhX2FuZ2xlcyIsInZlYzIiLHUudmJvX2FuZ2xlcywwLDIqYyksdGhpcy5wcm9nLnNldF9hdHRyaWJ1dGUoImFfdGV4Y29vcmQiLCJ2ZWMyIix1LnZib190ZXhjb29yZCwwLDIqYyksdGhpcy5pbmRleF9idWZmZXIuc2V0X3NpemUoMip4Lmxlbmd0aCksdGhpcy5pbmRleF9idWZmZXIuc2V0X2RhdGEoMCx4KSxnLnB1c2godGhpcy5wcm9nLmRyYXcodGhpcy5nbC5UUklBTkdMRVMsdGhpcy5pbmRleF9idWZmZXIpKSk7cmV0dXJuIGd9LGUucHJvdG90eXBlLl9zZXRfZGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9iYWtlKCksdGhpcy52Ym9fcG9zaXRpb24uc2V0X3NpemUoNCp0aGlzLlZfcG9zaXRpb24ubGVuZ3RoKSx0aGlzLnZib19wb3NpdGlvbi5zZXRfZGF0YSgwLHRoaXMuVl9wb3NpdGlvbiksdGhpcy52Ym9fdGFuZ2VudHMuc2V0X3NpemUoNCp0aGlzLlZfdGFuZ2VudHMubGVuZ3RoKSx0aGlzLnZib190YW5nZW50cy5zZXRfZGF0YSgwLHRoaXMuVl90YW5nZW50cyksdGhpcy52Ym9fYW5nbGVzLnNldF9zaXplKDQqdGhpcy5WX2FuZ2xlcy5sZW5ndGgpLHRoaXMudmJvX2FuZ2xlcy5zZXRfZGF0YSgwLHRoaXMuVl9hbmdsZXMpLHRoaXMudmJvX3RleGNvb3JkLnNldF9zaXplKDQqdGhpcy5WX3RleGNvb3JkLmxlbmd0aCksdGhpcy52Ym9fdGV4Y29vcmQuc2V0X2RhdGEoMCx0aGlzLlZfdGV4Y29vcmQpfSxlLnByb3RvdHlwZS5fc2V0X3Zpc3VhbHM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscztyZXR1cm4gZT1sKHRoaXMuZ2x5cGgudmlzdWFscy5saW5lLmxpbmVfY29sb3IudmFsdWUoKSx0aGlzLmdseXBoLnZpc3VhbHMubGluZS5saW5lX2FscGhhLnZhbHVlKCkpLHQ9dGhpcy5DQVBTW3RoaXMuZ2x5cGgudmlzdWFscy5saW5lLmxpbmVfY2FwLnZhbHVlKCldLGk9dGhpcy5KT0lOU1t0aGlzLmdseXBoLnZpc3VhbHMubGluZS5saW5lX2pvaW4udmFsdWUoKV0sdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X2NvbG9yIiwidmVjNCIsZSksdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X2xpbmV3aWR0aCIsImZsb2F0IixbdGhpcy5nbHlwaC52aXN1YWxzLmxpbmUubGluZV93aWR0aC52YWx1ZSgpXSksdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X2FudGlhbGlhcyIsImZsb2F0IixbLjldKSx0aGlzLnByb2cuc2V0X3VuaWZvcm0oInVfbGluZWNhcHMiLCJ2ZWMyIixbdCx0XSksdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X2xpbmVqb2luIiwiZmxvYXQiLFtpXSksdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X21pdGVyX2xpbWl0IiwiZmxvYXQiLFsxMF0pLG49dGhpcy5nbHlwaC52aXN1YWxzLmxpbmUubGluZV9kYXNoLnZhbHVlKCkscj0wLG89MSxuLmxlbmd0aCYmKHM9dGhpcy5kYXNoX2F0bGFzLmdldF9hdGxhc19kYXRhKG4pLHI9c1swXSxvPXNbMV0pLHRoaXMucHJvZy5zZXRfdW5pZm9ybSgidV9kYXNoX2luZGV4IiwiZmxvYXQiLFtyXSksdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X2Rhc2hfcGhhc2UiLCJmbG9hdCIsW3RoaXMuZ2x5cGgudmlzdWFscy5saW5lLmxpbmVfZGFzaF9vZmZzZXQudmFsdWUoKV0pLHRoaXMucHJvZy5zZXRfdW5pZm9ybSgidV9kYXNoX3BlcmlvZCIsImZsb2F0Iixbb10pLHRoaXMucHJvZy5zZXRfdW5pZm9ybSgidV9kYXNoX2NhcHMiLCJ2ZWMyIixbdCx0XSksdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X2Nsb3NlZCIsImZsb2F0IixbMF0pfSxlLnByb3RvdHlwZS5fYmFrZT1mdW5jdGlvbigpe3ZhciB0LGUscixuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTLHosUCxFLEEsQyxOLE8scSxELEksUixGLEIsTDtmb3IoeD10aGlzLm52ZXJ0aWNlcyxfPW5ldyBGbG9hdDY0QXJyYXkodGhpcy5nbHlwaC5feCksZD1uZXcgRmxvYXQ2NEFycmF5KHRoaXMuZ2x5cGguX3kpLGk9Yz1uZXcgRmxvYXQzMkFycmF5KDIqeCksbj1uZXcgRmxvYXQzMkFycmF5KDIqeCksYT1wPW5ldyBGbG9hdDMyQXJyYXkoNCp4KSx1PW5ldyBGbG9hdDMyQXJyYXkoMip4KSxtPXY9MCxTPXg7MDw9Uz92PFM6dj5TO209MDw9Uz8rK3Y6LS12KWlbMiptKzBdPV9bbV0rdGhpcy5fYmFrZWRfb2Zmc2V0WzBdLGlbMiptKzFdPWRbbV0rdGhpcy5fYmFrZWRfb2Zmc2V0WzFdO2Zvcih0aGlzLnRhbmdlbnRzPXI9bmV3IEZsb2F0MzJBcnJheSgyKngtMiksbT1rPTAsej14LTE7MDw9ej9rPHo6az56O209MDw9ej8rK2s6LS1rKXJbMiptKzBdPWNbMioobSsxKSswXS1jWzIqbSswXSxyWzIqbSsxXT1jWzIqKG0rMSkrMV0tY1syKm0rMV07Zm9yKG09aj0wLFA9eC0xOzA8PVA/ajxQOmo+UDttPTA8PVA/KytqOi0tailhWzQqKG0rMSkrMF09clsyKm0rMF0sYVs0KihtKzEpKzFdPXJbMiptKzFdLGFbNCptKzJdPXJbMiptKzBdLGFbNCptKzNdPXJbMiptKzFdO2ZvcihhWzBdPXJbMF0sYVsxXT1yWzFdLGFbNCooeC0xKSsyXT1yWzIqKHgtMikrMF0sYVs0Kih4LTEpKzNdPXJbMiooeC0yKSsxXSx0PW5ldyBGbG9hdDMyQXJyYXkoeCksbT1UPTAsRT14OzA8PUU/VDxFOlQ+RTttPTA8PUU/KytUOi0tVCl0W21dPU1hdGguYXRhbjIocFs0Km0rMF0qcFs0Km0rM10tcFs0Km0rMV0qcFs0Km0rMl0scFs0Km0rMF0qcFs0Km0rMl0rcFs0Km0rMV0qcFs0Km0rM10pO2ZvcihtPUQ9MCxBPXgtMTswPD1BP0Q8QTpEPkE7bT0wPD1BPysrRDotLUQpblsyKm0rMF09dFttXSxuWzIqbSsxXT10W20rMV07Zm9yKGI9NCp4LTQsdGhpcy5WX3Bvc2l0aW9uPXM9bmV3IEZsb2F0MzJBcnJheSgyKmIpLHRoaXMuVl9hbmdsZXM9bz1uZXcgRmxvYXQzMkFycmF5KDIqYiksdGhpcy5WX3RhbmdlbnRzPWw9bmV3IEZsb2F0MzJBcnJheSg0KmIpLHRoaXMuVl90ZXhjb29yZD1oPW5ldyBGbG9hdDMyQXJyYXkoMipiKSxNPTIsbT1JPTAsQz14OzA8PUM/STxDOkk+QzttPTA8PUM/KytJOi0tSSlmb3IoZz1SPTA7Ujw0O2c9KytSKXtmb3IoeT1GPTA7RjwyO3k9KytGKXNbMiooNCptK2ctTSkreV09aVsyKm0reV0sb1syKig0Km0rZykreV09blsyKm0reV07Zm9yKHk9Qj0wO0I8NDt5PSsrQilsWzQqKDQqbStnLU0pK3ldPWFbNCptK3ldfWZvcihtPUw9MCxOPXg7MDw9Tj9MPD1OOkw+PU47bT0wPD1OPysrTDotLUwpaFsyKig0Km0rMCkrMF09LTEsaFsyKig0Km0rMSkrMF09LTEsaFsyKig0Km0rMikrMF09MSxoWzIqKDQqbSszKSswXT0xLGhbMiooNCptKzApKzFdPS0xLGhbMiooNCptKzEpKzFdPTEsaFsyKig0Km0rMikrMV09LTEsaFsyKig0Km0rMykrMV09MTtmb3Iodz02Kih4LTEpLHRoaXMuSV90cmlhbmdsZXM9ZT1uZXcgVWludDMyQXJyYXkodykscT1bXSxtPWY9MCxPPXg7MDw9Tz9mPE86Zj5PO209MDw9Tz8rK2Y6LS1mKWVbNiptKzBdPTArNCptLGVbNiptKzFdPTErNCptLGVbNiptKzJdPTMrNCptLGVbNiptKzNdPTIrNCptLGVbNiptKzRdPTArNCptLHEucHVzaChlWzYqbSs1XT0zKzQqbSk7cmV0dXJuIHF9LGUucHJvdG90eXBlLl91cGRhdGVfc2NhbGU9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHY7Zm9yKHA9dGhpcy5udmVydGljZXMsYz00KnAtNCxuPXRoaXMudGFuZ2VudHMscj1uZXcgRmxvYXQzMkFycmF5KHAtMSksbz1uZXcgRmxvYXQzMkFycmF5KDIqcCksdGhpcy5WX3NlZ21lbnQ9aT1uZXcgRmxvYXQzMkFycmF5KDIqYyksYT1oPTAsbT1wLTE7MDw9bT9oPG06aD5tO2E9MDw9bT8rK2g6LS1oKXJbYV09TWF0aC5zcXJ0KE1hdGgucG93KG5bMiphKzBdKnQsMikrTWF0aC5wb3coblsyKmErMV0qZSwyKSk7Zm9yKHM9MCxhPV89MCxnPXAtMTswPD1nP188ZzpfPmc7YT0wPD1nPysrXzotLV8pcys9clthXSxvWzIqKGErMSkrMF09cyxvWzIqYSsxXT1zO2ZvcihhPWQ9MCx5PXA7MDw9eT9kPHk6ZD55O2E9MDw9eT8rK2Q6LS1kKWZvcihsPWY9MDtmPDQ7bD0rK2YpZm9yKHU9dj0wO3Y8Mjt1PSsrdilpWzIqKDQqYStsKSt1XT1vWzIqYSt1XTtyZXR1cm4gdGhpcy5jdW1zdW09cyx0aGlzLnZib19zZWdtZW50LnNldF9zaXplKDQqdGhpcy5WX3NlZ21lbnQubGVuZ3RoKSx0aGlzLnZib19zZWdtZW50LnNldF9kYXRhKDAsdGhpcy5WX3NlZ21lbnQpfSxlfShuKSxlLmV4cG9ydHM9e0xpbmVHTEdseXBoOml9fSx7Ii4uLy4uLy4uL2NvcmUvbG9nZ2luZyI6ImNvcmUvbG9nZ2luZyIsIi4vYmFzZSI6Im1vZGVscy9nbHlwaHMvd2ViZ2wvYmFzZSIsZ2xvbzI6Imdsb28yIn1dLCJtb2RlbHMvZ2x5cGhzL3dlYmdsL21haW4iOltmdW5jdGlvbih0LGUscil7dmFyIG4sbztuPXQoIi4vbGluZSIpLG89dCgiLi9tYXJrZXJzIiksZS5leHBvcnRzPXtMaW5lR0xHbHlwaDpuLkxpbmVHTEdseXBoLENpcmNsZUdMR2x5cGg6by5DaXJjbGVHTEdseXBoLFNxdWFyZUdMR2x5cGg6by5TcXVhcmVHTEdseXBoLEFubnVsdXNHTEdseXBoOm8uQW5udWx1c0dMR2x5cGgsRGlhbW9uZEdMR2x5cGg6by5EaWFtb25kR0xHbHlwaCxUcmlhbmdsZUdMR2x5cGg6by5UcmlhbmdsZUdMR2x5cGgsSW52ZXJ0ZWRUcmlhbmdsZUdMR2x5cGg6by5JbnZlcnRlZFRyaWFuZ2xlR0xHbHlwaCxDcm9zc0dMR2x5cGg6by5Dcm9zc0dMR2x5cGgsQ2lyY2xlQ3Jvc3NHTEdseXBoOm8uQ2lyY2xlQ3Jvc3NHTEdseXBoLFNxdWFyZUNyb3NzR0xHbHlwaDpvLlNxdWFyZUNyb3NzR0xHbHlwaCxEaWFtb25kQ3Jvc3NHTEdseXBoOm8uRGlhbW9uZENyb3NzR0xHbHlwaCxYR0xHbHlwaDpvLlhHTEdseXBoLENpcmNsZVhHTEdseXBoOm8uQ2lyY2xlWEdMR2x5cGgsU3F1YXJlWEdMR2x5cGg6by5TcXVhcmVYR0xHbHlwaCxBc3Rlcmlza0dMR2x5cGg6by5Bc3Rlcmlza0dMR2x5cGh9fSx7Ii4vbGluZSI6Im1vZGVscy9nbHlwaHMvd2ViZ2wvbGluZSIsIi4vbWFya2VycyI6Im1vZGVscy9nbHlwaHMvd2ViZ2wvbWFya2VycyJ9XSwibW9kZWxzL2dseXBocy93ZWJnbC9tYXJrZXJzIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrLGo9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKVQuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sVD17fS5oYXNPd25Qcm9wZXJ0eTt4PXQoImdsb28yIiksTT10KCIuLi8uLi8uLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIsaz10KCIuL2Jhc2UiKSxpPWsuQmFzZUdMR2x5cGgsdz1rLmxpbmVfd2lkdGgsYj1rLmF0dGFjaF9mbG9hdCx2PWsuYXR0YWNoX2NvbG9yLF89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGooZSx0KSxlLnByb3RvdHlwZS5WRVJUPSJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcbmNvbnN0IGZsb2F0IFNRUlRfMiA9IDEuNDE0MjEzNTYyMzczMDk1MTtcbi8vXG51bmlmb3JtIGZsb2F0IHVfcGl4ZWxfcmF0aW87XG51bmlmb3JtIHZlYzIgdV9jYW52YXNfc2l6ZTtcbnVuaWZvcm0gdmVjMiB1X29mZnNldDtcbnVuaWZvcm0gdmVjMiB1X3NjYWxlO1xudW5pZm9ybSBmbG9hdCB1X2FudGlhbGlhcztcbi8vXG5hdHRyaWJ1dGUgZmxvYXQgYV94O1xuYXR0cmlidXRlIGZsb2F0IGFfeTtcbmF0dHJpYnV0ZSBmbG9hdCBhX3NpemU7XG5hdHRyaWJ1dGUgZmxvYXQgYV9hbmdsZTsgIC8vIGluIHJhZGlhbnNcbmF0dHJpYnV0ZSBmbG9hdCBhX2xpbmV3aWR0aDtcbmF0dHJpYnV0ZSB2ZWM0ICBhX2ZnX2NvbG9yO1xuYXR0cmlidXRlIHZlYzQgIGFfYmdfY29sb3I7XG4vL1xudmFyeWluZyBmbG9hdCB2X2xpbmV3aWR0aDtcbnZhcnlpbmcgZmxvYXQgdl9zaXplO1xudmFyeWluZyB2ZWM0ICB2X2ZnX2NvbG9yO1xudmFyeWluZyB2ZWM0ICB2X2JnX2NvbG9yO1xudmFyeWluZyB2ZWMyICB2X3JvdGF0aW9uO1xuXG52b2lkIG1haW4gKHZvaWQpXG57XG4gICAgdl9zaXplID0gYV9zaXplICogdV9waXhlbF9yYXRpbztcbiAgICB2X2xpbmV3aWR0aCA9IGFfbGluZXdpZHRoICogdV9waXhlbF9yYXRpbztcbiAgICB2X2ZnX2NvbG9yID0gYV9mZ19jb2xvcjtcbiAgICB2X2JnX2NvbG9yID0gYV9iZ19jb2xvcjtcbiAgICB2X3JvdGF0aW9uID0gdmVjMihjb3MoLWFfYW5nbGUpLCBzaW4oLWFfYW5nbGUpKTtcbiAgICAvLyBDYWxjdWxhdGUgcG9zaXRpb24gLSB0aGUgLTAuNSBpcyB0byBjb3JyZWN0IGZvciBjYW52YXMgb3JpZ2luXG4gICAgdmVjMiBwb3MgPSAodmVjMihhX3gsIGFfeSkgKyB1X29mZnNldCkgKiB1X3NjYWxlOyAvLyBpbiBwaXhlbHNcbiAgICBwb3MgKz0gMC41OyAgLy8gbWFrZSB1cCBmb3IgQm9rZWgncyBvZmZzZXRcbiAgICBwb3MgLz0gdV9jYW52YXNfc2l6ZSAvIHVfcGl4ZWxfcmF0aW87ICAvLyBpbiAwLi4xXG4gICAgZ2xfUG9zaXRpb24gPSB2ZWM0KHBvcyoyLjAtMS4wLCAwLjAsIDEuMCk7XG4gICAgZ2xfUG9zaXRpb24ueSAqPSAtMS4wO1xuICAgIGdsX1BvaW50U2l6ZSA9IFNRUlRfMiAqIHZfc2l6ZSArIDIuMCAqICh2X2xpbmV3aWR0aCArIDEuNSp1X2FudGlhbGlhcyk7XG59IixlLnByb3RvdHlwZS5GUkFHPSJwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcbmNvbnN0IGZsb2F0IFNRUlRfMiA9IDEuNDE0MjEzNTYyMzczMDk1MTtcbmNvbnN0IGZsb2F0IFBJID0gMy4xNDE1OTI2NTM1ODk3OTMyMzg0NjI2NDtcbi8vXG51bmlmb3JtIGZsb2F0IHVfYW50aWFsaWFzO1xuLy9cbnZhcnlpbmcgdmVjNCAgdl9mZ19jb2xvcjtcbnZhcnlpbmcgdmVjNCAgdl9iZ19jb2xvcjtcbnZhcnlpbmcgZmxvYXQgdl9saW5ld2lkdGg7XG52YXJ5aW5nIGZsb2F0IHZfc2l6ZTtcbnZhcnlpbmcgdmVjMiAgdl9yb3RhdGlvbjtcblxuTUFSS0VSQ09ERVxuXG52ZWM0IG91dGxpbmUoZmxvYXQgZGlzdGFuY2UsIGZsb2F0IGxpbmV3aWR0aCwgZmxvYXQgYW50aWFsaWFzLCB2ZWM0IGZnX2NvbG9yLCB2ZWM0IGJnX2NvbG9yKVxue1xuICAgIHZlYzQgZnJhZ19jb2xvcjtcbiAgICBmbG9hdCB0ID0gbGluZXdpZHRoLzIuMCAtIGFudGlhbGlhcztcbiAgICBmbG9hdCBzaWduZWRfZGlzdGFuY2UgPSBkaXN0YW5jZTtcbiAgICBmbG9hdCBib3JkZXJfZGlzdGFuY2UgPSBhYnMoc2lnbmVkX2Rpc3RhbmNlKSAtIHQ7XG4gICAgZmxvYXQgYWxwaGEgPSBib3JkZXJfZGlzdGFuY2UvYW50aWFsaWFzO1xuICAgIGFscGhhID0gZXhwKC1hbHBoYSphbHBoYSk7XG5cbiAgICAvLyBJZiBmZyBhbHBoYSBpcyB6ZXJvLCBpdCBwcm9iYWJseSBtZWFucyBubyBvdXRsaW5lLiBUbyBhdm9pZCBhIGRhcmsgb3V0bGluZVxuICAgIC8vIHNoaW5pbmcgdGhyb3VnaCBkdWUgdG8gYWEsIHdlIHNldCB0aGUgZmcgY29sb3IgdG8gdGhlIGJnIGNvbG9yLiBBdm9pZCBpZiAoaS5lLiBicmFuY2hpbmcpLlxuICAgIGZsb2F0IHNlbGVjdCA9IGZsb2F0KGJvb2woZmdfY29sb3IuYSkpO1xuICAgIGZnX2NvbG9yLnJnYiA9IHNlbGVjdCAqIGZnX2NvbG9yLnJnYiArICgxLjAgIC0gc2VsZWN0KSAqIGJnX2NvbG9yLnJnYjtcbiAgICAvLyBTaW1pbGFybHksIGlmIHdlIHdhbnQgYSB0cmFuc3BhcmVudCBiZ1xuICAgIHNlbGVjdCA9IGZsb2F0KGJvb2woYmdfY29sb3IuYSkpO1xuICAgIGJnX2NvbG9yLnJnYiA9IHNlbGVjdCAqIGJnX2NvbG9yLnJnYiArICgxLjAgIC0gc2VsZWN0KSAqIGZnX2NvbG9yLnJnYjtcblxuICAgIGlmKCBib3JkZXJfZGlzdGFuY2UgPCAwLjApXG4gICAgICAgIGZyYWdfY29sb3IgPSBmZ19jb2xvcjtcbiAgICBlbHNlIGlmKCBzaWduZWRfZGlzdGFuY2UgPCAwLjAgKSB7XG4gICAgICAgIGZyYWdfY29sb3IgPSBtaXgoYmdfY29sb3IsIGZnX2NvbG9yLCBzcXJ0KGFscGhhKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYoIGFicyhzaWduZWRfZGlzdGFuY2UpIDwgKGxpbmV3aWR0aC8yLjAgKyBhbnRpYWxpYXMpICkge1xuICAgICAgICAgICAgZnJhZ19jb2xvciA9IHZlYzQoZmdfY29sb3IucmdiLCBmZ19jb2xvci5hICogYWxwaGEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGlzY2FyZDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZnJhZ19jb2xvcjtcbn1cblxudm9pZCBtYWluKClcbntcbiAgICB2ZWMyIFAgPSBnbF9Qb2ludENvb3JkLnh5IC0gdmVjMigwLjUsIDAuNSk7XG4gICAgUCA9IHZlYzIodl9yb3RhdGlvbi54KlAueCAtIHZfcm90YXRpb24ueSpQLnksXG4gICAgICAgICAgICAgdl9yb3RhdGlvbi55KlAueCArIHZfcm90YXRpb24ueCpQLnkpO1xuICAgIGZsb2F0IHBvaW50X3NpemUgPSBTUVJUXzIqdl9zaXplICArIDIuMCAqICh2X2xpbmV3aWR0aCArIDEuNSp1X2FudGlhbGlhcyk7XG4gICAgZmxvYXQgZGlzdGFuY2UgPSBtYXJrZXIoUCpwb2ludF9zaXplLCB2X3NpemUpO1xuICAgIGdsX0ZyYWdDb2xvciA9IG91dGxpbmUoZGlzdGFuY2UsIHZfbGluZXdpZHRoLCB1X2FudGlhbGlhcywgdl9mZ19jb2xvciwgdl9iZ19jb2xvcik7XG4gICAgLy9nbF9GcmFnQ29sb3IucmdiICo9IGdsX0ZyYWdDb2xvci5hOyAgLy8gcHJlLW11bHRpcGx5IGFscGhhXG59IixlLnByb3RvdHlwZS5NQVJLRVJDT0RFPSI8ZGVmaW5lZCBpbiBzdWJjbGFzc2VzPiIsZS5wcm90b3R5cGUuaW5pdD1mdW5jdGlvbigpe3ZhciB0LGU7cmV0dXJuIGU9dGhpcy5nbCx0PXRoaXMuRlJBRy5yZXBsYWNlKC9NQVJLRVJDT0RFLyx0aGlzLk1BUktFUkNPREUpLHRoaXMubGFzdF90cmFucz17fSx0aGlzLnByb2c9bmV3IHguUHJvZ3JhbShlKSx0aGlzLnByb2cuc2V0X3NoYWRlcnModGhpcy5WRVJULHQpLHRoaXMudmJvX3g9bmV3IHguVmVydGV4QnVmZmVyKGUpLHRoaXMucHJvZy5zZXRfYXR0cmlidXRlKCJhX3giLCJmbG9hdCIsdGhpcy52Ym9feCksdGhpcy52Ym9feT1uZXcgeC5WZXJ0ZXhCdWZmZXIoZSksdGhpcy5wcm9nLnNldF9hdHRyaWJ1dGUoImFfeSIsImZsb2F0Iix0aGlzLnZib195KSx0aGlzLnZib19zPW5ldyB4LlZlcnRleEJ1ZmZlcihlKSx0aGlzLnByb2cuc2V0X2F0dHJpYnV0ZSgiYV9zaXplIiwiZmxvYXQiLHRoaXMudmJvX3MpLHRoaXMudmJvX2E9bmV3IHguVmVydGV4QnVmZmVyKGUpLHRoaXMucHJvZy5zZXRfYXR0cmlidXRlKCJhX2FuZ2xlIiwiZmxvYXQiLHRoaXMudmJvX2EpLHRoaXMudmJvX2xpbmV3aWR0aD1uZXcgeC5WZXJ0ZXhCdWZmZXIoZSksdGhpcy52Ym9fZmdfY29sb3I9bmV3IHguVmVydGV4QnVmZmVyKGUpLHRoaXMudmJvX2JnX2NvbG9yPW5ldyB4LlZlcnRleEJ1ZmZlcihlKSx0aGlzLmluZGV4X2J1ZmZlcj1uZXcgeC5JbmRleEJ1ZmZlcihlKX0sZS5wcm90b3R5cGUuZHJhdz1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHg7aWYoYz1lLmdsZ2x5cGgscD1jLm52ZXJ0aWNlcyxjLmRhdGFfY2hhbmdlZCl7aWYoIWlzRmluaXRlKHIuZHgpfHwhaXNGaW5pdGUoci5keSkpcmV0dXJuO2MuX2Jha2VkX29mZnNldD1bci5keCxyLmR5XSxjLl9zZXRfZGF0YShwKSxjLmRhdGFfY2hhbmdlZD0hMX1lbHNlIG51bGw9PXRoaXMuZ2x5cGguX3JhZGl1c3x8ci5zeD09PXRoaXMubGFzdF90cmFucy5zeCYmci5zeT09PXRoaXMubGFzdF90cmFucy5zeXx8KHRoaXMubGFzdF90cmFucz1yLHRoaXMudmJvX3Muc2V0X2RhdGEoMCxuZXcgRmxvYXQzMkFycmF5KGZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47Zm9yKHI9dGhpcy5nbHlwaC5zcmFkaXVzLG49W10sdD0wLGU9ci5sZW5ndGg7dDxlO3QrKyl5PXJbdF0sbi5wdXNoKDIqeSk7cmV0dXJuIG59LmNhbGwodGhpcykpKSk7aWYodGhpcy52aXN1YWxzX2NoYW5nZWQmJih0aGlzLl9zZXRfdmlzdWFscyhwKSx0aGlzLnZpc3VhbHNfY2hhbmdlZD0hMSksbj1jLl9iYWtlZF9vZmZzZXQsdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X3BpeGVsX3JhdGlvIiwiZmxvYXQiLFtyLnBpeGVsX3JhdGlvXSksdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X2NhbnZhc19zaXplIiwidmVjMiIsW3Iud2lkdGgsci5oZWlnaHRdKSx0aGlzLnByb2cuc2V0X3VuaWZvcm0oInVfb2Zmc2V0IiwidmVjMiIsW3IuZHgtblswXSxyLmR5LW5bMV1dKSx0aGlzLnByb2cuc2V0X3VuaWZvcm0oInVfc2NhbGUiLCJ2ZWMyIixbci5zeCxyLnN5XSksdGhpcy5wcm9nLnNldF9hdHRyaWJ1dGUoImFfeCIsImZsb2F0IixjLnZib194KSx0aGlzLnByb2cuc2V0X2F0dHJpYnV0ZSgiYV95IiwiZmxvYXQiLGMudmJvX3kpLHRoaXMucHJvZy5zZXRfYXR0cmlidXRlKCJhX3NpemUiLCJmbG9hdCIsYy52Ym9fcyksdGhpcy5wcm9nLnNldF9hdHRyaWJ1dGUoImFfYW5nbGUiLCJmbG9hdCIsYy52Ym9fYSksMCE9PXQubGVuZ3RoKXtpZih0Lmxlbmd0aD09PXApcmV0dXJuIHRoaXMucHJvZy5kcmF3KHRoaXMuZ2wuUE9JTlRTLFswLHBdKTtpZihwPDY1NTM1KXJldHVybiBiPXdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50LGIuaW5kZXhPZigiTVNJRSAiKStiLmluZGV4T2YoIlRyaWRlbnQvIikrYi5pbmRleE9mKCJFZGdlLyIpPjAmJk0ud2FybigiV2ViR0wgd2FybmluZzogSUUgaXMga25vd24gdG8gcHJvZHVjZSAxcHggc3ByaXRlcyB3aGl0aCBzZWxlY3Rpb25zLiIpLHRoaXMuaW5kZXhfYnVmZmVyLnNldF9zaXplKDIqdC5sZW5ndGgpLHRoaXMuaW5kZXhfYnVmZmVyLnNldF9kYXRhKDAsbmV3IFVpbnQxNkFycmF5KHQpKSx0aGlzLnByb2cuZHJhdyh0aGlzLmdsLlBPSU5UUyx0aGlzLmluZGV4X2J1ZmZlcik7Zm9yKHM9NjRlMyxpPVtdLGE9bD0wLGQ9TWF0aC5jZWlsKHAvcyk7MDw9ZD9sPGQ6bD5kO2E9MDw9ZD8rK2w6LS1sKWkucHVzaChbXSk7Zm9yKGE9dT0wLGY9dC5sZW5ndGg7MDw9Zj91PGY6dT5mO2E9MDw9Zj8rK3U6LS11KXg9dFthXSVzLG89TWF0aC5mbG9vcih0W2FdL3MpLGlbb10ucHVzaCh4KTtmb3IoZz1bXSxvPWg9MCxtPWkubGVuZ3RoOzA8PW0/aDxtOmg+bTtvPTA8PW0/KytoOi0taCl2PW5ldyBVaW50MTZBcnJheShpW29dKSxfPW8qcyo0LDAhPT12Lmxlbmd0aCYmKHRoaXMucHJvZy5zZXRfYXR0cmlidXRlKCJhX3giLCJmbG9hdCIsYy52Ym9feCwwLF8pLHRoaXMucHJvZy5zZXRfYXR0cmlidXRlKCJhX3kiLCJmbG9hdCIsYy52Ym9feSwwLF8pLHRoaXMucHJvZy5zZXRfYXR0cmlidXRlKCJhX3NpemUiLCJmbG9hdCIsYy52Ym9fcywwLF8pLHRoaXMucHJvZy5zZXRfYXR0cmlidXRlKCJhX2FuZ2xlIiwiZmxvYXQiLGMudmJvX2EsMCxfKSx0aGlzLnZib19saW5ld2lkdGgudXNlZCYmdGhpcy5wcm9nLnNldF9hdHRyaWJ1dGUoImFfbGluZXdpZHRoIiwiZmxvYXQiLHRoaXMudmJvX2xpbmV3aWR0aCwwLF8pLHRoaXMudmJvX2ZnX2NvbG9yLnVzZWQmJnRoaXMucHJvZy5zZXRfYXR0cmlidXRlKCJhX2ZnX2NvbG9yIiwidmVjNCIsdGhpcy52Ym9fZmdfY29sb3IsMCw0Kl8pLHRoaXMudmJvX2JnX2NvbG9yLnVzZWQmJnRoaXMucHJvZy5zZXRfYXR0cmlidXRlKCJhX2JnX2NvbG9yIiwidmVjNCIsdGhpcy52Ym9fYmdfY29sb3IsMCw0Kl8pLHRoaXMuaW5kZXhfYnVmZmVyLnNldF9zaXplKDIqdi5sZW5ndGgpLHRoaXMuaW5kZXhfYnVmZmVyLnNldF9kYXRhKDAsdiksZy5wdXNoKHRoaXMucHJvZy5kcmF3KHRoaXMuZ2wuUE9JTlRTLHRoaXMuaW5kZXhfYnVmZmVyKSkpO3JldHVybiBnfX0sZS5wcm90b3R5cGUuX3NldF9kYXRhPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhO2ZvcihuPTQqdCx0aGlzLnZib194LnNldF9zaXplKG4pLHRoaXMudmJvX3kuc2V0X3NpemUobiksdGhpcy52Ym9fYS5zZXRfc2l6ZShuKSx0aGlzLnZib19zLnNldF9zaXplKG4pLHM9bmV3IEZsb2F0NjRBcnJheSh0aGlzLmdseXBoLl94KSxhPW5ldyBGbG9hdDY0QXJyYXkodGhpcy5nbHlwaC5feSksZT1yPTAsbz10OzA8PW8/cjxvOnI+bztlPTA8PW8/KytyOi0tcilzW2VdKz10aGlzLl9iYWtlZF9vZmZzZXRbMF0sYVtlXSs9dGhpcy5fYmFrZWRfb2Zmc2V0WzFdO3JldHVybiB0aGlzLnZib194LnNldF9kYXRhKDAsbmV3IEZsb2F0MzJBcnJheShzKSksdGhpcy52Ym9feS5zZXRfZGF0YSgwLG5ldyBGbG9hdDMyQXJyYXkoYSkpLG51bGwhPXRoaXMuZ2x5cGguX2FuZ2xlJiZ0aGlzLnZib19hLnNldF9kYXRhKDAsbmV3IEZsb2F0MzJBcnJheSh0aGlzLmdseXBoLl9hbmdsZSkpLG51bGwhPXRoaXMuZ2x5cGguX3JhZGl1cz90aGlzLnZib19zLnNldF9kYXRhKDAsbmV3IEZsb2F0MzJBcnJheShmdW5jdGlvbigpe3ZhciB0LGUscixuO2ZvcihyPXRoaXMuZ2x5cGguc3JhZGl1cyxuPVtdLHQ9MCxlPXIubGVuZ3RoO3Q8ZTt0KyspaT1yW3RdLG4ucHVzaCgyKmkpO3JldHVybiBufS5jYWxsKHRoaXMpKSk6dGhpcy52Ym9fcy5zZXRfZGF0YSgwLG5ldyBGbG9hdDMyQXJyYXkodGhpcy5nbHlwaC5fc2l6ZSkpfSxlLnByb3RvdHlwZS5fc2V0X3Zpc3VhbHM9ZnVuY3Rpb24odCl7cmV0dXJuIGIodGhpcy5wcm9nLHRoaXMudmJvX2xpbmV3aWR0aCwiYV9saW5ld2lkdGgiLHQsdGhpcy5nbHlwaC52aXN1YWxzLmxpbmUsImxpbmVfd2lkdGgiKSx2KHRoaXMucHJvZyx0aGlzLnZib19mZ19jb2xvciwiYV9mZ19jb2xvciIsdCx0aGlzLmdseXBoLnZpc3VhbHMubGluZSwibGluZSIpLHYodGhpcy5wcm9nLHRoaXMudmJvX2JnX2NvbG9yLCJhX2JnX2NvbG9yIix0LHRoaXMuZ2x5cGgudmlzdWFscy5maWxsLCJmaWxsIiksdGhpcy5wcm9nLnNldF91bmlmb3JtKCJ1X2FudGlhbGlhcyIsImZsb2F0IixbLjhdKX0sZX0oaSksYT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaihlLHQpLGUucHJvdG90eXBlLkdMWVBIPSJjaXJjbGUiLGUucHJvdG90eXBlLk1BUktFUkNPREU9Ii8vIC0tLSBkaXNjXG5mbG9hdCBtYXJrZXIodmVjMiBQLCBmbG9hdCBzaXplKVxue1xuICAgIHJldHVybiBsZW5ndGgoUCkgLSBzaXplLzIuMDtcbn0iLGV9KF8pLGY9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGooZSx0KSxlLnByb3RvdHlwZS5HTFlQSD0ic3F1YXJlIixlLnByb3RvdHlwZS5NQVJLRVJDT0RFPSIvLyAtLS0gc3F1YXJlXG5mbG9hdCBtYXJrZXIodmVjMiBQLCBmbG9hdCBzaXplKVxue1xuICAgIHJldHVybiBtYXgoYWJzKFAueCksIGFicyhQLnkpKSAtIHNpemUvMi4wO1xufSIsZX0oXyksbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaihlLHQpLGUucHJvdG90eXBlLkdMWVBIPSJhbm51bHVzIixlLnByb3RvdHlwZS5NQVJLRVJDT0RFPSJmbG9hdCBtYXJrZXIodmVjMiBQLCBmbG9hdCBzaXplKVxue1xuICAgIGZsb2F0IHIxID0gbGVuZ3RoKFApIC0gc2l6ZS8yLjA7XG4gICAgZmxvYXQgcjIgPSBsZW5ndGgoUCkgLSBzaXplLzQuMDsgIC8vIGhhbGYgd2lkdGhcbiAgICByZXR1cm4gbWF4KHIxLCAtcjIpO1xufSIsZX0oXyksYz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaihlLHQpLGUucHJvdG90eXBlLkdMWVBIPSJkaWFtb25kIixlLnByb3RvdHlwZS5NQVJLRVJDT0RFPSIvLyAtLS0gZGlhbW9uZFxuZmxvYXQgbWFya2VyKHZlYzIgUCwgZmxvYXQgc2l6ZSlcbntcbiAgICBmbG9hdCB4ID0gU1FSVF8yIC8gMi4wICogKFAueCAqIDEuNSAtIFAueSk7XG4gICAgZmxvYXQgeSA9IFNRUlRfMiAvIDIuMCAqIChQLnggKiAxLjUgKyBQLnkpO1xuICAgIGZsb2F0IHIxID0gbWF4KGFicyh4KSwgYWJzKHkpKSAtIHNpemUgLyAoMi4wICogU1FSVF8yKTtcbiAgICByZXR1cm4gcjEgLyBTUVJUXzI7XG59IixlfShfKSxnPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBqKGUsdCksZS5wcm90b3R5cGUuR0xZUEg9InRyaWFuZ2xlIixlLnByb3RvdHlwZS5NQVJLRVJDT0RFPSJmbG9hdCBtYXJrZXIodmVjMiBQLCBmbG9hdCBzaXplKVxue1xuICAgIFAueSAtPSBzaXplICogMC4zO1xuICAgIGZsb2F0IHggPSBTUVJUXzIgLyAyLjAgKiAoUC54ICogMS43IC0gUC55KTtcbiAgICBmbG9hdCB5ID0gU1FSVF8yIC8gMi4wICogKFAueCAqIDEuNyArIFAueSk7XG4gICAgZmxvYXQgcjEgPSBtYXgoYWJzKHgpLCBhYnMoeSkpIC0gc2l6ZSAvIDEuNjtcbiAgICBmbG9hdCByMiA9IFAueTtcbiAgICByZXR1cm4gbWF4KHIxIC8gU1FSVF8yLCByMik7ICAvLyBJbnN0ZXJzZWN0IGRpYW1vbmQgd2l0aCByZWN0YW5nbGVcbn0iLGV9KF8pLHA9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGooZSx0KSxlLnByb3RvdHlwZS5HTFlQSD0iaW52ZXJ0ZWR0cmlhbmdsZSIsZS5wcm90b3R5cGUuTUFSS0VSQ09ERT0iZmxvYXQgbWFya2VyKHZlYzIgUCwgZmxvYXQgc2l6ZSlcbntcbiAgICBQLnkgKz0gc2l6ZSAqIDAuMztcbiAgICBmbG9hdCB4ID0gU1FSVF8yIC8gMi4wICogKFAueCAqIDEuNyAtIFAueSk7XG4gICAgZmxvYXQgeSA9IFNRUlRfMiAvIDIuMCAqIChQLnggKiAxLjcgKyBQLnkpO1xuICAgIGZsb2F0IHIxID0gbWF4KGFicyh4KSwgYWJzKHkpKSAtIHNpemUgLyAxLjY7XG4gICAgZmxvYXQgcjIgPSAtIFAueTtcbiAgICByZXR1cm4gbWF4KHIxIC8gU1FSVF8yLCByMik7ICAvLyBJbnN0ZXJzZWN0IGRpYW1vbmQgd2l0aCByZWN0YW5nbGVcbn0iLGV9KF8pLHU9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGooZSx0KSxlLnByb3RvdHlwZS5HTFlQSD0iY3Jvc3MiLGUucHJvdG90eXBlLk1BUktFUkNPREU9J2Zsb2F0IG1hcmtlcih2ZWMyIFAsIGZsb2F0IHNpemUpXG57XG4gICAgZmxvYXQgc3F1YXJlID0gbWF4KGFicyhQLngpLCBhYnMoUC55KSkgLSBzaXplIC8gMi41OyAgLy8gMi41IGlzIGEgdHdlYWtcbiAgICBmbG9hdCBjcm9zcyA9IG1pbihhYnMoUC54KSwgYWJzKFAueSkpIC0gc2l6ZSAvIDEwMC4wOyAgLy8gYml0IG9mICJ3aWR0aCIgZm9yIGFhXG4gICAgcmV0dXJuIG1heChzcXVhcmUsIGNyb3NzKTtcbn0nLGV9KF8pLHM9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGooZSx0KSxlLnByb3RvdHlwZS5HTFlQSD0iY2lyY2xlY3Jvc3MiLGUucHJvdG90eXBlLk1BUktFUkNPREU9ImZsb2F0IG1hcmtlcih2ZWMyIFAsIGZsb2F0IHNpemUpXG57XG4gICAgLy8gRGVmaW5lIHF1YWRyYW50c1xuICAgIGZsb2F0IHFzID0gc2l6ZSAvIDIuMDsgIC8vIHF1YWRyYW50IHNpemVcbiAgICBmbG9hdCBzMSA9IG1heChhYnMoUC54IC0gcXMpLCBhYnMoUC55IC0gcXMpKSAtIHFzO1xuICAgIGZsb2F0IHMyID0gbWF4KGFicyhQLnggKyBxcyksIGFicyhQLnkgLSBxcykpIC0gcXM7XG4gICAgZmxvYXQgczMgPSBtYXgoYWJzKFAueCAtIHFzKSwgYWJzKFAueSArIHFzKSkgLSBxcztcbiAgICBmbG9hdCBzNCA9IG1heChhYnMoUC54ICsgcXMpLCBhYnMoUC55ICsgcXMpKSAtIHFzO1xuICAgIC8vIEludGVyc2VjdCBtYWluIHNoYXBlIHdpdGggcXVhZHJhbnRzICh0byBmb3JtIGNyb3NzKVxuICAgIGZsb2F0IGNpcmNsZSA9IGxlbmd0aChQKSAtIHNpemUvMi4wO1xuICAgIGZsb2F0IGMxID0gbWF4KGNpcmNsZSwgczEpO1xuICAgIGZsb2F0IGMyID0gbWF4KGNpcmNsZSwgczIpO1xuICAgIGZsb2F0IGMzID0gbWF4KGNpcmNsZSwgczMpO1xuICAgIGZsb2F0IGM0ID0gbWF4KGNpcmNsZSwgczQpO1xuICAgIC8vIFVuaW9uXG4gICAgcmV0dXJuIG1pbihtaW4obWluKGMxLCBjMiksIGMzKSwgYzQpO1xufSIsZX0oXyksZD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaihlLHQpLGUucHJvdG90eXBlLkdMWVBIPSJzcXVhcmVjcm9zcyIsZS5wcm90b3R5cGUuTUFSS0VSQ09ERT0iZmxvYXQgbWFya2VyKHZlYzIgUCwgZmxvYXQgc2l6ZSlcbntcbiAgICAvLyBEZWZpbmUgcXVhZHJhbnRzXG4gICAgZmxvYXQgcXMgPSBzaXplIC8gMi4wOyAgLy8gcXVhZHJhbnQgc2l6ZVxuICAgIGZsb2F0IHMxID0gbWF4KGFicyhQLnggLSBxcyksIGFicyhQLnkgLSBxcykpIC0gcXM7XG4gICAgZmxvYXQgczIgPSBtYXgoYWJzKFAueCArIHFzKSwgYWJzKFAueSAtIHFzKSkgLSBxcztcbiAgICBmbG9hdCBzMyA9IG1heChhYnMoUC54IC0gcXMpLCBhYnMoUC55ICsgcXMpKSAtIHFzO1xuICAgIGZsb2F0IHM0ID0gbWF4KGFicyhQLnggKyBxcyksIGFicyhQLnkgKyBxcykpIC0gcXM7XG4gICAgLy8gSW50ZXJzZWN0IG1haW4gc2hhcGUgd2l0aCBxdWFkcmFudHMgKHRvIGZvcm0gY3Jvc3MpXG4gICAgZmxvYXQgc3F1YXJlID0gbWF4KGFicyhQLngpLCBhYnMoUC55KSkgLSBzaXplLzIuMDtcbiAgICBmbG9hdCBjMSA9IG1heChzcXVhcmUsIHMxKTtcbiAgICBmbG9hdCBjMiA9IG1heChzcXVhcmUsIHMyKTtcbiAgICBmbG9hdCBjMyA9IG1heChzcXVhcmUsIHMzKTtcbiAgICBmbG9hdCBjNCA9IG1heChzcXVhcmUsIHM0KTtcbiAgICAvLyBVbmlvblxuICAgIHJldHVybiBtaW4obWluKG1pbihjMSwgYzIpLCBjMyksIGM0KTtcbn0iLGV9KF8pLGg9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGooZSx0KSxlLnByb3RvdHlwZS5HTFlQSD0iZGlhbW9uZGNyb3NzIixlLnByb3RvdHlwZS5NQVJLRVJDT0RFPSJmbG9hdCBtYXJrZXIodmVjMiBQLCBmbG9hdCBzaXplKVxue1xuICAgIC8vIERlZmluZSBxdWFkcmFudHNcbiAgICBmbG9hdCBxcyA9IHNpemUgLyAyLjA7ICAvLyBxdWFkcmFudCBzaXplXG4gICAgZmxvYXQgczEgPSBtYXgoYWJzKFAueCAtIHFzKSwgYWJzKFAueSAtIHFzKSkgLSBxcztcbiAgICBmbG9hdCBzMiA9IG1heChhYnMoUC54ICsgcXMpLCBhYnMoUC55IC0gcXMpKSAtIHFzO1xuICAgIGZsb2F0IHMzID0gbWF4KGFicyhQLnggLSBxcyksIGFicyhQLnkgKyBxcykpIC0gcXM7XG4gICAgZmxvYXQgczQgPSBtYXgoYWJzKFAueCArIHFzKSwgYWJzKFAueSArIHFzKSkgLSBxcztcbiAgICAvLyBJbnRlcnNlY3QgbWFpbiBzaGFwZSB3aXRoIHF1YWRyYW50cyAodG8gZm9ybSBjcm9zcylcbiAgICBmbG9hdCB4ID0gU1FSVF8yIC8gMi4wICogKFAueCAqIDEuNSAtIFAueSk7XG4gICAgZmxvYXQgeSA9IFNRUlRfMiAvIDIuMCAqIChQLnggKiAxLjUgKyBQLnkpO1xuICAgIGZsb2F0IGRpYW1vbmQgPSBtYXgoYWJzKHgpLCBhYnMoeSkpIC0gc2l6ZSAvICgyLjAgKiBTUVJUXzIpO1xuICAgIGRpYW1vbmQgLz0gU1FSVF8yO1xuICAgIGZsb2F0IGMxID0gbWF4KGRpYW1vbmQsIHMxKTtcbiAgICBmbG9hdCBjMiA9IG1heChkaWFtb25kLCBzMik7XG4gICAgZmxvYXQgYzMgPSBtYXgoZGlhbW9uZCwgczMpO1xuICAgIGZsb2F0IGM0ID0gbWF4KGRpYW1vbmQsIHM0KTtcbiAgICAvLyBVbmlvblxuICAgIHJldHVybiBtaW4obWluKG1pbihjMSwgYzIpLCBjMyksIGM0KTtcbn0iLGV9KF8pLHk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGooZSx0KSxlLnByb3RvdHlwZS5HTFlQSD0ieCIsZS5wcm90b3R5cGUuTUFSS0VSQ09ERT0nZmxvYXQgbWFya2VyKHZlYzIgUCwgZmxvYXQgc2l6ZSlcbntcbiAgICBmbG9hdCBjaXJjbGUgPSBsZW5ndGgoUCkgLSBzaXplIC8gMS42O1xuICAgIGZsb2F0IFggPSBtaW4oYWJzKFAueCAtIFAueSksIGFicyhQLnggKyBQLnkpKSAtIHNpemUgLyAxMDAuMDsgIC8vIGJpdCBvZiAid2lkdGgiIGZvciBhYVxuICAgIHJldHVybiBtYXgoY2lyY2xlLCBYKTtcbn0nLGV9KF8pLGw9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGooZSx0KSxlLnByb3RvdHlwZS5HTFlQSD0iY2lyY2xleCIsZS5wcm90b3R5cGUuTUFSS0VSQ09ERT0nZmxvYXQgbWFya2VyKHZlYzIgUCwgZmxvYXQgc2l6ZSlcbntcbiAgICBmbG9hdCB4ID0gUC54IC0gUC55O1xuICAgIGZsb2F0IHkgPSBQLnggKyBQLnk7XG4gICAgLy8gRGVmaW5lIHF1YWRyYW50c1xuICAgIGZsb2F0IHFzID0gc2l6ZSAvIDIuMDsgIC8vIHF1YWRyYW50IHNpemVcbiAgICBmbG9hdCBzMSA9IG1heChhYnMoeCAtIHFzKSwgYWJzKHkgLSBxcykpIC0gcXM7XG4gICAgZmxvYXQgczIgPSBtYXgoYWJzKHggKyBxcyksIGFicyh5IC0gcXMpKSAtIHFzO1xuICAgIGZsb2F0IHMzID0gbWF4KGFicyh4IC0gcXMpLCBhYnMoeSArIHFzKSkgLSBxcztcbiAgICBmbG9hdCBzNCA9IG1heChhYnMoeCArIHFzKSwgYWJzKHkgKyBxcykpIC0gcXM7XG4gICAgLy8gSW50ZXJzZWN0IG1haW4gc2hhcGUgd2l0aCBxdWFkcmFudHMgKHRvIGZvcm0gY3Jvc3MpXG4gICAgZmxvYXQgY2lyY2xlID0gbGVuZ3RoKFApIC0gc2l6ZS8yLjA7XG4gICAgZmxvYXQgYzEgPSBtYXgoY2lyY2xlLCBzMSk7XG4gICAgZmxvYXQgYzIgPSBtYXgoY2lyY2xlLCBzMik7XG4gICAgZmxvYXQgYzMgPSBtYXgoY2lyY2xlLCBzMyk7XG4gICAgZmxvYXQgYzQgPSBtYXgoY2lyY2xlLCBzNCk7XG4gICAgLy8gVW5pb25cbiAgICBmbG9hdCBhbG1vc3QgPSBtaW4obWluKG1pbihjMSwgYzIpLCBjMyksIGM0KTtcbiAgICAvLyBJbiB0aGlzIGNhc2UsIHRoZSBYIGlzIGFsc28gb3V0c2lkZSBvZiB0aGUgbWFpbiBzaGFwZVxuICAgIGZsb2F0IFhtYXNrID0gbGVuZ3RoKFApIC0gc2l6ZSAvIDEuNjsgIC8vIGEgY2lyY2xlXG4gICAgZmxvYXQgWCA9IG1pbihhYnMoUC54IC0gUC55KSwgYWJzKFAueCArIFAueSkpIC0gc2l6ZSAvIDEwMC4wOyAgLy8gYml0IG9mICJ3aWR0aCIgZm9yIGFhXG4gICAgcmV0dXJuIG1pbihtYXgoWCwgWG1hc2spLCBhbG1vc3QpO1xufScsZX0oXyksbT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaihlLHQpLGUucHJvdG90eXBlLkdMWVBIPSJzcXVhcmV4IixlLnByb3RvdHlwZS5NQVJLRVJDT0RFPSJmbG9hdCBtYXJrZXIodmVjMiBQLCBmbG9hdCBzaXplKVxue1xuICAgIGZsb2F0IHggPSBQLnggLSBQLnk7XG4gICAgZmxvYXQgeSA9IFAueCArIFAueTtcbiAgICAvLyBEZWZpbmUgcXVhZHJhbnRzXG4gICAgZmxvYXQgcXMgPSBzaXplIC8gMi4wOyAgLy8gcXVhZHJhbnQgc2l6ZVxuICAgIGZsb2F0IHMxID0gbWF4KGFicyh4IC0gcXMpLCBhYnMoeSAtIHFzKSkgLSBxcztcbiAgICBmbG9hdCBzMiA9IG1heChhYnMoeCArIHFzKSwgYWJzKHkgLSBxcykpIC0gcXM7XG4gICAgZmxvYXQgczMgPSBtYXgoYWJzKHggLSBxcyksIGFicyh5ICsgcXMpKSAtIHFzO1xuICAgIGZsb2F0IHM0ID0gbWF4KGFicyh4ICsgcXMpLCBhYnMoeSArIHFzKSkgLSBxcztcbiAgICAvLyBJbnRlcnNlY3QgbWFpbiBzaGFwZSB3aXRoIHF1YWRyYW50cyAodG8gZm9ybSBjcm9zcylcbiAgICBmbG9hdCBzcXVhcmUgPSBtYXgoYWJzKFAueCksIGFicyhQLnkpKSAtIHNpemUvMi4wO1xuICAgIGZsb2F0IGMxID0gbWF4KHNxdWFyZSwgczEpO1xuICAgIGZsb2F0IGMyID0gbWF4KHNxdWFyZSwgczIpO1xuICAgIGZsb2F0IGMzID0gbWF4KHNxdWFyZSwgczMpO1xuICAgIGZsb2F0IGM0ID0gbWF4KHNxdWFyZSwgczQpO1xuICAgIC8vIFVuaW9uXG4gICAgcmV0dXJuIG1pbihtaW4obWluKGMxLCBjMiksIGMzKSwgYzQpO1xufSIsZX0oXyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaihlLHQpLGUucHJvdG90eXBlLkdMWVBIPSJhc3RlcmlzayIsZS5wcm90b3R5cGUuTUFSS0VSQ09ERT0nZmxvYXQgbWFya2VyKHZlYzIgUCwgZmxvYXQgc2l6ZSlcbntcbiAgICAvLyBNYXNrc1xuICAgIGZsb2F0IGRpYW1vbmQgPSBtYXgoYWJzKFNRUlRfMiAvIDIuMCAqIChQLnggLSBQLnkpKSwgYWJzKFNRUlRfMiAvIDIuMCAqIChQLnggKyBQLnkpKSkgLSBzaXplIC8gKDIuMCAqIFNRUlRfMik7XG4gICAgZmxvYXQgc3F1YXJlID0gbWF4KGFicyhQLngpLCBhYnMoUC55KSkgLSBzaXplIC8gKDIuMCAqIFNRUlRfMik7XG4gICAgLy8gU2hhcGVzXG4gICAgZmxvYXQgWCA9IG1pbihhYnMoUC54IC0gUC55KSwgYWJzKFAueCArIFAueSkpIC0gc2l6ZSAvIDEwMC4wOyAgLy8gYml0IG9mICJ3aWR0aCIgZm9yIGFhXG4gICAgZmxvYXQgY3Jvc3MgPSBtaW4oYWJzKFAueCksIGFicyhQLnkpKSAtIHNpemUgLyAxMDAuMDsgIC8vIGJpdCBvZiAid2lkdGgiIGZvciBhYVxuICAgIC8vIFJlc3VsdCBpcyB1bmlvbiBvZiBtYXNrZWQgc2hhcGVzXG4gICAgcmV0dXJuIG1pbihtYXgoWCwgZGlhbW9uZCksIG1heChjcm9zcywgc3F1YXJlKSk7XG59JyxlfShfKSxlLmV4cG9ydHM9e0NpcmNsZUdMR2x5cGg6YSxTcXVhcmVHTEdseXBoOmYsQW5udWx1c0dMR2x5cGg6bixEaWFtb25kR0xHbHlwaDpjLFRyaWFuZ2xlR0xHbHlwaDpnLEludmVydGVkVHJpYW5nbGVHTEdseXBoOnAsQ3Jvc3NHTEdseXBoOnUsQ2lyY2xlQ3Jvc3NHTEdseXBoOnMsU3F1YXJlQ3Jvc3NHTEdseXBoOmQsRGlhbW9uZENyb3NzR0xHbHlwaDpoLFhHTEdseXBoOnksQ2lyY2xlWEdMR2x5cGg6bCxTcXVhcmVYR0xHbHlwaDptLEFzdGVyaXNrR0xHbHlwaDpvfX0seyIuLi8uLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuL2Jhc2UiOiJtb2RlbHMvZ2x5cGhzL3dlYmdsL2Jhc2UiLGdsb28yOiJnbG9vMiJ9XSwibW9kZWxzL2dseXBocy93ZWRnZSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2dseXBoIiksbD10KCIuLi8uLi9jb21tb24vaGl0dGVzdCIpLHU9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksYT10KCIuLi8uLi9jb3JlL3V0aWwvbWF0aCIpLmFuZ2xlX2JldHdlZW4saT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLl9pbmRleF9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3h5X2luZGV4KCl9LGUucHJvdG90eXBlLl9tYXBfZGF0YT1mdW5jdGlvbigpe3JldHVybiJkYXRhIj09PXRoaXMubW9kZWwucHJvcGVydGllcy5yYWRpdXMudW5pdHM/dGhpcy5zcmFkaXVzPXRoaXMuc2Rpc3QodGhpcy5yZW5kZXJlci54bWFwcGVyLHRoaXMuX3gsdGhpcy5fcmFkaXVzKTp0aGlzLnNyYWRpdXM9dGhpcy5fcmFkaXVzfSxlLnByb3RvdHlwZS5fcmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscDtmb3IoYz1yLnN4LHA9ci5zeSxoPXIuc3JhZGl1cyxvPXIuX3N0YXJ0X2FuZ2xlLG49ci5fZW5kX2FuZ2xlLGk9dGhpcy5tb2RlbC5wcm9wZXJ0aWVzLmRpcmVjdGlvbi52YWx1ZSgpLHU9W10sYT0wLGw9ZS5sZW5ndGg7YTxsO2ErKylzPWVbYV0saXNOYU4oY1tzXStwW3NdK2hbc10rb1tzXStuW3NdKXx8KHQuYmVnaW5QYXRoKCksdC5hcmMoY1tzXSxwW3NdLGhbc10sb1tzXSxuW3NdLGkpLHQubGluZVRvKGNbc10scFtzXSksdC5jbG9zZVBhdGgoKSx0aGlzLnZpc3VhbHMuZmlsbC5kb2l0JiYodGhpcy52aXN1YWxzLmZpbGwuc2V0X3ZlY3Rvcml6ZSh0LHMpLHQuZmlsbCgpKSx0aGlzLnZpc3VhbHMubGluZS5kb2l0Pyh0aGlzLnZpc3VhbHMubGluZS5zZXRfdmVjdG9yaXplKHQscyksdS5wdXNoKHQuc3Ryb2tlKCkpKTp1LnB1c2godm9pZCAwKSk7cmV0dXJuIHV9LGUucHJvdG90eXBlLl9oaXRfcG9pbnQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTLHosUCxFLEEsQyxOLE8scSxELEksUixGLEI7Zm9yKGc9W3QudngsdC52eV0sUD1nWzBdLEM9Z1sxXSxxPXRoaXMucmVuZGVyZXIueG1hcHBlci5tYXBfZnJvbV90YXJnZXQoUCwhMCksUj10aGlzLnJlbmRlcmVyLnltYXBwZXIubWFwX2Zyb21fdGFyZ2V0KEMsITApLCJkYXRhIj09PXRoaXMubW9kZWwucHJvcGVydGllcy5yYWRpdXMudW5pdHM/KEQ9cS10aGlzLm1heF9yYWRpdXMsST1xK3RoaXMubWF4X3JhZGl1cyxGPVItdGhpcy5tYXhfcmFkaXVzLEI9Uit0aGlzLm1heF9yYWRpdXMpOihFPVAtdGhpcy5tYXhfcmFkaXVzLEE9UCt0aGlzLm1heF9yYWRpdXMseT10aGlzLnJlbmRlcmVyLnhtYXBwZXIudl9tYXBfZnJvbV90YXJnZXQoW0UsQV0sITApLEQ9eVswXSxJPXlbMV0sTj1DLXRoaXMubWF4X3JhZGl1cyxPPUMrdGhpcy5tYXhfcmFkaXVzLHY9dGhpcy5yZW5kZXJlci55bWFwcGVyLnZfbWFwX2Zyb21fdGFyZ2V0KFtOLE9dLCEwKSxGPXZbMF0sQj12WzFdKSxuPVtdLHI9bC52YWxpZGF0ZV9iYm94X2Nvb3JkcyhbRCxJXSxbRixCXSksYj1mdW5jdGlvbigpe3ZhciB0LGUsbixvO2ZvcihuPXRoaXMuaW5kZXguc2VhcmNoKHIpLG89W10sdD0wLGU9bi5sZW5ndGg7dDxlO3QrKylmPW5bdF0sby5wdXNoKGYuaSk7cmV0dXJuIG99LmNhbGwodGhpcyksYz0wLF89Yi5sZW5ndGg7YzxfO2MrKyloPWJbY10sbT1NYXRoLnBvdyh0aGlzLnNyYWRpdXNbaF0sMiksaz10aGlzLnJlbmRlcmVyLnhtYXBwZXIubWFwX3RvX3RhcmdldChxLCEwKSxqPXRoaXMucmVuZGVyZXIueG1hcHBlci5tYXBfdG9fdGFyZ2V0KHRoaXMuX3hbaF0sITApLFM9dGhpcy5yZW5kZXJlci55bWFwcGVyLm1hcF90b190YXJnZXQoUiwhMCksej10aGlzLnJlbmRlcmVyLnltYXBwZXIubWFwX3RvX3RhcmdldCh0aGlzLl95W2hdLCEwKSxpPU1hdGgucG93KGstaiwyKStNYXRoLnBvdyhTLXosMiksaTw9bSYmbi5wdXNoKFtoLGldKTtmb3Iobz10aGlzLm1vZGVsLnByb3BlcnRpZXMuZGlyZWN0aW9uLnZhbHVlKCksdT1bXSxwPTAsZD1uLmxlbmd0aDtwPGQ7cCsrKXg9bltwXSxoPXhbMF0saT14WzFdLE09dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcuY2FudmFzLnZ4X3RvX3N4KFApLFQ9dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcuY2FudmFzLnZ5X3RvX3N5KEMpLGU9TWF0aC5hdGFuMihULXRoaXMuc3lbaF0sTS10aGlzLnN4W2hdKSxhKC1lLC10aGlzLl9zdGFydF9hbmdsZVtoXSwtdGhpcy5fZW5kX2FuZ2xlW2hdLG8pJiZ1LnB1c2goW2gsaV0pO3JldHVybiB3PWwuY3JlYXRlX2hpdF90ZXN0X3Jlc3VsdCgpLHdbIjFkIl0uaW5kaWNlcz1zLmNoYWluKHUpLnNvcnRCeShmdW5jdGlvbih0KXtyZXR1cm4gdFsxXX0pLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gdFswXX0pLnZhbHVlKCksd30sZS5wcm90b3R5cGUuZHJhd19sZWdlbmQ9ZnVuY3Rpb24odCxlLHIsbixvKXtyZXR1cm4gdGhpcy5fZ2VuZXJpY19hcmVhX2xlZ2VuZCh0LGUscixuLG8pfSxlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJXZWRnZSIsZS5jb29yZHMoW1sieCIsInkiXV0pLGUubWl4aW5zKFsibGluZSIsImZpbGwiXSksZS5kZWZpbmUoe2RpcmVjdGlvbjpbdS5EaXJlY3Rpb24sImFudGljbG9jayJdLHJhZGl1czpbdS5EaXN0YW5jZVNwZWNdLHN0YXJ0X2FuZ2xlOlt1LkFuZ2xlU3BlY10sZW5kX2FuZ2xlOlt1LkFuZ2xlU3BlY119KSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzppfX0seyIuLi8uLi9jb21tb24vaGl0dGVzdCI6ImNvbW1vbi9oaXR0ZXN0IiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vY29yZS91dGlsL21hdGgiOiJjb3JlL3V0aWwvbWF0aCIsIi4vZ2x5cGgiOiJtb2RlbHMvZ2x5cGhzL2dseXBoIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvZ3JpZHMvZ3JpZCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpaC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxoPXt9Lmhhc093blByb3BlcnR5O2E9dCgidW5kZXJzY29yZSIpLGk9dCgiLi4vcmVuZGVyZXJzL2d1aWRlX3JlbmRlcmVyIikscz10KCIuLi9yZW5kZXJlcnMvcmVuZGVyZXIiKSxsPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHUoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5feF9yYW5nZV9uYW1lPXRoaXMubWdldCgieF9yYW5nZV9uYW1lIiksdGhpcy5feV9yYW5nZV9uYW1lPXRoaXMubWdldCgieV9yYW5nZV9uYW1lIil9LGUucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbigpe3ZhciB0O2lmKHRoaXMubW9kZWwudmlzaWJsZSE9PSExKXJldHVybiB0PXRoaXMucGxvdF92aWV3LmNhbnZhc192aWV3LmN0eCx0LnNhdmUoKSx0aGlzLl9kcmF3X3JlZ2lvbnModCksdGhpcy5fZHJhd19taW5vcl9ncmlkcyh0KSx0aGlzLl9kcmF3X2dyaWRzKHQpLHQucmVzdG9yZSgpfSxlLnByb3RvdHlwZS5iaW5kX2Jva2VoX2V2ZW50cz1mdW5jdGlvbigpe3JldHVybiB0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZSIsdGhpcy5yZXF1ZXN0X3JlbmRlcil9LGUucHJvdG90eXBlLl9kcmF3X3JlZ2lvbnM9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGEsbCx1LGgsYyxwO2lmKHRoaXMudmlzdWFscy5iYW5kX2ZpbGwuZG9pdClmb3Iobj10aGlzLm1vZGVsLmdyaWRfY29vcmRzKCJtYWpvciIsITEpLGM9blswXSxwPW5bMV0sdGhpcy52aXN1YWxzLmJhbmRfZmlsbC5zZXRfdmFsdWUodCksZT1yPTAsbz1jLmxlbmd0aC0xOzA8PW8/cjxvOnI+bztlPTA8PW8/KytyOi0tcillJTI9PT0xJiYoaT10aGlzLnBsb3Rfdmlldy5tYXBfdG9fc2NyZWVuKGNbZV0scFtlXSx0aGlzLl94X3JhbmdlX25hbWUsdGhpcy5feV9yYW5nZV9uYW1lKSxhPWlbMF0sdT1pWzFdLHM9dGhpcy5wbG90X3ZpZXcubWFwX3RvX3NjcmVlbihjW2UrMV0scFtlKzFdLHRoaXMuX3hfcmFuZ2VfbmFtZSx0aGlzLl95X3JhbmdlX25hbWUpLGw9c1swXSxoPXNbMV0sdC5maWxsUmVjdChhWzBdLHVbMF0sbFsxXS1hWzBdLGhbMV0tdVswXSksdC5maWxsKCkpfSxlLnByb3RvdHlwZS5fZHJhd19ncmlkcz1mdW5jdGlvbih0KXt2YXIgZSxyLG47aWYodGhpcy52aXN1YWxzLmdyaWRfbGluZS5kb2l0KXJldHVybiBlPXRoaXMubW9kZWwuZ3JpZF9jb29yZHMoIm1ham9yIikscj1lWzBdLG49ZVsxXSx0aGlzLl9kcmF3X2dyaWRfaGVscGVyKHQsdGhpcy52aXN1YWxzLmdyaWRfbGluZSxyLG4pfSxlLnByb3RvdHlwZS5fZHJhd19taW5vcl9ncmlkcz1mdW5jdGlvbih0KXt2YXIgZSxyLG47aWYodGhpcy52aXN1YWxzLm1pbm9yX2dyaWRfbGluZS5kb2l0KXJldHVybiBlPXRoaXMubW9kZWwuZ3JpZF9jb29yZHMoIm1pbm9yIikscj1lWzBdLG49ZVsxXSx0aGlzLl9kcmF3X2dyaWRfaGVscGVyKHQsdGhpcy52aXN1YWxzLm1pbm9yX2dyaWRfbGluZSxyLG4pfSxlLnByb3RvdHlwZS5fZHJhd19ncmlkX2hlbHBlcj1mdW5jdGlvbih0LGUscixuKXt2YXIgbyxpLHMsYSxsLHUsaCxjO2ZvcihlLnNldF92YWx1ZSh0KSxvPWk9MCxhPXIubGVuZ3RoOzA8PWE/aTxhOmk+YTtvPTA8PWE/KytpOi0taSl7Zm9yKGw9dGhpcy5wbG90X3ZpZXcubWFwX3RvX3NjcmVlbihyW29dLG5bb10sdGhpcy5feF9yYW5nZV9uYW1lLHRoaXMuX3lfcmFuZ2VfbmFtZSksaD1sWzBdLGM9bFsxXSx0LmJlZ2luUGF0aCgpLHQubW92ZVRvKE1hdGgucm91bmQoaFswXSksTWF0aC5yb3VuZChjWzBdKSksbz1zPTEsdT1oLmxlbmd0aDsxPD11P3M8dTpzPnU7bz0xPD11PysrczotLXMpdC5saW5lVG8oTWF0aC5yb3VuZChoW29dKSxNYXRoLnJvdW5kKGNbb10pKTt0LnN0cm9rZSgpfX0sZX0ocy5WaWV3KSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PW8sZS5wcm90b3R5cGUudHlwZT0iR3JpZCIsZS5taXhpbnMoWyJsaW5lOmdyaWRfIiwibGluZTptaW5vcl9ncmlkXyIsImZpbGw6YmFuZF8iXSksZS5kZWZpbmUoe2JvdW5kczpbbC5BbnksImF1dG8iXSxkaW1lbnNpb246W2wuTnVtYmVyLDBdLHRpY2tlcjpbbC5JbnN0YW5jZV0seF9yYW5nZV9uYW1lOltsLlN0cmluZywiZGVmYXVsdCJdLHlfcmFuZ2VfbmFtZTpbbC5TdHJpbmcsImRlZmF1bHQiXX0pLGUub3ZlcnJpZGUoe2xldmVsOiJ1bmRlcmxheSIsYmFuZF9maWxsX2NvbG9yOm51bGwsYmFuZF9maWxsX2FscGhhOjAsZ3JpZF9saW5lX2NvbG9yOiIjZTVlNWU1IixtaW5vcl9ncmlkX2xpbmVfY29sb3I6bnVsbH0pLGUucHJvdG90eXBlLnJhbmdlcz1mdW5jdGlvbigpe3ZhciB0LGUscixuO3JldHVybiBlPXRoaXMuZ2V0KCJkaW1lbnNpb24iKSxyPShlKzEpJTIsdD10aGlzLnBsb3QucGxvdF9jYW52YXMuZ2V0KCJmcmFtZSIpLG49W3QuZ2V0KCJ4X3JhbmdlcyIpW3RoaXMuZ2V0KCJ4X3JhbmdlX25hbWUiKV0sdC5nZXQoInlfcmFuZ2VzIilbdGhpcy5nZXQoInlfcmFuZ2VfbmFtZSIpXV0sW25bZV0sbltyXV19LGUucHJvdG90eXBlLmNvbXB1dGVkX2JvdW5kcz1mdW5jdGlvbigpe3ZhciB0LGUscixuLG8saSxzO3JldHVybiBvPXRoaXMucmFuZ2VzKCkscj1vWzBdLHQ9b1sxXSxzPXRoaXMuZ2V0KCJib3VuZHMiKSxuPVtyLmdldCgibWluIiksci5nZXQoIm1heCIpXSxhLmlzQXJyYXkocyk/KGk9TWF0aC5taW4oc1swXSxzWzFdKSxlPU1hdGgubWF4KHNbMF0sc1sxXSksaTxuWzBdP2k9blswXTppPm5bMV0mJihpPW51bGwpLGU+blsxXT9lPW5bMV06ZTxuWzBdJiYoZT1udWxsKSk6KGk9blswXSxlPW5bMV0pLFtpLGVdfSxlLnByb3RvdHlwZS5ncmlkX2Nvb3Jkcz1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdyxNLGssaixUO2ZvcihudWxsPT1lJiYoZT0hMCksaD10aGlzLmdldCgiZGltZW5zaW9uIikscD0oaCsxKSUyLGI9dGhpcy5yYW5nZXMoKSx2PWJbMF0scz1iWzFdLHg9dGhpcy5jb21wdXRlZF9ib3VuZHMoKSxrPXhbMF0sdT14WzFdLFQ9TWF0aC5taW4oayx1KSx1PU1hdGgubWF4KGssdSksaz1ULGo9dGhpcy5nZXQoInRpY2tlciIpLmdldF90aWNrcyhrLHUsdix7fSlbdF0sZz12LmdldCgibWluIiksbT12LmdldCgibWF4Iiksbz1zLmdldCgibWluIiksbj1zLmdldCgibWF4IiksaT1bW10sW11dLGM9Xz0wLHc9ai5sZW5ndGg7MDw9dz9fPHc6Xz53O2M9MDw9dz8rK186LS1fKWlmKGpbY10hPT1nJiZqW2NdIT09bXx8IWUpe2ZvcihhPVtdLGw9W10scj0yLHk9ZD0wLE09cjswPD1NP2Q8TTpkPk07eT0wPD1NPysrZDotLWQpZj1vKyhuLW8pLyhyLTEpKnksYS5wdXNoKGpbY10pLGwucHVzaChmKTtpW2hdLnB1c2goYSksaVtwXS5wdXNoKGwpfXJldHVybiBpfSxlfShpLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm4sVmlldzpvfX0seyIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi9yZW5kZXJlcnMvZ3VpZGVfcmVuZGVyZXIiOiJtb2RlbHMvcmVuZGVyZXJzL2d1aWRlX3JlbmRlcmVyIiwiLi4vcmVuZGVyZXJzL3JlbmRlcmVyIjoibW9kZWxzL3JlbmRlcmVycy9yZW5kZXJlciIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2xheW91dHMvYm94IjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF8sZD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpZi5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxmPXt9Lmhhc093blByb3BlcnR5LG09W10uaW5kZXhPZnx8ZnVuY3Rpb24odCl7Zm9yKHZhciBlPTAscj10aGlzLmxlbmd0aDtlPHI7ZSsrKWlmKGUgaW4gdGhpcyYmdGhpc1tlXT09PXQpcmV0dXJuIGU7cmV0dXJuLTF9O2M9dCgidW5kZXJzY29yZSIpLF89dCgiLi4vLi4vY29yZS9sYXlvdXQvc29sdmVyIiksaT1fLkVRLHM9Xy5HRSxsPV8uU3RyZW5ndGgsdT1fLlZhcmlhYmxlLGg9Xy5XRUFLX0VRLHA9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksYT10KCIuL2xheW91dF9kb20iKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBkKGUsdCksZS5wcm90b3R5cGUuY2xhc3NOYW1lPSJiay1ncmlkIixlLnByb3RvdHlwZS5iaW5kX2Jva2VoX2V2ZW50cz1mdW5jdGlvbigpe3JldHVybiBlLl9fc3VwZXJfXy5iaW5kX2Jva2VoX2V2ZW50cy5jYWxsKHRoaXMpLHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiY2hhbmdlOmNoaWxkcmVuIix0aGlzLmJ1aWxkX2NoaWxkX3ZpZXdzKX0sZS5wcm90b3R5cGUuZ2V0X2hlaWdodD1mdW5jdGlvbigpe3ZhciB0LGUscjtyZXR1cm4gZT10aGlzLm1vZGVsLmdldF9sYXlvdXRhYmxlX2NoaWxkcmVuKCksdD1jLm1hcChlLGZ1bmN0aW9uKHQpe3JldHVybiB0Ll9oZWlnaHQuX3ZhbHVlfSkscj10aGlzLm1vZGVsLl9ob3Jpem9udGFsP2MucmVkdWNlKHQsZnVuY3Rpb24odCxlKXtyZXR1cm4gTWF0aC5tYXgodCxlKX0pOmMucmVkdWNlKHQsZnVuY3Rpb24odCxlKXtyZXR1cm4gdCtlfSl9LGUucHJvdG90eXBlLmdldF93aWR0aD1mdW5jdGlvbigpe3ZhciB0LGUscjtyZXR1cm4gZT10aGlzLm1vZGVsLmdldF9sYXlvdXRhYmxlX2NoaWxkcmVuKCksdD1jLm1hcChlLGZ1bmN0aW9uKHQpe3JldHVybiB0Ll93aWR0aC5fdmFsdWV9KSxyPXRoaXMubW9kZWwuX2hvcml6b250YWw/Yy5yZWR1Y2UodCxmdW5jdGlvbih0LGUpe3JldHVybiB0K2V9KTpjLnJlZHVjZSh0LGZ1bmN0aW9uKHQsZSl7cmV0dXJuIE1hdGgubWF4KHQsZSl9KX0sZX0oYS5WaWV3KSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUodCxyKXtlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5jYWxsKHRoaXMsdCxyKSx0aGlzLl9jaGlsZF9lcXVhbF9zaXplX3dpZHRoPW5ldyB1LHRoaXMuX2NoaWxkX2VxdWFsX3NpemVfaGVpZ2h0PW5ldyB1LHRoaXMuX2JveF9lcXVhbF9zaXplX3RvcD1uZXcgdSx0aGlzLl9ib3hfZXF1YWxfc2l6ZV9ib3R0b209bmV3IHUsdGhpcy5fYm94X2VxdWFsX3NpemVfbGVmdD1uZXcgdSx0aGlzLl9ib3hfZXF1YWxfc2l6ZV9yaWdodD1uZXcgdSx0aGlzLl9ib3hfY2VsbF9hbGlnbl90b3A9bmV3IHUsdGhpcy5fYm94X2NlbGxfYWxpZ25fYm90dG9tPW5ldyB1LHRoaXMuX2JveF9jZWxsX2FsaWduX2xlZnQ9bmV3IHUsdGhpcy5fYm94X2NlbGxfYWxpZ25fcmlnaHQ9bmV3IHV9cmV0dXJuIGQoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9byxlLmRlZmluZSh7Y2hpbGRyZW46W3AuQXJyYXksW11dfSksZS5pbnRlcm5hbCh7c3BhY2luZzpbcC5OdW1iZXIsNl19KSxlLnByb3RvdHlwZS5nZXRfbGF5b3V0YWJsZV9jaGlsZHJlbj1mdW5jdGlvbigpe3JldHVybiB0aGlzLmdldCgiY2hpbGRyZW4iKX0sZS5wcm90b3R5cGUudmFyaWFibGVzX3VwZGF0ZWQ9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbjtmb3Iobj10aGlzLmdldF9sYXlvdXRhYmxlX2NoaWxkcmVuKCksZT0wLHI9bi5sZW5ndGg7ZTxyO2UrKyl0PW5bZV0sdC50cmlnZ2VyKCJjaGFuZ2UiKTtyZXR1cm4gdGhpcy50cmlnZ2VyKCJjaGFuZ2UiKX0sZS5wcm90b3R5cGUuZ2V0X2VkaXRfdmFyaWFibGVzPWZ1bmN0aW9uKCl7dmFyIHQscixuLG8saTtmb3Iocj1lLl9fc3VwZXJfXy5nZXRfZWRpdF92YXJpYWJsZXMuY2FsbCh0aGlzKSxpPXRoaXMuZ2V0X2xheW91dGFibGVfY2hpbGRyZW4oKSxuPTAsbz1pLmxlbmd0aDtuPG87bisrKXQ9aVtuXSxyPXIuY29uY2F0KHQuZ2V0X2VkaXRfdmFyaWFibGVzKCkpO3JldHVybiByfSxlLnByb3RvdHlwZS5nZXRfY29uc3RyYWluZWRfdmFyaWFibGVzPWZ1bmN0aW9uKCl7dmFyIHQ7cmV0dXJuIHQ9ZS5fX3N1cGVyX18uZ2V0X2NvbnN0cmFpbmVkX3ZhcmlhYmxlcy5jYWxsKHRoaXMpLHQ9Yy5leHRlbmQodCx7ImJveC1lcXVhbC1zaXplLXRvcCI6dGhpcy5fYm94X2VxdWFsX3NpemVfdG9wLCJib3gtZXF1YWwtc2l6ZS1ib3R0b20iOnRoaXMuX2JveF9lcXVhbF9zaXplX2JvdHRvbSwiYm94LWVxdWFsLXNpemUtbGVmdCI6dGhpcy5fYm94X2VxdWFsX3NpemVfbGVmdCwiYm94LWVxdWFsLXNpemUtcmlnaHQiOnRoaXMuX2JveF9lcXVhbF9zaXplX3JpZ2h0LCJib3gtY2VsbC1hbGlnbi10b3AiOnRoaXMuX2JveF9jZWxsX2FsaWduX3RvcCwiYm94LWNlbGwtYWxpZ24tYm90dG9tIjp0aGlzLl9ib3hfY2VsbF9hbGlnbl9ib3R0b20sImJveC1jZWxsLWFsaWduLWxlZnQiOnRoaXMuX2JveF9jZWxsX2FsaWduX2xlZnQsImJveC1jZWxsLWFsaWduLXJpZ2h0Ijp0aGlzLl9ib3hfY2VsbF9hbGlnbl9yaWdodH0pfSxlLnByb3RvdHlwZS5nZXRfY29uc3RyYWludHM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGEsbCx1LHAsXyxkLGYsbTtpZihyPVtdLGU9dGhpcy5nZXRfbGF5b3V0YWJsZV9jaGlsZHJlbigpLDA9PT1lLmxlbmd0aClyZXR1cm4gcjtmb3Iobz0wLHU9ZS5sZW5ndGg7bzx1O28rKyl0PWVbb10sdGhpcy5fdGVzdF9sYXlvdXRhYmxlKHQpLG09dC5nZXRfY29uc3RyYWluZWRfdmFyaWFibGVzKCksZj1jLmtleXMobSksXz10aGlzLl9jaGlsZF9yZWN0KG0pLHRoaXMuX2hvcml6b250YWw/dGhpcy5faGFzX3ZhcigiaGVpZ2h0IixmKSYmci5wdXNoKGkoXy5oZWlnaHQsWy0xLHRoaXMuX2hlaWdodF0pKTp0aGlzLl9oYXNfdmFyKCJ3aWR0aCIsZikmJnIucHVzaChpKF8ud2lkdGgsWy0xLHRoaXMuX3dpZHRoXSkpLHRoaXMuX2hvcml6b250YWw/dGhpcy5faGFzX3ZhcihbImJveC1lcXVhbC1zaXplLWxlZnQiLCJib3gtZXF1YWwtc2l6ZS1yaWdodCIsIndpZHRoIl0sZikmJnIucHVzaChpKFstMSxtWyJib3gtZXF1YWwtc2l6ZS1sZWZ0Il1dLFstMSxtWyJib3gtZXF1YWwtc2l6ZS1yaWdodCJdXSxtLndpZHRoLHRoaXMuX2NoaWxkX2VxdWFsX3NpemVfd2lkdGgpKTp0aGlzLl9oYXNfdmFyKFsiYm94LWVxdWFsLXNpemUtdG9wIiwiYm94LWVxdWFsLXNpemUtYm90dG9tIiwiaGVpZ2h0Il0sZikmJnIucHVzaChpKFstMSxtWyJib3gtZXF1YWwtc2l6ZS10b3AiXV0sWy0xLG1bImJveC1lcXVhbC1zaXplLWJvdHRvbSJdXSxtLmhlaWdodCx0aGlzLl9jaGlsZF9lcXVhbF9zaXplX2hlaWdodCkpLHI9ci5jb25jYXQodC5nZXRfY29uc3RyYWludHMoKSk7Zm9yKGw9dGhpcy5faW5mbyhlWzBdLmdldF9jb25zdHJhaW5lZF92YXJpYWJsZXMoKSksci5wdXNoKGkobC5zcGFuLnN0YXJ0LDApKSxuPWE9MSxkPWUubGVuZ3RoOzE8PWQ/YTxkOmE+ZDtuPTE8PWQ/KythOi0tYSlwPXRoaXMuX2luZm8oZVtuXS5nZXRfY29uc3RyYWluZWRfdmFyaWFibGVzKCkpLGwuc3Bhbi5zaXplJiZyLnB1c2goaShsLnNwYW4uc3RhcnQsbC5zcGFuLnNpemUsWy0xLHAuc3Bhbi5zdGFydF0pKSwKci5wdXNoKGgobC53aGl0ZXNwYWNlLmFmdGVyLHAud2hpdGVzcGFjZS5iZWZvcmUsMC10aGlzLnNwYWNpbmcpKSxyLnB1c2gocyhsLndoaXRlc3BhY2UuYWZ0ZXIscC53aGl0ZXNwYWNlLmJlZm9yZSwwLXRoaXMuc3BhY2luZykpLGw9cDtyZXR1cm4gdGhpcy5faG9yaXpvbnRhbD90aGlzLl9oYXNfdmFyKCJ3aWR0aCIsZikmJnIucHVzaChpKGwuc3Bhbi5zdGFydCxsLnNwYW4uc2l6ZSxbLTEsdGhpcy5fd2lkdGhdKSk6dGhpcy5faGFzX3ZhcigiaGVpZ2h0IixmKSYmci5wdXNoKGkobC5zcGFuLnN0YXJ0LGwuc3Bhbi5zaXplLFstMSx0aGlzLl9oZWlnaHRdKSkscj1yLmNvbmNhdCh0aGlzLl9hbGlnbl9vdXRlcl9lZGdlc19jb25zdHJhaW50cyghMCkpLHI9ci5jb25jYXQodGhpcy5fYWxpZ25fb3V0ZXJfZWRnZXNfY29uc3RyYWludHMoITEpKSxyPXIuY29uY2F0KHRoaXMuX2FsaWduX2lubmVyX2NlbGxfZWRnZXNfY29uc3RyYWludHMoKSkscj1yLmNvbmNhdCh0aGlzLl9ib3hfZXF1YWxfc2l6ZV9ib3VuZHMoITApKSxyPXIuY29uY2F0KHRoaXMuX2JveF9lcXVhbF9zaXplX2JvdW5kcyghMSkpLHI9ci5jb25jYXQodGhpcy5fYm94X2NlbGxfYWxpZ25fYm91bmRzKCEwKSkscj1yLmNvbmNhdCh0aGlzLl9ib3hfY2VsbF9hbGlnbl9ib3VuZHMoITEpKSxyPXIuY29uY2F0KHRoaXMuX2JveF93aGl0ZXNwYWNlKCEwKSkscj1yLmNvbmNhdCh0aGlzLl9ib3hfd2hpdGVzcGFjZSghMSkpfSxlLnByb3RvdHlwZS5faGFzX3Zhcj1mdW5jdGlvbih0LGUpe3ZhciByO3JldHVybiByPSJzdHJpbmciPT10eXBlb2YgdD9bdF06dCxjLmV2ZXJ5KHIsZnVuY3Rpb24odCl7cmV0dXJuIG0uY2FsbChlLHQpPj0wfSl9LGUucHJvdG90eXBlLl90ZXN0X2xheW91dGFibGU9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saTtpZihvPVsib3JpZ2luLXgiLCJvcmlnaW4teSIsIndoaXRlc3BhY2UtdG9wIiwid2hpdGVzcGFjZS1yaWdodCIsIndoaXRlc3BhY2UtYm90dG9tIiwid2hpdGVzcGFjZS1sZWZ0Il0sbnVsbD09dC5nZXRfY29uc3RyYWluZWRfdmFyaWFibGVzKXRocm93IG5ldyBFcnJvcih0KyIgaXMgbWlzc2luZyBnZXRfY29uc3RyYWluZWRfdmFyaWFibGVzIG1ldGhvZCIpO2ZvcihpPXQuZ2V0X2NvbnN0cmFpbmVkX3ZhcmlhYmxlcygpLGU9MCxuPW8ubGVuZ3RoO2U8bjtlKyspe2lmKHI9b1tlXSxtLmNhbGwoYy5rZXlzKGkpLHIpPDApdGhyb3cgbmV3IEVycm9yKHQrIiBpcyBtaXNzaW5nIGNvbnN0cmFpbmVkX3ZhcmlhYmxlICIrcik7aWYoIWlbcl1pbnN0YW5jZW9mIHUpdGhyb3cgbmV3IEVycm9yKHQrIiAiK3IrIiBpcyBub3QgYSBzb2x2ZXIgVmFyaWFibGUiKX1yZXR1cm4hMH0sZS5wcm90b3R5cGUuX2NoaWxkX3JlY3Q9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saTtyZXR1cm4gbj10LndpZHRoLGU9dC5oZWlnaHQscj1bdFsib3JpZ2luLXgiXSx0WyJvcmlnaW4teSJdXSxvPXJbMF0saT1yWzFdLHt4Om8seTppLHdpZHRoOm4saGVpZ2h0OmV9fSxlLnByb3RvdHlwZS5fc3Bhbj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5faG9yaXpvbnRhbD97c3RhcnQ6dC54LHNpemU6dC53aWR0aH06e3N0YXJ0OnQueSxzaXplOnQuaGVpZ2h0fX0sZS5wcm90b3R5cGUuX2luZm89ZnVuY3Rpb24odCl7dmFyIGUscjtyZXR1cm4gcj10aGlzLl9ob3Jpem9udGFsP3tiZWZvcmU6dFsid2hpdGVzcGFjZS1sZWZ0Il0sYWZ0ZXI6dFsid2hpdGVzcGFjZS1yaWdodCJdfTp7YmVmb3JlOnRbIndoaXRlc3BhY2UtdG9wIl0sYWZ0ZXI6dFsid2hpdGVzcGFjZS1ib3R0b20iXX0sZT10aGlzLl9zcGFuKHRoaXMuX2NoaWxkX3JlY3QodCkpLHtzcGFuOmUsd2hpdGVzcGFjZTpyfX0sZS5wcm90b3R5cGUuX2ZsYXR0ZW5fY2VsbF9lZGdlX3ZhcmlhYmxlcz1mdW5jdGlvbih0KXt2YXIgcixuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHc7Zm9yKHg9dD9lLl90b3BfYm90dG9tX2lubmVyX2NlbGxfZWRnZV92YXJpYWJsZXM6ZS5fbGVmdF9yaWdodF9pbm5lcl9jZWxsX2VkZ2VfdmFyaWFibGVzLHI9dCE9PXRoaXMuX2hvcml6b250YWwsbD10aGlzLmdldF9sYXlvdXRhYmxlX2NoaWxkcmVuKCksbz1sLmxlbmd0aCxoPXt9LGk9MCxjPTAsZj1sLmxlbmd0aDtjPGY7YysrKXtmb3IoYT1sW2NdLHM9YSBpbnN0YW5jZW9mIGU/YS5fZmxhdHRlbl9jZWxsX2VkZ2VfdmFyaWFibGVzKHQpOnt9LG49YS5nZXRfY29uc3RyYWluZWRfdmFyaWFibGVzKCkscD0wLG09eC5sZW5ndGg7cDxtO3ArKylnPXhbcF0sZyBpbiBuJiYoc1tnXT1bbltnXV0pO2ZvcihfIGluIHMpdz1zW19dLHI/KHY9Xy5zcGxpdCgiICIpLGQ9dlswXSxiPXYubGVuZ3RoPjE/dlsxXToiIix1PXRoaXMuX2hvcml6b250YWw/InJvdyI6ImNvbCIseT1kKyIgIit1KyItIitvKyItIitpKyItIitiKTp5PV8seSBpbiBoP2hbeV09aFt5XS5jb25jYXQodyk6aFt5XT13O2krPTF9cmV0dXJuIGh9LGUucHJvdG90eXBlLl9hbGlnbl9pbm5lcl9jZWxsX2VkZ2VzX2NvbnN0cmFpbnRzPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxzLGEsbDtpZih0PVtdLHRoaXMuX2lzX3Jvb3Qpe2U9dGhpcy5fZmxhdHRlbl9jZWxsX2VkZ2VfdmFyaWFibGVzKHRoaXMuX2hvcml6b250YWwpO2ZvcihvIGluIGUpaWYobD1lW29dLGwubGVuZ3RoPjEpZm9yKHM9bFswXSxyPW49MSxhPWwubGVuZ3RoOzE8PWE/bjxhOm4+YTtyPTE8PWE/KytuOi0tbil0LnB1c2goaShsW3JdLFstMSxzXSkpfXJldHVybiB0fSxlLnByb3RvdHlwZS5fZmluZF9lZGdlX2xlYXZlcz1mdW5jdGlvbih0KXt2YXIgcixuLG8saSxzLGEsbCx1O2lmKG89dGhpcy5nZXRfbGF5b3V0YWJsZV9jaGlsZHJlbigpLGE9W1tdLFtdXSxvLmxlbmd0aD4wKWlmKHRoaXMuX2hvcml6b250YWw9PT10KXU9b1swXSxpPW9bby5sZW5ndGgtMV0sdSBpbnN0YW5jZW9mIGU/YVswXT1hWzBdLmNvbmNhdCh1Ll9maW5kX2VkZ2VfbGVhdmVzKHQpWzBdKTphWzBdLnB1c2godSksaSBpbnN0YW5jZW9mIGU/YVsxXT1hWzFdLmNvbmNhdChpLl9maW5kX2VkZ2VfbGVhdmVzKHQpWzFdKTphWzFdLnB1c2goaSk7ZWxzZSBmb3Iocz0wLGw9by5sZW5ndGg7czxsO3MrKylyPW9bc10sciBpbnN0YW5jZW9mIGU/KG49ci5fZmluZF9lZGdlX2xlYXZlcyh0KSxhWzBdPWFbMF0uY29uY2F0KG5bMF0pLGFbMV09YVsxXS5jb25jYXQoblsxXSkpOihhWzBdLnB1c2gociksYVsxXS5wdXNoKHIpKTtyZXR1cm4gYX0sZS5wcm90b3R5cGUuX2FsaWduX291dGVyX2VkZ2VzX2NvbnN0cmFpbnRzPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLHMsYSxsLHUsaCxjO3JldHVybiBhPXRoaXMuX2ZpbmRfZWRnZV9sZWF2ZXModCksaD1hWzBdLG89YVsxXSx0PyhjPSJvbi1lZGdlLWFsaWduLWxlZnQiLHM9Im9uLWVkZ2UtYWxpZ24tcmlnaHQiKTooYz0ib24tZWRnZS1hbGlnbi10b3AiLHM9Im9uLWVkZ2UtYWxpZ24tYm90dG9tIikscj1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpLHM7Zm9yKHI9W10sbj0wLGk9dC5sZW5ndGg7bjxpO24rKylvPXRbbl0scz1vLmdldF9jb25zdHJhaW5lZF92YXJpYWJsZXMoKSxlIGluIHMmJnIucHVzaChzW2VdKTtyZXR1cm4gcn0sdT1yKGgsYyksbj1yKG8scyksbD1bXSxlPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLHM7aWYodC5sZW5ndGg+MSl7Zm9yKHI9dFswXSxuPW89MSxzPXQubGVuZ3RoOzE8PXM/bzxzOm8+cztuPTE8PXM/KytvOi0tbyllPXRbbl0sbC5wdXNoKGkoWy0xLHJdLGUpKTtyZXR1cm4gbnVsbH19LGUodSksZShuKSxsfSxlLnByb3RvdHlwZS5fYm94X2luc2V0c19mcm9tX2NoaWxkX2luc2V0cz1mdW5jdGlvbih0LGUscixuKXt2YXIgbyxhLGwsdSxoLGMscCxfLGQ7cmV0dXJuIGM9dGhpcy5fZmluZF9lZGdlX2xlYXZlcyh0KSxfPWNbMF0sYT1jWzFdLHQ/KGQ9ZSsiLWxlZnQiLGw9ZSsiLXJpZ2h0IixoPXRoaXNbcisiX2xlZnQiXSx1PXRoaXNbcisiX3JpZ2h0Il0pOihkPWUrIi10b3AiLGw9ZSsiLWJvdHRvbSIsaD10aGlzW3IrIl90b3AiXSx1PXRoaXNbcisiX2JvdHRvbSJdKSxwPVtdLG89ZnVuY3Rpb24odCxlLHIpe3ZhciBvLGEsbCx1LGg7Zm9yKG89W10sYT0wLHU9ZS5sZW5ndGg7YTx1O2ErKylsPWVbYV0saD1sLmdldF9jb25zdHJhaW5lZF92YXJpYWJsZXMoKSxyIGluIGgmJihuP3AucHVzaChzKFstMSx0XSxoW3JdKSk6cC5wdXNoKGkoWy0xLHRdLGhbcl0pKSk7cmV0dXJuIG51bGx9LG8oaCxfLGQpLG8odSxhLGwpLHB9LGUucHJvdG90eXBlLl9ib3hfZXF1YWxfc2l6ZV9ib3VuZHM9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2JveF9pbnNldHNfZnJvbV9jaGlsZF9pbnNldHModCwiYm94LWVxdWFsLXNpemUiLCJfYm94X2VxdWFsX3NpemUiLCExKX0sZS5wcm90b3R5cGUuX2JveF9jZWxsX2FsaWduX2JvdW5kcz1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fYm94X2luc2V0c19mcm9tX2NoaWxkX2luc2V0cyh0LCJib3gtY2VsbC1hbGlnbiIsIl9ib3hfY2VsbF9hbGlnbiIsITEpfSxlLnByb3RvdHlwZS5fYm94X3doaXRlc3BhY2U9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2JveF9pbnNldHNfZnJvbV9jaGlsZF9pbnNldHModCwid2hpdGVzcGFjZSIsIl93aGl0ZXNwYWNlIiwhMCl9LGUuX2xlZnRfcmlnaHRfaW5uZXJfY2VsbF9lZGdlX3ZhcmlhYmxlcz1bImJveC1jZWxsLWFsaWduLWxlZnQiLCJib3gtY2VsbC1hbGlnbi1yaWdodCJdLGUuX3RvcF9ib3R0b21faW5uZXJfY2VsbF9lZGdlX3ZhcmlhYmxlcz1bImJveC1jZWxsLWFsaWduLXRvcCIsImJveC1jZWxsLWFsaWduLWJvdHRvbSJdLGV9KGEuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bixWaWV3Om99fSx7Ii4uLy4uL2NvcmUvbGF5b3V0L3NvbHZlciI6ImNvcmUvbGF5b3V0L3NvbHZlciIsIi4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vbGF5b3V0X2RvbSI6Im1vZGVscy9sYXlvdXRzL2xheW91dF9kb20iLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9sYXlvdXRzL2NvbHVtbiI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscz1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxhPXt9Lmhhc093blByb3BlcnR5O249dCgiLi9ib3giKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBzKGUsdCksZS5wcm90b3R5cGUuY2xhc3NOYW1lPSJiay1ncmlkLWNvbHVtbiIsZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUodCxyKXtlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5jYWxsKHRoaXMsdCxyKSx0aGlzLl9ob3Jpem9udGFsPSExfXJldHVybiBzKGUsdCksZS5wcm90b3R5cGUudHlwZT0iQ29sdW1uIixlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e1ZpZXc6aSxNb2RlbDpvfX0seyIuL2JveCI6Im1vZGVscy9sYXlvdXRzL2JveCJ9XSwibW9kZWxzL2xheW91dHMvbGF5b3V0X2RvbSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGc9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXkuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0seT17fS5oYXNPd25Qcm9wZXJ0eTtwPXQoInVuZGVyc2NvcmUiKSxuPXQoImpxdWVyeSIpLHU9dCgiLi4vLi4vbW9kZWwiKSxmPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG09dCgiLi4vLi4vY29yZS9sYXlvdXQvc29sdmVyIikscz1tLkdFLGk9bS5FUSxoPW0uU3RyZW5ndGgsYz1tLlZhcmlhYmxlLF89dCgiLi4vLi4vY29tbW9uL2J1aWxkX3ZpZXdzIiksbz10KCIuLi8uLi9jb3JlL2Jva2VoX3ZpZXciKSxkPXQoIi4uLy4uL2NvcmUvbG9nZ2luZyIpLmxvZ2dlcixsPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBnKGUsdCksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy4kZWwuYXR0cigiaWQiLCJtb2RlbGlkXyIrdGhpcy5tb2RlbC5pZCksdGhpcy4kZWwuYWRkQ2xhc3MoImJrLWxheW91dC0iK3RoaXMubW9kZWwuc2l6aW5nX21vZGUpLHRoaXMuY2hpbGRfdmlld3M9e30sdGhpcy5idWlsZF9jaGlsZF92aWV3cyghMSl9LGUucHJvdG90eXBlLmJ1aWxkX2NoaWxkX3ZpZXdzPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGk7Zm9yKG51bGw9PXQmJih0PSEwKSx0aGlzLnVuYmluZF9ib2tlaF9ldmVudHMoKSx0JiYodGhpcy5tb2RlbC5kb2N1bWVudC5faW52YWxpZGF0ZV9hbGxfbW9kZWxzKCksdGhpcy5tb2RlbC5kb2N1bWVudC5faW5pdF9zb2x2ZXIoKSksbj10aGlzLm1vZGVsLmdldF9sYXlvdXRhYmxlX2NoaWxkcmVuKCksdGhpcy5jaGlsZF92aWV3cz17fSxfKHRoaXMuY2hpbGRfdmlld3MsbiksdGhpcy4kZWwuZW1wdHkoKSxvPTAsaT1uLmxlbmd0aDtvPGk7bysrKWU9bltvXSxyPXRoaXMuY2hpbGRfdmlld3NbZS5pZF0sdGhpcy4kZWwuYXBwZW5kKHIuJGVsKTtyZXR1cm4gdGhpcy5iaW5kX2Jva2VoX2V2ZW50cygpfSxlLnByb3RvdHlwZS51bmJpbmRfYm9rZWhfZXZlbnRzPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47dGhpcy5zdG9wTGlzdGVuaW5nKCksZT10aGlzLmNoaWxkX3ZpZXdzLHI9W107Zm9yKHQgaW4gZSluPWVbdF0sbi5zdG9wTGlzdGVuaW5nKCksci5wdXNoKCJmdW5jdGlvbiI9PXR5cGVvZiBuLnVuYmluZF9ib2tlaF9ldmVudHM/bi51bmJpbmRfYm9rZWhfZXZlbnRzKCk6dm9pZCAwKTtyZXR1cm4gcn0sZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gdGhpcy5saXN0ZW5Ubyh0aGlzLm1vZGVsLCJjaGFuZ2UiLHRoaXMucmVuZGVyKSwiZml4ZWQiPT09dGhpcy5tb2RlbC5zaXppbmdfbW9kZT90aGlzLmxpc3RlblRvT25jZSh0aGlzLm1vZGVsLmRvY3VtZW50LnNvbHZlcigpLCJyZXNpemUiLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiB0LnJlbmRlcigpfX0odGhpcykpOnRoaXMubGlzdGVuVG8odGhpcy5tb2RlbC5kb2N1bWVudC5zb2x2ZXIoKSwicmVzaXplIixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdC5yZW5kZXIoKX19KHRoaXMpKSx0PSJDaGFuZ2luZyBzaXppbmdfbW9kZSBhZnRlciBpbml0aWFsaXphdGlvbiBpcyBub3QgY3VycmVudGx5IHN1cHBvcnRlZC4iLHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiY2hhbmdlOnNpemluZ19tb2RlIixmdW5jdGlvbigpe3JldHVybiBkLndhcm4odCl9KX0sZS5wcm90b3R5cGUucmVuZGVyPWZ1bmN0aW9uKCl7dmFyIHQsZSxyO2lmKGU9dGhpcy5tb2RlbC5kb2N1bWVudC5zb2x2ZXIoKSwiZml4ZWQiPT09dGhpcy5tb2RlbC5zaXppbmdfbW9kZSYmKG51bGwhPXRoaXMubW9kZWwud2lkdGg/cj10aGlzLm1vZGVsLndpZHRoOihyPXRoaXMuZ2V0X3dpZHRoKCksdGhpcy5tb2RlbC53aWR0aD1yKSxudWxsIT10aGlzLm1vZGVsLmhlaWdodD90PXRoaXMubW9kZWwuaGVpZ2h0Oih0PXRoaXMuZ2V0X2hlaWdodCgpLHRoaXMubW9kZWwuaGVpZ2h0PXQpLGUuc3VnZ2VzdF92YWx1ZSh0aGlzLm1vZGVsLl93aWR0aCxyKSxlLnN1Z2dlc3RfdmFsdWUodGhpcy5tb2RlbC5faGVpZ2h0LHQpLGUudXBkYXRlX3ZhcmlhYmxlcygpLHRoaXMuJGVsLmNzcyh7d2lkdGg6cixoZWlnaHQ6dH0pKSwic2NhbGVfd2lkdGgiPT09dGhpcy5tb2RlbC5zaXppbmdfbW9kZSYmKHQ9dGhpcy5nZXRfaGVpZ2h0KCksZS5zdWdnZXN0X3ZhbHVlKHRoaXMubW9kZWwuX2hlaWdodCx0KSxlLnVwZGF0ZV92YXJpYWJsZXMoKSx0aGlzLiRlbC5jc3Moe3dpZHRoOnRoaXMubW9kZWwuX3dpZHRoLl92YWx1ZSxoZWlnaHQ6dGhpcy5tb2RlbC5faGVpZ2h0Ll92YWx1ZX0pKSwic2NhbGVfaGVpZ2h0Ij09PXRoaXMubW9kZWwuc2l6aW5nX21vZGUmJihyPXRoaXMuZ2V0X3dpZHRoKCksZS5zdWdnZXN0X3ZhbHVlKHRoaXMubW9kZWwuX3dpZHRoLHIpLGUudXBkYXRlX3ZhcmlhYmxlcygpLHRoaXMuJGVsLmNzcyh7d2lkdGg6dGhpcy5tb2RlbC5fd2lkdGguX3ZhbHVlLGhlaWdodDp0aGlzLm1vZGVsLl9oZWlnaHQuX3ZhbHVlfSkpLCJzdHJldGNoX2JvdGgiPT09dGhpcy5tb2RlbC5zaXppbmdfbW9kZSlyZXR1cm4gdGhpcy4kZWwuY3NzKHtwb3NpdGlvbjoiYWJzb2x1dGUiLGxlZnQ6dGhpcy5tb2RlbC5fZG9tX2xlZnQuX3ZhbHVlLHRvcDp0aGlzLm1vZGVsLl9kb21fdG9wLl92YWx1ZSx3aWR0aDp0aGlzLm1vZGVsLl93aWR0aC5fdmFsdWUsaGVpZ2h0OnRoaXMubW9kZWwuX2hlaWdodC5fdmFsdWV9KX0sZS5wcm90b3R5cGUuZ2V0X2hlaWdodD1mdW5jdGlvbigpe3JldHVybiBudWxsfSxlLnByb3RvdHlwZS5nZXRfd2lkdGg9ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbH0sZX0obyksYT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gZyhlLHQpLGUucHJvdG90eXBlLnR5cGU9IkxheW91dERPTSIsZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0LHIpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0LHIpLHRoaXMuX3dpZHRoPW5ldyBjKCJfd2lkdGggIit0aGlzLmlkKSx0aGlzLl9oZWlnaHQ9bmV3IGMoIl9oZWlnaHQgIit0aGlzLmlkKSx0aGlzLl9sZWZ0PW5ldyBjKCJfbGVmdCAiK3RoaXMuaWQpLHRoaXMuX3JpZ2h0PW5ldyBjKCJfcmlnaHQgIit0aGlzLmlkKSx0aGlzLl90b3A9bmV3IGMoIl90b3AgIit0aGlzLmlkKSx0aGlzLl9ib3R0b209bmV3IGMoIl9ib3R0b20gIit0aGlzLmlkKSx0aGlzLl9kb21fdG9wPW5ldyBjKCJfZG9tX3RvcCAiK3RoaXMuaWQpLHRoaXMuX2RvbV9sZWZ0PW5ldyBjKCJfZG9tX2xlZnQgIit0aGlzLmlkKSx0aGlzLl93aWR0aF9taW51c19yaWdodD1uZXcgYygiX3dpZHRoX21pbnVzX3JpZ2h0ICIrdGhpcy5pZCksdGhpcy5faGVpZ2h0X21pbnVzX2JvdHRvbT1uZXcgYygiX2hlaWdodF9taW51c19ib3R0b20gIit0aGlzLmlkKSx0aGlzLl93aGl0ZXNwYWNlX3RvcD1uZXcgYyx0aGlzLl93aGl0ZXNwYWNlX2JvdHRvbT1uZXcgYyx0aGlzLl93aGl0ZXNwYWNlX2xlZnQ9bmV3IGMsdGhpcy5fd2hpdGVzcGFjZV9yaWdodD1uZXcgY30sZS5wcm90b3R5cGUuZ2V0X2NvbnN0cmFpbnRzPWZ1bmN0aW9uKCl7dmFyIHQ7cmV0dXJuIHQ9W10sdC5wdXNoKHModGhpcy5fZG9tX2xlZnQpKSx0LnB1c2gocyh0aGlzLl9kb21fdG9wKSksdC5wdXNoKHModGhpcy5fbGVmdCkpLHQucHVzaChzKHRoaXMuX3dpZHRoLFstMSx0aGlzLl9yaWdodF0pKSx0LnB1c2gocyh0aGlzLl90b3ApKSx0LnB1c2gocyh0aGlzLl9oZWlnaHQsWy0xLHRoaXMuX2JvdHRvbV0pKSx0LnB1c2goaSh0aGlzLl93aWR0aF9taW51c19yaWdodCxbLTEsdGhpcy5fd2lkdGhdLHRoaXMuX3JpZ2h0KSksdC5wdXNoKGkodGhpcy5faGVpZ2h0X21pbnVzX2JvdHRvbSxbLTEsdGhpcy5faGVpZ2h0XSx0aGlzLl9ib3R0b20pKSx0fSxlLnByb3RvdHlwZS5nZXRfbGF5b3V0YWJsZV9jaGlsZHJlbj1mdW5jdGlvbigpe3JldHVybltdfSxlLnByb3RvdHlwZS5nZXRfZWRpdF92YXJpYWJsZXM9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gdD1bXSwiZml4ZWQiPT09dGhpcy5zaXppbmdfbW9kZSYmKHQucHVzaCh7ZWRpdF92YXJpYWJsZTp0aGlzLl9oZWlnaHQsc3RyZW5ndGg6aC5zdHJvbmd9KSx0LnB1c2goe2VkaXRfdmFyaWFibGU6dGhpcy5fd2lkdGgsc3RyZW5ndGg6aC5zdHJvbmd9KSksInNjYWxlX3dpZHRoIj09PXRoaXMuc2l6aW5nX21vZGUmJnQucHVzaCh7ZWRpdF92YXJpYWJsZTp0aGlzLl9oZWlnaHQsc3RyZW5ndGg6aC5zdHJvbmd9KSwic2NhbGVfaGVpZ2h0Ij09PXRoaXMuc2l6aW5nX21vZGUmJnQucHVzaCh7ZWRpdF92YXJpYWJsZTp0aGlzLl93aWR0aCxzdHJlbmd0aDpoLnN0cm9uZ30pLHR9LGUucHJvdG90eXBlLmdldF9jb25zdHJhaW5lZF92YXJpYWJsZXM9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gdD17Im9yaWdpbi14Ijp0aGlzLl9kb21fbGVmdCwib3JpZ2luLXkiOnRoaXMuX2RvbV90b3AsIndoaXRlc3BhY2UtdG9wIjp0aGlzLl93aGl0ZXNwYWNlX3RvcCwid2hpdGVzcGFjZS1ib3R0b20iOnRoaXMuX3doaXRlc3BhY2VfYm90dG9tLCJ3aGl0ZXNwYWNlLWxlZnQiOnRoaXMuX3doaXRlc3BhY2VfbGVmdCwid2hpdGVzcGFjZS1yaWdodCI6dGhpcy5fd2hpdGVzcGFjZV9yaWdodH0sInN0cmV0Y2hfYm90aCI9PT10aGlzLnNpemluZ19tb2RlJiYodD1wLmV4dGVuZCh0LHt3aWR0aDp0aGlzLl93aWR0aCxoZWlnaHQ6dGhpcy5faGVpZ2h0fSkpLCJzY2FsZV93aWR0aCI9PT10aGlzLnNpemluZ19tb2RlJiYodD1wLmV4dGVuZCh0LHt3aWR0aDp0aGlzLl93aWR0aH0pKSwic2NhbGVfaGVpZ2h0Ij09PXRoaXMuc2l6aW5nX21vZGUmJih0PXAuZXh0ZW5kKHQse2hlaWdodDp0aGlzLl9oZWlnaHR9KSksdH0sZS5kZWZpbmUoe2hlaWdodDpbZi5OdW1iZXJdLHdpZHRoOltmLk51bWJlcl0sZGlzYWJsZWQ6W2YuQm9vbCwhMV0sc2l6aW5nX21vZGU6W2YuU2l6aW5nTW9kZSwiZml4ZWQiXX0pLGUuaW50ZXJuYWwoe2xheW91dGFibGU6W2YuQm9vbCwhMF19KSxlfSh1KSxlLmV4cG9ydHM9e01vZGVsOmEsVmlldzpsfX0seyIuLi8uLi9jb21tb24vYnVpbGRfdmlld3MiOiJjb21tb24vYnVpbGRfdmlld3MiLCIuLi8uLi9jb3JlL2Jva2VoX3ZpZXciOiJjb3JlL2Jva2VoX3ZpZXciLCIuLi8uLi9jb3JlL2xheW91dC9zb2x2ZXIiOiJjb3JlL2xheW91dC9zb2x2ZXIiLCIuLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi9tb2RlbCI6Im1vZGVsIixqcXVlcnk6ImpxdWVyeSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2xheW91dHMvcm93IjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlhLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGE9e30uaGFzT3duUHJvcGVydHk7bj10KCIuL2JveCIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHMoZSx0KSxlLnByb3RvdHlwZS5jbGFzc05hbWU9ImJrLWdyaWQtcm93IixlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSh0LHIpe2UuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmNhbGwodGhpcyx0LHIpLHRoaXMuX2hvcml6b250YWw9ITB9cmV0dXJuIHMoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJSb3ciLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17VmlldzppLE1vZGVsOm99fSx7Ii4vYm94IjoibW9kZWxzL2xheW91dHMvYm94In1dLCJtb2RlbHMvbGF5b3V0cy9zcGFjZXIiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpbC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxsPXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLG49dCgiLi9sYXlvdXRfZG9tIiksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gYShlLHQpLGUucHJvdG90eXBlLmNsYXNzTmFtZT0iYmstc3BhY2VyLWJveCIsZS5wcm90b3R5cGUucmVuZGVyPWZ1bmN0aW9uKCl7aWYoZS5fX3N1cGVyX18ucmVuZGVyLmNhbGwodGhpcyksImZpeGVkIj09PXRoaXMuc2l6aW5nX21vZGUpcmV0dXJuIHRoaXMuJGVsLmNzcyh7d2lkdGg6dGhpcy5tb2RlbC53aWR0aCxoZWlnaHQ6dGhpcy5tb2RlbC5oZWlnaHR9KX0sZS5wcm90b3R5cGUuZ2V0X2hlaWdodD1mdW5jdGlvbigpe3JldHVybiAxfSxlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGEoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJTcGFjZXIiLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLmdldF9jb25zdHJhaW5lZF92YXJpYWJsZXM9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gdD1lLl9fc3VwZXJfXy5nZXRfY29uc3RyYWluZWRfdmFyaWFibGVzLmNhbGwodGhpcyksdD1zLmV4dGVuZCh0LHsib24tZWRnZS1hbGlnbi10b3AiOnRoaXMuX3RvcCwib24tZWRnZS1hbGlnbi1ib3R0b20iOnRoaXMuX2hlaWdodF9taW51c19ib3R0b20sIm9uLWVkZ2UtYWxpZ24tbGVmdCI6dGhpcy5fbGVmdCwib24tZWRnZS1hbGlnbi1yaWdodCI6dGhpcy5fd2lkdGhfbWludXNfcmlnaHQsImJveC1jZWxsLWFsaWduLXRvcCI6dGhpcy5fdG9wLCJib3gtY2VsbC1hbGlnbi1ib3R0b20iOnRoaXMuX2hlaWdodF9taW51c19ib3R0b20sImJveC1jZWxsLWFsaWduLWxlZnQiOnRoaXMuX2xlZnQsImJveC1jZWxsLWFsaWduLXJpZ2h0Ijp0aGlzLl93aWR0aF9taW51c19yaWdodCwiYm94LWVxdWFsLXNpemUtdG9wIjp0aGlzLl90b3AsImJveC1lcXVhbC1zaXplLWJvdHRvbSI6dGhpcy5faGVpZ2h0X21pbnVzX2JvdHRvbSwiYm94LWVxdWFsLXNpemUtbGVmdCI6dGhpcy5fbGVmdCwiYm94LWVxdWFsLXNpemUtcmlnaHQiOnRoaXMuX3dpZHRoX21pbnVzX3JpZ2h0fSl9LGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi9sYXlvdXRfZG9tIjoibW9kZWxzL2xheW91dHMvbGF5b3V0X2RvbSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL2xheW91dHMvd2lkZ2V0X2JveCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpdi5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSx2PXt9Lmhhc093blByb3BlcnR5O189dCgidW5kZXJzY29yZSIpLG49dCgianF1ZXJ5IiksZD10KCIuLi8uLi9jb21tb24vYnVpbGRfdmlld3MiKSxvPXQoIi4uLy4uL2NvcmUvYm9rZWhfdmlldyIpLGc9dCgiLi4vLi4vY29yZS9sYXlvdXQvc29sdmVyIiksaD1nLldFQUtfRVEscz1nLkdFLGk9Zy5FUSxsPWcuU3RyZW5ndGgsdT1nLlZhcmlhYmxlLGY9dCgiLi4vLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLG09dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksYT10KCIuLi9sYXlvdXRzL2xheW91dF9kb20iKSxwPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB5KGUsdCksZS5wcm90b3R5cGUuY2xhc3NOYW1lPSJiay13aWRnZXQtYm94IixlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0KSx0aGlzLnJlbmRlcigpfSxlLnByb3RvdHlwZS5iaW5kX2Jva2VoX2V2ZW50cz1mdW5jdGlvbigpe3JldHVybiBlLl9fc3VwZXJfXy5iaW5kX2Jva2VoX2V2ZW50cy5jYWxsKHRoaXMpLHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiY2hhbmdlOmNoaWxkcmVuIixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdC5idWlsZF9jaGlsZF92aWV3cygpfX0odGhpcykpfSxlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbjtyZXR1cm4gcj10aGlzLm1vZGVsLmRvY3VtZW50LnNvbHZlcigpLCJmaXhlZCIhPT10aGlzLm1vZGVsLnNpemluZ19tb2RlJiYic2NhbGVfaGVpZ2h0IiE9PXRoaXMubW9kZWwuc2l6aW5nX21vZGV8fChuPXRoaXMuZ2V0X3dpZHRoKCksdGhpcy5tb2RlbC5fd2lkdGguX3ZhbHVlIT09biYmKHIuc3VnZ2VzdF92YWx1ZSh0aGlzLm1vZGVsLl93aWR0aCxuKSxyLnVwZGF0ZV92YXJpYWJsZXMoKSkpLCJmaXhlZCIhPT10aGlzLm1vZGVsLnNpemluZ19tb2RlJiYic2NhbGVfd2lkdGgiIT09dGhpcy5tb2RlbC5zaXppbmdfbW9kZXx8KGU9dGhpcy5nZXRfaGVpZ2h0KCksdGhpcy5tb2RlbC5faGVpZ2h0Ll92YWx1ZSE9PWUmJihyLnN1Z2dlc3RfdmFsdWUodGhpcy5tb2RlbC5faGVpZ2h0LGUpLHIudXBkYXRlX3ZhcmlhYmxlcygpKSksdD10aGlzLm1vZGVsLl93aWR0aC5fdmFsdWUtMjA+MD90aGlzLm1vZGVsLl93aWR0aC5fdmFsdWUtMjA6IjEwMCUiLCJzdHJldGNoX2JvdGgiPT09dGhpcy5tb2RlbC5zaXppbmdfbW9kZT90aGlzLiRlbC5jc3Moe3Bvc2l0aW9uOiJhYnNvbHV0ZSIsbGVmdDp0aGlzLm1vZGVsLl9kb21fbGVmdC5fdmFsdWUsdG9wOnRoaXMubW9kZWwuX2RvbV90b3AuX3ZhbHVlLHdpZHRoOnRoaXMubW9kZWwuX3dpZHRoLl92YWx1ZSxoZWlnaHQ6dGhpcy5tb2RlbC5faGVpZ2h0Ll92YWx1ZX0pOnRoaXMuJGVsLmNzcyh7d2lkdGg6dH0pfSxlLnByb3RvdHlwZS5nZXRfaGVpZ2h0PWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47ZT0wLG49dGhpcy5jaGlsZF92aWV3cztmb3IociBpbiBuKXYuY2FsbChuLHIpJiYodD1uW3JdLGUrPXQuZWwuc2Nyb2xsSGVpZ2h0KTtyZXR1cm4gZSsyMH0sZS5wcm90b3R5cGUuZ2V0X3dpZHRoPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbztpZihudWxsIT10aGlzLm1vZGVsLndpZHRoKXJldHVybiB0aGlzLm1vZGVsLndpZHRoO289dGhpcy5lbC5zY3JvbGxXaWR0aCsyMCxuPXRoaXMuY2hpbGRfdmlld3M7Zm9yKHIgaW4gbil2LmNhbGwobixyKSYmKHQ9bltyXSxlPXQuZWwuc2Nyb2xsV2lkdGgsZT5vJiYobz1lKSk7cmV0dXJuIG99LGV9KGEuVmlldyksYz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4geShlLHQpLGUucHJvdG90eXBlLnR5cGU9IldpZGdldEJveCIsZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PXAsZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtpZihlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0KSwiZml4ZWQiPT09dGhpcy5zaXppbmdfbW9kZSYmbnVsbD09PXRoaXMud2lkdGgmJih0aGlzLndpZHRoPTMwMCxmLmluZm8oIldpZGdldEJveCBtb2RlIGlzIGZpeGVkLCBidXQgbm8gd2lkdGggc3BlY2lmaWVkLiBVc2luZyBkZWZhdWx0IG9mIDMwMC4iKSksInNjYWxlX2hlaWdodCI9PT10aGlzLnNpemluZ19tb2RlKXJldHVybiBmLndhcm4oInNpemluZ19tb2RlIGBzY2FsZV9oZWlnaHRgIGlzIG5vdCBleHBlcmltZW50YWwgZm9yIFdpZGdldEJveC4gUGxlYXNlIHJlcG9ydCB5b3VyIHJlc3VsdHMgdG8gdGhlIGJva2VoIGRldiB0ZWFtIHNvIHdlIGNhbiBpbXByb3ZlLiIpfSxlLnByb3RvdHlwZS5nZXRfZWRpdF92YXJpYWJsZXM9ZnVuY3Rpb24oKXt2YXIgdCxyLG4sbyxpO2ZvcihyPWUuX19zdXBlcl9fLmdldF9lZGl0X3ZhcmlhYmxlcy5jYWxsKHRoaXMpLGk9dGhpcy5nZXRfbGF5b3V0YWJsZV9jaGlsZHJlbigpLG49MCxvPWkubGVuZ3RoO248bztuKyspdD1pW25dLHI9ci5jb25jYXQodC5nZXRfZWRpdF92YXJpYWJsZXMoKSk7cmV0dXJuIHJ9LGUucHJvdG90eXBlLmdldF9jb25zdHJhaW50cz1mdW5jdGlvbigpe3ZhciB0LHIsbixvLGk7Zm9yKHI9ZS5fX3N1cGVyX18uZ2V0X2NvbnN0cmFpbnRzLmNhbGwodGhpcyksaT10aGlzLmdldF9sYXlvdXRhYmxlX2NoaWxkcmVuKCksbj0wLG89aS5sZW5ndGg7bjxvO24rKyl0PWlbbl0scj1yLmNvbmNhdCh0LmdldF9jb25zdHJhaW50cygpKTtyZXR1cm4gcn0sZS5wcm90b3R5cGUuZ2V0X2NvbnN0cmFpbmVkX3ZhcmlhYmxlcz1mdW5jdGlvbigpe3ZhciB0O3JldHVybiB0PWUuX19zdXBlcl9fLmdldF9jb25zdHJhaW5lZF92YXJpYWJsZXMuY2FsbCh0aGlzKSx0PV8uZXh0ZW5kKHQseyJvbi1lZGdlLWFsaWduLXRvcCI6dGhpcy5fdG9wLCJvbi1lZGdlLWFsaWduLWJvdHRvbSI6dGhpcy5faGVpZ2h0X21pbnVzX2JvdHRvbSwib24tZWRnZS1hbGlnbi1sZWZ0Ijp0aGlzLl9sZWZ0LCJvbi1lZGdlLWFsaWduLXJpZ2h0Ijp0aGlzLl93aWR0aF9taW51c19yaWdodCwiYm94LWNlbGwtYWxpZ24tdG9wIjp0aGlzLl90b3AsImJveC1jZWxsLWFsaWduLWJvdHRvbSI6dGhpcy5faGVpZ2h0X21pbnVzX2JvdHRvbSwiYm94LWNlbGwtYWxpZ24tbGVmdCI6dGhpcy5fbGVmdCwiYm94LWNlbGwtYWxpZ24tcmlnaHQiOnRoaXMuX3dpZHRoX21pbnVzX3JpZ2h0LCJib3gtZXF1YWwtc2l6ZS10b3AiOnRoaXMuX3RvcCwiYm94LWVxdWFsLXNpemUtYm90dG9tIjp0aGlzLl9oZWlnaHRfbWludXNfYm90dG9tfSksImZpeGVkIiE9PXRoaXMuc2l6aW5nX21vZGUmJih0PV8uZXh0ZW5kKHQseyJib3gtZXF1YWwtc2l6ZS1sZWZ0Ijp0aGlzLl9sZWZ0LCJib3gtZXF1YWwtc2l6ZS1yaWdodCI6dGhpcy5fd2lkdGhfbWludXNfcmlnaHR9KSksdH0sZS5wcm90b3R5cGUuZ2V0X2xheW91dGFibGVfY2hpbGRyZW49ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jaGlsZHJlbn0sZS5kZWZpbmUoe2NoaWxkcmVuOlttLkFycmF5LFtdXX0pLGV9KGEuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6Y319LHsiLi4vLi4vY29tbW9uL2J1aWxkX3ZpZXdzIjoiY29tbW9uL2J1aWxkX3ZpZXdzIiwiLi4vLi4vY29yZS9ib2tlaF92aWV3IjoiY29yZS9ib2tlaF92aWV3IiwiLi4vLi4vY29yZS9sYXlvdXQvc29sdmVyIjoiY29yZS9sYXlvdXQvc29sdmVyIiwiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vbGF5b3V0cy9sYXlvdXRfZG9tIjoibW9kZWxzL2xheW91dHMvbGF5b3V0X2RvbSIsanF1ZXJ5OiJqcXVlcnkiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9tYXBwZXJzL2NhdGVnb3JpY2FsX21hcHBlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscz1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxhPXt9Lmhhc093blByb3BlcnR5O2k9dCgidW5kZXJzY29yZSIpLG89dCgiLi9saW5lYXJfbWFwcGVyIiksbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gcyhlLHQpLGUucHJvdG90eXBlLm1hcF90b190YXJnZXQ9ZnVuY3Rpb24odCxyKXt2YXIgbixvLHMsYSxsLHU7cmV0dXJuIG51bGw9PXImJihyPSExKSxpLmlzTnVtYmVyKHQpP3I/dDplLl9fc3VwZXJfXy5tYXBfdG9fdGFyZ2V0LmNhbGwodGhpcyx0KTooYT10aGlzLmdldCgic291cmNlX3JhbmdlIiksbz1hLmdldCgiZmFjdG9ycyIpLHQuaW5kZXhPZigiOiIpPj0wPyhsPXQuc3BsaXQoIjoiKSxuPWxbMF0scz1sWzFdLHM9cGFyc2VGbG9hdChzKSx1PW8uaW5kZXhPZihuKSsuNSthLmdldCgib2Zmc2V0Iikrcyk6dT1vLmluZGV4T2YodCkrMSthLmdldCgib2Zmc2V0Iikscj91OmUuX19zdXBlcl9fLm1hcF90b190YXJnZXQuY2FsbCh0aGlzLHUpKX0sZS5wcm90b3R5cGUudl9tYXBfdG9fdGFyZ2V0PWZ1bmN0aW9uKHQscil7dmFyIG4sbyxzLGEsbCx1LGgsYyxwLF87aWYobnVsbD09ciYmKHI9ITEpLGkuaXNOdW1iZXIodFswXSkpcmV0dXJuIHI/dDplLl9fc3VwZXJfXy52X21hcF90b190YXJnZXQuY2FsbCh0aGlzLHQpO2Zvcih1PXRoaXMuZ2V0KCJzb3VyY2VfcmFuZ2UiKSxvPXUuZ2V0KCJmYWN0b3JzIikscD1BcnJheSh0Lmxlbmd0aCkscz1hPTAsaD10Lmxlbmd0aDswPD1oP2E8aDphPmg7cz0wPD1oPysrYTotLWEpXz10W3NdLF8uaW5kZXhPZigiOiIpPj0wPyhjPV8uc3BsaXQoIjoiKSxuPWNbMF0sbD1jWzFdLGw9cGFyc2VGbG9hdChsKSxwW3NdPW8uaW5kZXhPZihuKSsuNSt1LmdldCgib2Zmc2V0IikrbCk6cFtzXT1vLmluZGV4T2YoXykrMSt1LmdldCgib2Zmc2V0Iik7cmV0dXJuIHI/cDplLl9fc3VwZXJfXy52X21hcF90b190YXJnZXQuY2FsbCh0aGlzLHApfSxlLnByb3RvdHlwZS5tYXBfZnJvbV90YXJnZXQ9ZnVuY3Rpb24odCxyKXt2YXIgbixvO3JldHVybiBudWxsPT1yJiYocj0hMSksdD1lLl9fc3VwZXJfXy5tYXBfZnJvbV90YXJnZXQuY2FsbCh0aGlzLHQpLHI/dDoobz10aGlzLmdldCgic291cmNlX3JhbmdlIiksbj1vLmdldCgiZmFjdG9ycyIpLG5bTWF0aC5mbG9vcih0LS41LW8uZ2V0KCJvZmZzZXQiKSldKX0sZS5wcm90b3R5cGUudl9tYXBfZnJvbV90YXJnZXQ9ZnVuY3Rpb24odCxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGM7Zm9yKG51bGw9PXImJihyPSExKSxjPWUuX19zdXBlcl9fLnZfbWFwX2Zyb21fdGFyZ2V0LmNhbGwodGhpcyx0KSxvPWk9MCxsPWMubGVuZ3RoOzA8PWw/aTxsOmk+bDtvPTA8PWw/KytpOi0taSljW29dPWNbb107aWYocilyZXR1cm4gYztmb3IoaD1BcnJheShjKSxhPXRoaXMuZ2V0KCJzb3VyY2VfcmFuZ2UiKSxuPWEuZ2V0KCJmYWN0b3JzIiksbz1zPTAsdT10Lmxlbmd0aDswPD11P3M8dTpzPnU7bz0wPD11PysrczotLXMpaFtvXT1uW01hdGguZmxvb3IoY1tvXS0uNS1hLmdldCgib2Zmc2V0IikpXTtyZXR1cm4gaH0sZX0oby5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpufX0seyIuL2xpbmVhcl9tYXBwZXIiOiJtb2RlbHMvbWFwcGVycy9saW5lYXJfbWFwcGVyIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvbWFwcGVycy9jb2xvcl9tYXBwZXIiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpbC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxsPXt9Lmhhc093blByb3BlcnR5O2k9dCgidW5kZXJzY29yZSIpLHM9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksbz10KCIuLi8uLi9tb2RlbCIpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGEoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJDb2xvck1hcHBlciIsZS5kZWZpbmUoe3BhbGV0dGU6W3MuQW55XSxoaWdoOltzLk51bWJlcl0sbG93OltzLk51bWJlcl0sbmFuX2NvbG9yOltzLkNvbG9yLCJncmF5Il19KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5fbGl0dGxlX2VuZGlhbj10aGlzLl9pc19saXR0bGVfZW5kaWFuKCksdGhpcy5fcGFsZXR0ZT10aGlzLl9idWlsZF9wYWxldHRlKHRoaXMucGFsZXR0ZSksdGhpcy5saXN0ZW5Ubyh0aGlzLCJjaGFuZ2UiLGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3BhbGV0dGU9dGhpcy5fYnVpbGRfcGFsZXR0ZSh0aGlzLnBhbGV0dGUpfSl9LGUucHJvdG90eXBlLnZfbWFwX3NjcmVlbj1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsLHU7aWYodT10aGlzLl9nZXRfdmFsdWVzKHQsdGhpcy5fcGFsZXR0ZSksZT1uZXcgQXJyYXlCdWZmZXIoNCp0Lmxlbmd0aCkscj1uZXcgVWludDMyQXJyYXkoZSksdGhpcy5fbGl0dGxlX2VuZGlhbilmb3Iobj1vPTAscz10Lmxlbmd0aDswPD1zP288czpvPnM7bj0wPD1zPysrbzotLW8pbD11W25dLHJbbl09MjU1PDwyNHwoMTY3MTE2ODAmbCk+PjE2fDY1MjgwJmx8KDI1NSZsKTw8MTY7ZWxzZSBmb3Iobj1pPTAsYT10Lmxlbmd0aDswPD1hP2k8YTppPmE7bj0wPD1hPysraTotLWkpbD11W25dLHJbbl09bDw8OHwyNTU7cmV0dXJuIGV9LGUucHJvdG90eXBlLmNvbXB1dGU9ZnVuY3Rpb24odCl7cmV0dXJuIG51bGx9LGUucHJvdG90eXBlLnZfY29tcHV0ZT1mdW5jdGlvbih0KXt2YXIgZTtyZXR1cm4gZT10aGlzLl9nZXRfdmFsdWVzKHQsdGhpcy5wYWxldHRlKX0sZS5wcm90b3R5cGUuX2dldF92YWx1ZXM9ZnVuY3Rpb24odCxlKXtyZXR1cm5bXX0sZS5wcm90b3R5cGUuX2lzX2xpdHRsZV9lbmRpYW49ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbjtyZXR1cm4gdD1uZXcgQXJyYXlCdWZmZXIoNCkscj1uZXcgVWludDhDbGFtcGVkQXJyYXkodCksZT1uZXcgVWludDMyQXJyYXkodCksZVsxXT0xNjg0OTYxNDEsbj0hMCwxMD09PXJbNF0mJjExPT09cls1XSYmMTI9PT1yWzZdJiYxMz09PXJbN10mJihuPSExKSxufSxlLnByb3RvdHlwZS5fYnVpbGRfcGFsZXR0ZT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxzO2ZvcihvPW5ldyBVaW50MzJBcnJheSh0Lmxlbmd0aCksZT1mdW5jdGlvbih0KXtyZXR1cm4gaS5pc051bWJlcih0KT90OnBhcnNlSW50KHQuc2xpY2UoMSksMTYpfSxyPW49MCxzPXQubGVuZ3RoOzA8PXM/bjxzOm4+cztyPTA8PXM/KytuOi0tbilvW3JdPWUodFtyXSk7cmV0dXJuIG99LGV9KG8pLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vbW9kZWwiOiJtb2RlbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL21hcHBlcnMvZ3JpZF9tYXBwZXIiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlzLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHM9e30uaGFzT3duUHJvcGVydHk7bz10KCIuLi8uLi9tb2RlbCIpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGkoZSx0KSxlLnByb3RvdHlwZS5tYXBfdG9fdGFyZ2V0PWZ1bmN0aW9uKHQsZSl7dmFyIHIsbjtyZXR1cm4gcj10aGlzLmdldCgiZG9tYWluX21hcHBlciIpLm1hcF90b190YXJnZXQodCksbj10aGlzLmdldCgiY29kb21haW5fbWFwcGVyIikubWFwX3RvX3RhcmdldChlKSxbcixuXX0sZS5wcm90b3R5cGUudl9tYXBfdG9fdGFyZ2V0PWZ1bmN0aW9uKHQsZSl7dmFyIHIsbjtyZXR1cm4gcj10aGlzLmdldCgiZG9tYWluX21hcHBlciIpLnZfbWFwX3RvX3RhcmdldCh0KSxuPXRoaXMuZ2V0KCJjb2RvbWFpbl9tYXBwZXIiKS52X21hcF90b190YXJnZXQoZSksW3Isbl19LGUucHJvdG90eXBlLm1hcF9mcm9tX3RhcmdldD1mdW5jdGlvbih0LGUpe3ZhciByLG47cmV0dXJuIHI9dGhpcy5nZXQoImRvbWFpbl9tYXBwZXIiKS5tYXBfZnJvbV90YXJnZXQodCksbj10aGlzLmdldCgiY29kb21haW5fbWFwcGVyIikubWFwX2Zyb21fdGFyZ2V0KGUpLFtyLG5dfSxlLnByb3RvdHlwZS52X21hcF9mcm9tX3RhcmdldD1mdW5jdGlvbih0LGUpe3ZhciByLG47cmV0dXJuIHI9dGhpcy5nZXQoImRvbWFpbl9tYXBwZXIiKS52X21hcF9mcm9tX3RhcmdldCh0KSxuPXRoaXMuZ2V0KCJjb2RvbWFpbl9tYXBwZXIiKS52X21hcF9mcm9tX3RhcmdldChlKSxbcixuXX0sZX0obyksZS5leHBvcnRzPXtNb2RlbDpufX0seyIuLi8uLi9tb2RlbCI6Im1vZGVsIn1dLCJtb2RlbHMvbWFwcGVycy9saW5lYXJfY29sb3JfbWFwcGVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlhLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGE9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2NvbG9yX21hcHBlciIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHMoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJMaW5lYXJDb2xvck1hcHBlciIsZS5wcm90b3R5cGUuX2dldF92YWx1ZXM9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8scyxhLGwsdSxoLGMscCxfLGQsZjtmb3IodT1udWxsIT0oXz10aGlzLmdldCgibG93IikpP186aS5taW4odCksYT1udWxsIT0oZD10aGlzLmdldCgiaGlnaCIpKT9kOmkubWF4KHQpLGw9ZS5sZW5ndGgtMSxmPVtdLGg9MS8oYS11KSxwPTEvZS5sZW5ndGgsbj0wLHM9dC5sZW5ndGg7bjxzO24rKylyPXRbbl0saXNOYU4ocik/Zi5wdXNoKHRoaXMubmFuX2NvbG9yKTooYz0oci11KSpoLG89TWF0aC5mbG9vcihjL3ApLG88MD9vPTA6bz49bCYmKG89bCksZi5wdXNoKGVbb10pKTtyZXR1cm4gZn0sZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvfX0seyIuL2NvbG9yX21hcHBlciI6Im1vZGVscy9tYXBwZXJzL2NvbG9yX21hcHBlciIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL21hcHBlcnMvbGluZWFyX21hcHBlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscz1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxhPXt9Lmhhc093blByb3BlcnR5O289dCgiLi4vLi4vbW9kZWwiKSxpPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHMoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoIm1hcHBlcl9zdGF0ZSIsdGhpcy5fbWFwcGVyX3N0YXRlLCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoIm1hcHBlcl9zdGF0ZSIsdGhpcyxbInNvdXJjZV9yYW5nZSIsInRhcmdldF9yYW5nZSJdKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoIm1hcHBlcl9zdGF0ZSIsdGhpcy5nZXQoInNvdXJjZV9yYW5nZSIpLFsic3RhcnQiLCJlbmQiXSksdGhpcy5hZGRfZGVwZW5kZW5jaWVzKCJtYXBwZXJfc3RhdGUiLHRoaXMuZ2V0KCJ0YXJnZXRfcmFuZ2UiKSxbInN0YXJ0IiwiZW5kIl0pfSxlLnByb3RvdHlwZS5tYXBfdG9fdGFyZ2V0PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbjtyZXR1cm4gcj10aGlzLmdldCgibWFwcGVyX3N0YXRlIiksbj1yWzBdLGU9clsxXSxuKnQrZX0sZS5wcm90b3R5cGUudl9tYXBfdG9fdGFyZ2V0PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGw7Zm9yKGk9dGhpcy5nZXQoIm1hcHBlcl9zdGF0ZSIpLGE9aVswXSxvPWlbMV0scz1uZXcgRmxvYXQ2NEFycmF5KHQubGVuZ3RoKSxyPWU9MCxuPXQubGVuZ3RoO2U8bjtyPSsrZSlsPXRbcl0sc1tyXT1hKmwrbztyZXR1cm4gc30sZS5wcm90b3R5cGUubWFwX2Zyb21fdGFyZ2V0PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbjtyZXR1cm4gcj10aGlzLmdldCgibWFwcGVyX3N0YXRlIiksbj1yWzBdLGU9clsxXSwodC1lKS9ufSxlLnByb3RvdHlwZS52X21hcF9mcm9tX3RhcmdldD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsO2ZvcihpPXRoaXMuZ2V0KCJtYXBwZXJfc3RhdGUiKSxhPWlbMF0sbz1pWzFdLHM9bmV3IEZsb2F0NjRBcnJheSh0Lmxlbmd0aCkscj1lPTAsbj10Lmxlbmd0aDtlPG47cj0rK2UpbD10W3JdLHNbcl09KGwtbykvYTtyZXR1cm4gc30sZS5wcm90b3R5cGUuX21hcHBlcl9zdGF0ZT1mdW5jdGlvbigpe3ZhciB0LGUscixuLG8saTtyZXR1cm4gbj10aGlzLmdldCgic291cmNlX3JhbmdlIikuZ2V0KCJzdGFydCIpLHI9dGhpcy5nZXQoInNvdXJjZV9yYW5nZSIpLmdldCgiZW5kIiksaT10aGlzLmdldCgidGFyZ2V0X3JhbmdlIikuZ2V0KCJzdGFydCIpLG89dGhpcy5nZXQoInRhcmdldF9yYW5nZSIpLmdldCgiZW5kIiksZT0oby1pKS8oci1uKSx0PS0oZSpuKStpLFtlLHRdfSxlLmludGVybmFsKHtzb3VyY2VfcmFuZ2U6W2kuQW55XSx0YXJnZXRfcmFuZ2U6W2kuQW55XX0pLGV9KG8pLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vbW9kZWwiOiJtb2RlbCJ9XSwibW9kZWxzL21hcHBlcnMvbG9nX2NvbG9yX21hcHBlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscz1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxhPXt9Lmhhc093blByb3BlcnR5O2k9dCgidW5kZXJzY29yZSIpLG49dCgiLi9jb2xvcl9tYXBwZXIiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBzKGUsdCksZS5wcm90b3R5cGUudHlwZT0iTG9nQ29sb3JNYXBwZXIiLGUucHJvdG90eXBlLl9nZXRfdmFsdWVzPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLHMsYSxsLHUsaCxjLHAsXyxkLGY7Zm9yKGM9ZS5sZW5ndGgsdT1udWxsIT0ocD10aGlzLmdldCgibG93IikpP3A6aS5taW4odCksbj1udWxsIT0oXz10aGlzLmdldCgiaGlnaCIpKT9fOmkubWF4KHQpLGQ9Yy8oTWF0aC5sb2cxcChuKS1NYXRoLmxvZzFwKHUpKSxoPWUubGVuZ3RoLTEsZj1bXSxvPTAsYT10Lmxlbmd0aDtvPGE7bysrKXI9dFtvXSxpc05hTihyKT9mLnB1c2godGhpcy5uYW5fY29sb3IpOihyPm4mJihyPW4pLHI8dSYmKHI9dSksbD1NYXRoLmxvZzFwKHIpLU1hdGgubG9nMXAodSkscz1NYXRoLmZsb29yKGwqZCkscz5oJiYocz1oKSxmLnB1c2goZVtzXSkpO3JldHVybiBmfSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm99fSx7Ii4vY29sb3JfbWFwcGVyIjoibW9kZWxzL21hcHBlcnMvY29sb3JfbWFwcGVyIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvbWFwcGVycy9sb2dfbWFwcGVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlhLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGE9e30uaGFzT3duUHJvcGVydHk7bz10KCIuLi8uLi9tb2RlbCIpLGk9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gcyhlLHQpLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgibWFwcGVyX3N0YXRlIix0aGlzLl9tYXBwZXJfc3RhdGUsITApLHRoaXMuYWRkX2RlcGVuZGVuY2llcygibWFwcGVyX3N0YXRlIix0aGlzLFsic291cmNlX3JhbmdlIiwidGFyZ2V0X3JhbmdlIl0pLHRoaXMuYWRkX2RlcGVuZGVuY2llcygibWFwcGVyX3N0YXRlIix0aGlzLmdldCgic291cmNlX3JhbmdlIiksWyJzdGFydCIsImVuZCJdKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoIm1hcHBlcl9zdGF0ZSIsdGhpcy5nZXQoInRhcmdldF9yYW5nZSIpLFsic3RhcnQiLCJlbmQiXSl9LGUucHJvdG90eXBlLm1hcF90b190YXJnZXQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGE7cmV0dXJuIGk9dGhpcy5nZXQoIm1hcHBlcl9zdGF0ZSIpLGE9aVswXSxvPWlbMV0scj1pWzJdLGU9aVszXSxzPTAsMD09PXI/bj0wOihuPShNYXRoLmxvZyh0KS1lKS9yLCFpc05hTihuKSYmaXNGaW5pdGUobil8fChuPTApKSxzPW4qYStvfSxlLnByb3RvdHlwZS52X21hcF90b190YXJnZXQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGEsbCx1LGgsYyxwLF87aWYoaD10aGlzLmdldCgibWFwcGVyX3N0YXRlIikscD1oWzBdLHU9aFsxXSxuPWhbMl0scj1oWzNdLGM9bmV3IEZsb2F0NjRBcnJheSh0Lmxlbmd0aCksMD09PW4pbz10Lm1hcChmdW5jdGlvbih0KXtyZXR1cm4gMH0pO2Vsc2UgZm9yKG89dC5tYXAoZnVuY3Rpb24odCl7cmV0dXJuKE1hdGgubG9nKHQpLXIpL259KSxlPWk9MCxhPW8ubGVuZ3RoO2k8YTtlPSsraSlfPW9bZV0sIWlzTmFOKG9bZV0pJiZpc0Zpbml0ZShvW2VdKXx8KG9bZV09MCk7Zm9yKGU9cz0wLGw9dC5sZW5ndGg7czxsO2U9KytzKV89dFtlXSxjW2VdPW9bZV0qcCt1O3JldHVybiBjfSxlLnByb3RvdHlwZS5tYXBfZnJvbV90YXJnZXQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzO3JldHVybiBpPXRoaXMuZ2V0KCJtYXBwZXJfc3RhdGUiKSxzPWlbMF0sbz1pWzFdLHI9aVsyXSxlPWlbM10sbj0odC1vKS9zLG49TWF0aC5leHAocipuK2UpfSxlLnByb3RvdHlwZS52X21hcF9mcm9tX3RhcmdldD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsLHUsaCxjO2Zvcih1PW5ldyBGbG9hdDY0QXJyYXkodC5sZW5ndGgpLGw9dGhpcy5nZXQoIm1hcHBlcl9zdGF0ZSIpLGg9bFswXSxhPWxbMV0sbj1sWzJdLHI9bFszXSxvPXQubWFwKGZ1bmN0aW9uKHQpe3JldHVybih0LWEpL2h9KSxlPWk9MCxzPXQubGVuZ3RoO2k8cztlPSsraSljPXRbZV0sdVtlXT1NYXRoLmV4cChuKm9bZV0rcik7cmV0dXJuIHV9LGUucHJvdG90eXBlLl9nZXRfc2FmZV9zY2FsZT1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpO3JldHVybiBpPXQ8MD8wOnQscj1lPDA/MDplLGk9PT1yJiYoMD09PWk/KG89WzEsMTBdLGk9b1swXSxyPW9bMV0pOihuPU1hdGgubG9nKGkpL01hdGgubG9nKDEwKSxpPU1hdGgucG93KDEwLE1hdGguZmxvb3IobikpLHI9TWF0aC5jZWlsKG4pIT09TWF0aC5mbG9vcihuKT9NYXRoLnBvdygxMCxNYXRoLmNlaWwobikpOk1hdGgucG93KDEwLE1hdGguY2VpbChuKSsxKSkpLFtpLHJdfSxlLnByb3RvdHlwZS5fbWFwcGVyX3N0YXRlPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLHMsYSxsLHUsaCxjO3JldHVybiBsPXRoaXMuZ2V0KCJzb3VyY2VfcmFuZ2UiKS5nZXQoInN0YXJ0IiksYT10aGlzLmdldCgic291cmNlX3JhbmdlIikuZ2V0KCJlbmQiKSxjPXRoaXMuZ2V0KCJ0YXJnZXRfcmFuZ2UiKS5nZXQoInN0YXJ0IiksaD10aGlzLmdldCgidGFyZ2V0X3JhbmdlIikuZ2V0KCJlbmQiKSxzPWgtYyxvPXRoaXMuX2dldF9zYWZlX3NjYWxlKGwsYSksdT1vWzBdLHQ9b1sxXSwwPT09dT8ocj1NYXRoLmxvZyh0KSxlPTApOihyPU1hdGgubG9nKHQpLU1hdGgubG9nKHUpLGU9TWF0aC5sb2codSkpLGk9cyxuPWMsW2ksbixyLGVdfSxlLmludGVybmFsKHtzb3VyY2VfcmFuZ2U6W2kuQW55XSx0YXJnZXRfcmFuZ2U6W2kuQW55XX0pLGV9KG8pLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vbW9kZWwiOiJtb2RlbCJ9XSwibW9kZWxzL21hcmtlcnMvaW5kZXgiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdz1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpTS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxNPXt9Lmhhc093blByb3BlcnR5O249dCgiLi9tYXJrZXIiKSxvPU1hdGguc3FydCgzKSxmPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbztyZXR1cm4gbz1mdW5jdGlvbih0KXtmdW5jdGlvbiByKCl7cmV0dXJuIHIuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdyhyLHQpLHIucHJvdG90eXBlLl9yZW5kZXJfb25lPWUscn0obi5WaWV3KSxyPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIHIoKXtyZXR1cm4gci5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB3KHIsZSksci5wcm90b3R5cGUuZGVmYXVsdF92aWV3PW8sci5wcm90b3R5cGUudHlwZT10LHJ9KG4uTW9kZWwpLHtNb2RlbDpyLFZpZXc6b319LGw9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdC5tb3ZlVG8oLWUsZSksdC5saW5lVG8oZSwtZSksdC5tb3ZlVG8oLWUsLWUpLHQubGluZVRvKGUsZSl9LGk9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdC5tb3ZlVG8oMCxlKSx0LmxpbmVUbygwLC1lKSx0Lm1vdmVUbygtZSwwKSx0LmxpbmVUbyhlLDApfSxzPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQubW92ZVRvKDAsZSksdC5saW5lVG8oZS8xLjUsMCksdC5saW5lVG8oMCwtZSksdC5saW5lVG8oLWUvMS41LDApLHQuY2xvc2VQYXRoKCl9LGE9ZnVuY3Rpb24odCxlKXt2YXIgcixuO3JldHVybiBuPWUqbyxyPW4vMyx0Lm1vdmVUbygtZSxyKSx0LmxpbmVUbyhlLHIpLHQubGluZVRvKDAsci1uKSx0LmNsb3NlUGF0aCgpfSx1PWZ1bmN0aW9uKHQsZSxyLG4sbyxzLGEpe3ZhciB1O3U9LjY1Km8saSh0LG8pLGwodCx1KSxzLmRvaXQmJihzLnNldF92ZWN0b3JpemUodCxlKSx0LnN0cm9rZSgpKX0saD1mdW5jdGlvbih0LGUscixuLG8scyxhKXt0LmFyYygwLDAsbywwLDIqTWF0aC5QSSwhMSksYS5kb2l0JiYoYS5zZXRfdmVjdG9yaXplKHQsZSksdC5maWxsKCkpLHMuZG9pdCYmKHMuc2V0X3ZlY3Rvcml6ZSh0LGUpLGkodCxvKSx0LnN0cm9rZSgpKX0sYz1mdW5jdGlvbih0LGUscixuLG8saSxzKXt0LmFyYygwLDAsbywwLDIqTWF0aC5QSSwhMSkscy5kb2l0JiYocy5zZXRfdmVjdG9yaXplKHQsZSksdC5maWxsKCkpLGkuZG9pdCYmKGkuc2V0X3ZlY3Rvcml6ZSh0LGUpLGwodCxvKSx0LnN0cm9rZSgpKX0scD1mdW5jdGlvbih0LGUscixuLG8scyxhKXtpKHQsbykscy5kb2l0JiYocy5zZXRfdmVjdG9yaXplKHQsZSksdC5zdHJva2UoKSl9LF89ZnVuY3Rpb24odCxlLHIsbixvLGksYSl7cyh0LG8pLGEuZG9pdCYmKGEuc2V0X3ZlY3Rvcml6ZSh0LGUpLHQuZmlsbCgpKSxpLmRvaXQmJihpLnNldF92ZWN0b3JpemUodCxlKSx0LnN0cm9rZSgpKX0sZD1mdW5jdGlvbih0LGUscixuLG8sYSxsKXtzKHQsbyksbC5kb2l0JiYobC5zZXRfdmVjdG9yaXplKHQsZSksdC5maWxsKCkpLGEuZG9pdCYmKGEuc2V0X3ZlY3Rvcml6ZSh0LGUpLGkodCxvKSx0LnN0cm9rZSgpKX0sbT1mdW5jdGlvbih0LGUscixuLG8saSxzKXt0LnJvdGF0ZShNYXRoLlBJKSxhKHQsbyksdC5yb3RhdGUoLU1hdGguUEkpLHMuZG9pdCYmKHMuc2V0X3ZlY3Rvcml6ZSh0LGUpLHQuZmlsbCgpKSxpLmRvaXQmJihpLnNldF92ZWN0b3JpemUodCxlKSx0LnN0cm9rZSgpKX0sZz1mdW5jdGlvbih0LGUscixuLG8saSxzKXt2YXIgYTthPTIqbyx0LnJlY3QoLW8sLW8sYSxhKSxzLmRvaXQmJihzLnNldF92ZWN0b3JpemUodCxlKSx0LmZpbGwoKSksaS5kb2l0JiYoaS5zZXRfdmVjdG9yaXplKHQsZSksdC5zdHJva2UoKSl9LHk9ZnVuY3Rpb24odCxlLHIsbixvLHMsYSl7dmFyIGw7bD0yKm8sdC5yZWN0KC1vLC1vLGwsbCksYS5kb2l0JiYoYS5zZXRfdmVjdG9yaXplKHQsZSksdC5maWxsKCkpLHMuZG9pdCYmKHMuc2V0X3ZlY3Rvcml6ZSh0LGUpLGkodCxvKSx0LnN0cm9rZSgpKX0sdj1mdW5jdGlvbih0LGUscixuLG8saSxzKXt2YXIgYTthPTIqbyx0LnJlY3QoLW8sLW8sYSxhKSxzLmRvaXQmJihzLnNldF92ZWN0b3JpemUodCxlKSx0LmZpbGwoKSksaS5kb2l0JiYoaS5zZXRfdmVjdG9yaXplKHQsZSksbCh0LG8pLHQuc3Ryb2tlKCkpfSxiPWZ1bmN0aW9uKHQsZSxyLG4sbyxpLHMpe2EodCxvKSxzLmRvaXQmJihzLnNldF92ZWN0b3JpemUodCxlKSx0LmZpbGwoKSksaS5kb2l0JiYoaS5zZXRfdmVjdG9yaXplKHQsZSksdC5zdHJva2UoKSl9LHg9ZnVuY3Rpb24odCxlLHIsbixvLGkscyl7bCh0LG8pLGkuZG9pdCYmKGkuc2V0X3ZlY3Rvcml6ZSh0LGUpLHQuc3Ryb2tlKCkpfSxlLmV4cG9ydHM9e0FzdGVyaXNrOmYoIkFzdGVyaXNrIix1KSxDaXJjbGVDcm9zczpmKCJDaXJjbGVDcm9zcyIsaCksQ2lyY2xlWDpmKCJDaXJjbGVYIixjKSxDcm9zczpmKCJDcm9zcyIscCksRGlhbW9uZDpmKCJEaWFtb25kIixfKSxEaWFtb25kQ3Jvc3M6ZigiRGlhbW9uZENyb3NzIixkKSxJbnZlcnRlZFRyaWFuZ2xlOmYoIkludmVydGVkVHJpYW5nbGUiLG0pLFNxdWFyZTpmKCJTcXVhcmUiLGcpLFNxdWFyZUNyb3NzOmYoIlNxdWFyZUNyb3NzIix5KSxTcXVhcmVYOmYoIlNxdWFyZVgiLHYpLFRyaWFuZ2xlOmYoIlRyaWFuZ2xlIixiKSxYOmYoIlgiLHgpfX0seyIuL21hcmtlciI6Im1vZGVscy9tYXJrZXJzL21hcmtlciJ9XSwibW9kZWxzL21hcmtlcnMvbWFya2VyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1PWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSloLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGg9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbj10KCIuLi9nbHlwaHMvZ2x5cGgiKSxhPXQoIi4uLy4uL2NvbW1vbi9oaXR0ZXN0IiksbD10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5wcm90b3R5cGUuZHJhd19sZWdlbmQ9ZnVuY3Rpb24odCxlLHIsbixvKXt2YXIgaSxzLGEsbCx1LGgsYyxwO3JldHVybiB1PW51bGwhPShsPXRoaXMuZ2V0X3JlZmVyZW5jZV9wb2ludCgpKT9sOjAsYT1bdV0sYz17fSxjW3VdPShlK3IpLzIscD17fSxwW3VdPShuK28pLzIsaD17fSxoW3VdPS40Kk1hdGgubWluKE1hdGguYWJzKHItZSksTWF0aC5hYnMoby1uKSksaT17fSxpW3VdPTAscz17c3g6YyxzeTpwLF9zaXplOmgsX2FuZ2xlOml9LHRoaXMuX3JlbmRlcih0LGEscyl9LGUucHJvdG90eXBlLl9yZW5kZXI9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYztmb3IoaD1yLnN4LGM9ci5zeSxvPXIuX3NpemUsbj1yLl9hbmdsZSx1PVtdLHM9MCxhPWUubGVuZ3RoO3M8YTtzKyspaT1lW3NdLGlzTmFOKGhbaV0rY1tpXStvW2ldK25baV0pfHwobD1vW2ldLzIsdC5iZWdpblBhdGgoKSx0LnRyYW5zbGF0ZShoW2ldLGNbaV0pLG5baV0mJnQucm90YXRlKG5baV0pLAp0aGlzLl9yZW5kZXJfb25lKHQsaSxoW2ldLGNbaV0sbCx0aGlzLnZpc3VhbHMubGluZSx0aGlzLnZpc3VhbHMuZmlsbCksbltpXSYmdC5yb3RhdGUoLW5baV0pLHUucHVzaCh0LnRyYW5zbGF0ZSgtaFtpXSwtY1tpXSkpKTtyZXR1cm4gdX0sZS5wcm90b3R5cGUuX2luZGV4X2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5feHlfaW5kZXgoKX0sZS5wcm90b3R5cGUuX21hc2tfZGF0YT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsbCx1LGgsYyxwLF8sZCxmO3JldHVybiByPXRoaXMucmVuZGVyZXIucGxvdF92aWV3LmZyYW1lLmdldCgiaF9yYW5nZSIpLHM9ci5nZXQoInN0YXJ0IiktdGhpcy5tYXhfc2l6ZSxsPXIuZ2V0KCJlbmQiKSt0aGlzLm1heF9zaXplLG49dGhpcy5yZW5kZXJlci54bWFwcGVyLnZfbWFwX2Zyb21fdGFyZ2V0KFtzLGxdLCEwKSxwPW5bMF0sXz1uWzFdLGk9dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJ2X3JhbmdlIiksdT1pLmdldCgic3RhcnQiKS10aGlzLm1heF9zaXplLGg9aS5nZXQoImVuZCIpK3RoaXMubWF4X3NpemUsbz10aGlzLnJlbmRlcmVyLnltYXBwZXIudl9tYXBfZnJvbV90YXJnZXQoW3UsaF0sITApLGQ9b1swXSxmPW9bMV0sZT1hLnZhbGlkYXRlX2Jib3hfY29vcmRzKFtwLF9dLFtkLGZdKSxmdW5jdGlvbigpe3ZhciB0LHIsbixvO2ZvcihuPXRoaXMuaW5kZXguc2VhcmNoKGUpLG89W10sdD0wLHI9bi5sZW5ndGg7dDxyO3QrKyljPW5bdF0sby5wdXNoKGMuaSk7cmV0dXJuIG99LmNhbGwodGhpcyl9LGUucHJvdG90eXBlLl9oaXRfcG9pbnQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdyxNLGssaixULFM7Zm9yKGg9W3QudngsdC52eV0sZz1oWzBdLGI9aFsxXSxmPXRoaXMucmVuZGVyZXIucGxvdF92aWV3LmNhbnZhcy52eF90b19zeChnKSxtPXRoaXMucmVuZGVyZXIucGxvdF92aWV3LmNhbnZhcy52eV90b19zeShiKSx5PWctdGhpcy5tYXhfc2l6ZSx2PWcrdGhpcy5tYXhfc2l6ZSxjPXRoaXMucmVuZGVyZXIueG1hcHBlci52X21hcF9mcm9tX3RhcmdldChbeSx2XSwhMCksaz1jWzBdLGo9Y1sxXSx4PWItdGhpcy5tYXhfc2l6ZSx3PWIrdGhpcy5tYXhfc2l6ZSxwPXRoaXMucmVuZGVyZXIueW1hcHBlci52X21hcF9mcm9tX3RhcmdldChbeCx3XSwhMCksVD1wWzBdLFM9cFsxXSxlPWEudmFsaWRhdGVfYmJveF9jb29yZHMoW2ssal0sW1QsU10pLHI9ZnVuY3Rpb24oKXt2YXIgdCxyLG4sbztmb3Iobj10aGlzLmluZGV4LnNlYXJjaChlKSxvPVtdLHQ9MCxyPW4ubGVuZ3RoO3Q8cjt0KyspTT1uW3RdLG8ucHVzaChNLmkpO3JldHVybiBvfS5jYWxsKHRoaXMpLG89W10sbD0wLHU9ci5sZW5ndGg7bDx1O2wrKylpPXJbbF0sZD10aGlzLl9zaXplW2ldLzIsbj1NYXRoLmFicyh0aGlzLnN4W2ldLWYpK01hdGguYWJzKHRoaXMuc3lbaV0tbSksTWF0aC5hYnModGhpcy5zeFtpXS1mKTw9ZCYmTWF0aC5hYnModGhpcy5zeVtpXS1tKTw9ZCYmby5wdXNoKFtpLG5dKTtyZXR1cm4gXz1hLmNyZWF0ZV9oaXRfdGVzdF9yZXN1bHQoKSxfWyIxZCJdLmluZGljZXM9cy5jaGFpbihvKS5zb3J0QnkoZnVuY3Rpb24odCl7cmV0dXJuIHRbMV19KS5tYXAoZnVuY3Rpb24odCl7cmV0dXJuIHRbMF19KS52YWx1ZSgpLF99LGUucHJvdG90eXBlLl9oaXRfcmVjdD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsbCx1LGg7cmV0dXJuIHI9dGhpcy5yZW5kZXJlci54bWFwcGVyLnZfbWFwX2Zyb21fdGFyZ2V0KFt0LnZ4MCx0LnZ4MV0sITApLHM9clswXSxsPXJbMV0sbj10aGlzLnJlbmRlcmVyLnltYXBwZXIudl9tYXBfZnJvbV90YXJnZXQoW3QudnkwLHQudnkxXSwhMCksdT1uWzBdLGg9blsxXSxlPWEudmFsaWRhdGVfYmJveF9jb29yZHMoW3MsbF0sW3UsaF0pLG89YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksb1siMWQiXS5pbmRpY2VzPWZ1bmN0aW9uKCl7dmFyIHQscixuLG87Zm9yKG49dGhpcy5pbmRleC5zZWFyY2goZSksbz1bXSx0PTAscj1uLmxlbmd0aDt0PHI7dCsrKWk9blt0XSxvLnB1c2goaS5pKTtyZXR1cm4gb30uY2FsbCh0aGlzKSxvfSxlLnByb3RvdHlwZS5faGl0X3BvbHk9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGwsdSxoLGMscCxfLGQ7Zm9yKHM9W3QudngsdC52eV0sXz1zWzBdLGQ9c1sxXSxjPXRoaXMucmVuZGVyZXIucGxvdF92aWV3LmNhbnZhcy52X3Z4X3RvX3N4KF8pLHA9dGhpcy5yZW5kZXJlci5wbG90X3ZpZXcuY2FudmFzLnZfdnlfdG9fc3koZCksZT1mdW5jdGlvbigpe2g9W107Zm9yKHZhciB0PTAsZT10aGlzLnN4Lmxlbmd0aDswPD1lP3Q8ZTp0PmU7MDw9ZT90Kys6dC0tKWgucHVzaCh0KTtyZXR1cm4gaH0uYXBwbHkodGhpcykscj1bXSxuPWk9MCxsPWUubGVuZ3RoOzA8PWw/aTxsOmk+bDtuPTA8PWw/KytpOi0taSlvPWVbbl0sYS5wb2ludF9pbl9wb2x5KHRoaXMuc3hbbl0sdGhpcy5zeVtuXSxjLHApJiZyLnB1c2gobyk7cmV0dXJuIHU9YS5jcmVhdGVfaGl0X3Rlc3RfcmVzdWx0KCksdVsiMWQiXS5pbmRpY2VzPXIsdX0sZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5jb29yZHMoW1sieCIsInkiXV0pLGUubWl4aW5zKFsibGluZSIsImZpbGwiXSksZS5kZWZpbmUoe3NpemU6W2wuRGlzdGFuY2VTcGVjLHt1bml0czoic2NyZWVuIix2YWx1ZTo0fV0sYW5nbGU6W2wuQW5nbGVTcGVjLDBdfSksZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvLFZpZXc6aX19LHsiLi4vLi4vY29tbW9uL2hpdHRlc3QiOiJjb21tb24vaGl0dGVzdCIsIi4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4uL2dseXBocy9nbHlwaCI6Im1vZGVscy9nbHlwaHMvZ2x5cGgiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9wbG90cy9nbWFwX3Bsb3QiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHA9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKV8uY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sXz17fS5oYXNPd25Qcm9wZXJ0eTthPXQoInVuZGVyc2NvcmUiKSxoPXQoInByb2o0IiksYz1oLmRlZnMoIkdPT0dMRSIpLGw9dCgiLi4vLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLG89dCgiLi9nbWFwX3Bsb3RfY2FudmFzIikscz10KCIuL3Bsb3QiKSx1PXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHAoZSx0KSxlfShzLlZpZXcpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHAoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJHTWFwUGxvdCIsZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy5hcGlfa2V5fHxsLmVycm9yKCJhcGlfa2V5IGlzIHJlcXVpcmVkLiBTZWUgaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2dsZS5jb20vbWFwcy9kb2N1bWVudGF0aW9uL2phdmFzY3JpcHQvZ2V0LWFwaS1rZXkgZm9yIG1vcmUgaW5mb3JtYXRpb24gb24gaG93IHRvIG9idGFpbiB5b3VyIG93bi4iKSx0aGlzLl9wbG90X2NhbnZhcz1uZXcgby5Nb2RlbCh7cGxvdDp0aGlzfSksdGhpcy5wbG90X2NhbnZhcy50b29sYmFyPXRoaXMudG9vbGJhcn0sZS5kZWZpbmUoe21hcF9vcHRpb25zOlt1LkFueV0sYXBpX2tleTpbdS5TdHJpbmddfSksZX0ocy5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpuLFZpZXc6aX19LHsiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9nbWFwX3Bsb3RfY2FudmFzIjoibW9kZWxzL3Bsb3RzL2dtYXBfcGxvdF9jYW52YXMiLCIuL3Bsb3QiOiJtb2RlbHMvcGxvdHMvcGxvdCIscHJvajQ6InByb2o0Iix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvcGxvdHMvZ21hcF9wbG90X2NhbnZhcyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHQuYXBwbHkoZSxhcmd1bWVudHMpfX0sYz1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpcC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxwPXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLGw9dCgicHJvajQiKSx1PWwuZGVmcygiR09PR0xFIiksaT10KCIuL3Bsb3RfY2FudmFzIiksYT10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gdGhpcy5zZXRSYW5nZXM9aCh0aGlzLnNldFJhbmdlcyx0aGlzKSx0aGlzLmdldFByb2plY3RlZEJvdW5kcz1oKHRoaXMuZ2V0UHJvamVjdGVkQm91bmRzLHRoaXMpLHRoaXMuZ2V0TGF0TG5nQm91bmRzPWgodGhpcy5nZXRMYXRMbmdCb3VuZHMsdGhpcyksZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBjKGUsdCksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMscy5kZWZhdWx0cyh0LHRoaXMuZGVmYXVsdF9vcHRpb25zKSksdGhpcy56b29tX2NvdW50PTB9LGUucHJvdG90eXBlLmdldExhdExuZ0JvdW5kcz1mdW5jdGlvbigpe3ZhciB0LGUscixuLG8saSxzO3JldHVybiBlPXRoaXMubWFwLmdldEJvdW5kcygpLHI9ZS5nZXROb3J0aEVhc3QoKSx0PWUuZ2V0U291dGhXZXN0KCksbz10LmxuZygpLG49ci5sbmcoKSxzPXQubGF0KCksaT1yLmxhdCgpLFtvLG4scyxpXX0sZS5wcm90b3R5cGUuZ2V0UHJvamVjdGVkQm91bmRzPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLHMsYSxoLGMscDtyZXR1cm4gbz10aGlzLmdldExhdExuZ0JvdW5kcygpLGg9b1swXSxhPW9bMV0scD1vWzJdLGM9b1szXSxpPWwodSxbaCxwXSksZT1pWzBdLG49aVsxXSxzPWwodSxbYSxjXSksdD1zWzBdLHI9c1sxXSxbZSx0LG4scl19LGUucHJvdG90eXBlLnNldFJhbmdlcz1mdW5jdGlvbigpe3ZhciB0LGUscixuLG87cmV0dXJuIG89dGhpcy5nZXRQcm9qZWN0ZWRCb3VuZHMoKSxlPW9bMF0sdD1vWzFdLG49b1syXSxyPW9bM10sdGhpcy54X3JhbmdlLnNldCh7c3RhcnQ6ZSxlbmQ6dH0pLHRoaXMueV9yYW5nZS5zZXQoe3N0YXJ0Om4sZW5kOnJ9KX0sZS5wcm90b3R5cGUudXBkYXRlX3JhbmdlPWZ1bmN0aW9uKHQpe3ZhciByLG4sbyxpLHMsYSxsLHU7aWYodGhpcy5wYXVzZSgpLG51bGw9PXQuc2R4JiZudWxsPT10LnNkeXx8KHRoaXMubWFwLnBhbkJ5KHQuc2R4LHQuc2R5KSxlLl9fc3VwZXJfXy51cGRhdGVfcmFuZ2UuY2FsbCh0aGlzLHQpKSxudWxsIT10LmZhY3Rvcil7aWYoMTAhPT10aGlzLnpvb21fY291bnQpcmV0dXJuIHZvaWQodGhpcy56b29tX2NvdW50Kz0xKTt0aGlzLnpvb21fY291bnQ9MCxlLl9fc3VwZXJfXy51cGRhdGVfcmFuZ2UuY2FsbCh0aGlzLHQpLHU9dC5mYWN0b3I8MD8tMToxLG49dGhpcy5tYXAuZ2V0Wm9vbSgpLHI9bit1LHI+PTImJih0aGlzLm1hcC5zZXRab29tKHIpLGw9dGhpcy5nZXRQcm9qZWN0ZWRCb3VuZHMoKSxpPWxbMF0sbz1sWzFdLGE9bFsyXSxzPWxbM10sby1pPDAmJnRoaXMubWFwLnNldFpvb20obikpLHRoaXMuc2V0UmFuZ2VzKCl9cmV0dXJuIHRoaXMudW5wYXVzZSgpfSxlLnByb3RvdHlwZS5iaW5kX2Jva2VoX2V2ZW50cz1mdW5jdGlvbigpe3ZhciB0LHIsbixvLGksYTtyZXR1cm4gZS5fX3N1cGVyX18uYmluZF9ib2tlaF9ldmVudHMuY2FsbCh0aGlzKSxhPXRoaXMuZnJhbWUuZ2V0KCJ3aWR0aCIpLHI9dGhpcy5mcmFtZS5nZXQoImhlaWdodCIpLG49dGhpcy5jYW52YXMudnhfdG9fc3godGhpcy5mcmFtZS5nZXQoImxlZnQiKSksaT10aGlzLmNhbnZhcy52eV90b19zeSh0aGlzLmZyYW1lLmdldCgidG9wIikpLHRoaXMuY2FudmFzX3ZpZXcubWFwX2Rpdi5hdHRyKCJzdHlsZSIsInRvcDogIitpKyJweDsgbGVmdDogIituKyJweDsgcG9zaXRpb246IGFic29sdXRlIiksdGhpcy5jYW52YXNfdmlldy5tYXBfZGl2LmF0dHIoInN0eWxlIiwid2lkdGg6IithKyJweDsiKSx0aGlzLmNhbnZhc192aWV3Lm1hcF9kaXYuYXR0cigic3R5bGUiLCJoZWlnaHQ6IityKyJweDsiKSx0aGlzLmNhbnZhc192aWV3Lm1hcF9kaXYud2lkdGgoYSsicHgiKS5oZWlnaHQocisicHgiKSx0aGlzLmluaXRpYWxfem9vbT10aGlzLm1vZGVsLnBsb3QubWFwX29wdGlvbnMuem9vbSx0PWZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbigpe3ZhciBlLHIsbixvO3JldHVybiBuPXdpbmRvdy5nb29nbGUubWFwcyxyPXtzYXRlbGxpdGU6bi5NYXBUeXBlSWQuU0FURUxMSVRFLHRlcnJhaW46bi5NYXBUeXBlSWQuVEVSUkFJTixyb2FkbWFwOm4uTWFwVHlwZUlkLlJPQURNQVAsaHlicmlkOm4uTWFwVHlwZUlkLkhZQlJJRH0sbz10Lm1vZGVsLnBsb3QubWFwX29wdGlvbnMsZT17Y2VudGVyOm5ldyBuLkxhdExuZyhvLmxhdCxvLmxuZyksem9vbTpvLnpvb20sZGlzYWJsZURlZmF1bHRVSTohMCxtYXBUeXBlSWQ6cltvLm1hcF90eXBlXX0sbnVsbCE9by5zdHlsZXMmJihlLnN0eWxlcz1KU09OLnBhcnNlKG8uc3R5bGVzKSksdC5tYXA9bmV3IG4uTWFwKHQuY2FudmFzX3ZpZXcubWFwX2RpdlswXSxlKSxuLmV2ZW50LmFkZExpc3RlbmVyT25jZSh0Lm1hcCwiaWRsZSIsdC5zZXRSYW5nZXMpfX0odGhpcyksbnVsbD09d2luZG93Ll9ib2tlaF9nbWFwX2xvYWRzJiYod2luZG93Ll9ib2tlaF9nbWFwX2xvYWRzPVtdKSxudWxsIT13aW5kb3cuZ29vZ2xlJiZudWxsIT13aW5kb3cuZ29vZ2xlLm1hcHM/cy5kZWZlcih0KTpudWxsIT13aW5kb3cuX2Jva2VoX2dtYXBfY2FsbGJhY2s/d2luZG93Ll9ib2tlaF9nbWFwX2xvYWRzLnB1c2godCk6KHdpbmRvdy5fYm9rZWhfZ21hcF9sb2Fkcy5wdXNoKHQpLHdpbmRvdy5fYm9rZWhfZ21hcF9jYWxsYmFjaz1mdW5jdGlvbigpe3JldHVybiBzLmVhY2god2luZG93Ll9ib2tlaF9nbWFwX2xvYWRzLHMuZGVmZXIpfSxvPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpLG8udHlwZT0idGV4dC9qYXZhc2NyaXB0IixvLnNyYz0iaHR0cHM6Ly9tYXBzLmdvb2dsZWFwaXMuY29tL21hcHMvYXBpL2pzP2tleT0iK3RoaXMubW9kZWwucGxvdC5hcGlfa2V5KyImY2FsbGJhY2s9X2Jva2VoX2dtYXBfY2FsbGJhY2siLGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQobykpfSxlLnByb3RvdHlwZS5fbWFwX2hvb2s9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saTtyZXR1cm4gbj1lWzBdLG89ZVsxXSxpPWVbMl0scj1lWzNdLHRoaXMuY2FudmFzX3ZpZXcubWFwX2Rpdi5hdHRyKCJzdHlsZSIsInRvcDogIitvKyJweDsgbGVmdDogIituKyJweDsiKSx0aGlzLmNhbnZhc192aWV3Lm1hcF9kaXYud2lkdGgoaSsicHgiKS5oZWlnaHQocisicHgiKX0sZS5wcm90b3R5cGUuX3BhaW50X2VtcHR5PWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLGkscyxhO3JldHVybiBzPXRoaXMuY2FudmFzLmdldCgid2lkdGgiKSxpPXRoaXMuY2FudmFzLmdldCgiaGVpZ2h0Iiksbz1lWzBdLGE9ZVsxXSxuPWVbMl0scj1lWzNdLHQuY2xlYXJSZWN0KDAsMCxzLGkpLHQuYmVnaW5QYXRoKCksdC5tb3ZlVG8oMCwwKSx0LmxpbmVUbygwLGkpLHQubGluZVRvKHMsaSksdC5saW5lVG8ocywwKSx0LmxpbmVUbygwLDApLHQubW92ZVRvKG8sYSksdC5saW5lVG8obytuLGEpLHQubGluZVRvKG8rbixhK3IpLHQubGluZVRvKG8sYStyKSx0LmxpbmVUbyhvLGEpLHQuY2xvc2VQYXRoKCksdC5maWxsU3R5bGU9dGhpcy5tb2RlbC5wbG90LmJvcmRlcl9maWxsX2NvbG9yLHQuZmlsbCgpfSxlfShpLlZpZXcpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGMoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJHTWFwUGxvdENhbnZhcyIsZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PW8sZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0LHIpe3JldHVybiB0aGlzLnVzZV9tYXA9ITAsZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKX0sZX0oaS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpuLFZpZXc6b319LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9wbG90X2NhbnZhcyI6Im1vZGVscy9wbG90cy9wbG90X2NhbnZhcyIscHJvajQ6InByb2o0Iix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvcGxvdHMvcGxvdCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpdy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSx3PXt9Lmhhc093blByb3BlcnR5LE09W10uc2xpY2U7Zz10KCJ1bmRlcnNjb3JlIiksYj10KCIuLi8uLi9jb3JlL2xheW91dC9zb2x2ZXIiKSxtPWIuV0VBS19FUSxpPWIuR0Usbz1iLkVRLGM9Yi5TdHJlbmd0aCxmPWIuVmFyaWFibGUseT10KCIuLi8uLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIsdj10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxhPXQoIi4uL2xheW91dHMvbGF5b3V0X2RvbSIpLHA9dCgiLi4vYW5ub3RhdGlvbnMvdGl0bGUiKSxkPXQoIi4uL3Rvb2xzL3Rvb2xiYXIiKSxfPXQoIi4uLy4uL2NvbW1vbi90b29sX2V2ZW50cyIpLHU9dCgiLi9wbG90X2NhbnZhcyIpLk1vZGVsLG49dCgiLi4vc291cmNlcy9jb2x1bW5fZGF0YV9zb3VyY2UiKSxzPXQoIi4uL3JlbmRlcmVycy9nbHlwaF9yZW5kZXJlciIpLHA9dCgiLi4vYW5ub3RhdGlvbnMvdGl0bGUiKSxoPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB4KGUsdCksZS5wcm90b3R5cGUuY2xhc3NOYW1lPSJiay1wbG90LWxheW91dCIsZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gZS5fX3N1cGVyX18uYmluZF9ib2tlaF9ldmVudHMuY2FsbCh0aGlzKSx0PSJUaXRsZSBvYmplY3QgY2Fubm90IGJlIHJlcGxhY2VkLiBUcnkgY2hhbmdpbmcgcHJvcGVydGllcyBvbiB0aXRsZSB0byB1cGRhdGUgaXQgYWZ0ZXIgaW5pdGlhbGl6YXRpb24uIix0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZTp0aXRsZSIsZnVuY3Rpb24oZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHkud2Fybih0KX19KHRoaXMpKX0sZS5wcm90b3R5cGUucmVuZGVyPWZ1bmN0aW9uKCl7dmFyIHQscixuLG87aWYoZS5fX3N1cGVyX18ucmVuZGVyLmNhbGwodGhpcyksInNjYWxlX2JvdGgiPT09dGhpcy5tb2RlbC5zaXppbmdfbW9kZSlyZXR1cm4gcj10aGlzLmdldF93aWR0aF9oZWlnaHQoKSxvPXJbMF0sdD1yWzFdLG49dGhpcy5tb2RlbC5kb2N1bWVudC5zb2x2ZXIoKSxuLnN1Z2dlc3RfdmFsdWUodGhpcy5tb2RlbC5fd2lkdGgsbyksbi5zdWdnZXN0X3ZhbHVlKHRoaXMubW9kZWwuX2hlaWdodCx0KSx0aGlzLiRlbC5jc3Moe3Bvc2l0aW9uOiJhYnNvbHV0ZSIsbGVmdDp0aGlzLm1vZGVsLl9kb21fbGVmdC5fdmFsdWUsdG9wOnRoaXMubW9kZWwuX2RvbV90b3AuX3ZhbHVlLHdpZHRoOnRoaXMubW9kZWwuX3dpZHRoLnZhbHVlKCksaGVpZ2h0OnRoaXMubW9kZWwuX2hlaWdodC52YWx1ZSgpfSl9LGUucHJvdG90eXBlLmdldF93aWR0aF9oZWlnaHQ9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLGw7cmV0dXJuIHM9dGhpcy5lbC5wYXJlbnROb2RlLmNsaWVudEhlaWdodCxhPXRoaXMuZWwucGFyZW50Tm9kZS5jbGllbnRXaWR0aCx0PXRoaXMubW9kZWwuZ2V0X2FzcGVjdF9yYXRpbygpLG89YSxyPWEvdCxpPXMqdCxuPXMsbzxpPyhsPW8sZT1yKToobD1pLGU9biksW2wsZV19LGUucHJvdG90eXBlLmdldF9oZWlnaHQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tb2RlbC5fd2lkdGguX3ZhbHVlL3RoaXMubW9kZWwuZ2V0X2FzcGVjdF9yYXRpbygpfSxlLnByb3RvdHlwZS5nZXRfd2lkdGg9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tb2RlbC5faGVpZ2h0Ll92YWx1ZSp0aGlzLm1vZGVsLmdldF9hc3BlY3RfcmF0aW8oKX0sZX0oYS5WaWV3KSxsPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB4KGUsdCksZS5wcm90b3R5cGUudHlwZT0iUGxvdCIsZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWgsZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXt2YXIgcixuLG8saSxzLGEsbCxoLGMsXyxkO2ZvcihlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0KSxhPWcudmFsdWVzKHRoaXMuZXh0cmFfeF9yYW5nZXMpLmNvbmNhdCh0aGlzLnhfcmFuZ2UpLHI9MCxvPWEubGVuZ3RoO3I8bztyKyspXz1hW3JdLHM9Xy5nZXQoInBsb3RzIiksZy5pc0FycmF5KHMpJiYocz1zLmNvbmNhdCh0aGlzKSxfLnNldCgicGxvdHMiLHMpKTtmb3IobD1nLnZhbHVlcyh0aGlzLmV4dHJhX3lfcmFuZ2VzKS5jb25jYXQodGhpcy55X3JhbmdlKSxuPTAsaT1sLmxlbmd0aDtuPGk7bisrKWQ9bFtuXSxzPWQuZ2V0KCJwbG90cyIpLGcuaXNBcnJheShzKSYmKHM9cy5jb25jYXQodGhpcyksZC5zZXQoInBsb3RzIixzKSk7aWYodGhpcy5faG9yaXpvbnRhbD0hMSwibGVmdCIhPT0oaD10aGlzLnRvb2xiYXJfbG9jYXRpb24pJiYicmlnaHQiIT09aHx8KHRoaXMuX2hvcml6b250YWw9ITApLG51bGwhPXRoaXMubWluX2JvcmRlciYmKG51bGw9PXRoaXMubWluX2JvcmRlcl90b3AmJih0aGlzLm1pbl9ib3JkZXJfdG9wPXRoaXMubWluX2JvcmRlciksbnVsbD09dGhpcy5taW5fYm9yZGVyX2JvdHRvbSYmKHRoaXMubWluX2JvcmRlcl9ib3R0b209dGhpcy5taW5fYm9yZGVyKSxudWxsPT10aGlzLm1pbl9ib3JkZXJfbGVmdCYmKHRoaXMubWluX2JvcmRlcl9sZWZ0PXRoaXMubWluX2JvcmRlciksbnVsbD09dGhpcy5taW5fYm9yZGVyX3JpZ2h0JiYodGhpcy5taW5fYm9yZGVyX3JpZ2h0PXRoaXMubWluX2JvcmRlcikpLG51bGwhPXRoaXMudGl0bGUmJihjPWcuaXNTdHJpbmcodGhpcy50aXRsZSk/bmV3IHAuTW9kZWwoe3RleHQ6dGhpcy50aXRsZX0pOnRoaXMudGl0bGUsdGhpcy5hZGRfbGF5b3V0KGMsdGhpcy50aXRsZV9sb2NhdGlvbikpLHRoaXMuX3Bsb3RfY2FudmFzPW5ldyB1KHtwbG90OnRoaXN9KSx0aGlzLnRvb2xiYXIudG9vbGJhcl9sb2NhdGlvbj10aGlzLnRvb2xiYXJfbG9jYXRpb24sdGhpcy50b29sYmFyLnRvb2xiYXJfc3RpY2t5PXRoaXMudG9vbGJhcl9zdGlja3ksdGhpcy5wbG90X2NhbnZhcy50b29sYmFyPXRoaXMudG9vbGJhcixudWxsPT10aGlzLndpZHRoJiYodGhpcy53aWR0aD10aGlzLnBsb3Rfd2lkdGgpLG51bGw9PXRoaXMuaGVpZ2h0KXJldHVybiB0aGlzLmhlaWdodD10aGlzLnBsb3RfaGVpZ2h0fSxPYmplY3QuZGVmaW5lUHJvcGVydHkoZS5wcm90b3R5cGUsInBsb3RfY2FudmFzIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3Bsb3RfY2FudmFzfX0pLGUucHJvdG90eXBlLl9kb2NfYXR0YWNoZWQ9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhO2ZvcihzPVsiYWJvdmUiLCJiZWxvdyIsImxlZnQiLCJyaWdodCJdLHQ9MCxuPXMubGVuZ3RoO3Q8bjt0KyspZm9yKGE9c1t0XSxyPXRoaXMuZ2V0KGEpLGU9MCxvPXIubGVuZ3RoO2U8bztlKyspaT1yW2VdLHRoaXMucGxvdF9jYW52YXMuYWRkX3JlbmRlcmVyX3RvX2NhbnZhc19zaWRlKGksYSk7cmV0dXJuIHRoaXMucGxvdF9jYW52YXMuYXR0YWNoX2RvY3VtZW50KHRoaXMuZG9jdW1lbnQpLHRoaXMuX3NldF9vcmllbnRhdGlvbl92YXJpYWJsZXModGhpcyksdGhpcy5fc2V0X29yaWVudGF0aW9uX3ZhcmlhYmxlcyh0aGlzLnRvb2xiYXIpLHRoaXMuX3NldF9vcmllbnRhdGlvbl92YXJpYWJsZXModGhpcy5wbG90X2NhbnZhcyl9LGUucHJvdG90eXBlLmFkZF9yZW5kZXJlcnM9ZnVuY3Rpb24oKXt2YXIgdCxlO3JldHVybiB0PTE8PWFyZ3VtZW50cy5sZW5ndGg/TS5jYWxsKGFyZ3VtZW50cywwKTpbXSxlPXRoaXMuZ2V0KCJyZW5kZXJlcnMiKSxlPWUuY29uY2F0KHQpLHRoaXMuc2V0KCJyZW5kZXJlcnMiLGUpfSxlLnByb3RvdHlwZS5hZGRfbGF5b3V0PWZ1bmN0aW9uKHQsZSl7dmFyIHI7aWYobnVsbD09ZSYmKGU9ImNlbnRlciIpLG51bGwhPXQucHJvcHMucGxvdCYmKHQucGxvdD10aGlzKSx0aGlzLmFkZF9yZW5kZXJlcnModCksImNlbnRlciIhPT1lKXJldHVybiByPXRoaXMuZ2V0KGUpLHIucHVzaCh0KX0sZS5wcm90b3R5cGUuYWRkX2dseXBoPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbztyZXR1cm4gbnVsbD09ciYmKHI9e30pLG51bGw9PWUmJihlPW5ldyBuLk1vZGVsKSxyPWcuZXh0ZW5kKHt9LHIse2RhdGFfc291cmNlOmUsZ2x5cGg6dH0pLG89bmV3IHMuTW9kZWwociksdGhpcy5hZGRfcmVuZGVyZXJzKG8pLG99LGUucHJvdG90eXBlLmFkZF90b29scz1mdW5jdGlvbigpe3ZhciB0LGUscixuO3JldHVybiBuPTE8PWFyZ3VtZW50cy5sZW5ndGg/TS5jYWxsKGFyZ3VtZW50cywwKTpbXSxlPWZ1bmN0aW9uKCl7dmFyIGUsbyxpO2ZvcihpPVtdLGU9MCxvPW4ubGVuZ3RoO2U8bztlKyspcj1uW2VdLG51bGwhPXIub3ZlcmxheSYmdGhpcy5hZGRfcmVuZGVyZXJzKHIub3ZlcmxheSksbnVsbCE9ci5wbG90P2kucHVzaChyKToodD1nLmNsb25lKHIuYXR0cmlidXRlcyksdC5wbG90PXRoaXMsaS5wdXNoKG5ldyByLmNvbnN0cnVjdG9yKHQpKSk7cmV0dXJuIGl9LmNhbGwodGhpcyksdGhpcy50b29sYmFyLnRvb2xzPXRoaXMudG9vbGJhci50b29scy5jb25jYXQoZSl9LGUucHJvdG90eXBlLmdldF9hc3BlY3RfcmF0aW89ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy53aWR0aC90aGlzLmhlaWdodH0sZS5wcm90b3R5cGUuZ2V0X2xheW91dGFibGVfY2hpbGRyZW49ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gdD1bdGhpcy5wbG90X2NhbnZhc10sbnVsbCE9dGhpcy50b29sYmFyX2xvY2F0aW9uJiYodD1bdGhpcy50b29sYmFyLHRoaXMucGxvdF9jYW52YXNdKSx0fSxlLnByb3RvdHlwZS5nZXRfZWRpdF92YXJpYWJsZXM9ZnVuY3Rpb24oKXt2YXIgdCxyLG4sbyxpO2ZvcihyPWUuX19zdXBlcl9fLmdldF9lZGl0X3ZhcmlhYmxlcy5jYWxsKHRoaXMpLCJzY2FsZV9ib3RoIj09PXRoaXMuc2l6aW5nX21vZGUmJihyLnB1c2goe2VkaXRfdmFyaWFibGU6dGhpcy5fd2lkdGgsc3RyZW5ndGg6Yy5zdHJvbmd9KSxyLnB1c2goe2VkaXRfdmFyaWFibGU6dGhpcy5faGVpZ2h0LHN0cmVuZ3RoOmMuc3Ryb25nfSkpLGk9dGhpcy5nZXRfbGF5b3V0YWJsZV9jaGlsZHJlbigpLG49MCxvPWkubGVuZ3RoO248bztuKyspdD1pW25dLHI9ci5jb25jYXQodC5nZXRfZWRpdF92YXJpYWJsZXMoKSk7cmV0dXJuIHJ9LGUucHJvdG90eXBlLmdldF9jb25zdHJhaW50cz1mdW5jdGlvbigpe3ZhciB0LHIsbixzLGEsbCx1LGg7Zm9yKHI9ZS5fX3N1cGVyX18uZ2V0X2NvbnN0cmFpbnRzLmNhbGwodGhpcyksbnVsbCE9dGhpcy50b29sYmFyX2xvY2F0aW9uJiYodGhpcy50b29sYmFyX3N0aWNreT09PSEwP3IucHVzaChvKHRoaXMuX3NpemVhYmxlLFstMSx0aGlzLnBsb3RfY2FudmFzLl9zaXplYWJsZV0pKTpyLnB1c2gobyh0aGlzLl9zaXplYWJsZSxbLTEsdGhpcy5wbG90X2NhbnZhcy5fc2l6ZWFibGVdLFstMSx0aGlzLnRvb2xiYXIuX3NpemVhYmxlXSkpLHIucHVzaChvKHRoaXMuX2Z1bGwsWy0xLHRoaXMucGxvdF9jYW52YXMuX2Z1bGxdKSksImFib3ZlIj09PXRoaXMudG9vbGJhcl9sb2NhdGlvbiYmKGg9dGhpcy50b29sYmFyX3N0aWNreT09PSEwP3RoaXMucGxvdF9jYW52YXMuX3RvcDp0aGlzLnBsb3RfY2FudmFzLl9kb21fdG9wLHIucHVzaChvKGgsWy0xLHRoaXMudG9vbGJhci5fZG9tX3RvcF0sWy0xLHRoaXMudG9vbGJhci5faGVpZ2h0XSkpKSwiYmVsb3ciPT09dGhpcy50b29sYmFyX2xvY2F0aW9uJiYodGhpcy50b29sYmFyX3N0aWNreT09PSExJiZyLnB1c2gobyh0aGlzLnRvb2xiYXIuX2RvbV90b3AsWy0xLHRoaXMucGxvdF9jYW52YXMuX2hlaWdodF0sdGhpcy50b29sYmFyLl9ib3R0b20sWy0xLHRoaXMudG9vbGJhci5faGVpZ2h0XSkpLHRoaXMudG9vbGJhcl9zdGlja3k9PT0hMCYmKHIucHVzaChpKHRoaXMucGxvdF9jYW52YXMuYmVsb3dfcGFuZWwuX2hlaWdodCxbLTEsdGhpcy50b29sYmFyLl9oZWlnaHRdKSksci5wdXNoKG0odGhpcy50b29sYmFyLl9kb21fdG9wLFstMSx0aGlzLnBsb3RfY2FudmFzLl9oZWlnaHRdLHRoaXMucGxvdF9jYW52YXMuYmVsb3dfcGFuZWwuX2hlaWdodCkpKSksImxlZnQiPT09dGhpcy50b29sYmFyX2xvY2F0aW9uJiYoaD10aGlzLnRvb2xiYXJfc3RpY2t5PT09ITA/dGhpcy5wbG90X2NhbnZhcy5fbGVmdDp0aGlzLnBsb3RfY2FudmFzLl9kb21fbGVmdCxyLnB1c2gobyhoLFstMSx0aGlzLnRvb2xiYXIuX2RvbV9sZWZ0XSxbLTEsdGhpcy50b29sYmFyLl93aWR0aF0pKSksInJpZ2h0Ij09PXRoaXMudG9vbGJhcl9sb2NhdGlvbiYmKHRoaXMudG9vbGJhcl9zdGlja3k9PT0hMSYmci5wdXNoKG8odGhpcy50b29sYmFyLl9kb21fbGVmdCxbLTEsdGhpcy5wbG90X2NhbnZhcy5fd2lkdGhdLHRoaXMudG9vbGJhci5fcmlnaHQsWy0xLHRoaXMudG9vbGJhci5fd2lkdGhdKSksdGhpcy50b29sYmFyX3N0aWNreT09PSEwJiYoci5wdXNoKGkodGhpcy5wbG90X2NhbnZhcy5yaWdodF9wYW5lbC5fd2lkdGgsWy0xLHRoaXMudG9vbGJhci5fd2lkdGhdKSksci5wdXNoKG0odGhpcy50b29sYmFyLl9kb21fbGVmdCxbLTEsdGhpcy5wbG90X2NhbnZhcy5fd2lkdGhdLHRoaXMucGxvdF9jYW52YXMucmlnaHRfcGFuZWwuX3dpZHRoKSkpKSwiYWJvdmUiIT09KGE9dGhpcy50b29sYmFyX2xvY2F0aW9uKSYmImJlbG93IiE9PWF8fHIucHVzaChvKHRoaXMuX3dpZHRoLFstMSx0aGlzLnRvb2xiYXIuX3dpZHRoXSxbLTEsdGhpcy5wbG90X2NhbnZhcy5fd2lkdGhfbWludXNfcmlnaHRdKSksImxlZnQiIT09KGw9dGhpcy50b29sYmFyX2xvY2F0aW9uKSYmInJpZ2h0IiE9PWx8fChyLnB1c2gobyh0aGlzLl9oZWlnaHQsWy0xLHRoaXMudG9vbGJhci5faGVpZ2h0XSxbLTEsdGhpcy5wbG90X2NhbnZhcy5hYm92ZV9wYW5lbC5faGVpZ2h0XSkpLHIucHVzaChvKHRoaXMudG9vbGJhci5fZG9tX3RvcCxbLTEsdGhpcy5wbG90X2NhbnZhcy5hYm92ZV9wYW5lbC5faGVpZ2h0XSkpKSksbnVsbD09dGhpcy50b29sYmFyX2xvY2F0aW9uJiYoci5wdXNoKG8odGhpcy5fd2lkdGgsWy0xLHRoaXMucGxvdF9jYW52YXMuX3dpZHRoXSkpLHIucHVzaChvKHRoaXMuX2hlaWdodCxbLTEsdGhpcy5wbG90X2NhbnZhcy5faGVpZ2h0XSkpKSx1PXRoaXMuZ2V0X2xheW91dGFibGVfY2hpbGRyZW4oKSxuPTAscz11Lmxlbmd0aDtuPHM7bisrKXQ9dVtuXSxyPXIuY29uY2F0KHQuZ2V0X2NvbnN0cmFpbnRzKCkpO3JldHVybiByfSxlLnByb3RvdHlwZS5nZXRfY29uc3RyYWluZWRfdmFyaWFibGVzPWZ1bmN0aW9uKCl7dmFyIHQ7cmV0dXJuIHQ9ZS5fX3N1cGVyX18uZ2V0X2NvbnN0cmFpbmVkX3ZhcmlhYmxlcy5jYWxsKHRoaXMpLHQ9Zy5leHRlbmQodCx7Im9uLWVkZ2UtYWxpZ24tdG9wIjp0aGlzLnBsb3RfY2FudmFzLl90b3AsIm9uLWVkZ2UtYWxpZ24tYm90dG9tIjp0aGlzLnBsb3RfY2FudmFzLl9oZWlnaHRfbWludXNfYm90dG9tLCJvbi1lZGdlLWFsaWduLWxlZnQiOnRoaXMucGxvdF9jYW52YXMuX2xlZnQsIm9uLWVkZ2UtYWxpZ24tcmlnaHQiOnRoaXMucGxvdF9jYW52YXMuX3dpZHRoX21pbnVzX3JpZ2h0LCJib3gtY2VsbC1hbGlnbi10b3AiOnRoaXMucGxvdF9jYW52YXMuX3RvcCwiYm94LWNlbGwtYWxpZ24tYm90dG9tIjp0aGlzLnBsb3RfY2FudmFzLl9oZWlnaHRfbWludXNfYm90dG9tLCJib3gtY2VsbC1hbGlnbi1sZWZ0Ijp0aGlzLnBsb3RfY2FudmFzLl9sZWZ0LCJib3gtY2VsbC1hbGlnbi1yaWdodCI6dGhpcy5wbG90X2NhbnZhcy5fd2lkdGhfbWludXNfcmlnaHQsImJveC1lcXVhbC1zaXplLXRvcCI6dGhpcy5wbG90X2NhbnZhcy5fdG9wLCJib3gtZXF1YWwtc2l6ZS1ib3R0b20iOnRoaXMucGxvdF9jYW52YXMuX2hlaWdodF9taW51c19ib3R0b219KSwiZml4ZWQiIT09dGhpcy5zaXppbmdfbW9kZSYmKHQ9Zy5leHRlbmQodCx7ImJveC1lcXVhbC1zaXplLWxlZnQiOnRoaXMucGxvdF9jYW52YXMuX2xlZnQsImJveC1lcXVhbC1zaXplLXJpZ2h0Ijp0aGlzLnBsb3RfY2FudmFzLl93aWR0aF9taW51c19yaWdodH0pKSx0fSxlLnByb3RvdHlwZS5fc2V0X29yaWVudGF0aW9uX3ZhcmlhYmxlcz1mdW5jdGlvbih0KXtpZih0aGlzLl9ob3Jpem9udGFsPT09ITEmJih0Ll9zaXplYWJsZT10Ll9oZWlnaHQsdC5fZnVsbD10Ll93aWR0aCksdGhpcy5faG9yaXpvbnRhbD09PSEwKXJldHVybiB0Ll9zaXplYWJsZT10Ll93aWR0aCx0Ll9mdWxsPXQuX2hlaWdodH0sZS5taXhpbnMoWyJsaW5lOm91dGxpbmVfIiwiZmlsbDpiYWNrZ3JvdW5kXyIsImZpbGw6Ym9yZGVyXyJdKSxlLmRlZmluZSh7dG9vbGJhcjpbdi5JbnN0YW5jZSxmdW5jdGlvbigpe3JldHVybiBuZXcgZC5Nb2RlbH1dLHRvb2xiYXJfbG9jYXRpb246W3YuTG9jYXRpb24sInJpZ2h0Il0sdG9vbGJhcl9zdGlja3k6W3YuQm9vbCwhMF0scGxvdF93aWR0aDpbdi5OdW1iZXIsNjAwXSxwbG90X2hlaWdodDpbdi5OdW1iZXIsNjAwXSx0aXRsZTpbdi5BbnksZnVuY3Rpb24oKXtyZXR1cm4gbmV3IHAuTW9kZWwoe3RleHQ6IiJ9KX1dLHRpdGxlX2xvY2F0aW9uOlt2LkxvY2F0aW9uLCJhYm92ZSJdLGhfc3ltbWV0cnk6W3YuQm9vbCwhMF0sdl9zeW1tZXRyeTpbdi5Cb29sLCExXSxhYm92ZTpbdi5BcnJheSxbXV0sYmVsb3c6W3YuQXJyYXksW11dLGxlZnQ6W3YuQXJyYXksW11dLHJpZ2h0Olt2LkFycmF5LFtdXSxyZW5kZXJlcnM6W3YuQXJyYXksW11dLHhfcmFuZ2U6W3YuSW5zdGFuY2VdLGV4dHJhX3hfcmFuZ2VzOlt2LkFueSx7fV0seV9yYW5nZTpbdi5JbnN0YW5jZV0sZXh0cmFfeV9yYW5nZXM6W3YuQW55LHt9XSx4X21hcHBlcl90eXBlOlt2LlN0cmluZywiYXV0byJdLHlfbWFwcGVyX3R5cGU6W3YuU3RyaW5nLCJhdXRvIl0sdG9vbF9ldmVudHM6W3YuSW5zdGFuY2UsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IF8uTW9kZWx9XSxsb2RfZmFjdG9yOlt2Lk51bWJlciwxMF0sbG9kX2ludGVydmFsOlt2Lk51bWJlciwzMDBdLGxvZF90aHJlc2hvbGQ6W3YuTnVtYmVyLDJlM10sbG9kX3RpbWVvdXQ6W3YuTnVtYmVyLDUwMF0sd2ViZ2w6W3YuQm9vbCwhMV0saGlkcGk6W3YuQm9vbCwhMF0sbWluX2JvcmRlcjpbdi5OdW1iZXIsNV0sbWluX2JvcmRlcl90b3A6W3YuTnVtYmVyLG51bGxdLG1pbl9ib3JkZXJfbGVmdDpbdi5OdW1iZXIsbnVsbF0sbWluX2JvcmRlcl9ib3R0b206W3YuTnVtYmVyLG51bGxdLG1pbl9ib3JkZXJfcmlnaHQ6W3YuTnVtYmVyLG51bGxdfSksZS5vdmVycmlkZSh7b3V0bGluZV9saW5lX2NvbG9yOiIjZTVlNWU1Iixib3JkZXJfZmlsbF9jb2xvcjoiI2ZmZmZmZiIsYmFja2dyb3VuZF9maWxsX2NvbG9yOiIjZmZmZmZmIn0pLGV9KGEuTW9kZWwpLGUuZXhwb3J0cz17VmlldzpoLE1vZGVsOmx9fSx7Ii4uLy4uL2NvbW1vbi90b29sX2V2ZW50cyI6ImNvbW1vbi90b29sX2V2ZW50cyIsIi4uLy4uL2NvcmUvbGF5b3V0L3NvbHZlciI6ImNvcmUvbGF5b3V0L3NvbHZlciIsIi4uLy4uL2NvcmUvbG9nZ2luZyI6ImNvcmUvbG9nZ2luZyIsIi4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4uL2Fubm90YXRpb25zL3RpdGxlIjoibW9kZWxzL2Fubm90YXRpb25zL3RpdGxlIiwiLi4vbGF5b3V0cy9sYXlvdXRfZG9tIjoibW9kZWxzL2xheW91dHMvbGF5b3V0X2RvbSIsIi4uL3JlbmRlcmVycy9nbHlwaF9yZW5kZXJlciI6Im1vZGVscy9yZW5kZXJlcnMvZ2x5cGhfcmVuZGVyZXIiLCIuLi9zb3VyY2VzL2NvbHVtbl9kYXRhX3NvdXJjZSI6Im1vZGVscy9zb3VyY2VzL2NvbHVtbl9kYXRhX3NvdXJjZSIsIi4uL3Rvb2xzL3Rvb2xiYXIiOiJtb2RlbHMvdG9vbHMvdG9vbGJhciIsIi4vcGxvdF9jYW52YXMiOiJtb2RlbHMvcGxvdHMvcGxvdF9jYW52YXMiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9wbG90cy9wbG90X2NhbnZhcyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0sayxqPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHQuYXBwbHkoZSxhcmd1bWVudHMpfX0sVD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpUy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxTPXt9Lmhhc093blByb3BlcnR5LHo9W10uaW5kZXhPZnx8ZnVuY3Rpb24odCl7Zm9yKHZhciBlPTAscj10aGlzLmxlbmd0aDtlPHI7ZSsrKWlmKGUgaW4gdGhpcyYmdGhpc1tlXT09PXQpcmV0dXJuIGU7cmV0dXJuLTF9O209dCgidW5kZXJzY29yZSIpLG49dCgianF1ZXJ5Iiksbz10KCIuLi9jYW52YXMvY2FudmFzIiksaT10KCIuLi9jYW52YXMvY2FydGVzaWFuX2ZyYW1lIikscz10KCIuLi9yYW5nZXMvZGF0YV9yYW5nZTFkIiksdT10KCIuLi9yZW5kZXJlcnMvZ2x5cGhfcmVuZGVyZXIiKSxjPXQoIi4uL2xheW91dHMvbGF5b3V0X2RvbSIpLGQ9dCgiLi4vcmVuZGVyZXJzL3JlbmRlcmVyIiksZz10KCIuLi8uLi9jb21tb24vYnVpbGRfdmlld3MiKSxmPXQoIi4uLy4uL2NvbW1vbi91aV9ldmVudHMiKSx5PXQoIi4uLy4uL2NvcmUvZW51bXMiKSxoPXQoIi4uLy4uL2NvcmUvbGF5b3V0L2xheW91dF9jYW52YXMiKSx3PXQoIi4uLy4uL2NvcmUvbGF5b3V0L3NvbHZlciIpLGE9dy5FUSxsPXcuR0UsYj10KCIuLi8uLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIseD10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxNPXQoIi4uLy4uL2NvcmUvdXRpbC90aHJvdHRsZSIpLnRocm90dGxlLGs9dCgiLi4vLi4vY29yZS9sYXlvdXQvc2lkZV9wYW5lbCIpLnVwZGF0ZV9jb25zdHJhaW50cyx2PW51bGwsXz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIHRoaXMucmVtb3ZlPWoodGhpcy5yZW1vdmUsdGhpcyksdGhpcy5yZXF1ZXN0X3JlbmRlcj1qKHRoaXMucmVxdWVzdF9yZW5kZXIsdGhpcyksZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBUKGUsdCksZS5wcm90b3R5cGUuY2xhc3NOYW1lPSJiay1wbG90LXdyYXBwZXIiLGUucHJvdG90eXBlLnN0YXRlPXtoaXN0b3J5OltdLGluZGV4Oi0xfSxlLnByb3RvdHlwZS52aWV3X29wdGlvbnM9ZnVuY3Rpb24oKXtyZXR1cm4gbS5leHRlbmQoe3Bsb3RfbW9kZWw6dGhpcy5tb2RlbCxwbG90X3ZpZXc6dGhpc30sdGhpcy5vcHRpb25zKX0sZS5wcm90b3R5cGUucGF1c2U9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5pc19wYXVzZWQ9ITB9LGUucHJvdG90eXBlLnVucGF1c2U9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5pc19wYXVzZWQ9ITEsdGhpcy5yZXF1ZXN0X3JlbmRlcigpfSxlLnByb3RvdHlwZS5yZXF1ZXN0X3JlbmRlcj1mdW5jdGlvbigpe3RoaXMuaXNfcGF1c2VkfHx0aGlzLnRocm90dGxlZF9yZW5kZXIoKX0sZS5wcm90b3R5cGUucmVtb3ZlPWZ1bmN0aW9uKCl7dmFyIHQscixuLG87ZS5fX3N1cGVyX18ucmVtb3ZlLmNhbGwodGhpcykscj10aGlzLnRvb2xfdmlld3Msbj1bXTtmb3IodCBpbiByKW89clt0XSxuLnB1c2goby5yZW1vdmUoKSk7cmV0dXJuIG59LGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCl7dmFyIHIsbixvLGkscyxhLGwsdSxoLGMscDtmb3IoZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy5wYXVzZSgpLHRoaXMudmlzdWFscz17fSx1PXRoaXMubW9kZWwucGxvdC5taXhpbnMscj0wLG89dS5sZW5ndGg7cjxvO3IrKylwPXVbcl0saD1wLnNwbGl0KCI6IiksYT1oWzBdLGw9aFsxXSxudWxsPT1sJiYobD0iIiksdGhpcy52aXN1YWxzW2wrYV09bmV3IGQuVmlzdWFsc1thXSh7b2JqOnRoaXMubW9kZWwucGxvdCxwcmVmaXg6bH0pO2Zvcih0aGlzLl9pbml0aWFsX3N0YXRlX2luZm89e3JhbmdlOm51bGwsc2VsZWN0aW9uOnt9LGRpbWVuc2lvbnM6e3dpZHRoOnRoaXMubWdldCgiY2FudmFzIikuZ2V0KCJ3aWR0aCIpLGhlaWdodDp0aGlzLm1nZXQoImNhbnZhcyIpLmdldCgiaGVpZ2h0Iil9fSx0aGlzLmZyYW1lPXRoaXMubWdldCgiZnJhbWUiKSx0aGlzLnhfcmFuZ2U9dGhpcy5mcmFtZS5nZXQoInhfcmFuZ2VzIilbImRlZmF1bHQiXSx0aGlzLnlfcmFuZ2U9dGhpcy5mcmFtZS5nZXQoInlfcmFuZ2VzIilbImRlZmF1bHQiXSx0aGlzLnhtYXBwZXI9dGhpcy5mcmFtZS5nZXQoInhfbWFwcGVycyIpWyJkZWZhdWx0Il0sdGhpcy55bWFwcGVyPXRoaXMuZnJhbWUuZ2V0KCJ5X21hcHBlcnMiKVsiZGVmYXVsdCJdLHRoaXMuY2FudmFzPXRoaXMubWdldCgiY2FudmFzIiksdGhpcy5jYW52YXNfdmlldz1uZXcgdGhpcy5jYW52YXMuZGVmYXVsdF92aWV3KHttb2RlbDp0aGlzLmNhbnZhc30pLHRoaXMuJGVsLmFwcGVuZCh0aGlzLmNhbnZhc192aWV3LmVsKSx0aGlzLmNhbnZhc192aWV3LnJlbmRlcighMCksKHRoaXMubW9kZWwucGxvdC53ZWJnbHx8d2luZG93LmxvY2F0aW9uLnNlYXJjaC5pbmRleE9mKCJ3ZWJnbD0xIik+MCkmJndpbmRvdy5sb2NhdGlvbi5zZWFyY2guaW5kZXhPZigid2ViZ2w9MCIpPT09LTEmJnRoaXMuaW5pdF93ZWJnbCgpLHRoaXMudGhyb3R0bGVkX3JlbmRlcj1NKHRoaXMucmVuZGVyLDE1KSxudWxsPT10aGlzLm1vZGVsLmRvY3VtZW50Ll91bnJlbmRlcmVkX3Bsb3RzJiYodGhpcy5tb2RlbC5kb2N1bWVudC5fdW5yZW5kZXJlZF9wbG90cz17fSksdGhpcy5tb2RlbC5kb2N1bWVudC5fdW5yZW5kZXJlZF9wbG90c1t0aGlzLmlkXT0hMCx0aGlzLnVpX2V2ZW50X2J1cz1uZXcgZih7dG9vbGJhcjp0aGlzLm1nZXQoInRvb2xiYXIiKSxoaXRfYXJlYTp0aGlzLmNhbnZhc192aWV3LiRlbH0pLHRoaXMucmVuZGVyZXJfdmlld3M9e30sdGhpcy50b29sX3ZpZXdzPXt9LHRoaXMubGV2ZWxzPXt9LGM9eS5SZW5kZXJMZXZlbCxuPTAsaT1jLmxlbmd0aDtuPGk7bisrKXM9Y1tuXSx0aGlzLmxldmVsc1tzXT17fTtyZXR1cm4gdGhpcy5idWlsZF9sZXZlbHMoKSx0aGlzLmJpbmRfYm9rZWhfZXZlbnRzKCksdGhpcy51cGRhdGVfZGF0YXJhbmdlcygpLHRoaXMudW5wYXVzZSgpLGIuZGVidWcoIlBsb3RWaWV3IGluaXRpYWxpemVkIiksdGhpc30sZS5wcm90b3R5cGUuZ2V0X2NhbnZhc19lbGVtZW50PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuY2FudmFzX3ZpZXcuY3R4LmNhbnZhc30sZS5wcm90b3R5cGUuaW5pdF93ZWJnbD1mdW5jdGlvbigpe3ZhciB0LGUscjtyZXR1cm4gdD10aGlzLmNhbnZhc192aWV3LmN0eCxlPXYsbnVsbD09ZSYmKHY9ZT1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJjYW52YXMiKSxyPXtwcmVtdWx0aXBsaWVkQWxwaGE6ITB9LGUuZ2w9ZS5nZXRDb250ZXh0KCJ3ZWJnbCIscil8fGUuZ2V0Q29udGV4dCgiZXhwZXJpbWVudGFsLXdlYmdsIixyKSksbnVsbCE9ZS5nbD90LmdsY2FudmFzPWU6Yi53YXJuKCJXZWJHTCBpcyBub3Qgc3VwcG9ydGVkLCBmYWxsaW5nIGJhY2sgdG8gMkQgY2FudmFzLiIpfSxlLnByb3RvdHlwZS5wcmVwYXJlX3dlYmdsPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLGk7aWYobj10aGlzLmNhbnZhc192aWV3LmN0eCxyPXRoaXMuY2FudmFzX3ZpZXcuZ2V0X2NhbnZhc19lbGVtZW50KCksbi5nbGNhbnZhcylyZXR1cm4gbi5nbGNhbnZhcy53aWR0aD1yLndpZHRoLG4uZ2xjYW52YXMuaGVpZ2h0PXIuaGVpZ2h0LGk9bi5nbGNhbnZhcy5nbCxpLnZpZXdwb3J0KDAsMCxuLmdsY2FudmFzLndpZHRoLG4uZ2xjYW52YXMuaGVpZ2h0KSxpLmNsZWFyQ29sb3IoMCwwLDAsMCksaS5jbGVhcihpLkNPTE9SX0JVRkZFUl9CSVR8fGkuREVQVEhfQlVGRkVSX0JJVCksaS5lbmFibGUoaS5TQ0lTU09SX1RFU1QpLG89bi5nbGNhbnZhcy5oZWlnaHQtdCooZVsxXStlWzNdKSxpLnNjaXNzb3IodCplWzBdLG8sdCplWzJdLHQqZVszXSksaS5lbmFibGUoaS5CTEVORCksaS5ibGVuZEZ1bmNTZXBhcmF0ZShpLlNSQ19BTFBIQSxpLk9ORV9NSU5VU19TUkNfQUxQSEEsaS5PTkVfTUlOVVNfRFNUX0FMUEhBLGkuT05FKX0sZS5wcm90b3R5cGUuYmxpdF93ZWJnbD1mdW5jdGlvbih0KXt2YXIgZTtpZihlPXRoaXMuY2FudmFzX3ZpZXcuY3R4LGUuZ2xjYW52YXMpcmV0dXJuIGIuZGVidWcoImRyYXdpbmcgd2l0aCBXZWJHTCIpLGUucmVzdG9yZSgpLGUuZHJhd0ltYWdlKGUuZ2xjYW52YXMsMCwwKSxlLnNhdmUoKSxlLnNjYWxlKHQsdCksZS50cmFuc2xhdGUoLjUsLjUpfSxlLnByb3RvdHlwZS51cGRhdGVfZGF0YXJhbmdlcz1mdW5jdGlvbigpe3ZhciB0LGUscixuLG8saSxhLGwsdSxoLGMscCxfLGQsZixnLHksdix4LHcsTSxrLGo7bj10aGlzLm1vZGVsLmZyYW1lLGU9e30sZj10aGlzLnJlbmRlcmVyX3ZpZXdzO2ZvcihhIGluIGYpTT1mW2FdLHQ9bnVsbCE9KGc9TS5nbHlwaCkmJiJmdW5jdGlvbiI9PXR5cGVvZiBnLmJvdW5kcz9nLmJvdW5kcygpOnZvaWQgMCxudWxsIT10JiYoZVthXT10KTtmb3Iocj0hMSxvPSExLHk9bS52YWx1ZXMobi5nZXQoInhfcmFuZ2VzIikpLGk9MCx1PXkubGVuZ3RoO2k8dTtpKyspaz15W2ldLGsgaW5zdGFuY2VvZiBzLk1vZGVsJiYoay51cGRhdGUoZSwwLHRoaXMubW9kZWwuaWQpLGsuZ2V0KCJmb2xsb3ciKSYmKHI9ITApKSxudWxsIT1rLmdldCgiYm91bmRzIikmJihvPSEwKTtmb3Iodj1tLnZhbHVlcyhuLmdldCgieV9yYW5nZXMiKSksbD0wLGg9di5sZW5ndGg7bDxoO2wrKylqPXZbbF0saiBpbnN0YW5jZW9mIHMuTW9kZWwmJihqLnVwZGF0ZShlLDEsdGhpcy5tb2RlbC5pZCksai5nZXQoImZvbGxvdyIpJiYocj0hMCkpLG51bGwhPWouZ2V0KCJib3VuZHMiKSYmKG89ITApO2lmKHImJm8pe2ZvcihiLndhcm4oIkZvbGxvdyBlbmFibGVkIHNvIGJvdW5kcyBhcmUgdW5zZXQuIikseD1tLnZhbHVlcyhuLmdldCgieF9yYW5nZXMiKSksXz0wLGM9eC5sZW5ndGg7XzxjO18rKylrPXhbX10say5zZXQoImJvdW5kcyIsbnVsbCk7Zm9yKHc9bS52YWx1ZXMobi5nZXQoInlfcmFuZ2VzIikpLGQ9MCxwPXcubGVuZ3RoO2Q8cDtkKyspaj13W2RdLGouc2V0KCJib3VuZHMiLG51bGwpfXJldHVybiB0aGlzLnJhbmdlX3VwZGF0ZV90aW1lc3RhbXA9RGF0ZS5ub3coKX0sZS5wcm90b3R5cGUubWFwX3RvX3NjcmVlbj1mdW5jdGlvbih0LGUscixuKXtyZXR1cm4gbnVsbD09ciYmKHI9ImRlZmF1bHQiKSxudWxsPT1uJiYobj0iZGVmYXVsdCIpLHRoaXMuZnJhbWUubWFwX3RvX3NjcmVlbih0LGUsdGhpcy5jYW52YXMscixuKX0sZS5wcm90b3R5cGUucHVzaF9zdGF0ZT1mdW5jdGlvbih0LGUpe3ZhciByLG47cmV0dXJuIHI9KG51bGwhPShuPXRoaXMuc3RhdGUuaGlzdG9yeVt0aGlzLnN0YXRlLmluZGV4XSk/bi5pbmZvOnZvaWQgMCl8fHt9LGU9bS5leHRlbmQoe30sdGhpcy5faW5pdGlhbF9zdGF0ZV9pbmZvLHIsZSksdGhpcy5zdGF0ZS5oaXN0b3J5LnNsaWNlKDAsdGhpcy5zdGF0ZS5pbmRleCsxKSx0aGlzLnN0YXRlLmhpc3RvcnkucHVzaCh7dHlwZTp0LGluZm86ZX0pLHRoaXMuc3RhdGUuaW5kZXg9dGhpcy5zdGF0ZS5oaXN0b3J5Lmxlbmd0aC0xLHRoaXMudHJpZ2dlcigic3RhdGVfY2hhbmdlZCIpfSxlLnByb3RvdHlwZS5jbGVhcl9zdGF0ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLnN0YXRlPXtoaXN0b3J5OltdLGluZGV4Oi0xfSx0aGlzLnRyaWdnZXIoInN0YXRlX2NoYW5nZWQiKX0sZS5wcm90b3R5cGUuY2FuX3VuZG89ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zdGF0ZS5pbmRleD49MH0sZS5wcm90b3R5cGUuY2FuX3JlZG89ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zdGF0ZS5pbmRleDx0aGlzLnN0YXRlLmhpc3RvcnkubGVuZ3RoLTF9LGUucHJvdG90eXBlLnVuZG89ZnVuY3Rpb24oKXtpZih0aGlzLmNhbl91bmRvKCkpcmV0dXJuIHRoaXMuc3RhdGUuaW5kZXgtPTEsdGhpcy5fZG9fc3RhdGVfY2hhbmdlKHRoaXMuc3RhdGUuaW5kZXgpLHRoaXMudHJpZ2dlcigic3RhdGVfY2hhbmdlZCIpfSxlLnByb3RvdHlwZS5yZWRvPWZ1bmN0aW9uKCl7aWYodGhpcy5jYW5fcmVkbygpKXJldHVybiB0aGlzLnN0YXRlLmluZGV4Kz0xLHRoaXMuX2RvX3N0YXRlX2NoYW5nZSh0aGlzLnN0YXRlLmluZGV4KSx0aGlzLnRyaWdnZXIoInN0YXRlX2NoYW5nZWQiKX0sZS5wcm90b3R5cGUuX2RvX3N0YXRlX2NoYW5nZT1mdW5jdGlvbih0KXt2YXIgZSxyO2lmKGU9KG51bGwhPShyPXRoaXMuc3RhdGUuaGlzdG9yeVt0XSk/ci5pbmZvOnZvaWQgMCl8fHRoaXMuX2luaXRpYWxfc3RhdGVfaW5mbyxudWxsIT1lLnJhbmdlJiZ0aGlzLnVwZGF0ZV9yYW5nZShlLnJhbmdlKSxudWxsIT1lLnNlbGVjdGlvbiYmdGhpcy51cGRhdGVfc2VsZWN0aW9uKGUuc2VsZWN0aW9uKSxudWxsIT1lLmRpbWVuc2lvbnMpcmV0dXJuIHRoaXMuY2FudmFzX3ZpZXcuc2V0X2RpbXMoW2UuZGltZW5zaW9ucy53aWR0aCxlLmRpbWVuc2lvbnMuaGVpZ2h0XSl9LGUucHJvdG90eXBlLnJlc2V0X2RpbWVuc2lvbnM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy51cGRhdGVfZGltZW5zaW9ucyh0aGlzLmNhbnZhcy5pbml0aWFsX3dpZHRoLHRoaXMuY2FudmFzLmluaXRpYWxfaGVpZ2h0KX0sZS5wcm90b3R5cGUudXBkYXRlX2RpbWVuc2lvbnM9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5wYXVzZSgpLHRoaXMubW9kZWwucGxvdC53aWR0aD10LHRoaXMubW9kZWwucGxvdC5oZWlnaHQ9ZSx0aGlzLm1vZGVsLmRvY3VtZW50LnJlc2l6ZSgpLHRoaXMudW5wYXVzZSgpfSxlLnByb3RvdHlwZS5nZXRfc2VsZWN0aW9uPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpO2ZvcihpPVtdLHI9dGhpcy5tb2RlbC5wbG90LnJlbmRlcmVycyx0PTAsZT1yLmxlbmd0aDt0PGU7dCsrKW49clt0XSxuIGluc3RhbmNlb2YgdS5Nb2RlbCYmKG89bi5nZXQoImRhdGFfc291cmNlIikuZ2V0KCJzZWxlY3RlZCIpLGlbbi5pZF09byk7cmV0dXJuIGl9LGUucHJvdG90eXBlLnVwZGF0ZV9zZWxlY3Rpb249ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGE7Zm9yKG89dGhpcy5tb2RlbC5wbG90LnJlbmRlcmVycyxhPVtdLHI9MCxuPW8ubGVuZ3RoO3I8bjtyKyspcz1vW3JdLHMgaW5zdGFuY2VvZiB1Lk1vZGVsJiYoZT1zLmdldCgiZGF0YV9zb3VyY2UiKSxudWxsIT10PyhpPXMuaWQsei5jYWxsKHQsaSk+PTA/YS5wdXNoKGUuc2V0KCJzZWxlY3RlZCIsdFtzLmlkXSkpOmEucHVzaCh2b2lkIDApKTphLnB1c2goZS5nZXQoInNlbGVjdGlvbl9tYW5hZ2VyIikuY2xlYXIoKSkpO3JldHVybiBhfSxlLnByb3RvdHlwZS5yZXNldF9zZWxlY3Rpb249ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy51cGRhdGVfc2VsZWN0aW9uKG51bGwpfSxlLnByb3RvdHlwZS5fdXBkYXRlX3Jhbmdlc190b2dldGhlcj1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsLHUsaDtmb3IoaD0xLGU9MCxuPXQubGVuZ3RoO2U8bjtlKyspcz10W2VdLHU9c1swXSxpPXNbMV0saD1NYXRoLm1pbihoLHRoaXMuX2dldF93ZWlnaHRfdG9fY29uc3RyYWluX2ludGVydmFsKHUsaSkpO2lmKGg8MSl7Zm9yKGw9W10scj0wLG89dC5sZW5ndGg7cjxvO3IrKylhPXRbcl0sdT1hWzBdLGk9YVsxXSxpLnN0YXJ0PWgqaS5zdGFydCsoMS1oKSp1LmdldCgic3RhcnQiKSxsLnB1c2goaS5lbmQ9aCppLmVuZCsoMS1oKSp1LmdldCgiZW5kIikpO3JldHVybiBsfX0sZS5wcm90b3R5cGUuX3VwZGF0ZV9yYW5nZXNfaW5kaXZpZHVhbGx5PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseTtmb3Iobj0hMSxvPTAscz10Lmxlbmd0aDtvPHM7bysrKXA9dFtvXSxnPXBbMF0sYz1wWzFdLG09Zy5nZXQoInN0YXJ0Iik+Zy5nZXQoImVuZCIpLHJ8fCh5PXRoaXMuX2dldF93ZWlnaHRfdG9fY29uc3RyYWluX2ludGVydmFsKGcsYykseTwxJiYoYy5zdGFydD15KmMuc3RhcnQrKDEteSkqZy5nZXQoInN0YXJ0IiksYy5lbmQ9eSpjLmVuZCsoMS15KSpnLmdldCgiZW5kIikpKSxudWxsIT1nLmdldCgiYm91bmRzIikmJih1PWcuZ2V0KCJib3VuZHMiKVswXSxsPWcuZ2V0KCJib3VuZHMiKVsxXSxoPU1hdGguYWJzKGMuZW5kLWMuc3RhcnQpLG0/KG51bGwhPXUmJnU+PWMuZW5kJiYobj0hMCxjLmVuZD11LG51bGw9PWUmJm51bGw9PXJ8fChjLnN0YXJ0PXUraCkpLG51bGwhPWwmJmw8PWMuc3RhcnQmJihuPSEwLGMuc3RhcnQ9bCxudWxsPT1lJiZudWxsPT1yfHwoYy5lbmQ9bC1oKSkpOihudWxsIT11JiZ1Pj1jLnN0YXJ0JiYobj0hMCxjLnN0YXJ0PXUsbnVsbD09ZSYmbnVsbD09cnx8KGMuZW5kPXUraCkpLG51bGwhPWwmJmw8PWMuZW5kJiYobj0hMCxjLmVuZD1sLG51bGw9PWUmJm51bGw9PXJ8fChjLnN0YXJ0PWwtaCkpKSk7aWYoIXJ8fCFuKXtmb3IoZj1bXSxpPTAsYT10Lmxlbmd0aDtpPGE7aSsrKV89dFtpXSxnPV9bMF0sYz1fWzFdLGcuaGF2ZV91cGRhdGVkX2ludGVyYWN0aXZlbHk9ITAsZy5nZXQoInN0YXJ0IikhPT1jLnN0YXJ0fHxnLmdldCgiZW5kIikhPT1jLmVuZD8oZy5zZXQoYyksZi5wdXNoKG51bGwhPShkPWcuZ2V0KCJjYWxsYmFjayIpKT9kLmV4ZWN1dGUoZyk6dm9pZCAwKSk6Zi5wdXNoKHZvaWQgMCk7cmV0dXJuIGZ9fSxlLnByb3RvdHlwZS5fZ2V0X3dlaWdodF90b19jb25zdHJhaW5faW50ZXJ2YWw9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saSxzLGEsbCx1LGg7cmV0dXJuIHM9dC5nZXQoIm1pbl9pbnRlcnZhbCIpLG49dC5nZXQoIm1heF9pbnRlcnZhbCIpLGg9MSxudWxsIT10LmdldCgiYm91bmRzIikmJih1PXQuZ2V0KCJib3VuZHMiKSxpPXVbMF0scj11WzFdLG51bGwhPWkmJm51bGwhPXImJihvPU1hdGguYWJzKHItaSksbj1udWxsIT1uP01hdGgubWluKG4sbyk6bykpLG51bGw9PXMmJm51bGw9PW58fChsPU1hdGguYWJzKHQuZ2V0KCJlbmQiKS10LmdldCgic3RhcnQiKSksYT1NYXRoLmFicyhlLmVuZC1lLnN0YXJ0KSxzPjAmJmE8cyYmKGg9KGwtcykvKGwtYSkpLG4+MCYmYT5uJiYoaD0obi1sKS8oYS1sKSksaD1NYXRoLm1heCgwLE1hdGgubWluKDEsaCkpKSxofSxlLnByb3RvdHlwZS51cGRhdGVfcmFuZ2U9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYztpZih0aGlzLnBhdXNlLG51bGw9PXQpe2k9dGhpcy5mcmFtZS5nZXQoInhfcmFuZ2VzIik7Zm9yKG4gaW4gaSljPWlbbl0sYy5yZXNldCgpLG51bGwhPShzPWMuZ2V0KCJjYWxsYmFjayIpKSYmcy5leGVjdXRlKGMpO2E9dGhpcy5mcmFtZS5nZXQoInlfcmFuZ2VzIik7Zm9yKG4gaW4gYSljPWFbbl0sYy5yZXNldCgpLG51bGwhPShsPWMuZ2V0KCJjYWxsYmFjayIpKSYmbC5leGVjdXRlKGMpO3RoaXMudXBkYXRlX2RhdGFyYW5nZXMoKX1lbHNle289W10sdT10aGlzLmZyYW1lLmdldCgieF9yYW5nZXMiKTtmb3IobiBpbiB1KWM9dVtuXSxvLnB1c2goW2MsdC54cnNbbl1dKTtoPXRoaXMuZnJhbWUuZ2V0KCJ5X3JhbmdlcyIpO2ZvcihuIGluIGgpYz1oW25dLG8ucHVzaChbYyx0Lnlyc1tuXV0pO3ImJnRoaXMuX3VwZGF0ZV9yYW5nZXNfdG9nZXRoZXIobyksdGhpcy5fdXBkYXRlX3Jhbmdlc19pbmRpdmlkdWFsbHkobyxlLHIpfXJldHVybiB0aGlzLnVucGF1c2UoKX0sZS5wcm90b3R5cGUucmVzZXRfcmFuZ2U9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy51cGRhdGVfcmFuZ2UobnVsbCl9LGUucHJvdG90eXBlLmJ1aWxkX2xldmVscz1mdW5jdGlvbigpe3ZhciB0LGUscixuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLHksdixiLHg7Zm9yKHA9dGhpcy5tb2RlbC5wbG90LnJlbmRlcmVycyxjPXRoaXMubW9kZWwucGxvdC50b29sYmFyLnRvb2xzLGU9MCxuPWMubGVuZ3RoO2U8bjtlKyspZj1jW2VdLGQ9Zi5nZXQoInN5bnRoZXRpY19yZW5kZXJlcnMiKSxwPXAuY29uY2F0KGQpO2ZvcihoPW0ua2V5cyh0aGlzLnJlbmRlcmVyX3ZpZXdzKSx4PWcodGhpcy5yZW5kZXJlcl92aWV3cyxwLHRoaXMudmlld19vcHRpb25zKCkpLF89bS5kaWZmZXJlbmNlKGgsbS5wbHVjayhwLCJpZCIpKSxyPTAsbz1fLmxlbmd0aDtyPG87cisrKXQ9X1tyXSxkZWxldGUgdGhpcy5sZXZlbHMuZ2x5cGhbdF07Zm9yKHY9Zyh0aGlzLnRvb2xfdmlld3MsdGhpcy5tb2RlbC5wbG90LnRvb2xiYXIudG9vbHMsdGhpcy52aWV3X29wdGlvbnMoKSksbD0wLGk9eC5sZW5ndGg7bDxpO2wrKyliPXhbbF0sYT1iLm1nZXQoImxldmVsIiksdGhpcy5sZXZlbHNbYV1bYi5tb2RlbC5pZF09YixiLmJpbmRfYm9rZWhfZXZlbnRzKCk7Zm9yKHU9MCxzPXYubGVuZ3RoO3U8czt1KyspeT12W3VdLGE9eS5tZ2V0KCJsZXZlbCIpLHRoaXMubGV2ZWxzW2FdW3kubW9kZWwuaWRdPXkseS5iaW5kX2Jva2VoX2V2ZW50cygpLHRoaXMudWlfZXZlbnRfYnVzLnJlZ2lzdGVyX3Rvb2woeSk7cmV0dXJuIHRoaXN9LGUucHJvdG90eXBlLmJpbmRfYm9rZWhfZXZlbnRzPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47ZT10aGlzLm1vZGVsLmZyYW1lLmdldCgieF9yYW5nZXMiKTtmb3IodCBpbiBlKW49ZVt0XSx0aGlzLmxpc3RlblRvKG4sImNoYW5nZSIsdGhpcy5yZXF1ZXN0X3JlbmRlcik7cj10aGlzLm1vZGVsLmZyYW1lLmdldCgieV9yYW5nZXMiKTtmb3IodCBpbiByKW49clt0XSx0aGlzLmxpc3RlblRvKG4sImNoYW5nZSIsdGhpcy5yZXF1ZXN0X3JlbmRlcik7cmV0dXJuIHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbC5wbG90LCJjaGFuZ2U6cmVuZGVyZXJzIix0aGlzLmJ1aWxkX2xldmVscyksdGhpcy5saXN0ZW5Ubyh0aGlzLm1vZGVsLnBsb3QudG9vbGJhciwiY2hhbmdlOnRvb2xzIix0aGlzLmJ1aWxkX2xldmVscyksdGhpcy5saXN0ZW5Ubyh0aGlzLm1vZGVsLnBsb3QsImNoYW5nZSIsdGhpcy5yZXF1ZXN0X3JlbmRlciksdGhpcy5saXN0ZW5Ubyh0aGlzLm1vZGVsLnBsb3QsImRlc3Ryb3kiLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiB0LnJlbW92ZSgpfX0odGhpcykpLHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbC5wbG90LmRvY3VtZW50LnNvbHZlcigpLCJsYXlvdXRfdXBkYXRlIixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdC5yZXF1ZXN0X3JlbmRlcigpfX0odGhpcykpLHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbC5wbG90LmRvY3VtZW50LnNvbHZlcigpLCJyZXNpemUiLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiB0LnJlc2l6ZSgpfX0odGhpcykpLHRoaXMubGlzdGVuVG8odGhpcy5jYW52YXMsImNoYW5nZTpwaXhlbF9yYXRpbyIsZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHQucmVxdWVzdF9yZW5kZXIoKX19KHRoaXMpKX0sZS5wcm90b3R5cGUuc2V0X2luaXRpYWxfcmFuZ2U9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGksczt0PSEwLGk9e30scj10aGlzLmZyYW1lLmdldCgieF9yYW5nZXMiKTtmb3IoZSBpbiByKXtpZihvPXJbZV0sbnVsbD09by5nZXQoInN0YXJ0Iil8fG51bGw9PW8uZ2V0KCJlbmQiKXx8bS5pc05hTihvLmdldCgic3RhcnQiKStvLmdldCgiZW5kIikpKXt0PSExO2JyZWFrfWlbZV09e3N0YXJ0Om8uZ2V0KCJzdGFydCIpLGVuZDpvLmdldCgiZW5kIil9fWlmKHQpe3M9e30sbj10aGlzLmZyYW1lLmdldCgieV9yYW5nZXMiKTtmb3IoZSBpbiBuKXtpZihvPW5bZV0sbnVsbD09by5nZXQoInN0YXJ0Iil8fG51bGw9PW8uZ2V0KCJlbmQiKXx8bS5pc05hTihvLmdldCgic3RhcnQiKStvLmdldCgiZW5kIikpKXt0PSExO2JyZWFrfXNbZV09e3N0YXJ0Om8uZ2V0KCJzdGFydCIpLGVuZDpvLmdldCgiZW5kIil9fX1yZXR1cm4gdD8odGhpcy5faW5pdGlhbF9zdGF0ZV9pbmZvLnJhbmdlPXRoaXMuaW5pdGlhbF9yYW5nZV9pbmZvPXt4cnM6aSx5cnM6c30sYi5kZWJ1ZygiaW5pdGlhbCByYW5nZXMgc2V0IikpOmIud2FybigiY291bGQgbm90IHNldCBpbml0aWFsIHJhbmdlcyIpfSxlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24odCl7dmFyIGUscixvLGkscyxhLGw7aWYobnVsbD09dCYmKHQ9ITEpLGIudHJhY2UoIlBsb3RDYW52YXMucmVuZGVyKGZvcmNlX2NhbnZhcz0iK3QrIikgZm9yICIrdGhpcy5tb2RlbC5pZCksbnVsbCE9dGhpcy5tb2RlbC5kb2N1bWVudCl7RGF0ZS5ub3coKS10aGlzLmludGVyYWN0aXZlX3RpbWVzdGFtcDx0aGlzLm1vZGVsLnBsb3QubG9kX2ludGVydmFsPyh0aGlzLmludGVyYWN0aXZlPSEwLGk9dGhpcy5tb2RlbC5wbG90LmxvZF90aW1lb3V0LHNldFRpbWVvdXQoZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHQuaW50ZXJhY3RpdmUmJkRhdGUubm93KCktdC5pbnRlcmFjdGl2ZV90aW1lc3RhbXA+aSYmKHQuaW50ZXJhY3RpdmU9ITEpLHQucmVxdWVzdF9yZW5kZXIoKX19KHRoaXMpLGkpKTp0aGlzLmludGVyYWN0aXZlPSExLGE9dGhpcy5yZW5kZXJlcl92aWV3cztmb3IobyBpbiBhKWlmKGw9YVtvXSxudWxsPT10aGlzLnJhbmdlX3VwZGF0ZV90aW1lc3RhbXB8fGwuc2V0X2RhdGFfdGltZXN0YW1wPnRoaXMucmFuZ2VfdXBkYXRlX3RpbWVzdGFtcCl7dGhpcy51cGRhdGVfZGF0YXJhbmdlcygpO2JyZWFrfXJldHVybiB0aGlzLnVwZGF0ZV9jb25zdHJhaW50cygpLHRoaXMubW9kZWwuZ2V0KCJmcmFtZSIpLl91cGRhdGVfbWFwcGVycygpLGU9dGhpcy5jYW52YXNfdmlldy5jdHgsZS5waXhlbF9yYXRpbz1zPXRoaXMuY2FudmFzX3ZpZXcucGl4ZWxfcmF0aW8sZS5zYXZlKCksZS5zY2FsZShzLHMpLGUudHJhbnNsYXRlKC41LC41KSxyPVt0aGlzLmNhbnZhcy52eF90b19zeCh0aGlzLmZyYW1lLmdldCgibGVmdCIpKSx0aGlzLmNhbnZhcy52eV90b19zeSh0aGlzLmZyYW1lLmdldCgidG9wIikpLHRoaXMuZnJhbWUuZ2V0KCJ3aWR0aCIpLHRoaXMuZnJhbWUuZ2V0KCJoZWlnaHQiKV0sdGhpcy5fbWFwX2hvb2soZSxyKSx0aGlzLl9wYWludF9lbXB0eShlLHIpLHRoaXMucHJlcGFyZV93ZWJnbChzLHIpLGUuc2F2ZSgpLHRoaXMudmlzdWFscy5vdXRsaW5lX2xpbmUuZG9pdCYmKHRoaXMudmlzdWFscy5vdXRsaW5lX2xpbmUuc2V0X3ZhbHVlKGUpLGUuc3Ryb2tlUmVjdC5hcHBseShlLHIpKSxlLnJlc3RvcmUoKSx0aGlzLl9yZW5kZXJfbGV2ZWxzKGUsWyJpbWFnZSIsInVuZGVybGF5IiwiZ2x5cGgiXSxyKSx0aGlzLmJsaXRfd2ViZ2wocyksdGhpcy5fcmVuZGVyX2xldmVscyhlLFsiYW5ub3RhdGlvbiJdLHIpLHRoaXMuX3JlbmRlcl9sZXZlbHMoZSxbIm92ZXJsYXkiLCJ0b29sIl0pLG51bGw9PXRoaXMuaW5pdGlhbF9yYW5nZV9pbmZvJiZ0aGlzLnNldF9pbml0aWFsX3JhbmdlKCksZS5yZXN0b3JlKCksbnVsbCE9dGhpcy5tb2RlbC5kb2N1bWVudC5fdW5yZW5kZXJlZF9wbG90cyYmKGRlbGV0ZSB0aGlzLm1vZGVsLmRvY3VtZW50Ll91bnJlbmRlcmVkX3Bsb3RzW3RoaXMuaWRdLG0uaXNFbXB0eSh0aGlzLm1vZGVsLmRvY3VtZW50Ll91bnJlbmRlcmVkX3Bsb3RzKSk/KHRoaXMubW9kZWwuZG9jdW1lbnQuX3VucmVuZGVyZWRfcGxvdHM9bnVsbCxtLmRlbGF5KG4ucHJveHkodGhpcy5tb2RlbC5kb2N1bWVudC5yZXNpemUsdGhpcy5tb2RlbC5kb2N1bWVudCksMSkpOnZvaWQgMDsKfX0sZS5wcm90b3R5cGUucmVzaXplPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47bj10aGlzLm1vZGVsLl93aWR0aC5fdmFsdWUsZT10aGlzLm1vZGVsLl9oZWlnaHQuX3ZhbHVlLHRoaXMuY2FudmFzX3ZpZXcuc2V0X2RpbXMoW24sZV0sITApLHRoaXMuY2FudmFzX3ZpZXcucHJlcGFyZV9jYW52YXMoKTt0cnl7dGhpcy51cGRhdGVfY29uc3RyYWludHMoKX1jYXRjaCh0KXtyPXR9cmV0dXJuIHRoaXMuJGVsLmNzcyh7cG9zaXRpb246ImFic29sdXRlIixsZWZ0OnRoaXMubW9kZWwuX2RvbV9sZWZ0Ll92YWx1ZSx0b3A6dGhpcy5tb2RlbC5fZG9tX3RvcC5fdmFsdWUsd2lkdGg6dGhpcy5tb2RlbC5fd2lkdGguX3ZhbHVlLGhlaWdodDp0aGlzLm1vZGVsLl9oZWlnaHQuX3ZhbHVlfSl9LGUucHJvdG90eXBlLnVwZGF0ZV9jb25zdHJhaW50cz1mdW5jdGlvbigpe3ZhciB0LGUscixuO3I9dGhpcy5tb2RlbC5kb2N1bWVudC5zb2x2ZXIoKSxyLnN1Z2dlc3RfdmFsdWUodGhpcy5mcmFtZS5fd2lkdGgsdGhpcy5jYW52YXMuZ2V0KCJ3aWR0aCIpLTEpLHIuc3VnZ2VzdF92YWx1ZSh0aGlzLmZyYW1lLl9oZWlnaHQsdGhpcy5jYW52YXMuZ2V0KCJoZWlnaHQiKS0xKSxlPXRoaXMucmVuZGVyZXJfdmlld3M7Zm9yKHQgaW4gZSluPWVbdF0sbnVsbCE9bi5tb2RlbC5wYW5lbCYmayhuKTtyZXR1cm4gci51cGRhdGVfdmFyaWFibGVzKCExKX0sZS5wcm90b3R5cGUuX3JlbmRlcl9sZXZlbHM9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLGc7Zm9yKHQuc2F2ZSgpLG51bGwhPXImJih0LmJlZ2luUGF0aCgpLHQucmVjdC5hcHBseSh0LHIpLHQuY2xpcCgpLHQuYmVnaW5QYXRoKCkpLG89e30scD10aGlzLm1vZGVsLnBsb3QucmVuZGVyZXJzLG49aT0wLGE9cC5sZW5ndGg7aTxhO249KytpKV89cFtuXSxvW18uaWRdPW47Zm9yKGc9ZnVuY3Rpb24odCl7cmV0dXJuIG9bdC5tb2RlbC5pZF19LHM9MCxsPWUubGVuZ3RoO3M8bDtzKyspZm9yKGg9ZVtzXSxmPW0uc29ydEJ5KG0udmFsdWVzKHRoaXMubGV2ZWxzW2hdKSxnKSxjPTAsdT1mLmxlbmd0aDtjPHU7YysrKWQ9ZltjXSxkLnJlbmRlcigpO3JldHVybiB0LnJlc3RvcmUoKX0sZS5wcm90b3R5cGUuX21hcF9ob29rPWZ1bmN0aW9uKHQsZSl7fSxlLnByb3RvdHlwZS5fcGFpbnRfZW1wdHk9ZnVuY3Rpb24odCxlKXtpZih0LmNsZWFyUmVjdCgwLDAsdGhpcy5jYW52YXNfdmlldy5tZ2V0KCJ3aWR0aCIpLHRoaXMuY2FudmFzX3ZpZXcubWdldCgiaGVpZ2h0IikpLHRoaXMudmlzdWFscy5ib3JkZXJfZmlsbC5kb2l0JiYodGhpcy52aXN1YWxzLmJvcmRlcl9maWxsLnNldF92YWx1ZSh0KSx0LmZpbGxSZWN0KDAsMCx0aGlzLmNhbnZhc192aWV3Lm1nZXQoIndpZHRoIiksdGhpcy5jYW52YXNfdmlldy5tZ2V0KCJoZWlnaHQiKSksdC5jbGVhclJlY3QuYXBwbHkodCxlKSksdGhpcy52aXN1YWxzLmJhY2tncm91bmRfZmlsbC5kb2l0KXJldHVybiB0aGlzLnZpc3VhbHMuYmFja2dyb3VuZF9maWxsLnNldF92YWx1ZSh0KSx0LmZpbGxSZWN0LmFwcGx5KHQsZSl9LGV9KGQuVmlldykscD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gVChlLHQpLGUucHJvdG90eXBlLnR5cGU9IlBsb3RDYW52YXMiLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1fLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXt2YXIgbjtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLmNhbnZhcz1uZXcgby5Nb2RlbCh7bWFwOm51bGwhPShuPXRoaXMudXNlX21hcCkmJm4saW5pdGlhbF93aWR0aDp0aGlzLnBsb3QucGxvdF93aWR0aCxpbml0aWFsX2hlaWdodDp0aGlzLnBsb3QucGxvdF9oZWlnaHQsdXNlX2hpZHBpOnRoaXMucGxvdC5oaWRwaX0pLHRoaXMuZnJhbWU9bmV3IGkuTW9kZWwoe3hfcmFuZ2U6dGhpcy5wbG90LnhfcmFuZ2UsZXh0cmFfeF9yYW5nZXM6dGhpcy5wbG90LmV4dHJhX3hfcmFuZ2VzLHhfbWFwcGVyX3R5cGU6dGhpcy5wbG90LnhfbWFwcGVyX3R5cGUseV9yYW5nZTp0aGlzLnBsb3QueV9yYW5nZSxleHRyYV95X3Jhbmdlczp0aGlzLnBsb3QuZXh0cmFfeV9yYW5nZXMseV9tYXBwZXJfdHlwZTp0aGlzLnBsb3QueV9tYXBwZXJfdHlwZX0pLHRoaXMuYWJvdmVfcGFuZWw9bmV3IGguTW9kZWwsdGhpcy5iZWxvd19wYW5lbD1uZXcgaC5Nb2RlbCx0aGlzLmxlZnRfcGFuZWw9bmV3IGguTW9kZWwsdGhpcy5yaWdodF9wYW5lbD1uZXcgaC5Nb2RlbCxiLmRlYnVnKCJQbG90Q2FudmFzIGluaXRpYWxpemVkIil9LGUucHJvdG90eXBlLmFkZF9yZW5kZXJlcl90b19jYW52YXNfc2lkZT1mdW5jdGlvbih0LGUpe2lmKCJjZW50ZXIiIT09ZSlyZXR1cm4gdC5hZGRfcGFuZWwoZSl9LGUucHJvdG90eXBlLl9kb2NfYXR0YWNoZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jYW52YXMuYXR0YWNoX2RvY3VtZW50KHRoaXMuZG9jdW1lbnQpLHRoaXMuZnJhbWUuYXR0YWNoX2RvY3VtZW50KHRoaXMuZG9jdW1lbnQpLHRoaXMuYWJvdmVfcGFuZWwuYXR0YWNoX2RvY3VtZW50KHRoaXMuZG9jdW1lbnQpLHRoaXMuYmVsb3dfcGFuZWwuYXR0YWNoX2RvY3VtZW50KHRoaXMuZG9jdW1lbnQpLHRoaXMubGVmdF9wYW5lbC5hdHRhY2hfZG9jdW1lbnQodGhpcy5kb2N1bWVudCksdGhpcy5yaWdodF9wYW5lbC5hdHRhY2hfZG9jdW1lbnQodGhpcy5kb2N1bWVudCksYi5kZWJ1ZygiUGxvdENhbnZhcyBhdHRhY2hlZCB0byBkb2N1bWVudCIpfSxlLm92ZXJyaWRlKHtzaXppbmdfbW9kZToic3RyZXRjaF9ib3RoIn0pLGUuaW50ZXJuYWwoe3Bsb3Q6W3guSW5zdGFuY2VdLHRvb2xiYXI6W3guSW5zdGFuY2VdLGNhbnZhczpbeC5JbnN0YW5jZV0sZnJhbWU6W3guSW5zdGFuY2VdfSksZS5wcm90b3R5cGUuZ2V0X2xheW91dGFibGVfY2hpbGRyZW49ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLGw7Zm9yKHQ9W3RoaXMuYWJvdmVfcGFuZWwsdGhpcy5iZWxvd19wYW5lbCx0aGlzLmxlZnRfcGFuZWwsdGhpcy5yaWdodF9wYW5lbCx0aGlzLmNhbnZhcyx0aGlzLmZyYW1lXSxhPVsiYWJvdmUiLCJiZWxvdyIsImxlZnQiLCJyaWdodCJdLGU9MCxvPWEubGVuZ3RoO2U8bztlKyspZm9yKGw9YVtlXSxuPXRoaXMucGxvdC5nZXQobCkscj0wLGk9bi5sZW5ndGg7cjxpO3IrKylzPW5bcl0sbnVsbCE9cy5wYW5lbCYmdC5wdXNoKHMucGFuZWwpO3JldHVybiB0fSxlLnByb3RvdHlwZS5nZXRfZWRpdF92YXJpYWJsZXM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvO2ZvcihlPVtdLG89dGhpcy5nZXRfbGF5b3V0YWJsZV9jaGlsZHJlbigpLHI9MCxuPW8ubGVuZ3RoO3I8bjtyKyspdD1vW3JdLGU9ZS5jb25jYXQodC5nZXRfZWRpdF92YXJpYWJsZXMoKSk7cmV0dXJuIGV9LGUucHJvdG90eXBlLmdldF9jb25zdHJhaW50cz1mdW5jdGlvbigpe3ZhciB0LHIsbixvLGk7Zm9yKHI9ZS5fX3N1cGVyX18uZ2V0X2NvbnN0cmFpbnRzLmNhbGwodGhpcykscj1yLmNvbmNhdCh0aGlzLl9nZXRfY29uc3RhbnRfY29uc3RyYWludHMoKSkscj1yLmNvbmNhdCh0aGlzLl9nZXRfc2lkZV9jb25zdHJhaW50cygpKSxpPXRoaXMuZ2V0X2xheW91dGFibGVfY2hpbGRyZW4oKSxuPTAsbz1pLmxlbmd0aDtuPG87bisrKXQ9aVtuXSxyPXIuY29uY2F0KHQuZ2V0X2NvbnN0cmFpbnRzKCkpO3JldHVybiByfSxlLnByb3RvdHlwZS5fZ2V0X2NvbnN0YW50X2NvbnN0cmFpbnRzPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbztyZXR1cm4gbz10aGlzLnBsb3QubWluX2JvcmRlcl90b3AsZT10aGlzLnBsb3QubWluX2JvcmRlcl9ib3R0b20scj10aGlzLnBsb3QubWluX2JvcmRlcl9sZWZ0LG49dGhpcy5wbG90Lm1pbl9ib3JkZXJfcmlnaHQsdD1bXSx0LnB1c2gobCh0aGlzLmFib3ZlX3BhbmVsLl9oZWlnaHQsLW8pKSx0LnB1c2gobCh0aGlzLmJlbG93X3BhbmVsLl9oZWlnaHQsLWUpKSx0LnB1c2gobCh0aGlzLmxlZnRfcGFuZWwuX3dpZHRoLC1yKSksdC5wdXNoKGwodGhpcy5yaWdodF9wYW5lbC5fd2lkdGgsLW4pKSx0LnB1c2goYSh0aGlzLmFib3ZlX3BhbmVsLl90b3AsWy0xLHRoaXMuY2FudmFzLl90b3BdKSksdC5wdXNoKGEodGhpcy5hYm92ZV9wYW5lbC5fYm90dG9tLFstMSx0aGlzLmZyYW1lLl90b3BdKSksdC5wdXNoKGEodGhpcy5iZWxvd19wYW5lbC5fYm90dG9tLFstMSx0aGlzLmNhbnZhcy5fYm90dG9tXSkpLHQucHVzaChhKHRoaXMuYmVsb3dfcGFuZWwuX3RvcCxbLTEsdGhpcy5mcmFtZS5fYm90dG9tXSkpLHQucHVzaChhKHRoaXMubGVmdF9wYW5lbC5fbGVmdCxbLTEsdGhpcy5jYW52YXMuX2xlZnRdKSksdC5wdXNoKGEodGhpcy5sZWZ0X3BhbmVsLl9yaWdodCxbLTEsdGhpcy5mcmFtZS5fbGVmdF0pKSx0LnB1c2goYSh0aGlzLnJpZ2h0X3BhbmVsLl9yaWdodCxbLTEsdGhpcy5jYW52YXMuX3JpZ2h0XSkpLHQucHVzaChhKHRoaXMucmlnaHRfcGFuZWwuX2xlZnQsWy0xLHRoaXMuZnJhbWUuX3JpZ2h0XSkpLHQucHVzaChhKHRoaXMuYWJvdmVfcGFuZWwuX2hlaWdodCxbLTEsdGhpcy5fdG9wXSkpLHQucHVzaChhKHRoaXMuYWJvdmVfcGFuZWwuX2hlaWdodCxbLTEsdGhpcy5jYW52YXMuX3RvcF0sdGhpcy5mcmFtZS5fdG9wKSksdC5wdXNoKGEodGhpcy5iZWxvd19wYW5lbC5faGVpZ2h0LFstMSx0aGlzLl9oZWlnaHRdLHRoaXMuX2JvdHRvbSkpLHQucHVzaChhKHRoaXMuYmVsb3dfcGFuZWwuX2hlaWdodCxbLTEsdGhpcy5mcmFtZS5fYm90dG9tXSkpLHQucHVzaChhKHRoaXMubGVmdF9wYW5lbC5fd2lkdGgsWy0xLHRoaXMuX2xlZnRdKSksdC5wdXNoKGEodGhpcy5sZWZ0X3BhbmVsLl93aWR0aCxbLTEsdGhpcy5mcmFtZS5fbGVmdF0pKSx0LnB1c2goYSh0aGlzLnJpZ2h0X3BhbmVsLl93aWR0aCxbLTEsdGhpcy5fd2lkdGhdLHRoaXMuX3JpZ2h0KSksdC5wdXNoKGEodGhpcy5yaWdodF9wYW5lbC5fd2lkdGgsWy0xLHRoaXMuY2FudmFzLl9yaWdodF0sdGhpcy5mcmFtZS5fcmlnaHQpKSx0fSxlLnByb3RvdHlwZS5fZ2V0X3NpZGVfY29uc3RyYWludHM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxsLHUsaDtmb3IodD1bXSx1PVsiYWJvdmUiLCJiZWxvdyIsImxlZnQiLCJyaWdodCJdLGU9MCxpPXUubGVuZ3RoO2U8aTtlKyspe2ZvcihoPXVbZV0sbz10aGlzLnBsb3QuZ2V0KGgpLG49dGhpcy5mcmFtZSxyPTAscz1vLmxlbmd0aDtyPHM7cisrKWw9b1tyXSwiYWJvdmUiPT09aCYmdC5wdXNoKGEobi5wYW5lbC5fdG9wLFstMSxsLnBhbmVsLl9ib3R0b21dKSksImJlbG93Ij09PWgmJnQucHVzaChhKG4ucGFuZWwuX2JvdHRvbSxbLTEsbC5wYW5lbC5fdG9wXSkpLCJsZWZ0Ij09PWgmJnQucHVzaChhKG4ucGFuZWwuX2xlZnQsWy0xLGwucGFuZWwuX3JpZ2h0XSkpLCJyaWdodCI9PT1oJiZ0LnB1c2goYShuLnBhbmVsLl9yaWdodCxbLTEsbC5wYW5lbC5fbGVmdF0pKSxuPWw7MCE9PW8ubGVuZ3RoJiYoImFib3ZlIj09PWgmJnQucHVzaChhKG4ucGFuZWwuX3RvcCxbLTEsdGhpcy5hYm92ZV9wYW5lbC5fdG9wXSkpLCJiZWxvdyI9PT1oJiZ0LnB1c2goYShuLnBhbmVsLl9ib3R0b20sWy0xLHRoaXMuYmVsb3dfcGFuZWwuX2JvdHRvbV0pKSwibGVmdCI9PT1oJiZ0LnB1c2goYShuLnBhbmVsLl9sZWZ0LFstMSx0aGlzLmxlZnRfcGFuZWwuX2xlZnRdKSksInJpZ2h0Ij09PWgmJnQucHVzaChhKG4ucGFuZWwuX3JpZ2h0LFstMSx0aGlzLnJpZ2h0X3BhbmVsLl9yaWdodF0pKSl9cmV0dXJuIHR9LGUucHJvdG90eXBlLnBsb3RfY2FudmFzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9LGV9KGMuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6cCxWaWV3Ol99fSx7Ii4uLy4uL2NvbW1vbi9idWlsZF92aWV3cyI6ImNvbW1vbi9idWlsZF92aWV3cyIsIi4uLy4uL2NvbW1vbi91aV9ldmVudHMiOiJjb21tb24vdWlfZXZlbnRzIiwiLi4vLi4vY29yZS9lbnVtcyI6ImNvcmUvZW51bXMiLCIuLi8uLi9jb3JlL2xheW91dC9sYXlvdXRfY2FudmFzIjoiY29yZS9sYXlvdXQvbGF5b3V0X2NhbnZhcyIsIi4uLy4uL2NvcmUvbGF5b3V0L3NpZGVfcGFuZWwiOiJjb3JlL2xheW91dC9zaWRlX3BhbmVsIiwiLi4vLi4vY29yZS9sYXlvdXQvc29sdmVyIjoiY29yZS9sYXlvdXQvc29sdmVyIiwiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vY29yZS91dGlsL3Rocm90dGxlIjoiY29yZS91dGlsL3Rocm90dGxlIiwiLi4vY2FudmFzL2NhbnZhcyI6Im1vZGVscy9jYW52YXMvY2FudmFzIiwiLi4vY2FudmFzL2NhcnRlc2lhbl9mcmFtZSI6Im1vZGVscy9jYW52YXMvY2FydGVzaWFuX2ZyYW1lIiwiLi4vbGF5b3V0cy9sYXlvdXRfZG9tIjoibW9kZWxzL2xheW91dHMvbGF5b3V0X2RvbSIsIi4uL3Jhbmdlcy9kYXRhX3JhbmdlMWQiOiJtb2RlbHMvcmFuZ2VzL2RhdGFfcmFuZ2UxZCIsIi4uL3JlbmRlcmVycy9nbHlwaF9yZW5kZXJlciI6Im1vZGVscy9yZW5kZXJlcnMvZ2x5cGhfcmVuZGVyZXIiLCIuLi9yZW5kZXJlcnMvcmVuZGVyZXIiOiJtb2RlbHMvcmVuZGVyZXJzL3JlbmRlcmVyIixqcXVlcnk6ImpxdWVyeSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3Jhbmdlcy9kYXRhX3JhbmdlIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxvPXQoIi4vcmFuZ2UiKSxzPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGEoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJEYXRhUmFuZ2UiLGUuZGVmaW5lKHtuYW1lczpbcy5BcnJheSxbXV0scmVuZGVyZXJzOltzLkFycmF5LFtdXX0pLGV9KG8uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9yYW5nZSI6Im1vZGVscy9yYW5nZXMvcmFuZ2UiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9yYW5nZXMvZGF0YV9yYW5nZTFkIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1PWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSloLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGg9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2RhdGFfcmFuZ2UiKSxhPXQoIi4uLy4uL2NvcmUvbG9nZ2luZyIpLmxvZ2dlcixsPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLHM9dCgiLi4vLi4vY29yZS91dGlsL2Jib3giKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB1KGUsdCksZS5wcm90b3R5cGUudHlwZT0iRGF0YVJhbmdlMWQiLGUuZGVmaW5lKHtzdGFydDpbbC5OdW1iZXJdLGVuZDpbbC5OdW1iZXJdLHJhbmdlX3BhZGRpbmc6W2wuTnVtYmVyLC4xXSxmbGlwcGVkOltsLkJvb2wsITFdLGZvbGxvdzpbbC5TdHJpbmddLGZvbGxvd19pbnRlcnZhbDpbbC5OdW1iZXJdLGRlZmF1bHRfc3BhbjpbbC5OdW1iZXIsMl0sYm91bmRzOltsLkFueV0sbWluX2ludGVydmFsOltsLkFueV0sbWF4X2ludGVydmFsOltsLkFueV19KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoIm1pbiIsZnVuY3Rpb24oKXtyZXR1cm4gTWF0aC5taW4odGhpcy5nZXQoInN0YXJ0IiksdGhpcy5nZXQoImVuZCIpKX0sITApLHRoaXMuYWRkX2RlcGVuZGVuY2llcygibWluIix0aGlzLFsic3RhcnQiLCJlbmQiXSksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoIm1heCIsZnVuY3Rpb24oKXtyZXR1cm4gTWF0aC5tYXgodGhpcy5nZXQoInN0YXJ0IiksdGhpcy5nZXQoImVuZCIpKX0sITApLHRoaXMuYWRkX2RlcGVuZGVuY2llcygibWF4Iix0aGlzLFsic3RhcnQiLCJlbmQiXSksdGhpcy5wbG90X2JvdW5kcz17fSx0aGlzLmhhdmVfdXBkYXRlZF9pbnRlcmFjdGl2ZWx5PSExLHRoaXMuX2luaXRpYWxfc3RhcnQ9dGhpcy5nZXQoInN0YXJ0IiksdGhpcy5faW5pdGlhbF9lbmQ9dGhpcy5nZXQoImVuZCIpLHRoaXMuX2luaXRpYWxfcmFuZ2VfcGFkZGluZz10aGlzLmdldCgicmFuZ2VfcGFkZGluZyIpLHRoaXMuX2luaXRpYWxfZm9sbG93PXRoaXMuZ2V0KCJmb2xsb3ciKSx0aGlzLl9pbml0aWFsX2ZvbGxvd19pbnRlcnZhbD10aGlzLmdldCgiZm9sbG93X2ludGVydmFsIiksdGhpcy5faW5pdGlhbF9kZWZhdWx0X3NwYW49dGhpcy5nZXQoImRlZmF1bHRfc3BhbiIpfSxlLnByb3RvdHlwZS5jb21wdXRlZF9yZW5kZXJlcnM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxsLHUsaCxjO2lmKGk9dGhpcy5nZXQoIm5hbWVzIiksaD10aGlzLmdldCgicmVuZGVyZXJzIiksMD09PWgubGVuZ3RoKWZvcih1PXRoaXMuZ2V0KCJwbG90cyIpLGU9MCxuPXUubGVuZ3RoO2U8bjtlKyspcz11W2VdLHQ9cy5nZXQoInJlbmRlcmVycyIpLGM9ZnVuY3Rpb24oKXt2YXIgZSxyLG47Zm9yKG49W10sZT0wLHI9dC5sZW5ndGg7ZTxyO2UrKylsPXRbZV0sIkdseXBoUmVuZGVyZXIiPT09bC50eXBlJiZuLnB1c2gobCk7cmV0dXJuIG59KCksaD1oLmNvbmNhdChjKTtmb3IoaS5sZW5ndGg+MCYmKGg9ZnVuY3Rpb24oKXt2YXIgdCxlLHI7Zm9yKHI9W10sdD0wLGU9aC5sZW5ndGg7dDxlO3QrKylsPWhbdF0saS5pbmRleE9mKGwuZ2V0KCJuYW1lIikpPj0wJiZyLnB1c2gobCk7cmV0dXJuIHJ9KCkpLGEuZGVidWcoImNvbXB1dGVkICIraC5sZW5ndGgrIiByZW5kZXJlcnMgZm9yIERhdGFSYW5nZTFkICIrdGhpcy5pZCkscj0wLG89aC5sZW5ndGg7cjxvO3IrKylsPWhbcl0sYS50cmFjZSgiIC0gIitsLnR5cGUrIiAiK2wuaWQpO3JldHVybiBofSxlLnByb3RvdHlwZS5fY29tcHV0ZV9wbG90X2JvdW5kcz1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpO2ZvcihpPXMuZW1wdHkoKSxyPTAsbj10Lmxlbmd0aDtyPG47cisrKW89dFtyXSxudWxsIT1lW28uaWRdJiYoaT1zLnVuaW9uKGksZVtvLmlkXSkpO3JldHVybiBpfSxlLnByb3RvdHlwZS5fY29tcHV0ZV9taW5fbWF4PWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLGksYSxsLHU7aT1zLmVtcHR5KCk7Zm9yKHIgaW4gdCl1PXRbcl0saT1zLnVuaW9uKGksdSk7cmV0dXJuIDA9PT1lPyhhPVtpLm1pblgsaS5tYXhYXSxvPWFbMF0sbj1hWzFdKToobD1baS5taW5ZLGkubWF4WV0sbz1sWzBdLG49bFsxXSksW28sbl19LGUucHJvdG90eXBlLl9jb21wdXRlX3JhbmdlPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLGkscyxhLGwsdSxoLGM7cmV0dXJuIHM9dGhpcy5nZXQoInJhbmdlX3BhZGRpbmciKSxudWxsIT1zJiZzPjA/KGg9ZT09PXQ/dGhpcy5nZXQoImRlZmF1bHRfc3BhbiIpOihlLXQpKigxK3MpLHI9KGUrdCkvMixhPVtyLWgvMixyK2gvMl0sYz1hWzBdLG49YVsxXSk6KGw9W3QsZV0sYz1sWzBdLG49bFsxXSksaT0xLHRoaXMuZ2V0KCJmbGlwcGVkIikmJih1PVtuLGNdLGM9dVswXSxuPXVbMV0saT0tMSksbz10aGlzLmdldCgiZm9sbG93X2ludGVydmFsIiksbnVsbCE9byYmTWF0aC5hYnMoYy1uKT5vJiYoInN0YXJ0Ij09PXRoaXMuZ2V0KCJmb2xsb3ciKT9uPWMraSpvOiJlbmQiPT09dGhpcy5nZXQoImZvbGxvdyIpJiYoYz1uLWkqbykpLFtjLG5dfSxlLnByb3RvdHlwZS51cGRhdGU9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF87aWYoIXRoaXMuaGF2ZV91cGRhdGVkX2ludGVyYWN0aXZlbHkpcmV0dXJuIHA9dGhpcy5jb21wdXRlZF9yZW5kZXJlcnMoKSx0aGlzLnBsb3RfYm91bmRzW3JdPXRoaXMuX2NvbXB1dGVfcGxvdF9ib3VuZHMocCx0KSx1PXRoaXMuX2NvbXB1dGVfbWluX21heCh0aGlzLnBsb3RfYm91bmRzLGUpLGE9dVswXSxzPXVbMV0saD10aGlzLl9jb21wdXRlX3JhbmdlKGEscyksXz1oWzBdLGk9aFsxXSxudWxsIT10aGlzLl9pbml0aWFsX3N0YXJ0JiYoXz10aGlzLl9pbml0aWFsX3N0YXJ0KSxudWxsIT10aGlzLl9pbml0aWFsX2VuZCYmKGk9dGhpcy5faW5pdGlhbF9lbmQpLGM9W3RoaXMuZ2V0KCJzdGFydCIpLHRoaXMuZ2V0KCJlbmQiKV0sbz1jWzBdLG49Y1sxXSxfPT09byYmaT09PW58fChsPXt9LF8hPT1vJiYobC5zdGFydD1fKSxpIT09biYmKGwuZW5kPWkpLHRoaXMuc2V0KGwpKSwiYXV0byI9PT10aGlzLmdldCgiYm91bmRzIik/dGhpcy5zZXQoImJvdW5kcyIsW18saV0pOnZvaWQgMH0sZS5wcm90b3R5cGUucmVzZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5oYXZlX3VwZGF0ZWRfaW50ZXJhY3RpdmVseT0hMSx0aGlzLnNldCh7cmFuZ2VfcGFkZGluZzp0aGlzLl9pbml0aWFsX3JhbmdlX3BhZGRpbmcsZm9sbG93OnRoaXMuX2luaXRpYWxfZm9sbG93LGZvbGxvd19pbnRlcnZhbDp0aGlzLl9pbml0aWFsX2ZvbGxvd19pbnRlcnZhbCxkZWZhdWx0X3NwYW46dGhpcy5faW5pdGlhbF9kZWZhdWx0X3NwYW59KX0sZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvfX0seyIuLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi9jb3JlL3V0aWwvYmJveCI6ImNvcmUvdXRpbC9iYm94IiwiLi9kYXRhX3JhbmdlIjoibW9kZWxzL3Jhbmdlcy9kYXRhX3JhbmdlIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvcmFuZ2VzL2ZhY3Rvcl9yYW5nZSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlsLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGw9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIiksbz10KCIuL3JhbmdlIikscz10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGUudHlwZT0iRmFjdG9yUmFuZ2UiLGUuZGVmaW5lKHtvZmZzZXQ6W3MuTnVtYmVyLDBdLGZhY3RvcnM6W3MuQXJyYXksW11dLGJvdW5kczpbcy5BbnldLG1pbl9pbnRlcnZhbDpbcy5BbnldLG1heF9pbnRlcnZhbDpbcy5BbnldfSksZS5pbnRlcm5hbCh7X2JvdW5kc19hc19mYWN0b3JzOltzLkFueV0sc3RhcnQ6W3MuTnVtYmVyXSxlbmQ6W3MuTnVtYmVyXX0pLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSxudWxsIT10aGlzLmdldCgiYm91bmRzIikmJiJhdXRvIiE9PXRoaXMuZ2V0KCJib3VuZHMiKT90aGlzLnNldCgiX2JvdW5kc19hc19mYWN0b3JzIix0aGlzLmdldCgiYm91bmRzIikpOnRoaXMuc2V0KCJfYm91bmRzX2FzX2ZhY3RvcnMiLHRoaXMuZ2V0KCJmYWN0b3JzIikpLHRoaXMuX2luaXQoKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgibWluIixmdW5jdGlvbigpe3JldHVybiB0aGlzLmdldCgic3RhcnQiKX0sITEpLHRoaXMuYWRkX2RlcGVuZGVuY2llcygibWluIix0aGlzLFsiZmFjdG9ycyIsIm9mZnNldCJdKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgibWF4IixmdW5jdGlvbigpe3JldHVybiB0aGlzLmdldCgiZW5kIil9LCExKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoIm1heCIsdGhpcyxbImZhY3RvcnMiLCJvZmZzZXQiXSksdGhpcy5saXN0ZW5Ubyh0aGlzLCJjaGFuZ2U6ZmFjdG9ycyIsdGhpcy5fdXBkYXRlX2ZhY3RvcnMpLHRoaXMubGlzdGVuVG8odGhpcywiY2hhbmdlOm9mZnNldCIsdGhpcy5faW5pdCl9LGUucHJvdG90eXBlLnJlc2V0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2luaXQoKX0sZS5wcm90b3R5cGUuX3VwZGF0ZV9mYWN0b3JzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuc2V0KCJfYm91bmRzX2FzX2ZhY3RvcnMiLHRoaXMuZ2V0KCJmYWN0b3JzIikpLHRoaXMuX2luaXQoKX0sZS5wcm90b3R5cGUuX2luaXQ9ZnVuY3Rpb24oKXt2YXIgdCxlLHI7aWYoZT10aGlzLmdldCgiZmFjdG9ycyIpLG51bGwhPXRoaXMuZ2V0KCJib3VuZHMiKSYmImF1dG8iIT09dGhpcy5nZXQoImJvdW5kcyIpJiYoZT10aGlzLmdldCgiX2JvdW5kc19hc19mYWN0b3JzIiksdGhpcy5zZXQoImZhY3RvcnMiLGUpKSxyPS41K3RoaXMuZ2V0KCJvZmZzZXQiKSx0PWUubGVuZ3RoK3IsdGhpcy5zZXQoInN0YXJ0IixyKSx0aGlzLnNldCgiZW5kIix0KSxudWxsIT10aGlzLmdldCgiYm91bmRzIikpcmV0dXJuIHRoaXMuc2V0KCJib3VuZHMiLFtyLHRdKX0sZX0oby5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpufX0seyIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuL3JhbmdlIjoibW9kZWxzL3Jhbmdlcy9yYW5nZSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3Jhbmdlcy9yYW5nZSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlsLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGw9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIiksbj10KCIuLi8uLi9tb2RlbCIpLHM9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gYShlLHQpLGUucHJvdG90eXBlLnR5cGU9IlJhbmdlIixlLmRlZmluZSh7Y2FsbGJhY2s6W3MuSW5zdGFuY2VdfSksZS5pbnRlcm5hbCh7cGxvdHM6W3MuQXJyYXksW11dfSksZS5wcm90b3R5cGUucmVzZXQ9ZnVuY3Rpb24oKXt9LGV9KG4pLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vbW9kZWwiOiJtb2RlbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3Jhbmdlcy9yYW5nZTFkIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vcmFuZ2UiKSxzPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3ZhciB0LHI7cmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBlP2UuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKToocj1hcmd1bWVudHNbMF0sdD1hcmd1bWVudHNbMV0sbmV3IGUoe3N0YXJ0OnIsZW5kOnR9KSl9cmV0dXJuIGEoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJSYW5nZTFkIixlLmRlZmluZSh7c3RhcnQ6W3MuTnVtYmVyLDBdLGVuZDpbcy5OdW1iZXIsMV0sYm91bmRzOltzLkFueV0sbWluX2ludGVydmFsOltzLkFueV0sbWF4X2ludGVydmFsOltzLkFueV19KSxlLnByb3RvdHlwZS5fc2V0X2F1dG9fYm91bmRzPWZ1bmN0aW9uKCl7dmFyIHQsZTtpZigiYXV0byI9PT10aGlzLmdldCgiYm91bmRzIikpcmV0dXJuIGU9TWF0aC5taW4odGhpcy5faW5pdGlhbF9zdGFydCx0aGlzLl9pbml0aWFsX2VuZCksdD1NYXRoLm1heCh0aGlzLl9pbml0aWFsX3N0YXJ0LHRoaXMuX2luaXRpYWxfZW5kKSx0aGlzLnNldCgiYm91bmRzIixbZSx0XSl9LGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgibWluIixmdW5jdGlvbigpe3JldHVybiBNYXRoLm1pbih0aGlzLmdldCgic3RhcnQiKSx0aGlzLmdldCgiZW5kIikpfSwhMCksdGhpcy5hZGRfZGVwZW5kZW5jaWVzKCJtaW4iLHRoaXMsWyJzdGFydCIsImVuZCJdKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgibWF4IixmdW5jdGlvbigpe3JldHVybiBNYXRoLm1heCh0aGlzLmdldCgic3RhcnQiKSx0aGlzLmdldCgiZW5kIikpfSwhMCksdGhpcy5hZGRfZGVwZW5kZW5jaWVzKCJtYXgiLHRoaXMsWyJzdGFydCIsImVuZCJdKSx0aGlzLl9pbml0aWFsX3N0YXJ0PXRoaXMuZ2V0KCJzdGFydCIpLHRoaXMuX2luaXRpYWxfZW5kPXRoaXMuZ2V0KCJlbmQiKSx0aGlzLl9zZXRfYXV0b19ib3VuZHMoKX0sZS5wcm90b3R5cGUucmVzZXQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5zZXQoe3N0YXJ0OnRoaXMuX2luaXRpYWxfc3RhcnQsZW5kOnRoaXMuX2luaXRpYWxfZW5kfSksdGhpcy5fc2V0X2F1dG9fYm91bmRzKCl9LGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9yYW5nZSI6Im1vZGVscy9yYW5nZXMvcmFuZ2UiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9yZW5kZXJlcnMvZ2x5cGhfcmVuZGVyZXIiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxjPXt9Lmhhc093blByb3BlcnR5O2E9dCgidW5kZXJzY29yZSIpLHM9dCgiLi9yZW5kZXJlciIpLGk9dCgiLi4vc291cmNlcy9yZW1vdGVfZGF0YV9zb3VyY2UiKSxsPXQoIi4uLy4uL2NvcmUvbG9nZ2luZyIpLmxvZ2dlcix1PXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3ZhciByLG4sbyxzLGwsdSxoLGMscDtpZihlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0KSxyPXRoaXMubWdldCgiZ2x5cGgiKSxzPWEuY29udGFpbnMoci5taXhpbnMsImZpbGwiKSxsPWEuY29udGFpbnMoci5taXhpbnMsImxpbmUiKSxvPWEub21pdChhLmNsb25lKHIuYXR0cmlidXRlcyksImlkIiksaD1mdW5jdGlvbih0KXt2YXIgZTtyZXR1cm4gZT1hLmNsb25lKG8pLHMmJmEuZXh0ZW5kKGUsdC5maWxsKSxsJiZhLmV4dGVuZChlLHQubGluZSksbmV3IHIuY29uc3RydWN0b3IoZSl9LHRoaXMuZ2x5cGg9dGhpcy5idWlsZF9nbHlwaF92aWV3KHIpLHA9dGhpcy5tZ2V0KCJzZWxlY3Rpb25fZ2x5cGgiKSxudWxsPT1wJiYocD1oKHRoaXMubW9kZWwuc2VsZWN0aW9uX2RlZmF1bHRzKSksdGhpcy5zZWxlY3Rpb25fZ2x5cGg9dGhpcy5idWlsZF9nbHlwaF92aWV3KHApLGM9dGhpcy5tZ2V0KCJub25zZWxlY3Rpb25fZ2x5cGgiKSxudWxsPT1jJiYoYz1oKHRoaXMubW9kZWwubm9uc2VsZWN0aW9uX2RlZmF1bHRzKSksdGhpcy5ub25zZWxlY3Rpb25fZ2x5cGg9dGhpcy5idWlsZF9nbHlwaF92aWV3KGMpLHU9dGhpcy5tZ2V0KCJob3Zlcl9nbHlwaCIpLG51bGwhPXUmJih0aGlzLmhvdmVyX2dseXBoPXRoaXMuYnVpbGRfZ2x5cGhfdmlldyh1KSksbj1oKHRoaXMubW9kZWwuZGVjaW1hdGVkX2RlZmF1bHRzKSx0aGlzLmRlY2ltYXRlZF9nbHlwaD10aGlzLmJ1aWxkX2dseXBoX3ZpZXcobiksdGhpcy54bWFwcGVyPXRoaXMucGxvdF92aWV3LmZyYW1lLmdldCgieF9tYXBwZXJzIilbdGhpcy5tZ2V0KCJ4X3JhbmdlX25hbWUiKV0sdGhpcy55bWFwcGVyPXRoaXMucGxvdF92aWV3LmZyYW1lLmdldCgieV9tYXBwZXJzIilbdGhpcy5tZ2V0KCJ5X3JhbmdlX25hbWUiKV0sdGhpcy5zZXRfZGF0YSghMSksdGhpcy5tZ2V0KCJkYXRhX3NvdXJjZSIpaW5zdGFuY2VvZiBpLk1vZGVsKXJldHVybiB0aGlzLm1nZXQoImRhdGFfc291cmNlIikuc2V0dXAodGhpcy5wbG90X3ZpZXcsdGhpcy5nbHlwaCl9LGUucHJvdG90eXBlLmJ1aWxkX2dseXBoX3ZpZXc9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyB0LmRlZmF1bHRfdmlldyh7bW9kZWw6dCxyZW5kZXJlcjp0aGlzLHBsb3Rfdmlldzp0aGlzLnBsb3RfdmlldyxwbG90X21vZGVsOnRoaXMucGxvdF9tb2RlbH0pfSxlLnByb3RvdHlwZS5iaW5kX2Jva2VoX2V2ZW50cz1mdW5jdGlvbigpe3JldHVybiB0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZSIsdGhpcy5yZXF1ZXN0X3JlbmRlciksdGhpcy5saXN0ZW5Ubyh0aGlzLm1nZXQoImRhdGFfc291cmNlIiksImNoYW5nZSIsdGhpcy5zZXRfZGF0YSksdGhpcy5saXN0ZW5Ubyh0aGlzLm1nZXQoImRhdGFfc291cmNlIiksInBhdGNoIix0aGlzLnNldF9kYXRhKSx0aGlzLmxpc3RlblRvKHRoaXMubWdldCgiZGF0YV9zb3VyY2UiKSwic3RyZWFtIix0aGlzLnNldF9kYXRhKSx0aGlzLmxpc3RlblRvKHRoaXMubWdldCgiZGF0YV9zb3VyY2UiKSwic2VsZWN0Iix0aGlzLnJlcXVlc3RfcmVuZGVyKSxudWxsIT10aGlzLmhvdmVyX2dseXBoJiZ0aGlzLmxpc3RlblRvKHRoaXMubWdldCgiZGF0YV9zb3VyY2UiKSwiaW5zcGVjdCIsdGhpcy5yZXF1ZXN0X3JlbmRlciksdGhpcy5saXN0ZW5Ubyh0aGlzLm1nZXQoImdseXBoIiksInByb3BjaGFuZ2UiLGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZ2x5cGguc2V0X3Zpc3VhbHModGhpcy5tZ2V0KCJkYXRhX3NvdXJjZSIpKSx0aGlzLnJlcXVlc3RfcmVuZGVyKCl9KX0sZS5wcm90b3R5cGUuaGF2ZV9zZWxlY3Rpb25fZ2x5cGhzPWZ1bmN0aW9uKCl7cmV0dXJuIG51bGwhPXRoaXMuc2VsZWN0aW9uX2dseXBoJiZudWxsIT10aGlzLm5vbnNlbGVjdGlvbl9nbHlwaH0sZS5wcm90b3R5cGUuc2V0X2RhdGE9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saSxzLGEsdSxoLGM7Zm9yKG51bGw9PXQmJih0PSEwKSxjPURhdGUubm93KCksaD10aGlzLm1nZXQoImRhdGFfc291cmNlIiksdGhpcy5nbHlwaC5tb2RlbC5zZXQoe3hfcmFuZ2VfbmFtZTp0aGlzLm1nZXQoInhfcmFuZ2VfbmFtZSIpLHlfcmFuZ2VfbmFtZTp0aGlzLm1nZXQoInlfcmFuZ2VfbmFtZSIpfSx7c2lsZW50OiEwfSksdGhpcy5nbHlwaC5zZXRfZGF0YShoLGUpLHRoaXMuZ2x5cGguc2V0X3Zpc3VhbHMoaCksdGhpcy5kZWNpbWF0ZWRfZ2x5cGguc2V0X3Zpc3VhbHMoaCksdGhpcy5oYXZlX3NlbGVjdGlvbl9nbHlwaHMoKSYmKHRoaXMuc2VsZWN0aW9uX2dseXBoLnNldF92aXN1YWxzKGgpLHRoaXMubm9uc2VsZWN0aW9uX2dseXBoLnNldF92aXN1YWxzKGgpKSxudWxsIT10aGlzLmhvdmVyX2dseXBoJiZ0aGlzLmhvdmVyX2dseXBoLnNldF92aXN1YWxzKGgpLGk9aC5nZXRfbGVuZ3RoKCksbnVsbD09aSYmKGk9MSksdGhpcy5hbGxfaW5kaWNlcz1mdW5jdGlvbigpe3U9W107Zm9yKHZhciB0PTA7MDw9aT90PGk6dD5pOzA8PWk/dCsrOnQtLSl1LnB1c2godCk7cmV0dXJuIHV9LmFwcGx5KHRoaXMpLHM9dGhpcy5wbG90X21vZGVsLnBsb3QubG9kX2ZhY3Rvcix0aGlzLmRlY2ltYXRlZD1bXSxuPW89MCxhPU1hdGguZmxvb3IodGhpcy5hbGxfaW5kaWNlcy5sZW5ndGgvcyk7MDw9YT9vPGE6bz5hO249MDw9YT8rK286LS1vKXRoaXMuZGVjaW1hdGVkLnB1c2godGhpcy5hbGxfaW5kaWNlc1tuKnNdKTtpZihyPURhdGUubm93KCktYyxsLmRlYnVnKHRoaXMuZ2x5cGgubW9kZWwudHlwZSsiIEdseXBoUmVuZGVyZXIgKCIrdGhpcy5tb2RlbC5pZCsiKTogc2V0X2RhdGEgZmluaXNoZWQgaW4gIityKyJtcyIpLHRoaXMuc2V0X2RhdGFfdGltZXN0YW1wPURhdGUubm93KCksdClyZXR1cm4gdGhpcy5yZXF1ZXN0X3JlbmRlcigpfSxlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTO2lmKHRoaXMubW9kZWwudmlzaWJsZSE9PSExKXtpZihNPURhdGUubm93KCkscz10aGlzLmdseXBoLmdsZ2x5cGgsaz1EYXRlLm5vdygpLHRoaXMuZ2x5cGgubWFwX2RhdGEoKSxlPURhdGUubm93KCktTSxqPURhdGUubm93KCksYz1zP3RoaXMuYWxsX2luZGljZXM6dGhpcy5nbHlwaC5fbWFza19kYXRhKHRoaXMuYWxsX2luZGljZXMpLHI9RGF0ZS5ub3coKS1qLHQ9dGhpcy5wbG90X3ZpZXcuY2FudmFzX3ZpZXcuY3R4LHQuc2F2ZSgpLGI9dGhpcy5tZ2V0KCJkYXRhX3NvdXJjZSIpLmdldCgic2VsZWN0ZWQiKSxiPWImJjAhPT1iLmxlbmd0aD9iWyIwZCJdLmdseXBoP2M6YlsiMWQiXS5pbmRpY2VzLmxlbmd0aD4wP2JbIjFkIl0uaW5kaWNlczpbXTpbXSxwPXRoaXMubWdldCgiZGF0YV9zb3VyY2UiKS5nZXQoImluc3BlY3RlZCIpLHA9cCYmMCE9PXAubGVuZ3RoP3BbIjBkIl0uZ2x5cGg/YzpwWyIxZCJdLmluZGljZXMubGVuZ3RoPjA/cFsiMWQiXS5pbmRpY2VzOltdOltdLGc9dGhpcy5wbG90X21vZGVsLnBsb3QubG9kX3RocmVzaG9sZCx0aGlzLnBsb3Rfdmlldy5pbnRlcmFjdGl2ZSYmIXMmJm51bGwhPWcmJnRoaXMuYWxsX2luZGljZXMubGVuZ3RoPmc/KGM9dGhpcy5kZWNpbWF0ZWQsdT10aGlzLmRlY2ltYXRlZF9nbHlwaCx2PXRoaXMuZGVjaW1hdGVkX2dseXBoLHc9dGhpcy5zZWxlY3Rpb25fZ2x5cGgpOih1PXRoaXMuZ2x5cGgsdj10aGlzLm5vbnNlbGVjdGlvbl9nbHlwaCx3PXRoaXMuc2VsZWN0aW9uX2dseXBoKSxudWxsIT10aGlzLmhvdmVyX2dseXBoJiZwLmxlbmd0aCYmKGM9YS53aXRob3V0LmJpbmQobnVsbCxjKS5hcHBseShudWxsLHApKSxiLmxlbmd0aCYmdGhpcy5oYXZlX3NlbGVjdGlvbl9nbHlwaHMoKSl7Zm9yKFM9RGF0ZS5ub3coKSx4PXt9LF89MCxmPWIubGVuZ3RoO188ZjtfKyspaD1iW19dLHhbaF09ITA7Zm9yKGI9bmV3IEFycmF5LHk9bmV3IEFycmF5LGQ9MCxtPWMubGVuZ3RoO2Q8bTtkKyspaD1jW2RdLG51bGwhPXhbaF0/Yi5wdXNoKGgpOnkucHVzaChoKTtvPURhdGUubm93KCktUyxUPURhdGUubm93KCksdi5yZW5kZXIodCx5LHRoaXMuZ2x5cGgpLHcucmVuZGVyKHQsYix0aGlzLmdseXBoKSxudWxsIT10aGlzLmhvdmVyX2dseXBoJiZ0aGlzLmhvdmVyX2dseXBoLnJlbmRlcih0LHAsdGhpcy5nbHlwaCksbj1EYXRlLm5vdygpLVR9ZWxzZSBUPURhdGUubm93KCksdS5yZW5kZXIodCxjLHRoaXMuZ2x5cGgpLHRoaXMuaG92ZXJfZ2x5cGgmJnAubGVuZ3RoJiZ0aGlzLmhvdmVyX2dseXBoLnJlbmRlcih0LHAsdGhpcy5nbHlwaCksbj1EYXRlLm5vdygpLVQ7cmV0dXJuIHRoaXMubGFzdF9kdHJlbmRlcj1uLGk9RGF0ZS5ub3coKS1NLGwuZGVidWcodGhpcy5nbHlwaC5tb2RlbC50eXBlKyIgR2x5cGhSZW5kZXJlciAoIit0aGlzLm1vZGVsLmlkKyIpOiByZW5kZXIgZmluaXNoZWQgaW4gIitpKyJtcyIpLGwudHJhY2UoIiAtIG1hcF9kYXRhIGZpbmlzaGVkIGluICAgICAgIDogIitlKyJtcyIpLG51bGwhPXImJmwudHJhY2UoIiAtIG1hc2tfZGF0YSBmaW5pc2hlZCBpbiAgICAgIDogIityKyJtcyIpLG51bGwhPW8mJmwudHJhY2UoIiAtIHNlbGVjdGlvbiBtYXNrIGZpbmlzaGVkIGluIDogIitvKyJtcyIpLGwudHJhY2UoIiAtIGdseXBoIHJlbmRlcnMgZmluaXNoZWQgaW4gIDogIituKyJtcyIpLHQucmVzdG9yZSgpfX0sZS5wcm90b3R5cGUubWFwX3RvX3NjcmVlbj1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnBsb3Rfdmlldy5tYXBfdG9fc2NyZWVuKHQsZSx0aGlzLm1nZXQoInhfcmFuZ2VfbmFtZSIpLHRoaXMubWdldCgieV9yYW5nZV9uYW1lIikpfSxlLnByb3RvdHlwZS5kcmF3X2xlZ2VuZD1mdW5jdGlvbih0LGUscixuLG8pe3JldHVybiB0aGlzLmdseXBoLmRyYXdfbGVnZW5kKHQsZSxyLG4sbyl9LGUucHJvdG90eXBlLmhpdF90ZXN0PWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmdseXBoLmhpdF90ZXN0KHQpfSxlfShzLlZpZXcpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9byxlLnByb3RvdHlwZS50eXBlPSJHbHlwaFJlbmRlcmVyIixlLmRlZmluZSh7eF9yYW5nZV9uYW1lOlt1LlN0cmluZywiZGVmYXVsdCJdLHlfcmFuZ2VfbmFtZTpbdS5TdHJpbmcsImRlZmF1bHQiXSxkYXRhX3NvdXJjZTpbdS5JbnN0YW5jZV0sZ2x5cGg6W3UuSW5zdGFuY2VdLGhvdmVyX2dseXBoOlt1Lkluc3RhbmNlXSxub25zZWxlY3Rpb25fZ2x5cGg6W3UuSW5zdGFuY2VdLHNlbGVjdGlvbl9nbHlwaDpbdS5JbnN0YW5jZV19KSxlLm92ZXJyaWRlKHtsZXZlbDoiZ2x5cGgifSksZS5wcm90b3R5cGUuc2VsZWN0aW9uX2RlZmF1bHRzPXtmaWxsOnt9LGxpbmU6e319LGUucHJvdG90eXBlLmRlY2ltYXRlZF9kZWZhdWx0cz17ZmlsbDp7ZmlsbF9hbHBoYTouMyxmaWxsX2NvbG9yOiJncmV5In0sbGluZTp7bGluZV9hbHBoYTouMyxsaW5lX2NvbG9yOiJncmV5In19LGUucHJvdG90eXBlLm5vbnNlbGVjdGlvbl9kZWZhdWx0cz17ZmlsbDp7ZmlsbF9hbHBoYTouMixsaW5lX2FscGhhOi4yfSxsaW5lOnt9fSxlfShzLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm4sVmlldzpvfX0seyIuLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi9zb3VyY2VzL3JlbW90ZV9kYXRhX3NvdXJjZSI6Im1vZGVscy9zb3VyY2VzL3JlbW90ZV9kYXRhX3NvdXJjZSIsIi4vcmVuZGVyZXIiOiJtb2RlbHMvcmVuZGVyZXJzL3JlbmRlcmVyIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvcmVuZGVyZXJzL2d1aWRlX3JlbmRlcmVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxvPXQoIi4vcmVuZGVyZXIiKSxzPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGEoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJHdWlkZVJlbmRlcmVyIixlLmRlZmluZSh7cGxvdDpbcy5JbnN0YW5jZV19KSxlLm92ZXJyaWRlKHtsZXZlbDoib3ZlcmxheSJ9KSxlfShvLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm59fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vcmVuZGVyZXIiOiJtb2RlbHMvcmVuZGVyZXJzL3JlbmRlcmVyIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvcmVuZGVyZXJzL3JlbmRlcmVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4PWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl3LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHc9e30uaGFzT3duUHJvcGVydHk7dT10KCJ1bmRlcnNjb3JlIiksdj10KCJwcm9qNCIpLGI9di5kZWZzKCJHT09HTEUiKSxuPXQoImJhY2tib25lIiksbz10KCIuLi8uLi9jb3JlL2Jva2VoX3ZpZXciKSxmPXQoIi4uLy4uL2NvcmUvdXRpbC9jb2xvciIpLmNvbG9yMnJnYmEsbT10KCIuLi8uLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIseT10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxnPXQoIi4uLy4uL2NvcmUvcHJvcGVydHlfbWl4aW5zIiksZD10KCIuLi8uLi9jb3JlL3V0aWwvbWF0aCIpLmFycmF5X21heCxpPXQoIi4uLy4uL21vZGVsIiksaD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKHQscil7dmFyIG4sbyxpLHMsYSxsLGg7Zm9yKG51bGw9PXQucHJlZml4JiYodC5wcmVmaXg9IiIpLGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmNhbGwodGhpcyx0LHIpLHRoaXMuY2FjaGU9e30sYT10aGlzLmdldCgib2JqIiksbD10aGlzLmdldCgicHJlZml4Iiksbz1hLnByb3BlcnRpZXNbbCt0aGlzLmRvX2F0dHJdLnNwZWMsdGhpcy5kb2l0PSF1LmlzTnVsbChvLnZhbHVlKSxoPXRoaXMuYXR0cnMsaT0wLHM9aC5sZW5ndGg7aTxzO2krKyluPWhbaV0sdGhpc1tuXT1hLnByb3BlcnRpZXNbbCtuXX1yZXR1cm4geChlLHQpLGUucHJvdG90eXBlLndhcm1fY2FjaGU9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGEsbDtmb3IoYT10aGlzLmF0dHJzLGw9W10scj0wLG49YS5sZW5ndGg7cjxuO3IrKyllPWFbcl0sbz10aGlzLmdldCgib2JqIiksaT10aGlzLmdldCgicHJlZml4Iikscz1vLnByb3BlcnRpZXNbaStlXSx1LmlzVW5kZWZpbmVkKHMuc3BlYy52YWx1ZSk/bC5wdXNoKHRoaXMuY2FjaGVbZSsiX2FycmF5Il09cy5hcnJheSh0KSk6bC5wdXNoKHRoaXMuY2FjaGVbZV09cy5zcGVjLnZhbHVlKTtyZXR1cm4gbH0sZS5wcm90b3R5cGUuY2FjaGVfc2VsZWN0PWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvO3JldHVybiByPXRoaXMuZ2V0KCJvYmoiKSxuPXRoaXMuZ2V0KCJwcmVmaXgiKSxvPXIucHJvcGVydGllc1tuK3RdLHUuaXNVbmRlZmluZWQoby5zcGVjLnZhbHVlKT90aGlzLmNhY2hlW3RdPXRoaXMuY2FjaGVbdCsiX2FycmF5Il1bZV06dGhpcy5jYWNoZVt0XT1vLnNwZWMudmFsdWV9LGV9KG4uTW9kZWwpLHA9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHgoZSx0KSxlLnByb3RvdHlwZS5hdHRycz11LmtleXMoZy5saW5lKCkpLGUucHJvdG90eXBlLmRvX2F0dHI9ImxpbmVfY29sb3IiLGUucHJvdG90eXBlLnNldF92YWx1ZT1mdW5jdGlvbih0KXtyZXR1cm4gdC5zdHJva2VTdHlsZT10aGlzLmxpbmVfY29sb3IudmFsdWUoKSx0Lmdsb2JhbEFscGhhPXRoaXMubGluZV9hbHBoYS52YWx1ZSgpLHQubGluZVdpZHRoPXRoaXMubGluZV93aWR0aC52YWx1ZSgpLHQubGluZUpvaW49dGhpcy5saW5lX2pvaW4udmFsdWUoKSx0LmxpbmVDYXA9dGhpcy5saW5lX2NhcC52YWx1ZSgpLHQuc2V0TGluZURhc2godGhpcy5saW5lX2Rhc2gudmFsdWUoKSksdC5zZXRMaW5lRGFzaE9mZnNldCh0aGlzLmxpbmVfZGFzaF9vZmZzZXQudmFsdWUoKSl9LGUucHJvdG90eXBlLnNldF92ZWN0b3JpemU9ZnVuY3Rpb24odCxlKXtpZih0aGlzLmNhY2hlX3NlbGVjdCgibGluZV9jb2xvciIsZSksdC5zdHJva2VTdHlsZSE9PXRoaXMuY2FjaGUubGluZV9jb2xvciYmKHQuc3Ryb2tlU3R5bGU9dGhpcy5jYWNoZS5saW5lX2NvbG9yKSx0aGlzLmNhY2hlX3NlbGVjdCgibGluZV9hbHBoYSIsZSksdC5nbG9iYWxBbHBoYSE9PXRoaXMuY2FjaGUubGluZV9hbHBoYSYmKHQuZ2xvYmFsQWxwaGE9dGhpcy5jYWNoZS5saW5lX2FscGhhKSx0aGlzLmNhY2hlX3NlbGVjdCgibGluZV93aWR0aCIsZSksdC5saW5lV2lkdGghPT10aGlzLmNhY2hlLmxpbmVfd2lkdGgmJih0LmxpbmVXaWR0aD10aGlzLmNhY2hlLmxpbmVfd2lkdGgpLHRoaXMuY2FjaGVfc2VsZWN0KCJsaW5lX2pvaW4iLGUpLHQubGluZUpvaW4hPT10aGlzLmNhY2hlLmxpbmVfam9pbiYmKHQubGluZUpvaW49dGhpcy5jYWNoZS5saW5lX2pvaW4pLHRoaXMuY2FjaGVfc2VsZWN0KCJsaW5lX2NhcCIsZSksdC5saW5lQ2FwIT09dGhpcy5jYWNoZS5saW5lX2NhcCYmKHQubGluZUNhcD10aGlzLmNhY2hlLmxpbmVfY2FwKSx0aGlzLmNhY2hlX3NlbGVjdCgibGluZV9kYXNoIixlKSx0LmdldExpbmVEYXNoKCkhPT10aGlzLmNhY2hlLmxpbmVfZGFzaCYmdC5zZXRMaW5lRGFzaCh0aGlzLmNhY2hlLmxpbmVfZGFzaCksdGhpcy5jYWNoZV9zZWxlY3QoImxpbmVfZGFzaF9vZmZzZXQiLGUpLHQuZ2V0TGluZURhc2hPZmZzZXQoKSE9PXRoaXMuY2FjaGUubGluZV9kYXNoX29mZnNldClyZXR1cm4gdC5zZXRMaW5lRGFzaE9mZnNldCh0aGlzLmNhY2hlLmxpbmVfZGFzaF9vZmZzZXQpfSxlLnByb3RvdHlwZS5jb2xvcl92YWx1ZT1mdW5jdGlvbigpe3ZhciB0O3JldHVybiB0PWYodGhpcy5saW5lX2NvbG9yLnZhbHVlKCksdGhpcy5saW5lX2FscGhhLnZhbHVlKCkpLCJyZ2JhKCIrMjU1KnRbMF0rIiwiKzI1NSp0WzFdKyIsIisyNTUqdFsyXSsiLCIrdFszXSsiKSJ9LGV9KGgpLGM9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHgoZSx0KSxlLnByb3RvdHlwZS5hdHRycz11LmtleXMoZy5maWxsKCkpLGUucHJvdG90eXBlLmRvX2F0dHI9ImZpbGxfY29sb3IiLGUucHJvdG90eXBlLnNldF92YWx1ZT1mdW5jdGlvbih0KXtyZXR1cm4gdC5maWxsU3R5bGU9dGhpcy5maWxsX2NvbG9yLnZhbHVlKCksdC5nbG9iYWxBbHBoYT10aGlzLmZpbGxfYWxwaGEudmFsdWUoKX0sZS5wcm90b3R5cGUuc2V0X3ZlY3Rvcml6ZT1mdW5jdGlvbih0LGUpe2lmKHRoaXMuY2FjaGVfc2VsZWN0KCJmaWxsX2NvbG9yIixlKSx0LmZpbGxTdHlsZSE9PXRoaXMuY2FjaGUuZmlsbF9jb2xvciYmKHQuZmlsbFN0eWxlPXRoaXMuY2FjaGUuZmlsbF9jb2xvciksdGhpcy5jYWNoZV9zZWxlY3QoImZpbGxfYWxwaGEiLGUpLHQuZ2xvYmFsQWxwaGEhPT10aGlzLmNhY2hlLmZpbGxfYWxwaGEpcmV0dXJuIHQuZ2xvYmFsQWxwaGE9dGhpcy5jYWNoZS5maWxsX2FscGhhfSxlLnByb3RvdHlwZS5jb2xvcl92YWx1ZT1mdW5jdGlvbigpe3ZhciB0O3JldHVybiB0PWYodGhpcy5maWxsX2NvbG9yLnZhbHVlKCksdGhpcy5maWxsX2FscGhhLnZhbHVlKCkpLCJyZ2JhKCIrMjU1KnRbMF0rIiwiKzI1NSp0WzFdKyIsIisyNTUqdFsyXSsiLCIrdFszXSsiKSJ9LGV9KGgpLF89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHgoZSx0KSxlLnByb3RvdHlwZS5hdHRycz11LmtleXMoZy50ZXh0KCkpLGUucHJvdG90eXBlLmRvX2F0dHI9InRleHRfY29sb3IiLGUucHJvdG90eXBlLmNhY2hlX3NlbGVjdD1mdW5jdGlvbih0LHIpe3ZhciBuO3JldHVybiJmb250Ij09PXQ/KG49ZS5fX3N1cGVyX18uY2FjaGVfc2VsZWN0LmNhbGwodGhpcywidGV4dF9mb250X3N0eWxlIixyKSsiICIrZS5fX3N1cGVyX18uY2FjaGVfc2VsZWN0LmNhbGwodGhpcywidGV4dF9mb250X3NpemUiLHIpKyIgIitlLl9fc3VwZXJfXy5jYWNoZV9zZWxlY3QuY2FsbCh0aGlzLCJ0ZXh0X2ZvbnQiLHIpLHRoaXMuY2FjaGUuZm9udD1uKTplLl9fc3VwZXJfXy5jYWNoZV9zZWxlY3QuY2FsbCh0aGlzLHQscil9LGUucHJvdG90eXBlLmZvbnRfdmFsdWU9ZnVuY3Rpb24oKXt2YXIgdCxlLHI7cmV0dXJuIHQ9dGhpcy50ZXh0X2ZvbnQudmFsdWUoKSxlPXRoaXMudGV4dF9mb250X3NpemUudmFsdWUoKSxyPXRoaXMudGV4dF9mb250X3N0eWxlLnZhbHVlKCkscisiICIrZSsiICIrdH0sZS5wcm90b3R5cGUuY29sb3JfdmFsdWU9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gdD1mKHRoaXMudGV4dF9jb2xvci52YWx1ZSgpLHRoaXMudGV4dF9hbHBoYS52YWx1ZSgpKSwicmdiYSgiKzI1NSp0WzBdKyIsIisyNTUqdFsxXSsiLCIrMjU1KnRbMl0rIiwiK3RbM10rIikifSxlLnByb3RvdHlwZS5zZXRfdmFsdWU9ZnVuY3Rpb24odCl7cmV0dXJuIHQuZm9udD10aGlzLmZvbnRfdmFsdWUoKSx0LmZpbGxTdHlsZT10aGlzLnRleHRfY29sb3IudmFsdWUoKSx0Lmdsb2JhbEFscGhhPXRoaXMudGV4dF9hbHBoYS52YWx1ZSgpLHQudGV4dEFsaWduPXRoaXMudGV4dF9hbGlnbi52YWx1ZSgpLHQudGV4dEJhc2VsaW5lPXRoaXMudGV4dF9iYXNlbGluZS52YWx1ZSgpfSxlLnByb3RvdHlwZS5zZXRfdmVjdG9yaXplPWZ1bmN0aW9uKHQsZSl7aWYodGhpcy5jYWNoZV9zZWxlY3QoImZvbnQiLGUpLHQuZm9udCE9PXRoaXMuY2FjaGUuZm9udCYmKHQuZm9udD10aGlzLmNhY2hlLmZvbnQpLHRoaXMuY2FjaGVfc2VsZWN0KCJ0ZXh0X2NvbG9yIixlKSx0LmZpbGxTdHlsZSE9PXRoaXMuY2FjaGUudGV4dF9jb2xvciYmKHQuZmlsbFN0eWxlPXRoaXMuY2FjaGUudGV4dF9jb2xvciksdGhpcy5jYWNoZV9zZWxlY3QoInRleHRfYWxwaGEiLGUpLHQuZ2xvYmFsQWxwaGEhPT10aGlzLmNhY2hlLnRleHRfYWxwaGEmJih0Lmdsb2JhbEFscGhhPXRoaXMuY2FjaGUudGV4dF9hbHBoYSksdGhpcy5jYWNoZV9zZWxlY3QoInRleHRfYWxpZ24iLGUpLHQudGV4dEFsaWduIT09dGhpcy5jYWNoZS50ZXh0X2FsaWduJiYodC50ZXh0QWxpZ249dGhpcy5jYWNoZS50ZXh0X2FsaWduKSx0aGlzLmNhY2hlX3NlbGVjdCgidGV4dF9iYXNlbGluZSIsZSksdC50ZXh0QmFzZWxpbmUhPT10aGlzLmNhY2hlLnRleHRfYmFzZWxpbmUpcmV0dXJuIHQudGV4dEJhc2VsaW5lPXRoaXMuY2FjaGUudGV4dF9iYXNlbGluZX0sZX0oaCksbD17bGluZTpwLGZpbGw6Yyx0ZXh0Ol99LGE9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHgoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3ZhciByLG4sbyxpLHMsYSx1LGg7Zm9yKGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMucGxvdF9tb2RlbD10LnBsb3RfbW9kZWwsdGhpcy5wbG90X3ZpZXc9dC5wbG90X3ZpZXcsdGhpcy5ub2hpdF93YXJuZWQ9e30sdGhpcy52aXN1YWxzPXt9LHM9dGhpcy5tb2RlbC5taXhpbnMsdT1bXSxyPTAsbj1zLmxlbmd0aDtyPG47cisrKWg9c1tyXSxhPWguc3BsaXQoIjoiKSxvPWFbMF0saT1hWzFdLG51bGw9PWkmJihpPSIiKSx1LnB1c2godGhpcy52aXN1YWxzW2krb109bmV3IGxbb10oe29iajp0aGlzLm1vZGVsLHByZWZpeDppfSkpO3JldHVybiB1fSxlLnByb3RvdHlwZS5iaW5kX2Jva2VoX2V2ZW50cz1mdW5jdGlvbigpe30sZS5wcm90b3R5cGUucmVxdWVzdF9yZW5kZXI9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5wbG90X3ZpZXcucmVxdWVzdF9yZW5kZXIoKX0sZS5wcm90b3R5cGUubWFwX2RhdGE9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLGwsaCxjLHAsXyxkLGYsbSxnO2ZvcihvPXRoaXMubW9kZWwuX2Nvb3JkcyxlPTAsbj1vLmxlbmd0aDtlPG47ZSsrKWlmKGk9b1tlXSxtPWlbMF0sZz1pWzFdLF89InMiK20sZj0icyIrZyxtPSJfIittLGc9Il8iK2csdS5pc0FycmF5KG51bGwhPShzPXRoaXNbbV0pP3NbMF06dm9pZCAwKSlmb3IoYT1bW10sW11dLHRoaXNbX109YVswXSx0aGlzW2ZdPWFbMV0sdD1yPTAsbD10aGlzW21dLmxlbmd0aDswPD1sP3I8bDpyPmw7dD0wPD1sPysrcjotLXIpaD10aGlzLm1hcF90b19zY3JlZW4odGhpc1ttXVt0XSx0aGlzW2ddW3RdKSxwPWhbMF0sZD1oWzFdLHRoaXNbX10ucHVzaChwKSx0aGlzW2ZdLnB1c2goZCk7ZWxzZSBjPXRoaXMubWFwX3RvX3NjcmVlbih0aGlzW21dLHRoaXNbZ10pLHRoaXNbX109Y1swXSx0aGlzW2ZdPWNbMV07cmV0dXJuIHRoaXMuX21hcF9kYXRhKCl9LGUucHJvdG90eXBlLnByb2plY3RfeHk9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saSxzLGEsbCx1O2ZvcihpPVtdLGE9W10scj1uPTAsbD10Lmxlbmd0aDswPD1sP248bDpuPmw7cj0wPD1sPysrbjotLW4pdT12KGIsW3Rbcl0sZVtyXV0pLG89dVswXSxzPXVbMV0saVtyXT1vLGFbcl09cztyZXR1cm5baSxhXX0sZS5wcm90b3R5cGUucHJvamVjdF94c3lzPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLGkscyxhLGwsdTtmb3IoaT1bXSxhPVtdLHI9bj0wLGw9dC5sZW5ndGg7MDw9bD9uPGw6bj5sO3I9MDw9bD8rK246LS1uKXU9dGhpcy5wcm9qZWN0X3h5KHRbcl0sZVtyXSksbz11WzBdLHM9dVsxXSxpW3JdPW8sYVtyXT1zO3JldHVybltpLGFdfSxlLnByb3RvdHlwZS5zZXRfZGF0YT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpO249dGhpcy5tb2RlbC5wcm9wZXJ0aWVzO2ZvcihlIGluIG4pcj1uW2VdLHIuZGF0YXNwZWMmJighci5vcHRpb25hbHx8bnVsbCE9PXIuc3BlYy52YWx1ZXx8ZSBpbiB0aGlzLm1vZGVsLl9zZXRfYWZ0ZXJfZGVmYXVsdHMpJiYodGhpc1siXyIrZV09ci5hcnJheSh0KSxyIGluc3RhbmNlb2YgeS5EaXN0YW5jZSYmKHRoaXNbIm1heF8iK2VdPWQodGhpc1siXyIrZV0pKSk7cmV0dXJuIHRoaXMucGxvdF9tb2RlbC51c2VfbWFwJiYobnVsbCE9dGhpcy5feCYmKG89dGhpcy5wcm9qZWN0X3h5KHRoaXMuX3gsdGhpcy5feSksdGhpcy5feD1vWzBdLHRoaXMuX3k9b1sxXSksbnVsbCE9dGhpcy5feHMmJihpPXRoaXMucHJvamVjdF94c3lzKHRoaXMuX3hzLHRoaXMuX3lzKSx0aGlzLl94cz1pWzBdLHRoaXMuX3lzPWlbMV0pKSxudWxsIT10aGlzLmdsZ2x5cGgmJnRoaXMuZ2xnbHlwaC5zZXRfZGF0YV9jaGFuZ2VkKHRoaXMuX3gubGVuZ3RoKSx0aGlzLl9zZXRfZGF0YSgpLHRoaXMuaW5kZXg9dGhpcy5faW5kZXhfZGF0YSgpfSxlLnByb3RvdHlwZS5zZXRfdmlzdWFscz1mdW5jdGlvbih0KXt2YXIgZSxyLG47bj10aGlzLnZpc3VhbHM7Zm9yKGUgaW4gbilyPW5bZV0sci53YXJtX2NhY2hlKHQpO2lmKG51bGwhPXRoaXMuZ2xnbHlwaClyZXR1cm4gdGhpcy5nbGdseXBoLnNldF92aXN1YWxzX2NoYW5nZWQoKX0sZS5wcm90b3R5cGUuX3NldF9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuIG51bGx9LGUucHJvdG90eXBlLl9tYXBfZGF0YT1mdW5jdGlvbigpe3JldHVybiBudWxsfSxlLnByb3RvdHlwZS5faW5kZXhfZGF0YT1mdW5jdGlvbigpe3JldHVybiBudWxsfSxlLnByb3RvdHlwZS5fbWFza19kYXRhPWZ1bmN0aW9uKHQpe3JldHVybiB0fSxlLnByb3RvdHlwZS5fYm91bmRzPWZ1bmN0aW9uKHQpe3JldHVybiB0fSxlLnByb3RvdHlwZS5oaXRfdGVzdD1mdW5jdGlvbih0KXt2YXIgZSxyO3JldHVybiByPW51bGwsZT0iX2hpdF8iK3QudHlwZSxudWxsIT10aGlzW2VdP3I9dGhpc1tlXSh0KTpudWxsPT10aGlzLm5vaGl0X3dhcm5lZFt0LnR5cGVdJiYobS5kZWJ1ZygiJyIrdC50eXBlKyInIHNlbGVjdGlvbiBub3QgYXZhaWxhYmxlIGZvciAiK3RoaXMubW9kZWwudHlwZSksdGhpcy5ub2hpdF93YXJuZWRbdC50eXBlXT0hMCkscn0sZS5wcm90b3R5cGUubWFwX3RvX3NjcmVlbj1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnBsb3Rfdmlldy5tYXBfdG9fc2NyZWVuKHQsZSx0aGlzLm1nZXQoInhfcmFuZ2VfbmFtZSIpLHRoaXMubWdldCgieV9yYW5nZV9uYW1lIikpfSxlfShvKSxzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiB4KGUsdCksZS5wcm90b3R5cGUudHlwZT0iUmVuZGVyZXIiLGUuZGVmaW5lKHtsZXZlbDpbeS5SZW5kZXJMZXZlbCxudWxsXSx2aXNpYmxlOlt5LkJvb2wsITBdfSksZX0oaSksZS5leHBvcnRzPXtNb2RlbDpzLFZpZXc6YSxWaXN1YWxzOmx9fSx7Ii4uLy4uL2NvcmUvYm9rZWhfdmlldyI6ImNvcmUvYm9rZWhfdmlldyIsIi4uLy4uL2NvcmUvbG9nZ2luZyI6ImNvcmUvbG9nZ2luZyIsIi4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4uLy4uL2NvcmUvcHJvcGVydHlfbWl4aW5zIjoiY29yZS9wcm9wZXJ0eV9taXhpbnMiLCIuLi8uLi9jb3JlL3V0aWwvY29sb3IiOiJjb3JlL3V0aWwvY29sb3IiLCIuLi8uLi9jb3JlL3V0aWwvbWF0aCI6ImNvcmUvdXRpbC9tYXRoIiwiLi4vLi4vbW9kZWwiOiJtb2RlbCIsYmFja2JvbmU6ImJhY2tib25lIixwcm9qNDoicHJvajQiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy9zb3VyY2VzL2FqYXhfZGF0YV9zb3VyY2UiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdC5hcHBseShlLGFyZ3VtZW50cyl9fSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7bj10KCJqcXVlcnkiKSxzPXQoInVuZGVyc2NvcmUiKSxpPXQoIi4vcmVtb3RlX2RhdGFfc291cmNlIiksYT10KCIuLi8uLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIsbD10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gdGhpcy5nZXRfZGF0YT11KHRoaXMuZ2V0X2RhdGEsdGhpcyksdGhpcy5zZXR1cD11KHRoaXMuc2V0dXAsdGhpcyksdGhpcy5kZXN0cm95PXUodGhpcy5kZXN0cm95LHRoaXMpLGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLnR5cGU9IkFqYXhEYXRhU291cmNlIixlLmRlZmluZSh7bW9kZTpbbC5TdHJpbmcsInJlcGxhY2UiXSxjb250ZW50X3R5cGU6W2wuU3RyaW5nLCJhcHBsaWNhdGlvbi9qc29uIl0saHR0cF9oZWFkZXJzOltsLkFueSx7fV0sbWF4X3NpemU6W2wuTnVtYmVyXSxtZXRob2Q6W2wuU3RyaW5nLCJQT1NUIl0saWZfbW9kaWZpZWQ6W2wuQm9vbCwhMV19KSxlLnByb3RvdHlwZS5kZXN0cm95PWZ1bmN0aW9uKCl7aWYobnVsbCE9dGhpcy5pbnRlcnZhbClyZXR1cm4gY2xlYXJJbnRlcnZhbCh0aGlzLmludGVydmFsKX0sZS5wcm90b3R5cGUuc2V0dXA9ZnVuY3Rpb24odCxlKXtpZih0aGlzLnB2PXQsdGhpcy5nZXRfZGF0YSh0aGlzLmdldCgibW9kZSIpKSx0aGlzLmdldCgicG9sbGluZ19pbnRlcnZhbCIpKXJldHVybiB0aGlzLmludGVydmFsPXNldEludGVydmFsKHRoaXMuZ2V0X2RhdGEsdGhpcy5nZXQoInBvbGxpbmdfaW50ZXJ2YWwiKSx0aGlzLmdldCgibW9kZSIpLHRoaXMuZ2V0KCJtYXhfc2l6ZSIpLHRoaXMuZ2V0KCJpZl9tb2RpZmllZCIpKX0sZS5wcm90b3R5cGUuZ2V0X2RhdGE9ZnVuY3Rpb24odCxlLHIpe3JldHVybiBudWxsPT1lJiYoZT0wKSxudWxsPT1yJiYocj0hMSksbi5hamF4KHtkYXRhVHlwZToianNvbiIsaWZNb2RpZmllZDpyLHVybDp0aGlzLmdldCgiZGF0YV91cmwiKSx4aHJGaWVsZDp7d2l0aENyZWRlbnRpYWxzOiEwfSxtZXRob2Q6dGhpcy5nZXQoIm1ldGhvZCIpLGNvbnRlbnRUeXBlOnRoaXMuZ2V0KCJjb250ZW50X3R5cGUiKSxoZWFkZXJzOnRoaXMuZ2V0KCJodHRwX2hlYWRlcnMiKX0pLmRvbmUoZnVuY3Rpb24ocil7cmV0dXJuIGZ1bmN0aW9uKG4pe3ZhciBvLGkscyxsLHU7aWYoInJlcGxhY2UiPT09dClyLnNldCgiZGF0YSIsbik7ZWxzZSBpZigiYXBwZW5kIj09PXQpewpmb3IobD1yLmdldCgiZGF0YSIpLHU9ci5jb2x1bW5zKCksaT0wLHM9dS5sZW5ndGg7aTxzO2krKylvPXVbaV0sbltvXT1sW29dLmNvbmNhdChuW29dKS5zbGljZSgtZSk7ci5zZXQoImRhdGEiLG4pfWVsc2UgYS5lcnJvcigidW5zdXBwb3J0ZWQgbW9kZTogIit0KTtyZXR1cm4gYS50cmFjZShuKSxudWxsfX0odGhpcykpLmVycm9yKGZ1bmN0aW9uKCl7cmV0dXJuIGEuZXJyb3IoYXJndW1lbnRzKX0pLG51bGx9LGV9KGkuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9yZW1vdGVfZGF0YV9zb3VyY2UiOiJtb2RlbHMvc291cmNlcy9yZW1vdGVfZGF0YV9zb3VyY2UiLGpxdWVyeToianF1ZXJ5Iix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvc291cmNlcy9jb2x1bW5fZGF0YV9zb3VyY2UiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxjPXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLG89dCgiLi9kYXRhX3NvdXJjZSIpLGE9dCgiLi4vLi4vY29tbW9uL2hpdHRlc3QiKSxpPXQoIi4uLy4uL2NvbW1vbi9zZWxlY3Rpb25fbWFuYWdlciIpLGw9dCgiLi4vLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLHU9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLnR5cGU9IkNvbHVtbkRhdGFTb3VyY2UiLGUuZGVmaW5lKHtkYXRhOlt1LkFueSx7fV0sY29sdW1uX25hbWVzOlt1LkFycmF5LFtdXX0pLGUuaW50ZXJuYWwoe3NlbGVjdGlvbl9tYW5hZ2VyOlt1Lkluc3RhbmNlLGZ1bmN0aW9uKHQpe3JldHVybiBuZXcgaSh7c291cmNlOnR9KX1dLGluc3BlY3RlZDpbdS5BbnldfSksZS5wcm90b3R5cGUuZ2V0X2NvbHVtbj1mdW5jdGlvbih0KXt2YXIgZTtyZXR1cm4gbnVsbCE9KGU9dGhpcy5nZXQoImRhdGEiKVt0XSk/ZTpudWxsfSxlLnByb3RvdHlwZS5nZXRfbGVuZ3RoPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47cmV0dXJuIHQ9dGhpcy5nZXQoImRhdGEiKSwwPT09cy5rZXlzKHQpLmxlbmd0aD9udWxsOihyPXMudW5pcShmdW5jdGlvbigpe3ZhciByO3I9W107Zm9yKGUgaW4gdCluPXRbZV0sci5wdXNoKG4ubGVuZ3RoKTtyZXR1cm4gcn0oKSksci5sZW5ndGg+MSYmbC5kZWJ1ZygiZGF0YSBzb3VyY2UgaGFzIGNvbHVtbnMgb2YgaW5jb25zaXN0ZW50IGxlbmd0aHMiKSxyWzBdKX0sZS5wcm90b3R5cGUuY29sdW1ucz1mdW5jdGlvbigpe3JldHVybiBzLmtleXModGhpcy5nZXQoImRhdGEiKSl9LGUucHJvdG90eXBlLnN0cmVhbT1mdW5jdGlvbih0LGUpe3ZhciByLG4sbztyPXRoaXMuZ2V0KCJkYXRhIik7Zm9yKG4gaW4gdClvPXRbbl0scltuXT1yW25dLmNvbmNhdCh0W25dKSxyW25dLmxlbmd0aD5lJiYocltuXT1yW25dLnNsaWNlKC1lKSk7cmV0dXJuIHRoaXMuc2V0KCJkYXRhIixyLHtzaWxlbnQ6ITB9KSx0aGlzLnRyaWdnZXIoInN0cmVhbSIpfSxlLnByb3RvdHlwZS5wYXRjaD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsLHU7ZT10aGlzLmdldCgiZGF0YSIpO2ZvcihpIGluIHQpZm9yKHM9dFtpXSxyPW89MCxhPXMubGVuZ3RoOzA8PWE/bzxhOm8+YTtyPTA8PWE/KytvOi0tbylsPXNbcl0sbj1sWzBdLHU9bFsxXSxlW2ldW25dPXU7cmV0dXJuIHRoaXMuc2V0KCJkYXRhIixlLHtzaWxlbnQ6ITB9KSx0aGlzLnRyaWdnZXIoInBhdGNoIil9LGV9KG8uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29tbW9uL2hpdHRlc3QiOiJjb21tb24vaGl0dGVzdCIsIi4uLy4uL2NvbW1vbi9zZWxlY3Rpb25fbWFuYWdlciI6ImNvbW1vbi9zZWxlY3Rpb25fbWFuYWdlciIsIi4uLy4uL2NvcmUvbG9nZ2luZyI6ImNvcmUvbG9nZ2luZyIsIi4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vZGF0YV9zb3VyY2UiOiJtb2RlbHMvc291cmNlcy9kYXRhX3NvdXJjZSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3NvdXJjZXMvZGF0YV9zb3VyY2UiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl1LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHU9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIiksbz10KCIuLi8uLi9tb2RlbCIpLHM9dCgiLi4vLi4vY29tbW9uL2hpdHRlc3QiKSxhPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJEYXRhU291cmNlIixlLmRlZmluZSh7c2VsZWN0ZWQ6W2EuQW55LHMuY3JlYXRlX2hpdF90ZXN0X3Jlc3VsdCgpXSxjYWxsYmFjazpbYS5BbnldfSksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy5saXN0ZW5Ubyh0aGlzLCJjaGFuZ2U6c2VsZWN0ZWQiLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbigpe3ZhciBlO2lmKGU9dC5nZXQoImNhbGxiYWNrIiksbnVsbCE9ZSlyZXR1cm4gaS5pc0Z1bmN0aW9uKGUpP2UodCk6ZS5leGVjdXRlKHQpfX0odGhpcykpfSxlfShvKSxlLmV4cG9ydHM9e01vZGVsOm59fSx7Ii4uLy4uL2NvbW1vbi9oaXR0ZXN0IjoiY29tbW9uL2hpdHRlc3QiLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi9tb2RlbCI6Im1vZGVsIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvc291cmNlcy9nZW9qc29uX2RhdGFfc291cmNlIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpdS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSx1PXt9Lmhhc093blByb3BlcnR5O2k9dCgidW5kZXJzY29yZSIpLG49dCgiLi9jb2x1bW5fZGF0YV9zb3VyY2UiKSxzPXQoIi4uLy4uL2NvcmUvbG9nZ2luZyIpLmxvZ2dlcixhPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJHZW9KU09ORGF0YVNvdXJjZSIsZS5kZWZpbmUoe2dlb2pzb246W2EuQW55XX0pLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCl7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMuZ2VvanNvbl90b19jb2x1bW5fZGF0YSgpLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJkYXRhIix0aGlzLmdlb2pzb25fdG9fY29sdW1uX2RhdGEsITApLHRoaXMuYWRkX2RlcGVuZGVuY2llcygiZGF0YSIsdGhpcyxbImdlb2pzb24iXSl9LGUucHJvdG90eXBlLl9nZXRfbmV3X2xpc3RfYXJyYXk9ZnVuY3Rpb24odCl7dmFyIGUscjtyZXR1cm4gZT1uZXcgQXJyYXkodCkscj1pLm1hcChlLGZ1bmN0aW9uKHQpe3JldHVybltdfSl9LGUucHJvdG90eXBlLl9nZXRfbmV3X25hbl9hcnJheT1mdW5jdGlvbih0KXt2YXIgZSxyO3JldHVybiBlPW5ldyBBcnJheSh0KSxyPWkubWFwKGUsZnVuY3Rpb24odCl7cmV0dXJuIE5hTn0pfSxlLnByb3RvdHlwZS5fZmxhdHRlbl9mdW5jdGlvbj1mdW5jdGlvbih0LGUpe3JldHVybiB0LmNvbmNhdChbW05hTixOYU4sTmFOXV0pLmNvbmNhdChlKX0sZS5wcm90b3R5cGUuX2FkZF9wcm9wZXJ0aWVzPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBvLGk7aT1bXTtmb3IobyBpbiB0LnByb3BlcnRpZXMpZS5oYXNPd25Qcm9wZXJ0eShvKXx8KGVbb109dGhpcy5fZ2V0X25ld19uYW5fYXJyYXkobikpLGkucHVzaChlW29dW3JdPXQucHJvcGVydGllc1tvXSk7cmV0dXJuIGl9LGUucHJvdG90eXBlLl9hZGRfZ2VvbWV0cnk9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8sYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdyxNLGssaixULFMseixQLEUsQTtzd2l0Y2godC50eXBlKXtjYXNlIlBvaW50IjpyZXR1cm4gbz10LmNvb3JkaW5hdGVzLGUueFtyXT1vWzBdLGUueVtyXT1vWzFdLGUueltyXT1udWxsIT0odz1vWzJdKT93Ok5hTjtjYXNlIkxpbmVTdHJpbmciOmZvcihuPXQuY29vcmRpbmF0ZXMsej1bXSxoPWM9MCxfPW4ubGVuZ3RoO2M8XztoPSsrYylvPW5baF0sZS54c1tyXVtoXT1vWzBdLGUueXNbcl1baF09b1sxXSx6LnB1c2goZS56c1tyXVtoXT1udWxsIT0oTT1vWzJdKT9NOk5hTik7cmV0dXJuIHo7Y2FzZSJQb2x5Z29uIjpmb3IodC5jb29yZGluYXRlcy5sZW5ndGg+MSYmcy53YXJuKCJCb2tlaCBkb2VzIG5vdCBzdXBwb3J0IFBvbHlnb25zIHdpdGggaG9sZXMgaW4sIG9ubHkgZXh0ZXJpb3IgcmluZyB1c2VkLiIpLGE9dC5jb29yZGluYXRlc1swXSxQPVtdLGg9cD0wLGQ9YS5sZW5ndGg7cDxkO2g9KytwKW89YVtoXSxlLnhzW3JdW2hdPW9bMF0sZS55c1tyXVtoXT1vWzFdLFAucHVzaChlLnpzW3JdW2hdPW51bGwhPShrPW9bMl0pP2s6TmFOKTtyZXR1cm4gUDtjYXNlIk11bHRpUG9pbnQiOnJldHVybiBzLndhcm4oIk11bHRpUG9pbnQgbm90IHN1cHBvcnRlZCBpbiBCb2tlaCIpO2Nhc2UiTXVsdGlMaW5lU3RyaW5nIjpmb3IodT1pLnJlZHVjZSh0LmNvb3JkaW5hdGVzLHRoaXMuX2ZsYXR0ZW5fZnVuY3Rpb24pLEU9W10saD15PTAsZj11Lmxlbmd0aDt5PGY7aD0rK3kpbz11W2hdLGUueHNbcl1baF09b1swXSxlLnlzW3JdW2hdPW9bMV0sRS5wdXNoKGUuenNbcl1baF09bnVsbCE9KGo9b1syXSk/ajpOYU4pO3JldHVybiBFO2Nhc2UiTXVsdGlQb2x5Z29uIjpmb3IobD1bXSxUPXQuY29vcmRpbmF0ZXMsdj0wLG09VC5sZW5ndGg7djxtO3YrKyl4PVRbdl0seC5sZW5ndGg+MSYmcy53YXJuKCJCb2tlaCBkb2VzIG5vdCBzdXBwb3J0IFBvbHlnb25zIHdpdGggaG9sZXMgaW4sIG9ubHkgZXh0ZXJpb3IgcmluZyB1c2VkLiIpLGwucHVzaCh4WzBdKTtmb3IodT1pLnJlZHVjZShsLHRoaXMuX2ZsYXR0ZW5fZnVuY3Rpb24pLEE9W10saD1iPTAsZz11Lmxlbmd0aDtiPGc7aD0rK2Ipbz11W2hdLGUueHNbcl1baF09b1swXSxlLnlzW3JdW2hdPW9bMV0sQS5wdXNoKGUuenNbcl1baF09bnVsbCE9KFM9b1syXSk/UzpOYU4pO3JldHVybiBBO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKCJJbnZhbGlkIHR5cGUgIit0LnR5cGUpfX0sZS5wcm90b3R5cGUuX2dldF9pdGVtc19sZW5ndGg9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGEsbCx1LGgsYztmb3IoZT0wLG89YT0wLHU9dC5sZW5ndGg7YTx1O289KythKWlmKGk9dFtvXSxuPSJGZWF0dXJlIj09PWkudHlwZT9pLmdlb21ldHJ5OmksIkdlb21ldHJ5Q29sbGVjdGlvbiI9PT1uLnR5cGUpZm9yKGM9bi5nZW9tZXRyaWVzLHM9bD0wLGg9Yy5sZW5ndGg7bDxoO3M9KytsKXI9Y1tzXSxlKz0xO2Vsc2UgZSs9MTtyZXR1cm4gZX0sZS5wcm90b3R5cGUuZ2VvanNvbl90b19jb2x1bW5fZGF0YT1mdW5jdGlvbigpe3ZhciB0LGUscixuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmO2lmKG49SlNPTi5wYXJzZSh0aGlzLmdldCgiZ2VvanNvbiIpKSwiR2VvbWV0cnlDb2xsZWN0aW9uIiE9PShkPW4udHlwZSkmJiJGZWF0dXJlQ29sbGVjdGlvbiIhPT1kKXRocm93IG5ldyBFcnJvcigiQm9rZWggb25seSBzdXBwb3J0cyB0eXBlIEdlb21ldHJ5Q29sbGVjdGlvbiBhbmQgRmVhdHVyZUNvbGxlY3Rpb24gYXQgdG9wIGxldmVsIik7aWYoIkdlb21ldHJ5Q29sbGVjdGlvbiI9PT1uLnR5cGUpe2lmKG51bGw9PW4uZ2VvbWV0cmllcyl0aHJvdyBuZXcgRXJyb3IoIk5vIGdlb21ldHJpZXMgZm91bmQgaW4gR2VvbWV0cnlDb2xsZWN0aW9uIik7aWYoMD09PW4uZ2VvbWV0cmllcy5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKCJnZW9qc29uLmdlb21ldHJpZXMgbXVzdCBoYXZlIG9uZSBvciBtb3JlIGl0ZW1zIik7bD1uLmdlb21ldHJpZXN9aWYoIkZlYXR1cmVDb2xsZWN0aW9uIj09PW4udHlwZSl7aWYobnVsbD09bi5mZWF0dXJlcyl0aHJvdyBuZXcgRXJyb3IoIk5vIGZlYXR1cmVzIGZvdW5kIGluIEZlYXR1cmVzQ29sbGVjdGlvbiIpO2lmKDA9PT1uLmZlYXR1cmVzLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoImdlb2pzb24uZmVhdHVyZXMgbXVzdCBoYXZlIG9uZSBvciBtb3JlIGl0ZW1zIik7bD1uLmZlYXR1cmVzfWZvcihhPXRoaXMuX2dldF9pdGVtc19sZW5ndGgobCksZT17eDp0aGlzLl9nZXRfbmV3X25hbl9hcnJheShhKSx5OnRoaXMuX2dldF9uZXdfbmFuX2FycmF5KGEpLHo6dGhpcy5fZ2V0X25ld19uYW5fYXJyYXkoYSkseHM6dGhpcy5fZ2V0X25ld19saXN0X2FycmF5KGEpLHlzOnRoaXMuX2dldF9uZXdfbGlzdF9hcnJheShhKSx6czp0aGlzLl9nZXRfbmV3X2xpc3RfYXJyYXkoYSl9LHQ9MCxpPWg9MCxwPWwubGVuZ3RoO2g8cDtpPSsraClpZihzPWxbaV0sbz0iRmVhdHVyZSI9PT1zLnR5cGU/cy5nZW9tZXRyeTpzLCJHZW9tZXRyeUNvbGxlY3Rpb24iPT09by50eXBlKWZvcihmPW8uZ2VvbWV0cmllcyx1PWM9MCxfPWYubGVuZ3RoO2M8Xzt1PSsrYylyPWZbdV0sdGhpcy5fYWRkX2dlb21ldHJ5KHIsZSx0KSwiRmVhdHVyZSI9PT1zLnR5cGUmJnRoaXMuX2FkZF9wcm9wZXJ0aWVzKHMsZSx0LGEpLHQrPTE7ZWxzZSB0aGlzLl9hZGRfZ2VvbWV0cnkobyxlLHQpLCJGZWF0dXJlIj09PXMudHlwZSYmdGhpcy5fYWRkX3Byb3BlcnRpZXMocyxlLHQsYSksdCs9MTtyZXR1cm4gZX0sZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvfX0seyIuLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuL2NvbHVtbl9kYXRhX3NvdXJjZSI6Im1vZGVscy9zb3VyY2VzL2NvbHVtbl9kYXRhX3NvdXJjZSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3NvdXJjZXMvcmVtb3RlX2RhdGFfc291cmNlIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vY29sdW1uX2RhdGFfc291cmNlIikscz10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGUudHlwZT0iUmVtb3RlRGF0YVNvdXJjZSIsZS5kZWZpbmUoe2RhdGFfdXJsOltzLlN0cmluZ10scG9sbGluZ19pbnRlcnZhbDpbcy5OdW1iZXJdfSksZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvfX0seyIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuL2NvbHVtbl9kYXRhX3NvdXJjZSI6Im1vZGVscy9zb3VyY2VzL2NvbHVtbl9kYXRhX3NvdXJjZSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3RpY2tlcnMvYWRhcHRpdmVfdGlja2VyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGg9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWMuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sYz17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxzPXQoIi4vdXRpbCIpLmFyZ21pbixvPXQoIi4vY29udGludW91c190aWNrZXIiKSx1PXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGE9ZnVuY3Rpb24odCxlLHIpe3JldHVybiBNYXRoLm1heChlLE1hdGgubWluKHIsdCkpfSxsPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIG51bGw9PWUmJihlPU1hdGguRSksTWF0aC5sb2codCkvTWF0aC5sb2coZSl9LG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJBZGFwdGl2ZVRpY2tlciIsZS5kZWZpbmUoe2Jhc2U6W3UuTnVtYmVyLDEwXSxtYW50aXNzYXM6W3UuQXJyYXksWzEsMiw1XV0sbWluX2ludGVydmFsOlt1Lk51bWJlciwwXSxtYXhfaW50ZXJ2YWw6W3UuTnVtYmVyXX0pLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXt2YXIgbixvO3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0LHIpLG49aS5sYXN0KHRoaXMuZ2V0KCJtYW50aXNzYXMiKSkvdGhpcy5nZXQoImJhc2UiKSxvPWkuZmlyc3QodGhpcy5nZXQoIm1hbnRpc3NhcyIpKSp0aGlzLmdldCgiYmFzZSIpLHRoaXMuZXh0ZW5kZWRfbWFudGlzc2FzPWkuZmxhdHRlbihbbix0aGlzLmdldCgibWFudGlzc2FzIiksb10pLHRoaXMuYmFzZV9mYWN0b3I9MD09PXRoaXMuZ2V0X21pbl9pbnRlcnZhbCgpPzE6dGhpcy5nZXRfbWluX2ludGVydmFsKCl9LGUucHJvdG90eXBlLmdldF9pbnRlcnZhbD1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHUsaCxjLHAsXyxkO3JldHVybiBpPWUtdCxoPXRoaXMuZ2V0X2lkZWFsX2ludGVydmFsKHQsZSxyKSxkPU1hdGguZmxvb3IobChoL3RoaXMuYmFzZV9mYWN0b3IsdGhpcy5nZXQoImJhc2UiKSkpLGM9TWF0aC5wb3codGhpcy5nZXQoImJhc2UiKSxkKSp0aGlzLmJhc2VfZmFjdG9yLHA9aC9jLG89dGhpcy5leHRlbmRlZF9tYW50aXNzYXMsdT1vLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gTWF0aC5hYnMoci1pLyh0KmMpKX0pLG49b1tzKHUpXSxfPW4qYyxhKF8sdGhpcy5nZXRfbWluX2ludGVydmFsKCksdGhpcy5nZXRfbWF4X2ludGVydmFsKCkpfSxlfShvLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm59fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vY29udGludW91c190aWNrZXIiOiJtb2RlbHMvdGlja2Vycy9jb250aW51b3VzX3RpY2tlciIsIi4vdXRpbCI6Im1vZGVscy90aWNrZXJzL3V0aWwiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90aWNrZXJzL2Jhc2ljX3RpY2tlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscz1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxhPXt9Lmhhc093blByb3BlcnR5O2k9dCgidW5kZXJzY29yZSIpLG49dCgiLi9hZGFwdGl2ZV90aWNrZXIiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBzKGUsdCksZS5wcm90b3R5cGUudHlwZT0iQmFzaWNUaWNrZXIiLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi9hZGFwdGl2ZV90aWNrZXIiOiJtb2RlbHMvdGlja2Vycy9hZGFwdGl2ZV90aWNrZXIiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90aWNrZXJzL2NhdGVnb3JpY2FsX3RpY2tlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXMuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0scz17fS5oYXNPd25Qcm9wZXJ0eTtvPXQoIi4vdGlja2VyIiksbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaShlLHQpLGUucHJvdG90eXBlLnR5cGU9IkNhdGVnb3JpY2FsVGlja2VyIixlLnByb3RvdHlwZS5nZXRfdGlja3M9ZnVuY3Rpb24odCxlLHIsbil7dmFyIG8saSxzLGEsbCx1LGg7Zm9yKG89bi5kZXNpcmVkX25fdGlja3MsdT1bXSxpPXIuZ2V0KCJmYWN0b3JzIikscz1sPTAsaD1pLmxlbmd0aDswPD1oP2w8aDpsPmg7cz0wPD1oPysrbDotLWwpYT1zK3IuZ2V0KCJvZmZzZXQiKSxhKzE+dCYmYSsxPGUmJnUucHVzaChpW3NdKTtyZXR1cm57bWFqb3I6dSxtaW5vcjpbXX19LGV9KG8uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi90aWNrZXIiOiJtb2RlbHMvdGlja2Vycy90aWNrZXIifV0sIm1vZGVscy90aWNrZXJzL2NvbXBvc2l0ZV90aWNrZXIiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl1LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHU9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIiksbz10KCIuL2NvbnRpbnVvdXNfdGlja2VyIikscz10KCIuL3V0aWwiKS5hcmdtaW4sYT10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUudHlwZT0iQ29tcG9zaXRlVGlja2VyIixlLmRlZmluZSh7dGlja2VyczpbYS5BcnJheSxbXV19KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7dmFyIG47cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksbj10aGlzLmdldCgidGlja2VycyIpLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJtaW5faW50ZXJ2YWxzIixmdW5jdGlvbigpe3JldHVybiBpLmludm9rZShuLCJnZXRfbWluX2ludGVydmFsIil9LCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoIm1pbl9pbnRlcnZhbHMiLHRoaXMsWyJ0aWNrZXJzIl0pLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJtYXhfaW50ZXJ2YWxzIixmdW5jdGlvbigpe3JldHVybiBpLmludm9rZShuLCJnZXRfbWF4X2ludGVydmFsIil9LCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoIm1heF9pbnRlcnZhbHMiLHRoaXMsWyJ0aWNrZXJzIl0pLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJtaW5faW50ZXJ2YWwiLGZ1bmN0aW9uKCl7cmV0dXJuIGkuZmlyc3QodGhpcy5nZXQoIm1pbl9pbnRlcnZhbHMiKSl9LCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoIm1pbl9pbnRlcnZhbCIsdGhpcyxbIm1pbl9pbnRlcnZhbHMiXSksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoIm1heF9pbnRlcnZhbCIsZnVuY3Rpb24oKXtyZXR1cm4gaS5maXJzdCh0aGlzLmdldCgibWF4X2ludGVydmFscyIpKX0sITApLHRoaXMuYWRkX2RlcGVuZGVuY2llcygibWF4X2ludGVydmFsIix0aGlzLFsibWF4X2ludGVydmFsIl0pfSxlLnByb3RvdHlwZS5nZXRfYmVzdF90aWNrZXI9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8sYSxsLHUsaCxjLHA7cmV0dXJuIGw9ZS10LGg9dGhpcy5nZXRfaWRlYWxfaW50ZXJ2YWwodCxlLHIpLHA9W2kuc29ydGVkSW5kZXgodGhpcy5nZXQoIm1pbl9pbnRlcnZhbHMiKSxoKS0xLGkuc29ydGVkSW5kZXgodGhpcy5nZXQoIm1heF9pbnRlcnZhbHMiKSxoKV0sYz1bdGhpcy5nZXQoIm1pbl9pbnRlcnZhbHMiKVtwWzBdXSx0aGlzLmdldCgibWF4X2ludGVydmFscyIpW3BbMV1dXSx1PWMubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBNYXRoLmFicyhyLWwvdCl9KSxuPXModSksbj09PTEvMD90aGlzLmdldCgidGlja2VycyIpWzBdOihhPXBbbl0sbz10aGlzLmdldCgidGlja2VycyIpW2FdKX0sZS5wcm90b3R5cGUuZ2V0X2ludGVydmFsPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbjtyZXR1cm4gbj10aGlzLmdldF9iZXN0X3RpY2tlcih0LGUsciksbi5nZXRfaW50ZXJ2YWwodCxlLHIpfSxlLnByb3RvdHlwZS5nZXRfdGlja3Nfbm9fZGVmYXVsdHM9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG87cmV0dXJuIG49dGhpcy5nZXRfYmVzdF90aWNrZXIodCxlLHIpLG89bi5nZXRfdGlja3Nfbm9fZGVmYXVsdHModCxlLHIpfSxlfShvLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm59fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vY29udGludW91c190aWNrZXIiOiJtb2RlbHMvdGlja2Vycy9jb250aW51b3VzX3RpY2tlciIsIi4vdXRpbCI6Im1vZGVscy90aWNrZXJzL3V0aWwiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90aWNrZXJzL2NvbnRpbnVvdXNfdGlja2VyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxvPXQoIi4vdGlja2VyIikscz10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGUudHlwZT0iQ29udGludW91c1RpY2tlciIsZS5kZWZpbmUoe251bV9taW5vcl90aWNrczpbcy5OdW1iZXIsNV0sZGVzaXJlZF9udW1fdGlja3M6W3MuTnVtYmVyLDZdfSksZS5wcm90b3R5cGUuZ2V0X2ludGVydmFsPXZvaWQgMCxlLnByb3RvdHlwZS5nZXRfbWluX2ludGVydmFsPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZ2V0KCJtaW5faW50ZXJ2YWwiKX0sZS5wcm90b3R5cGUuZ2V0X21heF9pbnRlcnZhbD1mdW5jdGlvbigpe3ZhciB0O3JldHVybiBudWxsIT0odD10aGlzLmdldCgibWF4X2ludGVydmFsIikpP3Q6MS8wfSxlLnByb3RvdHlwZS5nZXRfaWRlYWxfaW50ZXJ2YWw9ZnVuY3Rpb24odCxlLHIpe3ZhciBuO3JldHVybiBuPWUtdCxuL3J9LGV9KG8uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi90aWNrZXIiOiJtb2RlbHMvdGlja2Vycy90aWNrZXIiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90aWNrZXJzL2RhdGV0aW1lX3RpY2tlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlnLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGc9e30uaGFzT3duUHJvcGVydHk7ZD10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2FkYXB0aXZlX3RpY2tlciIpLG89dCgiLi9jb21wb3NpdGVfdGlja2VyIikscz10KCIuL2RheXNfdGlja2VyIiksYT10KCIuL21vbnRoc190aWNrZXIiKSxfPXQoIi4veWVhcnNfdGlja2VyIiksZj10KCIuL3V0aWwiKSx1PWYuT05FX01JTExJLHA9Zi5PTkVfU0VDT05ELGg9Zi5PTkVfTUlOVVRFLGw9Zi5PTkVfSE9VUixjPWYuT05FX01PTlRILGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIG0oZSx0KSxlLnByb3RvdHlwZS50eXBlPSJEYXRldGltZVRpY2tlciIsZS5vdmVycmlkZSh7bnVtX21pbm9yX3RpY2tzOjAsdGlja2VyczpmdW5jdGlvbigpe3JldHVybltuZXcgbi5Nb2RlbCh7bWFudGlzc2FzOlsxLDIsNV0sYmFzZToxMCxtaW5faW50ZXJ2YWw6MCxtYXhfaW50ZXJ2YWw6NTAwKnUsbnVtX21pbm9yX3RpY2tzOjB9KSxuZXcgbi5Nb2RlbCh7bWFudGlzc2FzOlsxLDIsNSwxMCwxNSwyMCwzMF0sYmFzZTo2MCxtaW5faW50ZXJ2YWw6cCxtYXhfaW50ZXJ2YWw6MzAqaCxudW1fbWlub3JfdGlja3M6MH0pLG5ldyBuLk1vZGVsKHttYW50aXNzYXM6WzEsMiw0LDYsOCwxMl0sYmFzZToyNCxtaW5faW50ZXJ2YWw6bCxtYXhfaW50ZXJ2YWw6MTIqbCxudW1fbWlub3JfdGlja3M6MH0pLG5ldyBzLk1vZGVsKHtkYXlzOmQucmFuZ2UoMSwzMil9KSxuZXcgcy5Nb2RlbCh7ZGF5czpkLnJhbmdlKDEsMzEsMyl9KSxuZXcgcy5Nb2RlbCh7ZGF5czpbMSw4LDE1LDIyXX0pLG5ldyBzLk1vZGVsKHtkYXlzOlsxLDE1XX0pLG5ldyBhLk1vZGVsKHttb250aHM6ZC5yYW5nZSgwLDEyLDEpfSksbmV3IGEuTW9kZWwoe21vbnRoczpkLnJhbmdlKDAsMTIsMil9KSxuZXcgYS5Nb2RlbCh7bW9udGhzOmQucmFuZ2UoMCwxMiw0KX0pLG5ldyBhLk1vZGVsKHttb250aHM6ZC5yYW5nZSgwLDEyLDYpfSksbmV3IF8uTW9kZWwoe30pXX19KSxlfShvLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOml9fSx7Ii4vYWRhcHRpdmVfdGlja2VyIjoibW9kZWxzL3RpY2tlcnMvYWRhcHRpdmVfdGlja2VyIiwiLi9jb21wb3NpdGVfdGlja2VyIjoibW9kZWxzL3RpY2tlcnMvY29tcG9zaXRlX3RpY2tlciIsIi4vZGF5c190aWNrZXIiOiJtb2RlbHMvdGlja2Vycy9kYXlzX3RpY2tlciIsIi4vbW9udGhzX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL21vbnRoc190aWNrZXIiLCIuL3V0aWwiOiJtb2RlbHMvdGlja2Vycy91dGlsIiwiLi95ZWFyc190aWNrZXIiOiJtb2RlbHMvdGlja2Vycy95ZWFyc190aWNrZXIiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90aWNrZXJzL2RheXNfdGlja2VyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlfLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LF89e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksaT10KCIuL3NpbmdsZV9pbnRlcnZhbF90aWNrZXIiKSxjPXQoIi4vdXRpbCIpLGg9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksYT1jLmNvcHlfZGF0ZSx1PWMubGFzdF9tb250aF9ub19sYXRlcl90aGFuLG89Yy5PTkVfREFZLGw9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saSxzO2ZvcihzPXUobmV3IERhdGUodCkpLG89dShuZXcgRGF0ZShlKSksaT1hKG8pLG8uc2V0VVRDTW9udGgoby5nZXRVVENNb250aCgpKzEpLG49W10scj1zOzspaWYobi5wdXNoKGEocikpLHIuc2V0VVRDTW9udGgoci5nZXRVVENNb250aCgpKzEpLHI+bylicmVhaztyZXR1cm4gbn0sbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gcChlLHQpLGUucHJvdG90eXBlLnR5cGU9IkRheXNUaWNrZXIiLGUuZGVmaW5lKHtkYXlzOltoLkFycmF5LFtdXX0pLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXt2YXIgbixpO3JldHVybiB0Lm51bV9taW5vcl90aWNrcz0wLGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksbj10aGlzLmdldCgiZGF5cyIpLGk9bi5sZW5ndGg+MT8oblsxXS1uWzBdKSpvOjMxKm8sdGhpcy5zZXQoImludGVydmFsIixpKX0sZS5wcm90b3R5cGUuZ2V0X3RpY2tzX25vX2RlZmF1bHRzPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGksdSxoLGMscCxfO3JldHVybiBwPWwodCxlKSx1PXRoaXMuZ2V0KCJkYXlzIiksaD1mdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saSxzLGw7Zm9yKHI9W10scz0wLGw9dS5sZW5ndGg7czxsO3MrKyluPXVbc10sbz1hKHQpLG8uc2V0VVRDRGF0ZShuKSxpPW5ldyBEYXRlKG8uZ2V0VGltZSgpK2UvMiksaS5nZXRVVENNb250aCgpPT09dC5nZXRVVENNb250aCgpJiZyLnB1c2gobyk7cmV0dXJuIHJ9fSh0aGlzKSxjPXRoaXMuZ2V0KCJpbnRlcnZhbCIpLGk9cy5mbGF0dGVuKGZ1bmN0aW9uKCl7dmFyIHQsZSxyO2ZvcihyPVtdLHQ9MCxlPXAubGVuZ3RoO3Q8ZTt0Kyspbz1wW3RdLHIucHVzaChoKG8sYykpO3JldHVybiByfSgpKSxuPXMuaW52b2tlKGksImdldFRpbWUiKSxfPXMuZmlsdGVyKG4sZnVuY3Rpb24ocil7cmV0dXJuIHQ8PXImJnI8PWV9KSx7bWFqb3I6XyxtaW5vcjpbXX19LGV9KGkuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9zaW5nbGVfaW50ZXJ2YWxfdGlja2VyIjoibW9kZWxzL3RpY2tlcnMvc2luZ2xlX2ludGVydmFsX3RpY2tlciIsIi4vdXRpbCI6Im1vZGVscy90aWNrZXJzL3V0aWwiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90aWNrZXJzL2ZpeGVkX3RpY2tlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlsLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGw9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2NvbnRpbnVvdXNfdGlja2VyIikscz10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGUudHlwZT0iRml4ZWRUaWNrZXIiLGUuZGVmaW5lKHt0aWNrczpbcy5BcnJheSxbXV19KSxlLnByb3RvdHlwZS5nZXRfdGlja3Nfbm9fZGVmYXVsdHM9ZnVuY3Rpb24odCxlLHIpe3JldHVybnttYWpvcjp0aGlzLmdldCgidGlja3MiKSxtaW5vcjpbXX19LGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9jb250aW51b3VzX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL2NvbnRpbnVvdXNfdGlja2VyIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdGlja2Vycy9sb2dfdGlja2VyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vYWRhcHRpdmVfdGlja2VyIikscz1mdW5jdGlvbih0LGUscil7dmFyIG4sbztpZihpLmlzVW5kZWZpbmVkKGUpJiYoZT10LHQ9MCksaS5pc1VuZGVmaW5lZChyKSYmKHI9MSkscj4wJiZ0Pj1lfHxyPDAmJnQ8PWUpcmV0dXJuW107Zm9yKG89W10sbj10O3I+MD9uPGU6bj5lOylvLnB1c2gobiksbis9cjtyZXR1cm4gb30sbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gYShlLHQpLGUucHJvdG90eXBlLnR5cGU9IkxvZ1RpY2tlciIsZS5vdmVycmlkZSh7bWFudGlzc2FzOlsxLDVdfSksZS5wcm90b3R5cGUuZ2V0X3RpY2tzX25vX2RlZmF1bHRzPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTLHosUCxFLEEsQyxOLE8scSxEO2lmKFA9dGhpcy5nZXQoIm51bV9taW5vcl90aWNrcyIpLFM9W10sdDw9MCYmKHQ9MSksdD5lJiYoQT1bZSx0XSx0PUFbMF0sZT1BWzFdKSxuPXRoaXMuZ2V0KCJiYXNlIiksTT1NYXRoLmxvZyh0KS9NYXRoLmxvZyhuKSx4PU1hdGgubG9nKGUpL01hdGgubG9nKG4pLHc9eC1NLHc8Mil7aWYoYz10aGlzLmdldF9pbnRlcnZhbCh0LGUsciksQz1NYXRoLmZsb29yKHQvYyksbz1NYXRoLmNlaWwoZS9jKSx1PWkuaXNOYU4oQyl8fGkuaXNOYU4obyk/W106aS5yYW5nZShDLG8rMSkscT1mdW5jdGlvbigpe3ZhciB0LGUscjtmb3Iocj1bXSx0PTAsZT11Lmxlbmd0aDt0PGU7dCsrKWw9dVt0XSwwIT09bCYmci5wdXNoKGwqYyk7cmV0dXJuIHJ9KCksUD4xKXtmb3Ioaj1jL1AsVD1mdW5jdGlvbigpe3ZhciB0LGUscjtmb3Iocj1bXSxoPXQ9MSxlPVA7MTw9ZT90PD1lOnQ+PWU7aD0xPD1lPysrdDotLXQpci5wdXNoKGgqaik7cmV0dXJuIHJ9KCkscD0wLGY9VC5sZW5ndGg7cDxmO3ArKylEPVRbcF0sUy5wdXNoKHFbMF0tRCk7Zm9yKF89MCxtPXEubGVuZ3RoO188bTtfKyspZm9yKE89cVtfXSxkPTAsZz1ULmxlbmd0aDtkPGc7ZCsrKUQ9VFtkXSxTLnB1c2goTytEKX19ZWxzZSBpZihOPU1hdGguY2VpbChNKSxhPU1hdGguZmxvb3IoeCksYz1NYXRoLmNlaWwoKGEtTikvOSkscT1zKE4sYSxjKSwoYS1OKSVjPT09MCYmKHE9cS5jb25jYXQoW2FdKSkscT1xLm1hcChmdW5jdGlvbih0KXtyZXR1cm4gTWF0aC5wb3cobix0KX0pLFA+MSl7Zm9yKGo9TWF0aC5wb3cobixjKS9QLFQ9ZnVuY3Rpb24oKXt2YXIgdCxlLHI7Zm9yKHI9W10saD10PTEsZT1QOzE8PWU/dDw9ZTp0Pj1lO2g9MTw9ZT8rK3Q6LS10KXIucHVzaChoKmopO3JldHVybiByfSgpLGs9MCx5PVQubGVuZ3RoO2s8eTtrKyspRD1UW2tdLFMucHVzaChxWzBdL0QpO2Zvcih6PTAsdj1xLmxlbmd0aDt6PHY7eisrKWZvcihPPXFbel0sRT0wLGI9VC5sZW5ndGg7RTxiO0UrKylEPVRbRV0sUy5wdXNoKE8qRCl9cmV0dXJue21ham9yOnEsbWlub3I6U319LGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi9hZGFwdGl2ZV90aWNrZXIiOiJtb2RlbHMvdGlja2Vycy9hZGFwdGl2ZV90aWNrZXIiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90aWNrZXJzL21vbnRoc190aWNrZXIiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHA9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKV8uY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sXz17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxpPXQoIi4vc2luZ2xlX2ludGVydmFsX3RpY2tlciIpLGM9dCgiLi91dGlsIiksaD10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxhPWMuY29weV9kYXRlLHU9Yy5sYXN0X3llYXJfbm9fbGF0ZXJfdGhhbixvPWMuT05FX01PTlRILGw9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saTtmb3IoaT11KG5ldyBEYXRlKHQpKSxvPXUobmV3IERhdGUoZSkpLG8uc2V0VVRDRnVsbFllYXIoby5nZXRVVENGdWxsWWVhcigpKzEpLG49W10scj1pOzspaWYobi5wdXNoKGEocikpLHIuc2V0VVRDRnVsbFllYXIoci5nZXRVVENGdWxsWWVhcigpKzEpLHI+bylicmVhaztyZXR1cm4gbn0sbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gcChlLHQpLGUucHJvdG90eXBlLnR5cGU9Ik1vbnRoc1RpY2tlciIsZS5kZWZpbmUoe21vbnRoczpbaC5BcnJheSxbXV19KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7dmFyIG4saTtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSxpPXRoaXMuZ2V0KCJtb250aHMiKSxuPWkubGVuZ3RoPjE/KGlbMV0taVswXSkqbzoxMipvLHRoaXMuc2V0KCJpbnRlcnZhbCIsbil9LGUucHJvdG90eXBlLmdldF90aWNrc19ub19kZWZhdWx0cz1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHUsaCxjLHA7cmV0dXJuIHA9bCh0LGUpLHU9dGhpcy5nZXQoIm1vbnRocyIpLGg9ZnVuY3Rpb24odCl7cmV0dXJuIHUubWFwKGZ1bmN0aW9uKGUpe3ZhciByO3JldHVybiByPWEodCksci5zZXRVVENNb250aChlKSxyfSl9LGk9cy5mbGF0dGVuKGZ1bmN0aW9uKCl7dmFyIHQsZSxyO2ZvcihyPVtdLHQ9MCxlPXAubGVuZ3RoO3Q8ZTt0Kyspbz1wW3RdLHIucHVzaChoKG8pKTtyZXR1cm4gcn0oKSksbj1zLmludm9rZShpLCJnZXRUaW1lIiksYz1zLmZpbHRlcihuLGZ1bmN0aW9uKHIpe3JldHVybiB0PD1yJiZyPD1lfSkse21ham9yOmMsbWlub3I6W119fSxlfShpLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm59fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vc2luZ2xlX2ludGVydmFsX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL3NpbmdsZV9pbnRlcnZhbF90aWNrZXIiLCIuL3V0aWwiOiJtb2RlbHMvdGlja2Vycy91dGlsIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdGlja2Vycy9zaW5nbGVfaW50ZXJ2YWxfdGlja2VyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vY29udGludW91c190aWNrZXIiKSxzPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGEoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJTaW5nbGVJbnRlcnZhbFRpY2tlciIsZS5kZWZpbmUoe2ludGVydmFsOltzLk51bWJlcl19KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoIm1pbl9pbnRlcnZhbCIsZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5nZXQoImludGVydmFsIil9LCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoIm1pbl9pbnRlcnZhbCIsdGhpcyxbImludGVydmFsIl0pLHRoaXMuZGVmaW5lX2NvbXB1dGVkX3Byb3BlcnR5KCJtYXhfaW50ZXJ2YWwiLGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZ2V0KCJpbnRlcnZhbCIpfSwhMCksdGhpcy5hZGRfZGVwZW5kZW5jaWVzKCJtYXhfaW50ZXJ2YWwiLHRoaXMsWyJpbnRlcnZhbCJdKX0sZS5wcm90b3R5cGUuZ2V0X2ludGVydmFsPWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gdGhpcy5nZXQoImludGVydmFsIil9LGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9jb250aW51b3VzX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL2NvbnRpbnVvdXNfdGlja2VyIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdGlja2Vycy90aWNrZXIiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHM9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWEuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sYT17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4uLy4uL21vZGVsIiksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gcyhlLHQpLGUucHJvdG90eXBlLnR5cGU9IlRpY2tlciIsZS5wcm90b3R5cGUuZ2V0X3RpY2tzPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBvO3JldHVybiBvPW4uZGVzaXJlZF9uX3RpY2tzLHRoaXMuZ2V0X3RpY2tzX25vX2RlZmF1bHRzKHQsZSx0aGlzLmdldCgiZGVzaXJlZF9udW1fdGlja3MiKSl9LGUucHJvdG90eXBlLmdldF90aWNrc19ub19kZWZhdWx0cz1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHc7aWYobD10aGlzLmdldF9pbnRlcnZhbCh0LGUsciksdj1NYXRoLmZsb29yKHQvbCksbj1NYXRoLmNlaWwoZS9sKSxzPWkuaXNOYU4odil8fGkuaXNOYU4obik/W106aS5yYW5nZSh2LG4rMSkseD1mdW5jdGlvbigpe3ZhciB0LGUscjtmb3Iocj1bXSx0PTAsZT1zLmxlbmd0aDt0PGU7dCsrKW89c1t0XSxyLnB1c2gobypsKTtyZXR1cm4gcn0oKSx5PXRoaXMuZ2V0KCJudW1fbWlub3JfdGlja3MiKSxnPVtdLHk+MSl7Zm9yKGY9bC95LG09ZnVuY3Rpb24oKXt2YXIgdCxlLHI7Zm9yKHI9W10sYT10PTEsZT15OzE8PWU/dDw9ZTp0Pj1lO2E9MTw9ZT8rK3Q6LS10KXIucHVzaChhKmYpO3JldHVybiByfSgpLHU9MCxwPW0ubGVuZ3RoO3U8cDt1Kyspdz1tW3VdLGcucHVzaCh4WzBdLXcpO2ZvcihoPTAsXz14Lmxlbmd0aDtoPF87aCsrKWZvcihiPXhbaF0sYz0wLGQ9bS5sZW5ndGg7YzxkO2MrKyl3PW1bY10sZy5wdXNoKGIrdyl9cmV0dXJue21ham9yOngsbWlub3I6Z319LGV9KG4pLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi4vLi4vbW9kZWwiOiJtb2RlbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3RpY2tlcnMvdXRpbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQ7aD10KCJ1bmRlcnNjb3JlIiksaT0xLGw9MWUzLHM9NjAqbCxvPTYwKnMsbj0yNCpvLGE9MzAqbix1PTM2NSpuLGM9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9aC5taW4oaC5yYW5nZSh0Lmxlbmd0aCksZnVuY3Rpb24oZSl7cmV0dXJuIHRbZV19KX0scD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IERhdGUodC5nZXRUaW1lKCkpfSxfPWZ1bmN0aW9uKHQpe3JldHVybiB0PXAodCksdC5zZXRVVENEYXRlKDEpLHQuc2V0VVRDSG91cnMoMCksdC5zZXRVVENNaW51dGVzKDApLHQuc2V0VVRDU2Vjb25kcygwKSx0LnNldFVUQ01pbGxpc2Vjb25kcygwKSx0fSxkPWZ1bmN0aW9uKHQpe3JldHVybiB0PV8odCksdC5zZXRVVENNb250aCgwKSx0fSxlLmV4cG9ydHM9e2FyZ21pbjpjLGNvcHlfZGF0ZTpwLGxhc3RfbW9udGhfbm9fbGF0ZXJfdGhhbjpfLGxhc3RfeWVhcl9ub19sYXRlcl90aGFuOmQsT05FX01JTExJOmksT05FX1NFQ09ORDpsLE9ORV9NSU5VVEU6cyxPTkVfSE9VUjpvLE9ORV9EQVk6bixPTkVfTU9OVEg6YSxPTkVfWUVBUjp1fX0se3VuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90aWNrZXJzL3llYXJzX3RpY2tlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7YT10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2Jhc2ljX3RpY2tlciIpLGk9dCgiLi9zaW5nbGVfaW50ZXJ2YWxfdGlja2VyIiksdT10KCIuL3V0aWwiKSxsPXUubGFzdF95ZWFyX25vX2xhdGVyX3RoYW4sbz11Lk9ORV9ZRUFSLHM9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJZZWFyc1RpY2tlciIsZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0LHIpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0LHIpLHRoaXMuc2V0KCJpbnRlcnZhbCIsbyksdGhpcy5iYXNpY190aWNrZXI9bmV3IG4uTW9kZWwoe251bV9taW5vcl90aWNrczowfSl9LGUucHJvdG90eXBlLmdldF90aWNrc19ub19kZWZhdWx0cz1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsdSxoO3JldHVybiBpPWwobmV3IERhdGUodCkpLmdldFVUQ0Z1bGxZZWFyKCksbz1sKG5ldyBEYXRlKGUpKS5nZXRVVENGdWxsWWVhcigpLGg9dGhpcy5iYXNpY190aWNrZXIuZ2V0X3RpY2tzX25vX2RlZmF1bHRzKGksbyxyKS5tYWpvcixuPWZ1bmN0aW9uKCl7dmFyIHQsZSxyO2ZvcihyPVtdLHQ9MCxlPWgubGVuZ3RoO3Q8ZTt0KyspdT1oW3RdLHIucHVzaChEYXRlLlVUQyh1LDAsMSkpO3JldHVybiByfSgpLHM9YS5maWx0ZXIobixmdW5jdGlvbihyKXtyZXR1cm4gdDw9ciYmcjw9ZX0pLHttYWpvcjpzLG1pbm9yOltdfX0sZX0oaS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpzfX0seyIuL2Jhc2ljX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL2Jhc2ljX3RpY2tlciIsIi4vc2luZ2xlX2ludGVydmFsX3RpY2tlciI6Im1vZGVscy90aWNrZXJzL3NpbmdsZV9pbnRlcnZhbF90aWNrZXIiLCIuL3V0aWwiOiJtb2RlbHMvdGlja2Vycy91dGlsIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdGlsZXMvYmJveF90aWxlX3NvdXJjZSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlsLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGw9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIiksbz10KCIuL21lcmNhdG9yX3RpbGVfc291cmNlIikscz10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGUudHlwZT0iQkJveFRpbGVTb3VyY2UiLGUuZGVmaW5lKHt1c2VfbGF0bG9uOltzLkJvb2wsITFdfSksZS5wcm90b3R5cGUuZ2V0X2ltYWdlX3VybD1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHU7cmV0dXJuIG49dGhpcy5zdHJpbmdfbG9va3VwX3JlcGxhY2UodGhpcy5nZXQoInVybCIpLHRoaXMuZ2V0KCJleHRyYV91cmxfdmFycyIpKSx0aGlzLmdldCgidXNlX2xhdGxvbiIpPyhvPXRoaXMuZ2V0X3RpbGVfZ2VvZ3JhcGhpY19ib3VuZHModCxlLHIpLGE9b1swXSx1PW9bMV0scz1vWzJdLGw9b1szXSk6KGk9dGhpcy5nZXRfdGlsZV9tZXRlcl9ib3VuZHModCxlLHIpLGE9aVswXSx1PWlbMV0scz1pWzJdLGw9aVszXSksbi5yZXBsYWNlKCJ7WE1JTn0iLGEpLnJlcGxhY2UoIntZTUlOfSIsdSkucmVwbGFjZSgie1hNQVh9IixzKS5yZXBsYWNlKCJ7WU1BWH0iLGwpfSxlfShvKSxlLmV4cG9ydHM9e01vZGVsOm59fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vbWVyY2F0b3JfdGlsZV9zb3VyY2UiOiJtb2RlbHMvdGlsZXMvbWVyY2F0b3JfdGlsZV9zb3VyY2UiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90aWxlcy9keW5hbWljX2ltYWdlX3JlbmRlcmVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGg9ZnVuY3Rpb24odCxlKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdC5hcHBseShlLGFyZ3VtZW50cyl9fSxjPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlwLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHA9e30uaGFzT3duUHJvcGVydHk7YT10KCJ1bmRlcnNjb3JlIiksaT10KCIuL2ltYWdlX3Bvb2wiKSxzPXQoIi4uL3JlbmRlcmVycy9yZW5kZXJlciIpLGw9dCgiLi4vLi4vY29yZS9sb2dnaW5nIikubG9nZ2VyLHU9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIHRoaXMuX29uX2ltYWdlX2Vycm9yPWgodGhpcy5fb25faW1hZ2VfZXJyb3IsdGhpcyksdGhpcy5fb25faW1hZ2VfbG9hZD1oKHRoaXMuX29uX2ltYWdlX2xvYWQsdGhpcyksZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBjKGUsdCksZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5saXN0ZW5Ubyh0aGlzLm1vZGVsLCJjaGFuZ2UiLHRoaXMucmVxdWVzdF9yZW5kZXIpfSxlLnByb3RvdHlwZS5nZXRfZXh0ZW50PWZ1bmN0aW9uKCl7cmV0dXJuW3RoaXMueF9yYW5nZS5nZXQoInN0YXJ0IiksdGhpcy55X3JhbmdlLmdldCgic3RhcnQiKSx0aGlzLnhfcmFuZ2UuZ2V0KCJlbmQiKSx0aGlzLnlfcmFuZ2UuZ2V0KCJlbmQiKV19LGUucHJvdG90eXBlLl9zZXRfZGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLm1hcF9wbG90PXRoaXMucGxvdF92aWV3Lm1vZGVsLnBsb3QsdGhpcy5tYXBfY2FudmFzPXRoaXMucGxvdF92aWV3LmNhbnZhc192aWV3LmN0eCx0aGlzLm1hcF9mcmFtZT10aGlzLnBsb3Rfdmlldy5mcmFtZSx0aGlzLnhfcmFuZ2U9dGhpcy5tYXBfcGxvdC5nZXQoInhfcmFuZ2UiKSx0aGlzLnhfbWFwcGVyPXRoaXMubWFwX2ZyYW1lLmdldCgieF9tYXBwZXJzIilbImRlZmF1bHQiXSx0aGlzLnlfcmFuZ2U9dGhpcy5tYXBfcGxvdC5nZXQoInlfcmFuZ2UiKSx0aGlzLnlfbWFwcGVyPXRoaXMubWFwX2ZyYW1lLmdldCgieV9tYXBwZXJzIilbImRlZmF1bHQiXSx0aGlzLmxhc3RJbWFnZT12b2lkIDAsdGhpcy5leHRlbnQ9dGhpcy5nZXRfZXh0ZW50KCl9LGUucHJvdG90eXBlLl9tYXBfZGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmluaXRpYWxfZXh0ZW50PXRoaXMuZ2V0X2V4dGVudCgpfSxlLnByb3RvdHlwZS5fb25faW1hZ2VfbG9hZD1mdW5jdGlvbih0KXt2YXIgZTtpZihlPXQudGFyZ2V0LmltYWdlX2RhdGEsZS5pbWc9dC50YXJnZXQsZS5sb2FkZWQ9ITAsdGhpcy5sYXN0SW1hZ2U9ZSx0aGlzLmdldF9leHRlbnQoKS5qb2luKCI6Iik9PT1lLmNhY2hlX2tleSlyZXR1cm4gdGhpcy5yZXF1ZXN0X3JlbmRlcigpfSxlLnByb3RvdHlwZS5fb25faW1hZ2VfZXJyb3I9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGwuZXJyb3IoIkVycm9yIGxvYWRpbmcgaW1hZ2U6ICN7ZS50YXJnZXQuc3JjfSIpLGU9dC50YXJnZXQuaW1hZ2VfZGF0YSx0aGlzLm1nZXQoImltYWdlX3NvdXJjZSIpLnJlbW92ZV9pbWFnZShlKX0sZS5wcm90b3R5cGUuX2NyZWF0ZV9pbWFnZT1mdW5jdGlvbih0KXt2YXIgZTtyZXR1cm4gZT1uZXcgSW1hZ2UsZS5vbmxvYWQ9dGhpcy5fb25faW1hZ2VfbG9hZCxlLm9uZXJyb3I9dGhpcy5fb25faW1hZ2VfZXJyb3IsZS5hbHQ9IiIsZS5pbWFnZV9kYXRhPXtib3VuZHM6dCxsb2FkZWQ6ITEsY2FjaGVfa2V5OnQuam9pbigiOiIpfSx0aGlzLm1nZXQoImltYWdlX3NvdXJjZSIpLmFkZF9pbWFnZShlLmltYWdlX2RhdGEpLGUuc3JjPXRoaXMubWdldCgiaW1hZ2Vfc291cmNlIikuZ2V0X2ltYWdlX3VybCh0WzBdLHRbMV0sdFsyXSx0WzNdLE1hdGguY2VpbCh0aGlzLm1hcF9mcmFtZS5nZXQoImhlaWdodCIpKSxNYXRoLmNlaWwodGhpcy5tYXBfZnJhbWUuZ2V0KCJ3aWR0aCIpKSksZX0sZS5wcm90b3R5cGUucmVuZGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvO3JldHVybiBudWxsPT10aGlzLm1hcF9pbml0aWFsaXplZCYmKHRoaXMuX3NldF9kYXRhKCksdGhpcy5fbWFwX2RhdGEoKSx0aGlzLm1hcF9pbml0aWFsaXplZD0hMCksbj10aGlzLmdldF9leHRlbnQoKSx0aGlzLnJlbmRlcl90aW1lciYmY2xlYXJUaW1lb3V0KHRoaXMucmVuZGVyX3RpbWVyKSxvPXRoaXMubWdldCgiaW1hZ2Vfc291cmNlIikuaW1hZ2VzW24uam9pbigiOiIpXSxudWxsIT1vJiZvLmxvYWRlZD92b2lkIHRoaXMuX2RyYXdfaW1hZ2Uobi5qb2luKCI6IikpOihudWxsIT10aGlzLmxhc3RJbWFnZSYmdGhpcy5fZHJhd19pbWFnZSh0aGlzLmxhc3RJbWFnZS5jYWNoZV9rZXkpLG51bGw9PW8/dGhpcy5yZW5kZXJfdGltZXI9c2V0VGltZW91dChmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdC5fY3JlYXRlX2ltYWdlKG4pfX0odGhpcyksMTI1KTp2b2lkIDApfSxlLnByb3RvdHlwZS5fZHJhd19pbWFnZT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsLHUsaCxjO2lmKGU9dGhpcy5tZ2V0KCJpbWFnZV9zb3VyY2UiKS5pbWFnZXNbdF0sbnVsbCE9ZSlyZXR1cm4gdGhpcy5tYXBfY2FudmFzLnNhdmUoKSx0aGlzLl9zZXRfcmVjdCgpLHRoaXMubWFwX2NhbnZhcy5nbG9iYWxBbHBoYT10aGlzLm1nZXQoImFscGhhIikscj10aGlzLnBsb3Rfdmlldy5mcmFtZS5tYXBfdG9fc2NyZWVuKFtlLmJvdW5kc1swXV0sW2UuYm91bmRzWzNdXSx0aGlzLnBsb3Rfdmlldy5jYW52YXMpLGw9clswXSxjPXJbMV0sbj10aGlzLnBsb3Rfdmlldy5mcmFtZS5tYXBfdG9fc2NyZWVuKFtlLmJvdW5kc1syXV0sW2UuYm91bmRzWzFdXSx0aGlzLnBsb3Rfdmlldy5jYW52YXMpLGE9blswXSxoPW5bMV0sbD1sWzBdLGM9Y1swXSxhPWFbMF0saD1oWzBdLGk9YS1sLG89aC1jLHM9bCx1PWMsdGhpcy5tYXBfY2FudmFzLmRyYXdJbWFnZShlLmltZyxzLHUsaSxvKSx0aGlzLm1hcF9jYW52YXMucmVzdG9yZSgpfSxlLnByb3RvdHlwZS5fc2V0X3JlY3Q9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvO3JldHVybiByPXRoaXMucGxvdF9tb2RlbC5wbG90LnByb3BlcnRpZXMub3V0bGluZV9saW5lX3dpZHRoLnZhbHVlKCksZT10aGlzLnBsb3Rfdmlldy5jYW52YXMudnhfdG9fc3godGhpcy5tYXBfZnJhbWUuZ2V0KCJsZWZ0IikpK3IvMixuPXRoaXMucGxvdF92aWV3LmNhbnZhcy52eV90b19zeSh0aGlzLm1hcF9mcmFtZS5nZXQoInRvcCIpKStyLzIsbz10aGlzLm1hcF9mcmFtZS5nZXQoIndpZHRoIiktcix0PXRoaXMubWFwX2ZyYW1lLmdldCgiaGVpZ2h0Iiktcix0aGlzLm1hcF9jYW52YXMucmVjdChlLG4sbyx0KSx0aGlzLm1hcF9jYW52YXMuY2xpcCgpfSxlfShzLlZpZXcpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGMoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9byxlLnByb3RvdHlwZS50eXBlPSJEeW5hbWljSW1hZ2VSZW5kZXJlciIsZS5kZWZpbmUoe2FscGhhOlt1Lk51bWJlciwxXSxpbWFnZV9zb3VyY2U6W3UuSW5zdGFuY2VdLHJlbmRlcl9wYXJlbnRzOlt1LkJvb2wsITBdfSksZS5vdmVycmlkZSh7bGV2ZWw6InVuZGVybGF5In0pLGV9KHMuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bixWaWV3Om99fSx7Ii4uLy4uL2NvcmUvbG9nZ2luZyI6ImNvcmUvbG9nZ2luZyIsIi4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4uL3JlbmRlcmVycy9yZW5kZXJlciI6Im1vZGVscy9yZW5kZXJlcnMvcmVuZGVyZXIiLCIuL2ltYWdlX3Bvb2wiOiJtb2RlbHMvdGlsZXMvaW1hZ2VfcG9vbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3RpbGVzL2ltYWdlX3Bvb2wiOltmdW5jdGlvbih0LGUscil7dmFyIG47bj1mdW5jdGlvbigpe2Z1bmN0aW9uIHQoKXt0aGlzLmltYWdlcz1bXX1yZXR1cm4gdC5wcm90b3R5cGUucG9wPWZ1bmN0aW9uKCl7dmFyIHQ7cmV0dXJuIHQ9dGhpcy5pbWFnZXMucG9wKCksbnVsbCE9dD90Om5ldyBJbWFnZX0sdC5wcm90b3R5cGUucHVzaD1mdW5jdGlvbih0KXtpZighKHRoaXMuaW1hZ2VzLmxlbmd0aD41MCkpcmV0dXJuIHQuY29uc3RydWN0b3I9PT1BcnJheT9BcnJheS5wcm90b3R5cGUucHVzaC5hcHBseSh0aGlzLmltYWdlcyx0KTp0aGlzLmltYWdlcy5wdXNoKHQpfSx0fSgpLGUuZXhwb3J0cz1ufSx7fV0sIm1vZGVscy90aWxlcy9pbWFnZV9zb3VyY2UiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl1LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHU9e30uaGFzT3duUHJvcGVydHk7aT10KCJ1bmRlcnNjb3JlIikscz10KCIuLi8uLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIsYT10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxvPXQoIi4uLy4uL21vZGVsIiksbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKHQpe251bGw9PXQmJih0PXt9KSxlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyksdGhpcy5pbWFnZXM9e30sdGhpcy5ub3JtYWxpemVfY2FzZSgpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUudHlwZT0iSW1hZ2VTb3VyY2UiLGUuZGVmaW5lKHt1cmw6W2EuU3RyaW5nLCIiXSxleHRyYV91cmxfdmFyczpbYS5Bbnkse31dfSksZS5wcm90b3R5cGUubm9ybWFsaXplX2Nhc2U9ZnVuY3Rpb24oKXsiTm90ZTogc2hvdWxkIHByb2JhYmx5IGJlIHJlZmFjdG9yZWQgaW50byBzdWJjbGFzc2VzLiI7dmFyIHQ7cmV0dXJuIHQ9dGhpcy5nZXQoInVybCIpLHQ9dC5yZXBsYWNlKCJ7eG1pbn0iLCJ7WE1JTn0iKSx0PXQucmVwbGFjZSgie3ltaW59Iiwie1lNSU59IiksdD10LnJlcGxhY2UoInt4bWF4fSIsIntYTUFYfSIpLHQ9dC5yZXBsYWNlKCJ7eW1heH0iLCJ7WU1BWH0iKSx0PXQucmVwbGFjZSgie2hlaWdodH0iLCJ7SEVJR0hUfSIpLHQ9dC5yZXBsYWNlKCJ7d2lkdGh9Iiwie1dJRFRIfSIpLHRoaXMuc2V0KCJ1cmwiLHQpfSxlLnByb3RvdHlwZS5zdHJpbmdfbG9va3VwX3JlcGxhY2U9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG87bj10O2ZvcihyIGluIGUpbz1lW3JdLG49bi5yZXBsYWNlKCJ7IityKyJ9IixvLnRvU3RyaW5nKCkpO3JldHVybiBufSxlLnByb3RvdHlwZS5hZGRfaW1hZ2U9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuaW1hZ2VzW3QuY2FjaGVfa2V5XT10fSxlLnByb3RvdHlwZS5yZW1vdmVfaW1hZ2U9ZnVuY3Rpb24odCl7cmV0dXJuIGRlbGV0ZSB0aGlzLmltYWdlc1t0LmNhY2hlX2tleV19LGUucHJvdG90eXBlLmdldF9pbWFnZV91cmw9ZnVuY3Rpb24odCxlLHIsbixvLGkpe3ZhciBzO3JldHVybiBzPXRoaXMuc3RyaW5nX2xvb2t1cF9yZXBsYWNlKHRoaXMuZ2V0KCJ1cmwiKSx0aGlzLmdldCgiZXh0cmFfdXJsX3ZhcnMiKSksCnMucmVwbGFjZSgie1hNSU59Iix0KS5yZXBsYWNlKCJ7WU1JTn0iLGUpLnJlcGxhY2UoIntYTUFYfSIscikucmVwbGFjZSgie1lNQVh9IixuKS5yZXBsYWNlKCJ7V0lEVEh9IixpKS5yZXBsYWNlKCJ7SEVJR0hUfSIsbyl9LGV9KG8pLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vbW9kZWwiOiJtb2RlbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3RpbGVzL21lcmNhdG9yX3RpbGVfc291cmNlIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxvPXQoIi4vdGlsZV9zb3VyY2UiKSxzPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG49ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGEoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJNZXJjYXRvclRpbGVTb3VyY2UiLGUuZGVmaW5lKHt3cmFwX2Fyb3VuZDpbcy5Cb29sLCEwXX0pLGUub3ZlcnJpZGUoe3hfb3JpZ2luX29mZnNldDoyMDAzNzUwOC4zNCx5X29yaWdpbl9vZmZzZXQ6MjAwMzc1MDguMzQsaW5pdGlhbF9yZXNvbHV0aW9uOjE1NjU0My4wMzM5MjgwNDA5N30pLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCl7dmFyIHI7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMuX3Jlc29sdXRpb25zPWZ1bmN0aW9uKCl7dmFyIHQsZTtmb3IoZT1bXSxyPXQ9MDt0PD0zMDtyPSsrdCllLnB1c2godGhpcy5nZXRfcmVzb2x1dGlvbihyKSk7cmV0dXJuIGV9LmNhbGwodGhpcyl9LGUucHJvdG90eXBlLl9jb21wdXRlZF9pbml0aWFsX3Jlc29sdXRpb249ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbCE9dGhpcy5nZXQoImluaXRpYWxfcmVzb2x1dGlvbiIpP3RoaXMuZ2V0KCJpbml0aWFsX3Jlc29sdXRpb24iKToyKk1hdGguUEkqNjM3ODEzNy90aGlzLmdldCgidGlsZV9zaXplIil9LGUucHJvdG90eXBlLmlzX3ZhbGlkX3RpbGU9ZnVuY3Rpb24odCxlLHIpe3JldHVybiEoIXRoaXMuZ2V0KCJ3cmFwX2Fyb3VuZCIpJiYodDwwfHx0Pj1NYXRoLnBvdygyLHIpKSkmJiEoZTwwfHxlPj1NYXRoLnBvdygyLHIpKX0sZS5wcm90b3R5cGUucmV0YWluX2NoaWxkcmVuPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhO289dC5xdWFka2V5LG49by5sZW5ndGgscj1uKzMsaT10aGlzLnRpbGVzLHM9W107Zm9yKGUgaW4gaSlhPWlbZV0sMD09PWEucXVhZGtleS5pbmRleE9mKG8pJiZhLnF1YWRrZXkubGVuZ3RoPm4mJmEucXVhZGtleS5sZW5ndGg8PXI/cy5wdXNoKGEucmV0YWluPSEwKTpzLnB1c2godm9pZCAwKTtyZXR1cm4gc30sZS5wcm90b3R5cGUucmV0YWluX25laWdoYm9ycz1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxzLGEsbCx1LGgsYyxwLF8sZDtyPTQscz10LnRpbGVfY29vcmRzLGg9c1swXSxjPXNbMV0scD1zWzJdLG49ZnVuY3Rpb24oKXt2YXIgdCxlLG4sbztmb3Iobz1bXSxfPXQ9ZT1oLXIsbj1oK3I7ZTw9bj90PD1uOnQ+PW47Xz1lPD1uPysrdDotLXQpby5wdXNoKF8pO3JldHVybiBvfSgpLG89ZnVuY3Rpb24oKXt2YXIgdCxlLG4sbztmb3Iobz1bXSxkPXQ9ZT1jLXIsbj1jK3I7ZTw9bj90PD1uOnQ+PW47ZD1lPD1uPysrdDotLXQpby5wdXNoKGQpO3JldHVybiBvfSgpLGE9dGhpcy50aWxlcyxsPVtdO2ZvcihlIGluIGEpdT1hW2VdLHUudGlsZV9jb29yZHNbMl09PT1wJiZpLmNvbnRhaW5zKG4sdS50aWxlX2Nvb3Jkc1swXSkmJmkuY29udGFpbnMobyx1LnRpbGVfY29vcmRzWzFdKT9sLnB1c2godS5yZXRhaW49ITApOmwucHVzaCh2b2lkIDApO3JldHVybiBsfSxlLnByb3RvdHlwZS5yZXRhaW5fcGFyZW50cz1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpO3I9dC5xdWFka2V5LG49dGhpcy50aWxlcyxvPVtdO2ZvcihlIGluIG4paT1uW2VdLG8ucHVzaChpLnJldGFpbj0wPT09ci5pbmRleE9mKGkucXVhZGtleSkpO3JldHVybiBvfSxlLnByb3RvdHlwZS5jaGlsZHJlbl9ieV90aWxlX3h5ej1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjO2ZvcihjPXRoaXMuY2FsY3VsYXRlX3dvcmxkX3hfYnlfdGlsZV94eXoodCxlLHIpLDAhPT1jJiYobD10aGlzLm5vcm1hbGl6ZV94eXoodCxlLHIpLHQ9bFswXSxlPWxbMV0scj1sWzJdKSxhPXRoaXMudGlsZV94eXpfdG9fcXVhZGtleSh0LGUsciksbz1bXSxpPXM9MDtzPD0zO2k9cys9MSl1PXRoaXMucXVhZGtleV90b190aWxlX3h5eihhK2kudG9TdHJpbmcoKSksdD11WzBdLGU9dVsxXSxyPXVbMl0sMCE9PWMmJihoPXRoaXMuZGVub3JtYWxpemVfeHl6KHQsZSxyLGMpLHQ9aFswXSxlPWhbMV0scj1oWzJdKSxuPXRoaXMuZ2V0X3RpbGVfbWV0ZXJfYm91bmRzKHQsZSxyKSxudWxsIT1uJiZvLnB1c2goW3QsZSxyLG5dKTtyZXR1cm4gb30sZS5wcm90b3R5cGUucGFyZW50X2J5X3RpbGVfeHl6PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvO3JldHVybiBvPXRoaXMudGlsZV94eXpfdG9fcXVhZGtleSh0LGUsciksbj1vLnN1YnN0cmluZygwLG8ubGVuZ3RoLTEpLHRoaXMucXVhZGtleV90b190aWxlX3h5eihuKX0sZS5wcm90b3R5cGUuZ2V0X3Jlc29sdXRpb249ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2NvbXB1dGVkX2luaXRpYWxfcmVzb2x1dGlvbigpL01hdGgucG93KDIsdCl9LGUucHJvdG90eXBlLmdldF9yZXNvbHV0aW9uX2J5X2V4dGVudD1mdW5jdGlvbih0LGUscil7dmFyIG4sbztyZXR1cm4gbj0odFsyXS10WzBdKS9yLG89KHRbM10tdFsxXSkvZSxbbixvXX0sZS5wcm90b3R5cGUuZ2V0X2xldmVsX2J5X2V4dGVudD1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaDtmb3IodT0odFsyXS10WzBdKS9yLGg9KHRbM10tdFsxXSkvZSxsPU1hdGgubWF4KHUsaCksbj0wLGE9dGhpcy5fcmVzb2x1dGlvbnMsbz0wLGk9YS5sZW5ndGg7bzxpO28rKyl7aWYocz1hW29dLGw+cyl7aWYoMD09PW4pcmV0dXJuIDA7aWYobj4wKXJldHVybiBuLTF9bis9MX19LGUucHJvdG90eXBlLmdldF9jbG9zZXN0X2xldmVsX2J5X2V4dGVudD1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYTtyZXR1cm4gcz0odFsyXS10WzBdKS9yLGE9KHRbM10tdFsxXSkvZSxvPU1hdGgubWF4KHMsYSksaT10aGlzLl9yZXNvbHV0aW9ucyxuPXRoaXMuX3Jlc29sdXRpb25zLnJlZHVjZShmdW5jdGlvbih0LGUpe3JldHVybiBNYXRoLmFicyhlLW8pPE1hdGguYWJzKHQtbyk/ZTp0fSksdGhpcy5fcmVzb2x1dGlvbnMuaW5kZXhPZihuKX0sZS5wcm90b3R5cGUuc25hcF90b196b29tPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBvLGkscyxhLGwsdSxoLGMscDtyZXR1cm4gbz10aGlzLl9yZXNvbHV0aW9uc1tuXSxpPXIqbyxzPWUqbyx1PXRbMF0scD10WzFdLGw9dFsyXSxjPXRbM10sYT0oaS0obC11KSkvMixoPShzLShjLXApKS8yLFt1LWEscC1oLGwrYSxjK2hdfSxlLnByb3RvdHlwZS50bXNfdG9fd210cz1mdW5jdGlvbih0LGUscil7Ik5vdGUgdGhpcyB3b3JrcyBib3RoIHdheXMiO3JldHVyblt0LE1hdGgucG93KDIsciktMS1lLHJdfSxlLnByb3RvdHlwZS53bXRzX3RvX3Rtcz1mdW5jdGlvbih0LGUscil7Ik5vdGUgdGhpcyB3b3JrcyBib3RoIHdheXMiO3JldHVyblt0LE1hdGgucG93KDIsciktMS1lLHJdfSxlLnByb3RvdHlwZS5waXhlbHNfdG9fbWV0ZXJzPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk7cmV0dXJuIGk9dGhpcy5nZXRfcmVzb2x1dGlvbihyKSxuPXQqaS10aGlzLmdldCgieF9vcmlnaW5fb2Zmc2V0Iiksbz1lKmktdGhpcy5nZXQoInlfb3JpZ2luX29mZnNldCIpLFtuLG9dfSxlLnByb3RvdHlwZS5tZXRlcnNfdG9fcGl4ZWxzPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk7cmV0dXJuIGk9dGhpcy5nZXRfcmVzb2x1dGlvbihyKSxuPSh0K3RoaXMuZ2V0KCJ4X29yaWdpbl9vZmZzZXQiKSkvaSxvPShlK3RoaXMuZ2V0KCJ5X29yaWdpbl9vZmZzZXQiKSkvaSxbbixvXX0sZS5wcm90b3R5cGUucGl4ZWxzX3RvX3RpbGU9ZnVuY3Rpb24odCxlKXt2YXIgcixuO3JldHVybiByPU1hdGguY2VpbCh0L3BhcnNlRmxvYXQodGhpcy5nZXQoInRpbGVfc2l6ZSIpKSkscj0wPT09cj9yOnItMSxuPU1hdGgubWF4KE1hdGguY2VpbChlL3BhcnNlRmxvYXQodGhpcy5nZXQoInRpbGVfc2l6ZSIpKSktMSwwKSxbcixuXX0sZS5wcm90b3R5cGUucGl4ZWxzX3RvX3Jhc3Rlcj1mdW5jdGlvbih0LGUscil7dmFyIG47cmV0dXJuIG49dGhpcy5nZXQoInRpbGVfc2l6ZSIpPDxyLFt0LG4tZV19LGUucHJvdG90eXBlLm1ldGVyc190b190aWxlPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk7cmV0dXJuIGk9dGhpcy5tZXRlcnNfdG9fcGl4ZWxzKHQsZSxyKSxuPWlbMF0sbz1pWzFdLHRoaXMucGl4ZWxzX3RvX3RpbGUobixvKX0sZS5wcm90b3R5cGUuZ2V0X3RpbGVfbWV0ZXJfYm91bmRzPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw7cmV0dXJuIG49dGhpcy5waXhlbHNfdG9fbWV0ZXJzKHQqdGhpcy5nZXQoInRpbGVfc2l6ZSIpLGUqdGhpcy5nZXQoInRpbGVfc2l6ZSIpLHIpLHM9blswXSxsPW5bMV0sbz10aGlzLnBpeGVsc190b19tZXRlcnMoKHQrMSkqdGhpcy5nZXQoInRpbGVfc2l6ZSIpLChlKzEpKnRoaXMuZ2V0KCJ0aWxlX3NpemUiKSxyKSxpPW9bMF0sYT1vWzFdLG51bGwhPXMmJm51bGwhPWwmJm51bGwhPWkmJm51bGwhPWE/W3MsbCxpLGFdOnZvaWQgMH0sZS5wcm90b3R5cGUuZ2V0X3RpbGVfZ2VvZ3JhcGhpY19ib3VuZHM9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbDtyZXR1cm4gbj10aGlzLmdldF90aWxlX21ldGVyX2JvdW5kcyh0LGUsciksbD10aGlzLnV0aWxzLm1ldGVyc19leHRlbnRfdG9fZ2VvZ3JhcGhpYyhuKSxhPWxbMF0scz1sWzFdLGk9bFsyXSxvPWxbM10sW2EscyxpLG9dfSxlLnByb3RvdHlwZS5nZXRfdGlsZXNfYnlfZXh0ZW50PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseDtmb3IobnVsbD09ciYmKHI9MSksdj10WzBdLHg9dFsxXSx5PXRbMl0sYj10WzNdLGk9dGhpcy5tZXRlcnNfdG9fdGlsZSh2LHgsZSksZD1pWzBdLGc9aVsxXSxzPXRoaXMubWV0ZXJzX3RvX3RpbGUoeSxiLGUpLF89c1swXSxtPXNbMV0sZC09cixnLT1yLF8rPXIsbSs9cixjPVtdLGY9bj1hPW0sbD1nO24+PWw7Zj1uKz0tMSlmb3IocD1vPXU9ZCxoPV87bzw9aDtwPW8rPTEpdGhpcy5pc192YWxpZF90aWxlKHAsZixlKSYmYy5wdXNoKFtwLGYsZSx0aGlzLmdldF90aWxlX21ldGVyX2JvdW5kcyhwLGYsZSldKTtyZXR1cm4gYz10aGlzLnNvcnRfdGlsZXNfZnJvbV9jZW50ZXIoYyxbZCxnLF8sbV0pfSxlLnByb3RvdHlwZS5xdWFka2V5X3RvX3RpbGVfeHl6PWZ1bmN0aW9uKHQpeyJDb21wdXRlcyB0aWxlIHgsIHkgYW5kIHogdmFsdWVzIGJhc2VkIG9uIHF1YWRLZXkuIjt2YXIgZSxyLG4sbyxpLHMsYSxsO2ZvcihpPTAscz0wLGE9dC5sZW5ndGgsZT1yPW89YTtyPjA7ZT1yKz0tMSlpZihsPXQuY2hhckF0KGEtZSksbj0xPDxlLTEsIjAiIT09bClpZigiMSI9PT1sKWl8PW47ZWxzZSBpZigiMiI9PT1sKXN8PW47ZWxzZXtpZigiMyIhPT1sKXRocm93IG5ldyBUeXBlRXJyb3IoIkludmFsaWQgUXVhZGtleTogIit0KTtpfD1uLHN8PW59cmV0dXJuW2kscyxhXX0sZS5wcm90b3R5cGUudGlsZV94eXpfdG9fcXVhZGtleT1mdW5jdGlvbih0LGUscil7IkNvbXB1dGVzIHF1YWRrZXkgdmFsdWUgYmFzZWQgb24gdGlsZSB4LCB5IGFuZCB6IHZhbHVlcy4iO3ZhciBuLG8saSxzLGEsbDtmb3IoYT0iIixvPWk9bD1yO2k+MDtvPWkrPS0xKW49MCxzPTE8PG8tMSwwIT09KHQmcykmJihuKz0xKSwwIT09KGUmcykmJihuKz0yKSxhKz1uLnRvU3RyaW5nKCk7cmV0dXJuIGF9LGUucHJvdG90eXBlLmNoaWxkcmVuX2J5X3RpbGVfeHl6PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw7Zm9yKGE9dGhpcy50aWxlX3h5el90b19xdWFka2V5KHQsZSxyKSxvPVtdLGk9cz0wO3M8PTM7aT1zKz0xKWw9dGhpcy5xdWFka2V5X3RvX3RpbGVfeHl6KGEraS50b1N0cmluZygpKSx0PWxbMF0sZT1sWzFdLHI9bFsyXSxuPXRoaXMuZ2V0X3RpbGVfbWV0ZXJfYm91bmRzKHQsZSxyKSxudWxsIT1uJiZvLnB1c2goW3QsZSxyLG5dKTtyZXR1cm4gb30sZS5wcm90b3R5cGUucGFyZW50X2J5X3RpbGVfeHl6PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvO3JldHVybiBvPXRoaXMudGlsZV94eXpfdG9fcXVhZGtleSh0LGUsciksbj1vLnN1YnN0cmluZygwLG8ubGVuZ3RoLTEpLHRoaXMucXVhZGtleV90b190aWxlX3h5eihuKX0sZS5wcm90b3R5cGUuZ2V0X2Nsb3Nlc3RfcGFyZW50X2J5X3RpbGVfeHl6PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhO2ZvcihhPXRoaXMuY2FsY3VsYXRlX3dvcmxkX3hfYnlfdGlsZV94eXoodCxlLHIpLG89dGhpcy5ub3JtYWxpemVfeHl6KHQsZSxyKSx0PW9bMF0sZT1vWzFdLHI9b1syXSxuPXRoaXMudGlsZV94eXpfdG9fcXVhZGtleSh0LGUscik7bi5sZW5ndGg+MDspaWYobj1uLnN1YnN0cmluZygwLG4ubGVuZ3RoLTEpLGk9dGhpcy5xdWFka2V5X3RvX3RpbGVfeHl6KG4pLHQ9aVswXSxlPWlbMV0scj1pWzJdLHM9dGhpcy5kZW5vcm1hbGl6ZV94eXoodCxlLHIsYSksdD1zWzBdLGU9c1sxXSxyPXNbMl0sdGhpcy50aWxlX3h5el90b19rZXkodCxlLHIpaW4gdGhpcy50aWxlcylyZXR1cm5bdCxlLHJdO3JldHVyblswLDAsMF19LGUucHJvdG90eXBlLm5vcm1hbGl6ZV94eXo9ZnVuY3Rpb24odCxlLHIpe3ZhciBuO3JldHVybiB0aGlzLmdldCgid3JhcF9hcm91bmQiKT8obj1NYXRoLnBvdygyLHIpLFsodCVuK24pJW4sZSxyXSk6W3QsZSxyXX0sZS5wcm90b3R5cGUuZGVub3JtYWxpemVfeHl6PWZ1bmN0aW9uKHQsZSxyLG4pe3JldHVyblt0K24qTWF0aC5wb3coMixyKSxlLHJdfSxlLnByb3RvdHlwZS5kZW5vcm1hbGl6ZV9tZXRlcnM9ZnVuY3Rpb24odCxlLHIsbil7cmV0dXJuW3QrMipuKk1hdGguUEkqNjM3ODEzNyxlXX0sZS5wcm90b3R5cGUuY2FsY3VsYXRlX3dvcmxkX3hfYnlfdGlsZV94eXo9ZnVuY3Rpb24odCxlLHIpe3JldHVybiBNYXRoLmZsb29yKHQvTWF0aC5wb3coMixyKSl9LGV9KG8pLGUuZXhwb3J0cz1ufSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vdGlsZV9zb3VyY2UiOiJtb2RlbHMvdGlsZXMvdGlsZV9zb3VyY2UiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90aWxlcy9xdWFka2V5X3RpbGVfc291cmNlIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpcy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxzPXt9Lmhhc093blByb3BlcnR5O249dCgiLi9tZXJjYXRvcl90aWxlX3NvdXJjZSIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGkoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJRVUFES0VZVGlsZVNvdXJjZSIsZS5wcm90b3R5cGUuZ2V0X2ltYWdlX3VybD1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpO3JldHVybiBuPXRoaXMuc3RyaW5nX2xvb2t1cF9yZXBsYWNlKHRoaXMuZ2V0KCJ1cmwiKSx0aGlzLmdldCgiZXh0cmFfdXJsX3ZhcnMiKSksaT10aGlzLnRtc190b193bXRzKHQsZSxyKSx0PWlbMF0sZT1pWzFdLHI9aVsyXSxvPXRoaXMudGlsZV94eXpfdG9fcXVhZGtleSh0LGUsciksbi5yZXBsYWNlKCJ7UX0iLG8pfSxlfShuKSxlLmV4cG9ydHM9e01vZGVsOm99fSx7Ii4vbWVyY2F0b3JfdGlsZV9zb3VyY2UiOiJtb2RlbHMvdGlsZXMvbWVyY2F0b3JfdGlsZV9zb3VyY2UifV0sIm1vZGVscy90aWxlcy90aWxlX3JlbmRlcmVyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHQuYXBwbHkoZSxhcmd1bWVudHMpfX0sXz1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpZC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxkPXt9Lmhhc093blByb3BlcnR5LGY9W10uaW5kZXhPZnx8ZnVuY3Rpb24odCl7Zm9yKHZhciBlPTAscj10aGlzLmxlbmd0aDtlPHI7ZSsrKWlmKGUgaW4gdGhpcyYmdGhpc1tlXT09PXQpcmV0dXJuIGU7cmV0dXJuLTF9O2w9dCgidW5kZXJzY29yZSIpLG49dCgianF1ZXJ5Iiksbz10KCIuL2ltYWdlX3Bvb2wiKSxjPXQoIi4vd210c190aWxlX3NvdXJjZSIpLGk9dCgiLi4vcmVuZGVyZXJzL3JlbmRlcmVyIiksdT10KCIuLi8uLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIsaD10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxhPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gdGhpcy5fdXBkYXRlPXAodGhpcy5fdXBkYXRlLHRoaXMpLHRoaXMuX3ByZWZldGNoX3RpbGVzPXAodGhpcy5fcHJlZmV0Y2hfdGlsZXMsdGhpcyksdGhpcy5fb25fdGlsZV9lcnJvcj1wKHRoaXMuX29uX3RpbGVfZXJyb3IsdGhpcyksdGhpcy5fb25fdGlsZV9jYWNoZV9sb2FkPXAodGhpcy5fb25fdGlsZV9jYWNoZV9sb2FkLHRoaXMpLHRoaXMuX29uX3RpbGVfbG9hZD1wKHRoaXMuX29uX3RpbGVfbG9hZCx0aGlzKSx0aGlzLl9hZGRfYXR0cmlidXRpb249cCh0aGlzLl9hZGRfYXR0cmlidXRpb24sdGhpcyksZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBfKGUsdCksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5hdHRyaWJ1dGlvbkVsPW51bGwsZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5hcHBseSh0aGlzLGFyZ3VtZW50cyl9LGUucHJvdG90eXBlLmJpbmRfYm9rZWhfZXZlbnRzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiY2hhbmdlIix0aGlzLnJlcXVlc3RfcmVuZGVyKX0sZS5wcm90b3R5cGUuZ2V0X2V4dGVudD1mdW5jdGlvbigpe3JldHVyblt0aGlzLnhfcmFuZ2UuZ2V0KCJzdGFydCIpLHRoaXMueV9yYW5nZS5nZXQoInN0YXJ0IiksdGhpcy54X3JhbmdlLmdldCgiZW5kIiksdGhpcy55X3JhbmdlLmdldCgiZW5kIildfSxlLnByb3RvdHlwZS5fc2V0X2RhdGE9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5wb29sPW5ldyBvLHRoaXMubWFwX3Bsb3Q9dGhpcy5wbG90X21vZGVsLnBsb3QsdGhpcy5tYXBfY2FudmFzPXRoaXMucGxvdF92aWV3LmNhbnZhc192aWV3LmN0eCx0aGlzLm1hcF9mcmFtZT10aGlzLnBsb3RfbW9kZWwuZnJhbWUsdGhpcy54X3JhbmdlPXRoaXMubWFwX3Bsb3QuZ2V0KCJ4X3JhbmdlIiksdGhpcy54X21hcHBlcj10aGlzLm1hcF9mcmFtZS5nZXQoInhfbWFwcGVycyIpWyJkZWZhdWx0Il0sdGhpcy55X3JhbmdlPXRoaXMubWFwX3Bsb3QuZ2V0KCJ5X3JhbmdlIiksdGhpcy55X21hcHBlcj10aGlzLm1hcF9mcmFtZS5nZXQoInlfbWFwcGVycyIpWyJkZWZhdWx0Il0sdGhpcy5leHRlbnQ9dGhpcy5nZXRfZXh0ZW50KCksdGhpcy5fbGFzdF9oZWlnaHQ9dm9pZCAwLHRoaXMuX2xhc3Rfd2lkdGg9dm9pZCAwfSxlLnByb3RvdHlwZS5fYWRkX2F0dHJpYnV0aW9uPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG8saSxzO2lmKHQ9dGhpcy5tZ2V0KCJ0aWxlX3NvdXJjZSIpLmdldCgiYXR0cmlidXRpb24iKSxsLmlzU3RyaW5nKHQpJiZ0Lmxlbmd0aD4wKXJldHVybiBudWxsIT10aGlzLmF0dHJpYnV0aW9uRWw/dGhpcy5hdHRyaWJ1dGlvbkVsLmh0bWwodCk6KGU9dGhpcy5tYXBfcGxvdC5nZXQoIm91dGxpbmVfbGluZV93aWR0aCIpLHI9dGhpcy5tYXBfcGxvdC5nZXQoIm1pbl9ib3JkZXJfYm90dG9tIikrZSxzPXRoaXMubWFwX2ZyYW1lLmdldCgicmlnaHQiKS10aGlzLm1hcF9mcmFtZS5nZXQoIndpZHRoIiksbz10aGlzLm1hcF9mcmFtZS5nZXQoIndpZHRoIiktZSx0aGlzLmF0dHJpYnV0aW9uRWw9bigiPGRpdj4iKS5odG1sKHQpLmFkZENsYXNzKCJiay10aWxlLWF0dHJpYnV0aW9uIikuY3NzKHtwb3NpdGlvbjoiYWJzb2x1dGUiLGJvdHRvbTpyKyJweCIscmlnaHQ6cysicHgiLCJtYXgtd2lkdGgiOm8rInB4IiwiYmFja2dyb3VuZC1jb2xvciI6InJnYmEoMjU1LDI1NSwyNTUsMC44KSIsImZvbnQtc2l6ZSI6IjlwdCIsImZvbnQtZmFtaWx5Ijoic2Fucy1zZXJpZiJ9KSxpPXRoaXMucGxvdF92aWV3LiRlbC5maW5kKCJkaXYuYmstY2FudmFzLWV2ZW50cyIpLHRoaXMuYXR0cmlidXRpb25FbC5hcHBlbmRUbyhpKSl9LGUucHJvdG90eXBlLl9tYXBfZGF0YT1mdW5jdGlvbigpe3ZhciB0LGU7cmV0dXJuIHRoaXMuaW5pdGlhbF9leHRlbnQ9dGhpcy5nZXRfZXh0ZW50KCksZT10aGlzLm1nZXQoInRpbGVfc291cmNlIikuZ2V0X2xldmVsX2J5X2V4dGVudCh0aGlzLmluaXRpYWxfZXh0ZW50LHRoaXMubWFwX2ZyYW1lLmdldCgiaGVpZ2h0IiksdGhpcy5tYXBfZnJhbWUuZ2V0KCJ3aWR0aCIpKSx0PXRoaXMubWdldCgidGlsZV9zb3VyY2UiKS5zbmFwX3RvX3pvb20odGhpcy5pbml0aWFsX2V4dGVudCx0aGlzLm1hcF9mcmFtZS5nZXQoImhlaWdodCIpLHRoaXMubWFwX2ZyYW1lLmdldCgid2lkdGgiKSxlKSx0aGlzLnhfcmFuZ2Uuc2V0KCJzdGFydCIsdFswXSksdGhpcy55X3JhbmdlLnNldCgic3RhcnQiLHRbMV0pLHRoaXMueF9yYW5nZS5zZXQoImVuZCIsdFsyXSksdGhpcy55X3JhbmdlLnNldCgiZW5kIix0WzNdKSx0aGlzLl9hZGRfYXR0cmlidXRpb24oKX0sZS5wcm90b3R5cGUuX29uX3RpbGVfbG9hZD1mdW5jdGlvbih0KXt2YXIgZTtyZXR1cm4gZT10LnRhcmdldC50aWxlX2RhdGEsZS5pbWc9dC50YXJnZXQsZS5jdXJyZW50PSEwLGUubG9hZGVkPSEwLHRoaXMucmVxdWVzdF9yZW5kZXIoKX0sZS5wcm90b3R5cGUuX29uX3RpbGVfY2FjaGVfbG9hZD1mdW5jdGlvbih0KXt2YXIgZTtyZXR1cm4gZT10LnRhcmdldC50aWxlX2RhdGEsZS5pbWc9dC50YXJnZXQsZS5sb2FkZWQ9ITB9LGUucHJvdG90eXBlLl9vbl90aWxlX2Vycm9yPWZ1bmN0aW9uKHQpe3JldHVybiIifSxlLnByb3RvdHlwZS5fY3JlYXRlX3RpbGU9ZnVuY3Rpb24odCxlLHIsbixvKXt2YXIgaSxzLGE7cmV0dXJuIG51bGw9PW8mJihvPSExKSxpPXRoaXMubWdldCgidGlsZV9zb3VyY2UiKS5ub3JtYWxpemVfeHl6KHQsZSxyKSxhPXRoaXMucG9vbC5wb3AoKSxvP2Eub25sb2FkPXRoaXMuX29uX3RpbGVfY2FjaGVfbG9hZDphLm9ubG9hZD10aGlzLl9vbl90aWxlX2xvYWQsYS5vbmVycm9yPXRoaXMuX29uX3RpbGVfZXJyb3IsYS5hbHQ9IiIsYS50aWxlX2RhdGE9e3RpbGVfY29vcmRzOlt0LGUscl0sbm9ybWFsaXplZF9jb29yZHM6aSxxdWFka2V5OnRoaXMubWdldCgidGlsZV9zb3VyY2UiKS50aWxlX3h5el90b19xdWFka2V5KHQsZSxyKSxjYWNoZV9rZXk6dGhpcy5tZ2V0KCJ0aWxlX3NvdXJjZSIpLnRpbGVfeHl6X3RvX2tleSh0LGUsciksYm91bmRzOm4sbG9hZGVkOiExLHhfY29vcmQ6blswXSx5X2Nvb3JkOm5bM119LHRoaXMubWdldCgidGlsZV9zb3VyY2UiKS50aWxlc1thLnRpbGVfZGF0YS5jYWNoZV9rZXldPWEudGlsZV9kYXRhLGEuc3JjPShzPXRoaXMubWdldCgidGlsZV9zb3VyY2UiKSkuZ2V0X2ltYWdlX3VybC5hcHBseShzLGkpLGF9LGUucHJvdG90eXBlLl9lbmZvcmNlX2FzcGVjdF9yYXRpbz1mdW5jdGlvbigpe3ZhciB0LGUscjtyZXR1cm4odGhpcy5fbGFzdF9oZWlnaHQhPT10aGlzLm1hcF9mcmFtZS5nZXQoImhlaWdodCIpfHx0aGlzLl9sYXN0X3dpZHRoIT09dGhpcy5tYXBfZnJhbWUuZ2V0KCJ3aWR0aCIpKSYmKHQ9dGhpcy5nZXRfZXh0ZW50KCkscj10aGlzLm1nZXQoInRpbGVfc291cmNlIikuZ2V0X2xldmVsX2J5X2V4dGVudCh0LHRoaXMubWFwX2ZyYW1lLmdldCgiaGVpZ2h0IiksdGhpcy5tYXBfZnJhbWUuZ2V0KCJ3aWR0aCIpKSxlPXRoaXMubWdldCgidGlsZV9zb3VyY2UiKS5zbmFwX3RvX3pvb20odCx0aGlzLm1hcF9mcmFtZS5nZXQoImhlaWdodCIpLHRoaXMubWFwX2ZyYW1lLmdldCgid2lkdGgiKSxyKSx0aGlzLnhfcmFuZ2Uuc2V0KHtzdGFydDplWzBdLGVuZDplWzJdfSksdGhpcy55X3JhbmdlLnNldCh7c3RhcnQ6ZVsxXSxlbmQ6ZVszXX0pLHRoaXMuZXh0ZW50PWUsdGhpcy5fbGFzdF9oZWlnaHQ9dGhpcy5tYXBfZnJhbWUuZ2V0KCJoZWlnaHQiKSx0aGlzLl9sYXN0X3dpZHRoPXRoaXMubWFwX2ZyYW1lLmdldCgid2lkdGgiKSwhMCl9LGUucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbih0LGUscil7aWYobnVsbD09dGhpcy5tYXBfaW5pdGlhbGl6ZWQmJih0aGlzLl9zZXRfZGF0YSgpLHRoaXMuX21hcF9kYXRhKCksdGhpcy5tYXBfaW5pdGlhbGl6ZWQ9ITApLCF0aGlzLl9lbmZvcmNlX2FzcGVjdF9yYXRpbygpKXJldHVybiB0aGlzLl91cGRhdGUoKSxudWxsIT10aGlzLnByZWZldGNoX3RpbWVyJiZjbGVhclRpbWVvdXQodGhpcy5wcmVmZXRjaF90aW1lciksdGhpcy5wcmVmZXRjaF90aW1lcj1zZXRUaW1lb3V0KHRoaXMuX3ByZWZldGNoX3RpbGVzLDUwMCl9LGUucHJvdG90eXBlLl9kcmF3X3RpbGU9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGEsbCx1LGgsYztpZihjPXRoaXMubWdldCgidGlsZV9zb3VyY2UiKS50aWxlc1t0XSxudWxsIT1jKXJldHVybiBlPXRoaXMucGxvdF92aWV3LmZyYW1lLm1hcF90b19zY3JlZW4oW2MuYm91bmRzWzBdXSxbYy5ib3VuZHNbM11dLHRoaXMucGxvdF92aWV3LmNhbnZhcyksYT1lWzBdLGg9ZVsxXSxyPXRoaXMucGxvdF92aWV3LmZyYW1lLm1hcF90b19zY3JlZW4oW2MuYm91bmRzWzJdXSxbYy5ib3VuZHNbMV1dLHRoaXMucGxvdF92aWV3LmNhbnZhcykscz1yWzBdLHU9clsxXSxhPWFbMF0saD1oWzBdLHM9c1swXSx1PXVbMF0sbz1zLWEsbj11LWgsaT1hLGw9aCx0aGlzLm1hcF9jYW52YXMuZHJhd0ltYWdlKGMuaW1nLGksbCxvLG4pfSxlLnByb3RvdHlwZS5fc2V0X3JlY3Q9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvO3JldHVybiByPXRoaXMucGxvdF9tb2RlbC5wbG90LnByb3BlcnRpZXMub3V0bGluZV9saW5lX3dpZHRoLnZhbHVlKCksZT10aGlzLnBsb3Rfdmlldy5jYW52YXMudnhfdG9fc3godGhpcy5tYXBfZnJhbWUuZ2V0KCJsZWZ0IikpK3IvMixuPXRoaXMucGxvdF92aWV3LmNhbnZhcy52eV90b19zeSh0aGlzLm1hcF9mcmFtZS5nZXQoInRvcCIpKStyLzIsbz10aGlzLm1hcF9mcmFtZS5nZXQoIndpZHRoIiktcix0PXRoaXMubWFwX2ZyYW1lLmdldCgiaGVpZ2h0Iiktcix0aGlzLm1hcF9jYW52YXMucmVjdChlLG4sbyx0KSx0aGlzLm1hcF9jYW52YXMuY2xpcCgpfSxlLnByb3RvdHlwZS5fcmVuZGVyX3RpbGVzPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbjtmb3IodGhpcy5tYXBfY2FudmFzLnNhdmUoKSx0aGlzLl9zZXRfcmVjdCgpLHRoaXMubWFwX2NhbnZhcy5nbG9iYWxBbHBoYT10aGlzLm1nZXQoImFscGhhIiksZT0wLHI9dC5sZW5ndGg7ZTxyO2UrKyluPXRbZV0sdGhpcy5fZHJhd190aWxlKG4pO3JldHVybiB0aGlzLm1hcF9jYW52YXMucmVzdG9yZSgpfSxlLnByb3RvdHlwZS5fcHJlZmV0Y2hfdGlsZXM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2O2ZvcihfPXRoaXMubWdldCgidGlsZV9zb3VyY2UiKSxhPXRoaXMuZ2V0X2V4dGVudCgpLGw9dGhpcy5tYXBfZnJhbWUuZ2V0KCJoZWlnaHQiKSxmPXRoaXMubWFwX2ZyYW1lLmdldCgid2lkdGgiKSx2PXRoaXMubWdldCgidGlsZV9zb3VyY2UiKS5nZXRfbGV2ZWxfYnlfZXh0ZW50KGEsbCxmKSxkPXRoaXMubWdldCgidGlsZV9zb3VyY2UiKS5nZXRfdGlsZXNfYnlfZXh0ZW50KGEsdiksYz1bXSxwPXU9MCxoPU1hdGgubWluKDEwLGQubGVuZ3RoKTt1PD1oO3A9dSs9MSltPXBbMF0sZz1wWzFdLHk9cFsyXSx0PXBbM10sbj10aGlzLm1nZXQoInRpbGVfc291cmNlIikuY2hpbGRyZW5fYnlfdGlsZV94eXoobSxnLHkpLGMucHVzaChmdW5jdGlvbigpe3ZhciB0LGEsbDtmb3IobD1bXSx0PTAsYT1uLmxlbmd0aDt0PGE7dCsrKWU9blt0XSxvPWVbMF0saT1lWzFdLHM9ZVsyXSxyPWVbM10sXy50aWxlX3h5el90b19rZXkobyxpLHMpaW4gXy50aWxlc3x8bC5wdXNoKHRoaXMuX2NyZWF0ZV90aWxlKG8saSxzLHIsITApKTtyZXR1cm4gbH0uY2FsbCh0aGlzKSk7cmV0dXJuIGN9LGUucHJvdG90eXBlLl9mZXRjaF90aWxlcz1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsO2ZvcihvPVtdLHI9MCxuPXQubGVuZ3RoO3I8bjtyKyspaT10W3JdLHM9aVswXSxhPWlbMV0sbD1pWzJdLGU9aVszXSxvLnB1c2godGhpcy5fY3JlYXRlX3RpbGUocyxhLGwsZSkpO3JldHVybiBvfSxlLnByb3RvdHlwZS5fdXBkYXRlPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTLHosUCxFLEEsQyxOLE8scSxELEksUixGO2ZvcihDPXRoaXMubWdldCgidGlsZV9zb3VyY2UiKSxiPUMuZ2V0KCJtaW5fem9vbSIpLHY9Qy5nZXQoIm1heF96b29tIiksQy51cGRhdGUoKSx1PXRoaXMuZ2V0X2V4dGVudCgpLEY9dGhpcy5leHRlbnRbMl0tdGhpcy5leHRlbnRbMF08dVsyXS11WzBdLGg9dGhpcy5tYXBfZnJhbWUuZ2V0KCJoZWlnaHQiKSxPPXRoaXMubWFwX2ZyYW1lLmdldCgid2lkdGgiKSxSPUMuZ2V0X2xldmVsX2J5X2V4dGVudCh1LGgsTyksUD0hMSxSPGI/KHU9dGhpcy5leHRlbnQsUj1iLFA9ITApOlI+diYmKHU9dGhpcy5leHRlbnQsUj12LFA9ITApLFAmJih0aGlzLnhfcmFuZ2Uuc2V0KHt4X3JhbmdlOntzdGFydDp1WzBdLGVuZDp1WzJdfX0pLHRoaXMueV9yYW5nZS5zZXQoe3N0YXJ0OnVbMV0sZW5kOnVbM119KSx0aGlzLmV4dGVudD11KSx0aGlzLmV4dGVudD11LE49Qy5nZXRfdGlsZXNfYnlfZXh0ZW50KHUsUiksaz1bXSx4PVtdLHI9W10saT1bXSxjPTAsbT1OLmxlbmd0aDtjPG07YysrKXtpZihFPU5bY10scT1FWzBdLEQ9RVsxXSxJPUVbMl0sdD1FWzNdLGQ9Qy50aWxlX3h5el90b19rZXkocSxELEkpLEE9Qy50aWxlc1tkXSxudWxsIT1BJiZBLmxvYWRlZD09PSEwKXIucHVzaChkKTtlbHNlIGlmKHRoaXMubWdldCgicmVuZGVyX3BhcmVudHMiKSYmKHo9Qy5nZXRfY2xvc2VzdF9wYXJlbnRfYnlfdGlsZV94eXoocSxELEkpLGo9elswXSxUPXpbMV0sUz16WzJdLHc9Qy50aWxlX3h5el90b19rZXkoaixULFMpLE09Qy50aWxlc1t3XSxudWxsIT1NJiZNLmxvYWRlZCYmZi5jYWxsKGssdyk8MCYmay5wdXNoKHcpLEYpKWZvcihpPUMuY2hpbGRyZW5fYnlfdGlsZV94eXoocSxELEkpLHA9MCxnPWkubGVuZ3RoO3A8ZztwKyspZT1pW3BdLHM9ZVswXSxhPWVbMV0sbD1lWzJdLG49ZVszXSxvPUMudGlsZV94eXpfdG9fa2V5KHMsYSxsKSxvIGluIEMudGlsZXMmJmkucHVzaChvKTtudWxsPT1BJiZ4LnB1c2goRSl9Zm9yKHRoaXMuX3JlbmRlcl90aWxlcyhrKSx0aGlzLl9yZW5kZXJfdGlsZXMoaSksdGhpcy5fcmVuZGVyX3RpbGVzKHIpLF89MCx5PXIubGVuZ3RoO188eTtfKyspRT1yW19dLEMudGlsZXNbRV0uY3VycmVudD0hMDtyZXR1cm4gbnVsbCE9dGhpcy5yZW5kZXJfdGltZXImJmNsZWFyVGltZW91dCh0aGlzLnJlbmRlcl90aW1lciksdGhpcy5yZW5kZXJfdGltZXI9c2V0VGltZW91dChmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdC5fZmV0Y2hfdGlsZXMoeCl9fSh0aGlzKSw2NSl9LGV9KGkuVmlldykscz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gXyhlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1hLGUucHJvdG90eXBlLnR5cGU9IlRpbGVSZW5kZXJlciIsZS5kZWZpbmUoe2FscGhhOltoLk51bWJlciwxXSx4X3JhbmdlX25hbWU6W2guU3RyaW5nLCJkZWZhdWx0Il0seV9yYW5nZV9uYW1lOltoLlN0cmluZywiZGVmYXVsdCJdLHRpbGVfc291cmNlOltoLkluc3RhbmNlLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBjLk1vZGVsfV0scmVuZGVyX3BhcmVudHM6W2guQm9vbCwhMF19KSxlLm92ZXJyaWRlKHtsZXZlbDoidW5kZXJsYXkifSksZX0oaS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpzLFZpZXc6YX19LHsiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vcmVuZGVyZXJzL3JlbmRlcmVyIjoibW9kZWxzL3JlbmRlcmVycy9yZW5kZXJlciIsIi4vaW1hZ2VfcG9vbCI6Im1vZGVscy90aWxlcy9pbWFnZV9wb29sIiwiLi93bXRzX3RpbGVfc291cmNlIjoibW9kZWxzL3RpbGVzL3dtdHNfdGlsZV9zb3VyY2UiLGpxdWVyeToianF1ZXJ5Iix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdGlsZXMvdGlsZV9zb3VyY2UiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxjPXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLG49dCgiLi9pbWFnZV9wb29sIiksdT10KCIuL3RpbGVfdXRpbHMiKSxhPXQoIi4uLy4uL2NvcmUvbG9nZ2luZyIpLmxvZ2dlcixsPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89dCgiLi4vLi4vbW9kZWwiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUodCl7bnVsbD09dCYmKHQ9e30pLGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKSx0aGlzLnV0aWxzPW5ldyB1LlByb2plY3Rpb25VdGlscyx0aGlzLnBvb2w9bmV3IG4sdGhpcy50aWxlcz17fSx0aGlzLm5vcm1hbGl6ZV9jYXNlKCl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJUaWxlU291cmNlIixlLmRlZmluZSh7dXJsOltsLlN0cmluZywiIl0sdGlsZV9zaXplOltsLk51bWJlciwyNTZdLG1heF96b29tOltsLk51bWJlciwzMF0sbWluX3pvb206W2wuTnVtYmVyLDBdLGV4dHJhX3VybF92YXJzOltsLkFueSx7fV0sYXR0cmlidXRpb246W2wuU3RyaW5nLCIiXSx4X29yaWdpbl9vZmZzZXQ6W2wuTnVtYmVyXSx5X29yaWdpbl9vZmZzZXQ6W2wuTnVtYmVyXSxpbml0aWFsX3Jlc29sdXRpb246W2wuTnVtYmVyXX0pLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCl7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMubm9ybWFsaXplX2Nhc2UoKX0sZS5wcm90b3R5cGUuc3RyaW5nX2xvb2t1cF9yZXBsYWNlPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvO249dDtmb3IociBpbiBlKW89ZVtyXSxuPW4ucmVwbGFjZSgieyIrcisifSIsby50b1N0cmluZygpKTtyZXR1cm4gbn0sZS5wcm90b3R5cGUubm9ybWFsaXplX2Nhc2U9ZnVuY3Rpb24oKXsiTm90ZTogc2hvdWxkIHByb2JhYmx5IGJlIHJlZmFjdG9yZWQgaW50byBzdWJjbGFzc2VzLiI7dmFyIHQ7cmV0dXJuIHQ9dGhpcy5nZXQoInVybCIpLHQ9dC5yZXBsYWNlKCJ7eH0iLCJ7WH0iKSx0PXQucmVwbGFjZSgie3l9Iiwie1l9IiksdD10LnJlcGxhY2UoInt6fSIsIntafSIpLHQ9dC5yZXBsYWNlKCJ7cX0iLCJ7UX0iKSx0PXQucmVwbGFjZSgie3htaW59Iiwie1hNSU59IiksdD10LnJlcGxhY2UoInt5bWlufSIsIntZTUlOfSIpLHQ9dC5yZXBsYWNlKCJ7eG1heH0iLCJ7WE1BWH0iKSx0PXQucmVwbGFjZSgie3ltYXh9Iiwie1lNQVh9IiksdGhpcy5zZXQoInVybCIsdCl9LGUucHJvdG90eXBlLnVwZGF0ZT1mdW5jdGlvbigpe3ZhciB0LGUscixuO2EuZGVidWcoIlRpbGVTb3VyY2U6IHRpbGUgY2FjaGUgY291bnQ6ICIrT2JqZWN0LmtleXModGhpcy50aWxlcykubGVuZ3RoKSxlPXRoaXMudGlsZXMscj1bXTtmb3IodCBpbiBlKW49ZVt0XSxuLmN1cnJlbnQ9ITEsci5wdXNoKG4ucmV0YWluPSExKTtyZXR1cm4gcn0sZS5wcm90b3R5cGUudGlsZV94eXpfdG9fa2V5PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbjtyZXR1cm4gbj10KyI6IitlKyI6IityfSxlLnByb3RvdHlwZS5rZXlfdG9fdGlsZV94eXo9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGZ1bmN0aW9uKCl7dmFyIHIsbixvLGk7Zm9yKG89dC5zcGxpdCgiOiIpLGk9W10scj0wLG49by5sZW5ndGg7cjxuO3IrKyllPW9bcl0saS5wdXNoKHBhcnNlSW50KGUpKTtyZXR1cm4gaX0oKX0sZS5wcm90b3R5cGUuc29ydF90aWxlc19mcm9tX2NlbnRlcj1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpLHMsYTtyZXR1cm4gaT1lWzBdLGE9ZVsxXSxvPWVbMl0scz1lWzNdLHI9KG8taSkvMitpLG49KHMtYSkvMithLHQuc29ydChmdW5jdGlvbih0LGUpe3ZhciBvLGk7cmV0dXJuIG89TWF0aC5zcXJ0KE1hdGgucG93KHItdFswXSwyKStNYXRoLnBvdyhuLXRbMV0sMikpLGk9TWF0aC5zcXJ0KE1hdGgucG93KHItZVswXSwyKStNYXRoLnBvdyhuLWVbMV0sMikpLG8taX0pLHR9LGUucHJvdG90eXBlLnBydW5lX3RpbGVzPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbztlPXRoaXMudGlsZXM7Zm9yKHQgaW4gZSlvPWVbdF0sby5yZXRhaW49by5jdXJyZW50fHxvLnRpbGVfY29vcmRzWzJdPDMsby5jdXJyZW50JiYodGhpcy5yZXRhaW5fbmVpZ2hib3JzKG8pLHRoaXMucmV0YWluX2NoaWxkcmVuKG8pLHRoaXMucmV0YWluX3BhcmVudHMobykpO3I9dGhpcy50aWxlcyxuPVtdO2Zvcih0IGluIHIpbz1yW3RdLG8ucmV0YWluP24ucHVzaCh2b2lkIDApOm4ucHVzaCh0aGlzLnJlbW92ZV90aWxlKHQpKTtyZXR1cm4gbn0sZS5wcm90b3R5cGUucmVtb3ZlX3RpbGU9ZnVuY3Rpb24odCl7dmFyIGU7aWYoZT10aGlzLnRpbGVzW3RdLG51bGwhPWUpcmV0dXJuIHRoaXMucG9vbC5wdXNoKGUuaW1nKSxkZWxldGUgdGhpcy50aWxlc1t0XX0sZS5wcm90b3R5cGUuZ2V0X2ltYWdlX3VybD1mdW5jdGlvbih0LGUscil7dmFyIG47cmV0dXJuIG49dGhpcy5zdHJpbmdfbG9va3VwX3JlcGxhY2UodGhpcy5nZXQoInVybCIpLHRoaXMuZ2V0KCJleHRyYV91cmxfdmFycyIpKSxuLnJlcGxhY2UoIntYfSIsdCkucmVwbGFjZSgie1l9IixlKS5yZXBsYWNlKCJ7Wn0iLHIpfSxlLnByb3RvdHlwZS5yZXRhaW5fbmVpZ2hib3JzPWZ1bmN0aW9uKHQpe3Rocm93IEVycm9yKCJOb3QgSW1wbGVtZW50ZWQiKX0sZS5wcm90b3R5cGUucmV0YWluX3BhcmVudHM9ZnVuY3Rpb24odCl7dGhyb3cgRXJyb3IoIk5vdCBJbXBsZW1lbnRlZCIpfSxlLnByb3RvdHlwZS5yZXRhaW5fY2hpbGRyZW49ZnVuY3Rpb24odCl7dGhyb3cgRXJyb3IoIk5vdCBJbXBsZW1lbnRlZCIpfSxlLnByb3RvdHlwZS50aWxlX3h5el90b19xdWFka2V5PWZ1bmN0aW9uKHQsZSxyKXt0aHJvdyBFcnJvcigiTm90IEltcGxlbWVudGVkIil9LGUucHJvdG90eXBlLnF1YWRrZXlfdG9fdGlsZV94eXo9ZnVuY3Rpb24odCl7dGhyb3cgRXJyb3IoIk5vdCBJbXBsZW1lbnRlZCIpfSxlfShvKSxlLmV4cG9ydHM9aX0seyIuLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi9tb2RlbCI6Im1vZGVsIiwiLi9pbWFnZV9wb29sIjoibW9kZWxzL3RpbGVzL2ltYWdlX3Bvb2wiLCIuL3RpbGVfdXRpbHMiOiJtb2RlbHMvdGlsZXMvdGlsZV91dGlscyIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3RpbGVzL3RpbGVfdXRpbHMiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHM7aT10KCJwcm9qNCIpLG89aS5kZWZzKCJHT09HTEUiKSxzPWkuZGVmcygiV0dTODQiKSxuPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCgpe3RoaXMub3JpZ2luX3NoaWZ0PTIqTWF0aC5QSSo2Mzc4MTM3LzJ9cmV0dXJuIHQucHJvdG90eXBlLmdlb2dyYXBoaWNfdG9fbWV0ZXJzPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIGkocyxvLFt0LGVdKX0sdC5wcm90b3R5cGUubWV0ZXJzX3RvX2dlb2dyYXBoaWM9ZnVuY3Rpb24odCxlKXtyZXR1cm4gaShvLHMsW3QsZV0pfSx0LnByb3RvdHlwZS5nZW9ncmFwaGljX2V4dGVudF90b19tZXRlcnM9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzO3JldHVybiBvPXRbMF0scz10WzFdLG49dFsyXSxpPXRbM10sZT10aGlzLmdlb2dyYXBoaWNfdG9fbWV0ZXJzKG8scyksbz1lWzBdLHM9ZVsxXSxyPXRoaXMuZ2VvZ3JhcGhpY190b19tZXRlcnMobixpKSxuPXJbMF0saT1yWzFdLFtvLHMsbixpXX0sdC5wcm90b3R5cGUubWV0ZXJzX2V4dGVudF90b19nZW9ncmFwaGljPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscztyZXR1cm4gbz10WzBdLHM9dFsxXSxuPXRbMl0saT10WzNdLGU9dGhpcy5tZXRlcnNfdG9fZ2VvZ3JhcGhpYyhvLHMpLG89ZVswXSxzPWVbMV0scj10aGlzLm1ldGVyc190b19nZW9ncmFwaGljKG4saSksbj1yWzBdLGk9clsxXSxbbyxzLG4saV19LHR9KCksZS5leHBvcnRzPXtQcm9qZWN0aW9uVXRpbHM6bn19LHtwcm9qNDoicHJvajQifV0sIm1vZGVscy90aWxlcy90bXNfdGlsZV9zb3VyY2UiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlzLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHM9e30uaGFzT3duUHJvcGVydHk7bj10KCIuL21lcmNhdG9yX3RpbGVfc291cmNlIiksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaShlLHQpLGUucHJvdG90eXBlLnR5cGU9IlRNU1RpbGVTb3VyY2UiLGUucHJvdG90eXBlLmdldF9pbWFnZV91cmw9ZnVuY3Rpb24odCxlLHIpe3ZhciBuO3JldHVybiBuPXRoaXMuc3RyaW5nX2xvb2t1cF9yZXBsYWNlKHRoaXMuZ2V0KCJ1cmwiKSx0aGlzLmdldCgiZXh0cmFfdXJsX3ZhcnMiKSksbi5yZXBsYWNlKCJ7WH0iLHQpLnJlcGxhY2UoIntZfSIsZSkucmVwbGFjZSgie1p9IixyKX0sZX0obiksZS5leHBvcnRzPXtNb2RlbDpvfX0seyIuL21lcmNhdG9yX3RpbGVfc291cmNlIjoibW9kZWxzL3RpbGVzL21lcmNhdG9yX3RpbGVfc291cmNlIn1dLCJtb2RlbHMvdGlsZXMvd210c190aWxlX3NvdXJjZSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXMuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0scz17fS5oYXNPd25Qcm9wZXJ0eTtuPXQoIi4vbWVyY2F0b3JfdGlsZV9zb3VyY2UiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBpKGUsdCksZS5wcm90b3R5cGUudHlwZT0iV01UU1RpbGVTb3VyY2UiLGUucHJvdG90eXBlLmdldF9pbWFnZV91cmw9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG87cmV0dXJuIG49dGhpcy5zdHJpbmdfbG9va3VwX3JlcGxhY2UodGhpcy5nZXQoInVybCIpLHRoaXMuZ2V0KCJleHRyYV91cmxfdmFycyIpKSxvPXRoaXMudG1zX3RvX3dtdHModCxlLHIpLHQ9b1swXSxlPW9bMV0scj1vWzJdLG4ucmVwbGFjZSgie1h9Iix0KS5yZXBsYWNlKCJ7WX0iLGUpLnJlcGxhY2UoIntafSIscil9LGV9KG4pLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi9tZXJjYXRvcl90aWxlX3NvdXJjZSI6Im1vZGVscy90aWxlcy9tZXJjYXRvcl90aWxlX3NvdXJjZSJ9XSwibW9kZWxzL3Rvb2xzL2FjdGlvbnMvYWN0aW9uX3Rvb2wiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpbC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxsPXt9Lmhhc093blByb3BlcnR5O3M9dCgiLi4vYnV0dG9uX3Rvb2wiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGUuX2NsaWNrZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tb2RlbC50cmlnZ2VyKCJkbyIpfSxlfShzLkJ1dHRvblZpZXcpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGEoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0KSx0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImRvIix0aGlzWyJkbyJdKX0sZX0ocy5WaWV3KSxuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZX0ocy5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpuLFZpZXc6aSxCdXR0b25WaWV3Om99fSx7Ii4uL2J1dHRvbl90b29sIjoibW9kZWxzL3Rvb2xzL2J1dHRvbl90b29sIn1dLCJtb2RlbHMvdG9vbHMvYWN0aW9ucy9oZWxwX3Rvb2wiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl1LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHU9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2FjdGlvbl90b29sIiksYT10KCIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGVbImRvIl09ZnVuY3Rpb24oKXtyZXR1cm4gd2luZG93Lm9wZW4odGhpcy5tZ2V0KCJyZWRpcmVjdCIpKX0sZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWksZS5wcm90b3R5cGUudHlwZT0iSGVscFRvb2wiLGUucHJvdG90eXBlLnRvb2xfbmFtZT0iSGVscCIsZS5wcm90b3R5cGUuaWNvbj0iYmstdG9vbC1pY29uLWhlbHAiLGUuZGVmaW5lKHtoZWxwX3Rvb2x0aXA6W2EuU3RyaW5nLCJDbGljayB0aGUgcXVlc3Rpb24gbWFyayB0byBsZWFybiBtb3JlIGFib3V0IEJva2VoIHBsb3QgdG9vbHMuIl0scmVkaXJlY3Q6W2EuU3RyaW5nLCJodHRwOi8vYm9rZWgucHlkYXRhLm9yZy9lbi9sYXRlc3QvZG9jcy91c2VyX2d1aWRlL3Rvb2xzLmh0bWwiXX0pLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLm92ZXJyaWRlX2NvbXB1dGVkX3Byb3BlcnR5KCJ0b29sdGlwIixmdW5jdGlvbigpe3JldHVybiB0aGlzLmdldCgiaGVscF90b29sdGlwIil9KX0sZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvLFZpZXc6aX19LHsiLi4vLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9hY3Rpb25fdG9vbCI6Im1vZGVscy90b29scy9hY3Rpb25zL2FjdGlvbl90b29sIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdG9vbHMvYWN0aW9ucy9yZWRvX3Rvb2wiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHM9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWEuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sYT17fS5oYXNPd25Qcm9wZXJ0eTtuPXQoIi4vYWN0aW9uX3Rvb2wiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBzKGUsdCksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy5saXN0ZW5Ubyh0aGlzLnBsb3Rfdmlldywic3RhdGVfY2hhbmdlZCIsZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHQubW9kZWwuc2V0KCJkaXNhYmxlZCIsIXQucGxvdF92aWV3LmNhbl9yZWRvKCkpfX0odGhpcykpfSxlLnByb3RvdHlwZVsiZG8iXT1mdW5jdGlvbigpe3JldHVybiB0aGlzLnBsb3Rfdmlldy5yZWRvKCl9LGV9KG4uVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gcyhlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLnR5cGU9IlJlZG9Ub29sIixlLnByb3RvdHlwZS50b29sX25hbWU9IlJlZG8iLGUucHJvdG90eXBlLmljb249ImJrLXRvb2wtaWNvbi1yZWRvIixlLm92ZXJyaWRlKHtkaXNhYmxlZDohMH0pLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4vYWN0aW9uX3Rvb2wiOiJtb2RlbHMvdG9vbHMvYWN0aW9ucy9hY3Rpb25fdG9vbCJ9XSwibW9kZWxzL3Rvb2xzL2FjdGlvbnMvcmVzZXRfdG9vbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlsLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGw9e30uaGFzT3duUHJvcGVydHk7bj10KCIuL2FjdGlvbl90b29sIikscz10KCIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGVbImRvIl09ZnVuY3Rpb24oKXtpZih0aGlzLnBsb3Rfdmlldy5jbGVhcl9zdGF0ZSgpLHRoaXMucGxvdF92aWV3LnJlc2V0X3JhbmdlKCksdGhpcy5wbG90X3ZpZXcucmVzZXRfc2VsZWN0aW9uKCksdGhpcy5tb2RlbC5yZXNldF9zaXplKXJldHVybiB0aGlzLnBsb3Rfdmlldy5yZXNldF9kaW1lbnNpb25zKCl9LGV9KG4uVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gYShlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLnR5cGU9IlJlc2V0VG9vbCIsZS5wcm90b3R5cGUudG9vbF9uYW1lPSJSZXNldCIsZS5wcm90b3R5cGUuaWNvbj0iYmstdG9vbC1pY29uLXJlc2V0IixlLmRlZmluZSh7cmVzZXRfc2l6ZTpbcy5Cb29sLCEwXX0pLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4uLy4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vYWN0aW9uX3Rvb2wiOiJtb2RlbHMvdG9vbHMvYWN0aW9ucy9hY3Rpb25fdG9vbCJ9XSwibW9kZWxzL3Rvb2xzL2FjdGlvbnMvc2F2ZV90b29sIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vYWN0aW9uX3Rvb2wiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGVbImRvIl09ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbjtyZXR1cm4gZT10aGlzLnBsb3Rfdmlldy5nZXRfY2FudmFzX2VsZW1lbnQoKSxuPSJib2tlaF9wbG90LnBuZyIsbnVsbCE9ZS5tc1RvQmxvYj8odD1lLm1zVG9CbG9iKCksd2luZG93Lm5hdmlnYXRvci5tc1NhdmVCbG9iKHQsbikpOihyPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImEiKSxyLmhyZWY9ZS50b0RhdGFVUkwoImltYWdlL3BuZyIpLHIuZG93bmxvYWQ9bixyLnRhcmdldD0iX2JsYW5rIixyLmRpc3BhdGNoRXZlbnQobmV3IE1vdXNlRXZlbnQoImNsaWNrIikpKX0sZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBhKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWksZS5wcm90b3R5cGUudHlwZT0iU2F2ZVRvb2wiLGUucHJvdG90eXBlLnRvb2xfbmFtZT0iU2F2ZSIsZS5wcm90b3R5cGUuaWNvbj0iYmstdG9vbC1pY29uLXNhdmUiLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4vYWN0aW9uX3Rvb2wiOiJtb2RlbHMvdG9vbHMvYWN0aW9ucy9hY3Rpb25fdG9vbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3Rvb2xzL2FjdGlvbnMvdW5kb190b29sIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSlhLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGE9e30uaGFzT3duUHJvcGVydHk7bj10KCIuL2FjdGlvbl90b29sIiksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gcyhlLHQpLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCl7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMubGlzdGVuVG8odGhpcy5wbG90X3ZpZXcsInN0YXRlX2NoYW5nZWQiLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiB0Lm1vZGVsLnNldCgiZGlzYWJsZWQiLCF0LnBsb3Rfdmlldy5jYW5fdW5kbygpKX19KHRoaXMpKX0sZS5wcm90b3R5cGVbImRvIl09ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5wbG90X3ZpZXcudW5kbygpfSxlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHMoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJVbmRvVG9vbCIsZS5wcm90b3R5cGUudG9vbF9uYW1lPSJVbmRvIixlLnByb3RvdHlwZS5pY29uPSJiay10b29sLWljb24tdW5kbyIsZS5vdmVycmlkZSh7ZGlzYWJsZWQ6ITB9KSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzppfX0seyIuL2FjdGlvbl90b29sIjoibW9kZWxzL3Rvb2xzL2FjdGlvbnMvYWN0aW9uX3Rvb2wifV0sIm1vZGVscy90b29scy9idXR0b25fdG9vbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGM9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXAuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0scD17fS5oYXNPd25Qcm9wZXJ0eTtsPXQoInVuZGVyc2NvcmUiKSxuPXQoImJhY2tib25lIiksYT10KCIuL3Rvb2wiKSx1PXQoIi4vYnV0dG9uX3Rvb2xfdGVtcGxhdGUiKSxoPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGMoZSx0KSxlLnByb3RvdHlwZS50YWdOYW1lPSJsaSIsZS5wcm90b3R5cGUudGVtcGxhdGU9dSxlLnByb3RvdHlwZS5ldmVudHM9ZnVuY3Rpb24oKXtyZXR1cm57ImNsaWNrIC5iay10b29sYmFyLWJ1dHRvbiI6Il9jbGlja2VkIn19LGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCl7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMuJGVsLmh0bWwodGhpcy50ZW1wbGF0ZSh7bW9kZWw6dGhpcy5tb2RlbH0pKSx0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZTphY3RpdmUiLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiB0LnJlbmRlcigpfX0odGhpcykpLHRoaXMubGlzdGVuVG8odGhpcy5tb2RlbCwiY2hhbmdlOmRpc2FibGVkIixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdC5yZW5kZXIoKX19KHRoaXMpKSx0aGlzLnJlbmRlcigpfSxlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4kZWwuY2hpbGRyZW4oImJ1dHRvbiIpLnByb3AoImRpc2FibGVkIix0aGlzLm1vZGVsLmdldCgiZGlzYWJsZWQiKSkudG9nZ2xlQ2xhc3MoImFjdGl2ZSIsdGhpcy5tb2RlbC5nZXQoImFjdGl2ZSIpKSx0aGlzfSxlLnByb3RvdHlwZS5fY2xpY2tlZD1mdW5jdGlvbih0KXt9LGV9KG4uVmlldykscz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gYyhlLHQpLGV9KGEuVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gYyhlLHQpLGUucHJvdG90eXBlLmljb249bnVsbCxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoInRvb2x0aXAiLGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudG9vbF9uYW1lfSl9LGUuaW50ZXJuYWwoe2Rpc2FibGVkOltoLkJvb2xlYW4sITFdfSksZX0oYS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvLFZpZXc6cyxCdXR0b25WaWV3Oml9fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vYnV0dG9uX3Rvb2xfdGVtcGxhdGUiOiJtb2RlbHMvdG9vbHMvYnV0dG9uX3Rvb2xfdGVtcGxhdGUiLCIuL3Rvb2wiOiJtb2RlbHMvdG9vbHMvdG9vbCIsYmFja2JvbmU6ImJhY2tib25lIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdG9vbHMvYnV0dG9uX3Rvb2xfdGVtcGxhdGUiOltmdW5jdGlvbih0LGUscil7ZS5leHBvcnRzPWZ1bmN0aW9uKHQpe3R8fCh0PXt9KTt2YXIgZT1bXSxyPWZ1bmN0aW9uKHQpe3JldHVybiB0JiZ0LmVjb1NhZmU/dDoidW5kZWZpbmVkIiE9dHlwZW9mIHQmJm51bGwhPXQ/bih0KToiIn0sbj1mdW5jdGlvbih0KXtyZXR1cm4oIiIrdCkucmVwbGFjZSgvJi9nLCImYW1wOyIpLnJlcGxhY2UoLzwvZywiJmx0OyIpLnJlcGxhY2UoLz4vZywiJmd0OyIpLnJlcGxhY2UoLyIvZywiJnF1b3Q7Iil9O3JldHVybiBmdW5jdGlvbigpeyhmdW5jdGlvbigpe2UucHVzaCgnPGJ1dHRvbiB0eXBlPSJidXR0b24iIGNsYXNzPSJiay10b29sYmFyLWJ1dHRvbiBob3ZlciI+XG4gIDxkaXYgY2xhc3M9XCdiay1idG4taWNvbiAnKSxlLnB1c2gocih0aGlzLm1vZGVsLmljb24pKSxlLnB1c2goIicgLz5cbiAgPHNwYW4gY2xhc3M9J3RpcCc+IiksZS5wdXNoKHIodGhpcy5tb2RlbC5nZXQoInRvb2x0aXAiKSkpLGUucHVzaCgiPC9zcGFuPlxuPC9idXR0b24+XG4iKX0pLmNhbGwodGhpcyl9LmNhbGwodCksZS5qb2luKCIiKX19LHt9XSwibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL2JveF9zZWxlY3RfdG9vbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7bD10KCJ1bmRlcnNjb3JlIiksYT10KCIuL3NlbGVjdF90b29sIiksbj10KCIuLi8uLi9hbm5vdGF0aW9ucy9ib3hfYW5ub3RhdGlvbiIpLHU9dCgiLi4vLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLl9wYW5fc3RhcnQ9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9dGhpcy5wbG90X3ZpZXcuY2FudmFzLHRoaXMuX2Jhc2Vib2ludD1bZS5zeF90b192eCh0LmJva2VoLnN4KSxlLnN5X3RvX3Z5KHQuYm9rZWguc3kpXSxudWxsfSxlLnByb3RvdHlwZS5fcGFuPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGwsdTtyZXR1cm4gcj10aGlzLnBsb3Rfdmlldy5jYW52YXMsbj1bci5zeF90b192eCh0LmJva2VoLnN4KSxyLnN5X3RvX3Z5KHQuYm9rZWguc3kpXSxpPXRoaXMucGxvdF9tb2RlbC5nZXQoImZyYW1lIiksbz10aGlzLm1nZXQoImRpbWVuc2lvbnMiKSxzPXRoaXMubW9kZWwuX2dldF9kaW1fbGltaXRzKHRoaXMuX2Jhc2Vib2ludCxuLGksbyksbD1zWzBdLHU9c1sxXSx0aGlzLm1nZXQoIm92ZXJsYXkiKS51cGRhdGUoe2xlZnQ6bFswXSxyaWdodDpsWzFdLHRvcDp1WzFdLGJvdHRvbTp1WzBdfSksdGhpcy5tZ2V0KCJzZWxlY3RfZXZlcnlfbW91c2Vtb3ZlIikmJihlPW51bGwhPShhPXQuc3JjRXZlbnQuc2hpZnRLZXkpJiZhLHRoaXMuX3NlbGVjdChsLHUsITEsZSkpLG51bGx9LGUucHJvdG90eXBlLl9wYW5fZW5kPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGwsdTtyZXR1cm4gcj10aGlzLnBsb3Rfdmlldy5jYW52YXMsbj1bci5zeF90b192eCh0LmJva2VoLnN4KSxyLnN5X3RvX3Z5KHQuYm9rZWguc3kpXSxpPXRoaXMucGxvdF9tb2RlbC5nZXQoImZyYW1lIiksbz10aGlzLm1nZXQoImRpbWVuc2lvbnMiKSxzPXRoaXMubW9kZWwuX2dldF9kaW1fbGltaXRzKHRoaXMuX2Jhc2Vib2ludCxuLGksbyksbD1zWzBdLHU9c1sxXSxlPW51bGwhPShhPXQuc3JjRXZlbnQuc2hpZnRLZXkpJiZhLHRoaXMuX3NlbGVjdChsLHUsITAsZSksCnRoaXMubWdldCgib3ZlcmxheSIpLnVwZGF0ZSh7bGVmdDpudWxsLHJpZ2h0Om51bGwsdG9wOm51bGwsYm90dG9tOm51bGx9KSx0aGlzLl9iYXNlYm9pbnQ9bnVsbCx0aGlzLnBsb3Rfdmlldy5wdXNoX3N0YXRlKCJib3hfc2VsZWN0Iix7c2VsZWN0aW9uOnRoaXMucGxvdF92aWV3LmdldF9zZWxlY3Rpb24oKX0pLG51bGx9LGUucHJvdG90eXBlLl9zZWxlY3Q9ZnVuY3Rpb24odCxlLHIsbil7dmFyIG8saSxzLGEsbCx1LGgsYyxwLF8sZDtmb3IoYz10WzBdLHA9dFsxXSxfPWVbMF0sZD1lWzFdLG51bGw9PW4mJihuPSExKSxpPXt0eXBlOiJyZWN0Iix2eDA6Yyx2eDE6cCx2eTA6Xyx2eTE6ZH0sdT10aGlzLm1nZXQoImNvbXB1dGVkX3JlbmRlcmVycyIpLHM9MCxhPXUubGVuZ3RoO3M8YTtzKyspbD11W3NdLG89bC5nZXQoImRhdGFfc291cmNlIiksaD1vLmdldCgic2VsZWN0aW9uX21hbmFnZXIiKSxoLnNlbGVjdCh0aGlzLHRoaXMucGxvdF92aWV3LnJlbmRlcmVyX3ZpZXdzW2wuaWRdLGkscixuKTtyZXR1cm4gbnVsbCE9dGhpcy5tZ2V0KCJjYWxsYmFjayIpJiZ0aGlzLl9lbWl0X2NhbGxiYWNrKGkpLHRoaXMuX3NhdmVfZ2VvbWV0cnkoaSxyLG4pLG51bGx9LGUucHJvdG90eXBlLl9lbWl0X2NhbGxiYWNrPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGk7bj10aGlzLm1nZXQoImNvbXB1dGVkX3JlbmRlcmVycyIpWzBdLGU9dGhpcy5wbG90X21vZGVsLmdldCgiY2FudmFzIikscj10aGlzLnBsb3RfbW9kZWwuZ2V0KCJmcmFtZSIpLHQuc3gwPWUudnhfdG9fc3godC52eDApLHQuc3gxPWUudnhfdG9fc3godC52eDEpLHQuc3kwPWUudnlfdG9fc3kodC52eTApLHQuc3kxPWUudnlfdG9fc3kodC52eTEpLG89ci5nZXQoInhfbWFwcGVycyIpW24uZ2V0KCJ4X3JhbmdlX25hbWUiKV0saT1yLmdldCgieV9tYXBwZXJzIilbbi5nZXQoInlfcmFuZ2VfbmFtZSIpXSx0LngwPW8ubWFwX2Zyb21fdGFyZ2V0KHQudngwKSx0LngxPW8ubWFwX2Zyb21fdGFyZ2V0KHQudngxKSx0LnkwPWkubWFwX2Zyb21fdGFyZ2V0KHQudnkwKSx0LnkxPWkubWFwX2Zyb21fdGFyZ2V0KHQudnkxKSx0aGlzLm1nZXQoImNhbGxiYWNrIikuZXhlY3V0ZSh0aGlzLm1vZGVsLHtnZW9tZXRyeTp0fSl9LGV9KGEuVmlldykscz1mdW5jdGlvbigpe3JldHVybiBuZXcgbi5Nb2RlbCh7bGV2ZWw6Im92ZXJsYXkiLHJlbmRlcl9tb2RlOiJjc3MiLHRvcF91bml0czoic2NyZWVuIixsZWZ0X3VuaXRzOiJzY3JlZW4iLGJvdHRvbV91bml0czoic2NyZWVuIixyaWdodF91bml0czoic2NyZWVuIixmaWxsX2NvbG9yOiJsaWdodGdyZXkiLGZpbGxfYWxwaGE6LjUsbGluZV9jb2xvcjoiYmxhY2siLGxpbmVfYWxwaGE6MSxsaW5lX3dpZHRoOjIsbGluZV9kYXNoOls0LDRdfSl9LG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJCb3hTZWxlY3RUb29sIixlLnByb3RvdHlwZS50b29sX25hbWU9IkJveCBTZWxlY3QiLGUucHJvdG90eXBlLmljb249ImJrLXRvb2wtaWNvbi1ib3gtc2VsZWN0IixlLnByb3RvdHlwZS5ldmVudF90eXBlPSJwYW4iLGUucHJvdG90eXBlLmRlZmF1bHRfb3JkZXI9MzAsZS5kZWZpbmUoe2RpbWVuc2lvbnM6W3UuQXJyYXksWyJ3aWR0aCIsImhlaWdodCJdXSxzZWxlY3RfZXZlcnlfbW91c2Vtb3ZlOlt1LkJvb2wsITFdLGNhbGxiYWNrOlt1Lkluc3RhbmNlXSxvdmVybGF5Olt1Lkluc3RhbmNlLHNdfSksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0LHIpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0LHIpLHRoaXMub3ZlcnJpZGVfY29tcHV0ZWRfcHJvcGVydHkoInRvb2x0aXAiLGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2dldF9kaW1fdG9vbHRpcCh0aGlzLnRvb2xfbmFtZSx0aGlzLl9jaGVja19kaW1zKHRoaXMuZ2V0KCJkaW1lbnNpb25zIiksImJveCBzZWxlY3QgdG9vbCIpKX0sITEpLHRoaXMuYWRkX2RlcGVuZGVuY2llcygidG9vbHRpcCIsdGhpcyxbImRpbWVuc2lvbnMiXSl9LGV9KGEuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4uLy4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4uLy4uL2Fubm90YXRpb25zL2JveF9hbm5vdGF0aW9uIjoibW9kZWxzL2Fubm90YXRpb25zL2JveF9hbm5vdGF0aW9uIiwiLi9zZWxlY3RfdG9vbCI6Im1vZGVscy90b29scy9nZXN0dXJlcy9zZWxlY3RfdG9vbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL2JveF96b29tX3Rvb2wiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxjPXt9Lmhhc093blByb3BlcnR5O2w9dCgidW5kZXJzY29yZSIpLGE9dCgiLi9nZXN0dXJlX3Rvb2wiKSxuPXQoIi4uLy4uL2Fubm90YXRpb25zL2JveF9hbm5vdGF0aW9uIiksdT10KCIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBoKGUsdCksZS5wcm90b3R5cGUuX21hdGNoX2FzcGVjdD1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiO3JldHVybiBzPXIuZ2V0KCJoX3JhbmdlIikuZ2V0KCJlbmQiKSxhPXIuZ2V0KCJoX3JhbmdlIikuZ2V0KCJzdGFydCIpLGQ9ci5nZXQoInZfcmFuZ2UiKS5nZXQoImVuZCIpLG09ci5nZXQoInZfcmFuZ2UiKS5nZXQoInN0YXJ0IikseT1zLWEsaT1kLW0sbj15L2ksZz1NYXRoLmFicyh0WzBdLWVbMF0pLGY9TWF0aC5hYnModFsxXS1lWzFdKSxfPTA9PT1mPzA6Zy9mLF8+PW4/KHU9WzEsXy9uXSx2PXVbMF0sYj11WzFdKTooaD1bbi9fLDFdLHY9aFswXSxiPWhbMV0pLHRbMF08PWVbMF0/KGw9dFswXSxjPXRbMF0rZyp2LGM+cyYmKGM9cykpOihjPXRbMF0sbD10WzBdLWcqdixsPGEmJihsPWEpKSxnPU1hdGguYWJzKGMtbCksdFsxXTw9ZVsxXT8obz10WzFdLHA9dFsxXStnL24scD5kJiYocD1kKSk6KHA9dFsxXSxvPXRbMV0tZy9uLG88bSYmKG89bSkpLGY9TWF0aC5hYnMocC1vKSx0WzBdPD1lWzBdP2M9dFswXStuKmY6bD10WzBdLW4qZixbW2wsY10sW28scF1dfSxlLnByb3RvdHlwZS5fcGFuX3N0YXJ0PWZ1bmN0aW9uKHQpe3ZhciBlO3JldHVybiBlPXRoaXMucGxvdF92aWV3LmNhbnZhcyx0aGlzLl9iYXNlYm9pbnQ9W2Uuc3hfdG9fdngodC5ib2tlaC5zeCksZS5zeV90b192eSh0LmJva2VoLnN5KV0sbnVsbH0sZS5wcm90b3R5cGUuX3Bhbj1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsO3JldHVybiBlPXRoaXMucGxvdF92aWV3LmNhbnZhcyxyPVtlLnN4X3RvX3Z4KHQuYm9rZWguc3gpLGUuc3lfdG9fdnkodC5ib2tlaC5zeSldLG89dGhpcy5wbG90X21vZGVsLmdldCgiZnJhbWUiKSxuPXRoaXMubWdldCgiZGltZW5zaW9ucyIpLHRoaXMubWdldCgibWF0Y2hfYXNwZWN0IikmJjI9PT1uLmxlbmd0aD8oaT10aGlzLl9tYXRjaF9hc3BlY3QodGhpcy5fYmFzZWJvaW50LHIsbyksYT1pWzBdLGw9aVsxXSk6KHM9dGhpcy5tb2RlbC5fZ2V0X2RpbV9saW1pdHModGhpcy5fYmFzZWJvaW50LHIsbyxuKSxhPXNbMF0sbD1zWzFdKSx0aGlzLm1nZXQoIm92ZXJsYXkiKS51cGRhdGUoe2xlZnQ6YVswXSxyaWdodDphWzFdLHRvcDpsWzFdLGJvdHRvbTpsWzBdfSksbnVsbH0sZS5wcm90b3R5cGUuX3Bhbl9lbmQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGEsbDtyZXR1cm4gZT10aGlzLnBsb3Rfdmlldy5jYW52YXMscj1bZS5zeF90b192eCh0LmJva2VoLnN4KSxlLnN5X3RvX3Z5KHQuYm9rZWguc3kpXSxvPXRoaXMucGxvdF9tb2RlbC5nZXQoImZyYW1lIiksbj10aGlzLm1nZXQoImRpbWVuc2lvbnMiKSx0aGlzLm1nZXQoIm1hdGNoX2FzcGVjdCIpJiYyPT09bi5sZW5ndGg/KGk9dGhpcy5fbWF0Y2hfYXNwZWN0KHRoaXMuX2Jhc2Vib2ludCxyLG8pLGE9aVswXSxsPWlbMV0pOihzPXRoaXMubW9kZWwuX2dldF9kaW1fbGltaXRzKHRoaXMuX2Jhc2Vib2ludCxyLG8sbiksYT1zWzBdLGw9c1sxXSksdGhpcy5fdXBkYXRlKGEsbCksdGhpcy5tZ2V0KCJvdmVybGF5IikudXBkYXRlKHtsZWZ0Om51bGwscmlnaHQ6bnVsbCx0b3A6bnVsbCxib3R0b206bnVsbH0pLHRoaXMuX2Jhc2Vib2ludD1udWxsLG51bGx9LGUucHJvdG90eXBlLl91cGRhdGU9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saSxzLGEsbCx1LGgsYyxwO2lmKCEoTWF0aC5hYnModFsxXS10WzBdKTw9NXx8TWF0aC5hYnMoZVsxXS1lWzBdKTw9NSkpe2g9e30saT10aGlzLnBsb3Rfdmlldy5mcmFtZS5nZXQoInhfbWFwcGVycyIpO2ZvcihvIGluIGkpbj1pW29dLHM9bi52X21hcF9mcm9tX3RhcmdldCh0LCEwKSx1PXNbMF0scj1zWzFdLGhbb109e3N0YXJ0OnUsZW5kOnJ9O2M9e30sYT10aGlzLnBsb3Rfdmlldy5mcmFtZS5nZXQoInlfbWFwcGVycyIpO2ZvcihvIGluIGEpbj1hW29dLGw9bi52X21hcF9mcm9tX3RhcmdldChlLCEwKSx1PWxbMF0scj1sWzFdLGNbb109e3N0YXJ0OnUsZW5kOnJ9O3JldHVybiBwPXt4cnM6aCx5cnM6Y30sdGhpcy5wbG90X3ZpZXcucHVzaF9zdGF0ZSgiYm94X3pvb20iLHtyYW5nZTpwfSksdGhpcy5wbG90X3ZpZXcudXBkYXRlX3JhbmdlKHApfX0sZX0oYS5WaWV3KSxzPWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBuLk1vZGVsKHtsZXZlbDoib3ZlcmxheSIscmVuZGVyX21vZGU6ImNzcyIsdG9wX3VuaXRzOiJzY3JlZW4iLGxlZnRfdW5pdHM6InNjcmVlbiIsYm90dG9tX3VuaXRzOiJzY3JlZW4iLHJpZ2h0X3VuaXRzOiJzY3JlZW4iLGZpbGxfY29sb3I6ImxpZ2h0Z3JleSIsZmlsbF9hbHBoYTouNSxsaW5lX2NvbG9yOiJibGFjayIsbGluZV9hbHBoYToxLGxpbmVfd2lkdGg6MixsaW5lX2Rhc2g6WzQsNF19KX0sbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1pLGUucHJvdG90eXBlLnR5cGU9IkJveFpvb21Ub29sIixlLnByb3RvdHlwZS50b29sX25hbWU9IkJveCBab29tIixlLnByb3RvdHlwZS5pY29uPSJiay10b29sLWljb24tYm94LXpvb20iLGUucHJvdG90eXBlLmV2ZW50X3R5cGU9InBhbiIsZS5wcm90b3R5cGUuZGVmYXVsdF9vcmRlcj0yMCxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5vdmVycmlkZV9jb21wdXRlZF9wcm9wZXJ0eSgidG9vbHRpcCIsZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZ2V0X2RpbV90b29sdGlwKHRoaXMudG9vbF9uYW1lLHRoaXMuX2NoZWNrX2RpbXModGhpcy5nZXQoImRpbWVuc2lvbnMiKSwiYm94IHpvb20gdG9vbCIpKX0sITEpLHRoaXMuYWRkX2RlcGVuZGVuY2llcygidG9vbHRpcCIsdGhpcyxbImRpbWVuc2lvbnMiXSl9LGUuZGVmaW5lKHtkaW1lbnNpb25zOlt1LkFycmF5LFsid2lkdGgiLCJoZWlnaHQiXV0sb3ZlcmxheTpbdS5JbnN0YW5jZSxzXSxtYXRjaF9hc3BlY3Q6W3UuQm9vbCwhMV19KSxlfShhLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzppfX0seyIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi9hbm5vdGF0aW9ucy9ib3hfYW5ub3RhdGlvbiI6Im1vZGVscy9hbm5vdGF0aW9ucy9ib3hfYW5ub3RhdGlvbiIsIi4vZ2VzdHVyZV90b29sIjoibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL2dlc3R1cmVfdG9vbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL2dlc3R1cmVfdG9vbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXUuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sdT17fS5oYXNPd25Qcm9wZXJ0eTthPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4uL2J1dHRvbl90b29sIiksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUucHJvdG90eXBlLl9jbGlja2VkPWZ1bmN0aW9uKCl7dmFyIHQ7cmV0dXJuIHQ9dGhpcy5tb2RlbC5nZXQoImFjdGl2ZSIpLHRoaXMubW9kZWwuc2V0KCJhY3RpdmUiLCF0KX0sZX0obi5CdXR0b25WaWV3KSxzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuZXZlbnRfdHlwZT1udWxsLGUucHJvdG90eXBlLmRlZmF1bHRfb3JkZXI9bnVsbCxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzpzLEJ1dHRvblZpZXc6aX19LHsiLi4vYnV0dG9uX3Rvb2wiOiJtb2RlbHMvdG9vbHMvYnV0dG9uX3Rvb2wiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90b29scy9nZXN0dXJlcy9sYXNzb19zZWxlY3RfdG9vbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7bD10KCJ1bmRlcnNjb3JlIiksYT10KCIuL3NlbGVjdF90b29sIikscz10KCIuLi8uLi9hbm5vdGF0aW9ucy9wb2x5X2Fubm90YXRpb24iKSx1PXQoIi4uLy4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0KSx0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZTphY3RpdmUiLHRoaXMuX2FjdGl2ZV9jaGFuZ2UpLHRoaXMuZGF0YT1udWxsfSxlLnByb3RvdHlwZS5fYWN0aXZlX2NoYW5nZT1mdW5jdGlvbigpe2lmKCF0aGlzLm1nZXQoImFjdGl2ZSIpKXJldHVybiB0aGlzLl9jbGVhcl9vdmVybGF5KCl9LGUucHJvdG90eXBlLl9rZXl1cD1mdW5jdGlvbih0KXtpZigxMz09PXQua2V5Q29kZSlyZXR1cm4gdGhpcy5fY2xlYXJfb3ZlcmxheSgpfSxlLnByb3RvdHlwZS5fcGFuX3N0YXJ0PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbjtyZXR1cm4gZT10aGlzLnBsb3Rfdmlldy5jYW52YXMscj1lLnN4X3RvX3Z4KHQuYm9rZWguc3gpLG49ZS5zeV90b192eSh0LmJva2VoLnN5KSx0aGlzLmRhdGE9e3Z4OltyXSx2eTpbbl19LG51bGx9LGUucHJvdG90eXBlLl9wYW49ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGEsbDtpZihyPXRoaXMucGxvdF92aWV3LmNhbnZhcyxhPXIuc3hfdG9fdngodC5ib2tlaC5zeCksbD1yLnN5X3RvX3Z5KHQuYm9rZWguc3kpLG49dGhpcy5wbG90X21vZGVsLmdldCgiZnJhbWUiKS5nZXQoImhfcmFuZ2UiKSxzPXRoaXMucGxvdF9tb2RlbC5nZXQoImZyYW1lIikuZ2V0KCJ2X3JhbmdlIiksYT5uLmdldCgiZW5kIikmJihhPW4uZ2V0KCJlbmQiKSksYTxuLmdldCgic3RhcnQiKSYmKGE9bi5nZXQoInN0YXJ0IikpLGw+cy5nZXQoImVuZCIpJiYobD1zLmdldCgiZW5kIikpLGw8cy5nZXQoInN0YXJ0IikmJihsPXMuZ2V0KCJzdGFydCIpKSx0aGlzLmRhdGEudngucHVzaChhKSx0aGlzLmRhdGEudnkucHVzaChsKSxvPXRoaXMubWdldCgib3ZlcmxheSIpLG8udXBkYXRlKHt4czp0aGlzLmRhdGEudngseXM6dGhpcy5kYXRhLnZ5fSksdGhpcy5tZ2V0KCJzZWxlY3RfZXZlcnlfbW91c2Vtb3ZlIikpcmV0dXJuIGU9bnVsbCE9KGk9dC5zcmNFdmVudC5zaGlmdEtleSkmJmksdGhpcy5fc2VsZWN0KHRoaXMuZGF0YS52eCx0aGlzLmRhdGEudnksITEsZSl9LGUucHJvdG90eXBlLl9wYW5fZW5kPWZ1bmN0aW9uKHQpe3ZhciBlLHI7cmV0dXJuIHRoaXMuX2NsZWFyX292ZXJsYXkoKSxlPW51bGwhPShyPXQuc3JjRXZlbnQuc2hpZnRLZXkpJiZyLHRoaXMuX3NlbGVjdCh0aGlzLmRhdGEudngsdGhpcy5kYXRhLnZ5LCEwLGUpLHRoaXMucGxvdF92aWV3LnB1c2hfc3RhdGUoImxhc3NvX3NlbGVjdCIse3NlbGVjdGlvbjp0aGlzLnBsb3Rfdmlldy5nZXRfc2VsZWN0aW9uKCl9KX0sZS5wcm90b3R5cGUuX2NsZWFyX292ZXJsYXk9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tZ2V0KCJvdmVybGF5IikudXBkYXRlKHt4czpbXSx5czpbXX0pfSxlLnByb3RvdHlwZS5fc2VsZWN0PWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBvLGkscyxhLGwsdSxoO2ZvcihpPXt0eXBlOiJwb2x5Iix2eDp0LHZ5OmV9LHU9dGhpcy5tZ2V0KCJjb21wdXRlZF9yZW5kZXJlcnMiKSxzPTAsYT11Lmxlbmd0aDtzPGE7cysrKWw9dVtzXSxvPWwuZ2V0KCJkYXRhX3NvdXJjZSIpLGg9by5nZXQoInNlbGVjdGlvbl9tYW5hZ2VyIiksaC5zZWxlY3QodGhpcyx0aGlzLnBsb3Rfdmlldy5yZW5kZXJlcl92aWV3c1tsLmlkXSxpLHIsbik7cmV0dXJuIG51bGwhPXRoaXMubWdldCgiY2FsbGJhY2siKSYmdGhpcy5fZW1pdF9jYWxsYmFjayhpKSx0aGlzLl9zYXZlX2dlb21ldHJ5KGkscixuKSxudWxsfSxlLnByb3RvdHlwZS5fZW1pdF9jYWxsYmFjaz1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpO249dGhpcy5tZ2V0KCJjb21wdXRlZF9yZW5kZXJlcnMiKVswXSxlPXRoaXMucGxvdF9tb2RlbC5nZXQoImNhbnZhcyIpLHI9dGhpcy5wbG90X21vZGVsLmdldCgiZnJhbWUiKSx0LnN4PWUudl92eF90b19zeCh0LnZ4KSx0LnN5PWUudl92eV90b19zeSh0LnZ5KSxvPXIuZ2V0KCJ4X21hcHBlcnMiKVtuLmdldCgieF9yYW5nZV9uYW1lIildLGk9ci5nZXQoInlfbWFwcGVycyIpW24uZ2V0KCJ5X3JhbmdlX25hbWUiKV0sdC54PW8udl9tYXBfZnJvbV90YXJnZXQodC52eCksdC55PWkudl9tYXBfZnJvbV90YXJnZXQodC52eSksdGhpcy5tZ2V0KCJjYWxsYmFjayIpLmV4ZWN1dGUodGhpcy5tb2RlbCx7Z2VvbWV0cnk6dH0pfSxlfShhLlZpZXcpLG49ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IHMuTW9kZWwoe2xldmVsOiJvdmVybGF5Iix4c191bml0czoic2NyZWVuIix5c191bml0czoic2NyZWVuIixmaWxsX2NvbG9yOiJsaWdodGdyZXkiLGZpbGxfYWxwaGE6LjUsbGluZV9jb2xvcjoiYmxhY2siLGxpbmVfYWxwaGE6MSxsaW5lX3dpZHRoOjIsbGluZV9kYXNoOls0LDRdfSl9LG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJMYXNzb1NlbGVjdFRvb2wiLGUucHJvdG90eXBlLnRvb2xfbmFtZT0iTGFzc28gU2VsZWN0IixlLnByb3RvdHlwZS5pY29uPSJiay10b29sLWljb24tbGFzc28tc2VsZWN0IixlLnByb3RvdHlwZS5ldmVudF90eXBlPSJwYW4iLGUucHJvdG90eXBlLmRlZmF1bHRfb3JkZXI9MTIsZS5kZWZpbmUoe3NlbGVjdF9ldmVyeV9tb3VzZW1vdmU6W3UuQm9vbCwhMF0sY2FsbGJhY2s6W3UuSW5zdGFuY2VdLG92ZXJsYXk6W3UuSW5zdGFuY2Usbl19KSxlfShhLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzppfX0seyIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi9hbm5vdGF0aW9ucy9wb2x5X2Fubm90YXRpb24iOiJtb2RlbHMvYW5ub3RhdGlvbnMvcG9seV9hbm5vdGF0aW9uIiwiLi9zZWxlY3RfdG9vbCI6Im1vZGVscy90b29scy9nZXN0dXJlcy9zZWxlY3RfdG9vbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL3Bhbl90b29sIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpdS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSx1PXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLG49dCgiLi9nZXN0dXJlX3Rvb2wiKSxhPXQoIi4uLy4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS5fcGFuX3N0YXJ0PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscztyZXR1cm4gdGhpcy5sYXN0X2R4PTAsdGhpcy5sYXN0X2R5PTAsZT10aGlzLnBsb3Rfdmlldy5jYW52YXMscj10aGlzLnBsb3Rfdmlldy5mcmFtZSxpPWUuc3hfdG9fdngodC5ib2tlaC5zeCkscz1lLnN5X3RvX3Z5KHQuYm9rZWguc3kpLHIuY29udGFpbnMoaSxzKXx8KG49ci5nZXQoImhfcmFuZ2UiKSxvPXIuZ2V0KCJ2X3JhbmdlIiksKGk8bi5nZXQoInN0YXJ0Iil8fGk+bi5nZXQoImVuZCIpKSYmKHRoaXMudl9heGlzX29ubHk9ITApLChzPG8uZ2V0KCJzdGFydCIpfHxzPm8uZ2V0KCJlbmQiKSkmJih0aGlzLmhfYXhpc19vbmx5PSEwKSksdGhpcy5wbG90X3ZpZXcuaW50ZXJhY3RpdmVfdGltZXN0YW1wPURhdGUubm93KCl9LGUucHJvdG90eXBlLl9wYW49ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX3VwZGF0ZSh0LmRlbHRhWCwtdC5kZWx0YVkpLHRoaXMucGxvdF92aWV3LmludGVyYWN0aXZlX3RpbWVzdGFtcD1EYXRlLm5vdygpfSxlLnByb3RvdHlwZS5fcGFuX2VuZD1mdW5jdGlvbih0KXtpZih0aGlzLmhfYXhpc19vbmx5PSExLHRoaXMudl9heGlzX29ubHk9ITEsbnVsbCE9dGhpcy5wYW5faW5mbylyZXR1cm4gdGhpcy5wbG90X3ZpZXcucHVzaF9zdGF0ZSgicGFuIix7cmFuZ2U6dGhpcy5wYW5faW5mb30pfSxlLnByb3RvdHlwZS5fdXBkYXRlPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLGksYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdyxNLGssaixULFMseixQO289dGhpcy5wbG90X3ZpZXcuZnJhbWUsaD10LXRoaXMubGFzdF9keCxjPWUtdGhpcy5sYXN0X2R5LGk9cy5jbG9uZShvLmdldCgiaF9yYW5nZSIpKSx3PWkuZ2V0KCJzdGFydCIpLWgseD1pLmdldCgiZW5kIiktaCxTPXMuY2xvbmUoby5nZXQoInZfcmFuZ2UiKSksVD1TLmdldCgic3RhcnQiKS1jLGo9Uy5nZXQoImVuZCIpLWMscj10aGlzLm1nZXQoImRpbWVuc2lvbnMiKSxyLmluZGV4T2YoIndpZHRoIik+LTEmJiF0aGlzLnZfYXhpc19vbmx5Pyh2PXcsYj14LG09LWgpOih2PWkuZ2V0KCJzdGFydCIpLGI9aS5nZXQoImVuZCIpLG09MCksci5pbmRleE9mKCJoZWlnaHQiKT4tMSYmIXRoaXMuaF9heGlzX29ubHk/KE09VCxrPWosZz1jKTooTT1TLmdldCgic3RhcnQiKSxrPVMuZ2V0KCJlbmQiKSxnPTApLHRoaXMubGFzdF9keD10LHRoaXMubGFzdF9keT1lLHo9e30scD1vLmdldCgieF9tYXBwZXJzIik7Zm9yKHUgaW4gcClsPXBbdV0sXz1sLnZfbWFwX2Zyb21fdGFyZ2V0KFt2LGJdLCEwKSx5PV9bMF0sbj1fWzFdLHpbdV09e3N0YXJ0OnksZW5kOm59O1A9e30sZD1vLmdldCgieV9tYXBwZXJzIik7Zm9yKHUgaW4gZClsPWRbdV0sZj1sLnZfbWFwX2Zyb21fdGFyZ2V0KFtNLGtdLCEwKSx5PWZbMF0sbj1mWzFdLFBbdV09e3N0YXJ0OnksZW5kOm59O3JldHVybiB0aGlzLnBhbl9pbmZvPXt4cnM6eix5cnM6UCxzZHg6bSxzZHk6Z30sdGhpcy5wbG90X3ZpZXcudXBkYXRlX3JhbmdlKHRoaXMucGFuX2luZm8sYT0hMCksbnVsbH0sZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWksZS5wcm90b3R5cGUudHlwZT0iUGFuVG9vbCIsZS5wcm90b3R5cGUudG9vbF9uYW1lPSJQYW4iLGUucHJvdG90eXBlLmljb249ImJrLXRvb2wtaWNvbi1wYW4iLGUucHJvdG90eXBlLmV2ZW50X3R5cGU9InBhbiIsZS5wcm90b3R5cGUuZGVmYXVsdF9vcmRlcj0xMCxlLmRlZmluZSh7ZGltZW5zaW9uczpbYS5BcnJheSxbIndpZHRoIiwiaGVpZ2h0Il1dfSksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0LHIpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0LHIpLHRoaXMub3ZlcnJpZGVfY29tcHV0ZWRfcHJvcGVydHkoInRvb2x0aXAiLGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2dldF9kaW1fdG9vbHRpcCgiUGFuIix0aGlzLl9jaGVja19kaW1zKHRoaXMuZ2V0KCJkaW1lbnNpb25zIiksInBhbiB0b29sIikpfSwhMSksdGhpcy5hZGRfZGVwZW5kZW5jaWVzKCJ0b29sdGlwIix0aGlzLFsiZGltZW5zaW9ucyJdKX0sZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvLFZpZXc6aX19LHsiLi4vLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9nZXN0dXJlX3Rvb2wiOiJtb2RlbHMvdG9vbHMvZ2VzdHVyZXMvZ2VzdHVyZV90b29sIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdG9vbHMvZ2VzdHVyZXMvcG9seV9zZWxlY3RfdG9vbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7bD10KCJ1bmRlcnNjb3JlIiksYT10KCIuL3NlbGVjdF90b29sIiksbz10KCIuLi8uLi9hbm5vdGF0aW9ucy9wb2x5X2Fubm90YXRpb24iKSx1PXQoIi4uLy4uLy4uL2NvcmUvcHJvcGVydGllcyIpLHM9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0KSx0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZTphY3RpdmUiLHRoaXMuX2FjdGl2ZV9jaGFuZ2UpLHRoaXMuZGF0YT1udWxsfSxlLnByb3RvdHlwZS5fYWN0aXZlX2NoYW5nZT1mdW5jdGlvbigpe2lmKCF0aGlzLm1nZXQoImFjdGl2ZSIpKXJldHVybiB0aGlzLl9jbGVhcl9kYXRhKCl9LGUucHJvdG90eXBlLl9rZXl1cD1mdW5jdGlvbih0KXtpZigxMz09PXQua2V5Q29kZSlyZXR1cm4gdGhpcy5fY2xlYXJfZGF0YSgpfSxlLnByb3RvdHlwZS5fZG91YmxldGFwPWZ1bmN0aW9uKHQpe3ZhciBlLHI7cmV0dXJuIGU9bnVsbCE9KHI9dC5zcmNFdmVudC5zaGlmdEtleSkmJnIsdGhpcy5fc2VsZWN0KHRoaXMuZGF0YS52eCx0aGlzLmRhdGEudnksITAsZSksdGhpcy5fY2xlYXJfZGF0YSgpfSxlLnByb3RvdHlwZS5fY2xlYXJfZGF0YT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmRhdGE9bnVsbCx0aGlzLm1nZXQoIm92ZXJsYXkiKS51cGRhdGUoe3hzOltdLHlzOltdfSl9LGUucHJvdG90eXBlLl90YXA9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saTtyZXR1cm4gZT10aGlzLnBsb3Rfdmlldy5jYW52YXMsbz1lLnN4X3RvX3Z4KHQuYm9rZWguc3gpLGk9ZS5zeV90b192eSh0LmJva2VoLnN5KSxudWxsPT10aGlzLmRhdGE/KHRoaXMuZGF0YT17dng6W29dLHZ5OltpXX0sbnVsbCk6KHRoaXMuZGF0YS52eC5wdXNoKG8pLHRoaXMuZGF0YS52eS5wdXNoKGkpLG49dGhpcy5tZ2V0KCJvdmVybGF5Iikscj17fSxyLnZ4PWwuY2xvbmUodGhpcy5kYXRhLnZ4KSxyLnZ5PWwuY2xvbmUodGhpcy5kYXRhLnZ5KSxuLnVwZGF0ZSh7eHM6dGhpcy5kYXRhLnZ4LHlzOnRoaXMuZGF0YS52eX0pKX0sZS5wcm90b3R5cGUuX3NlbGVjdD1mdW5jdGlvbih0LGUscixuKXt2YXIgbyxpLHMsYSxsLHUsaDtmb3IoaT17dHlwZToicG9seSIsdng6dCx2eTplfSx1PXRoaXMubWdldCgiY29tcHV0ZWRfcmVuZGVyZXJzIikscz0wLGE9dS5sZW5ndGg7czxhO3MrKylsPXVbc10sbz1sLmdldCgiZGF0YV9zb3VyY2UiKSxoPW8uZ2V0KCJzZWxlY3Rpb25fbWFuYWdlciIpLGguc2VsZWN0KHRoaXMsdGhpcy5wbG90X3ZpZXcucmVuZGVyZXJfdmlld3NbbC5pZF0saSxyLG4pO3JldHVybiB0aGlzLl9zYXZlX2dlb21ldHJ5KGkscixuKSx0aGlzLnBsb3Rfdmlldy5wdXNoX3N0YXRlKCJwb2x5X3NlbGVjdCIse3NlbGVjdGlvbjp0aGlzLnBsb3Rfdmlldy5nZXRfc2VsZWN0aW9uKCl9KSxudWxsfSxlfShhLlZpZXcpLG49ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IG8uTW9kZWwoe2xldmVsOiJvdmVybGF5Iix4c191bml0czoic2NyZWVuIix5c191bml0czoic2NyZWVuIixmaWxsX2NvbG9yOiJsaWdodGdyZXkiLGZpbGxfYWxwaGE6LjUsbGluZV9jb2xvcjoiYmxhY2siLGxpbmVfYWxwaGE6MSxsaW5lX3dpZHRoOjIsbGluZV9kYXNoOls0LDRdfSl9LGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9cyxlLnByb3RvdHlwZS50eXBlPSJQb2x5U2VsZWN0VG9vbCIsZS5wcm90b3R5cGUudG9vbF9uYW1lPSJQb2x5IFNlbGVjdCIsZS5wcm90b3R5cGUuaWNvbj0iYmstdG9vbC1pY29uLXBvbHlnb24tc2VsZWN0IixlLnByb3RvdHlwZS5ldmVudF90eXBlPSJ0YXAiLGUucHJvdG90eXBlLmRlZmF1bHRfb3JkZXI9MTEsZS5kZWZpbmUoe292ZXJsYXk6W3UuSW5zdGFuY2Usbl19KSxlfShhLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOmksVmlldzpzfX0seyIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi9hbm5vdGF0aW9ucy9wb2x5X2Fubm90YXRpb24iOiJtb2RlbHMvYW5ub3RhdGlvbnMvcG9seV9hbm5vdGF0aW9uIiwiLi9zZWxlY3RfdG9vbCI6Im1vZGVscy90b29scy9nZXN0dXJlcy9zZWxlY3RfdG9vbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL3Jlc2l6ZV90b29sIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpdS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSx1PXt9Lmhhc093blByb3BlcnR5O3M9dCgidW5kZXJzY29yZSIpLG49dCgiLi9nZXN0dXJlX3Rvb2wiKSxhPXQoIi4uLy4uLy4uL2NvcmUvcHJvcGVydGllcyIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGwoZSx0KSxlLnByb3RvdHlwZS5jbGFzc05hbWU9ImJrLXJlc2l6ZS1wb3B1cCIsZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXt2YXIgcjtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCkscj10aGlzLnBsb3Rfdmlldy4kZWwuZmluZCgiZGl2LmJrLWNhbnZhcy13cmFwcGVyIiksdGhpcy4kZWwuYXBwZW5kVG8ociksdGhpcy4kZWwuaGlkZSgpLHRoaXMuYWN0aXZlPSExLG51bGx9LGUucHJvdG90eXBlLmFjdGl2YXRlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYWN0aXZlPSEwLHRoaXMucmVuZGVyKCksbnVsbH0sZS5wcm90b3R5cGUuZGVhY3RpdmF0ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmFjdGl2ZT0hMSx0aGlzLnJlbmRlcigpLG51bGx9LGUucHJvdG90eXBlLnJlbmRlcj1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbztyZXR1cm4gdGhpcy5hY3RpdmU/KGU9dGhpcy5wbG90X3ZpZXcuY2FudmFzLHI9dGhpcy5wbG90X3ZpZXcuZnJhbWUsbj1lLnZ4X3RvX3N4KHIuZ2V0KCJoX3JhbmdlIikuZ2V0KCJlbmQiKS00MCksbz1lLnZ5X3RvX3N5KHIuZ2V0KCJ2X3JhbmdlIikuZ2V0KCJzdGFydCIpKzQwKSx0aGlzLiRlbC5hdHRyKCJzdHlsZSIsInBvc2l0aW9uOmFic29sdXRlOyB0b3A6IitvKyJweDsgbGVmdDoiK24rInB4OyIpLHRoaXMuJGVsLnNob3coKSk6dGhpcy4kZWwuaGlkZSgpLHRoaXN9LGUucHJvdG90eXBlLl9wYW5fc3RhcnQ9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9dGhpcy5wbG90X3ZpZXcuY2FudmFzLHRoaXMuY2g9ZS5nZXQoImhlaWdodCIpLHRoaXMuY3c9ZS5nZXQoIndpZHRoIiksdGhpcy5wbG90X3ZpZXcuaW50ZXJhY3RpdmVfdGltZXN0YW1wPURhdGUubm93KCksbnVsbH0sZS5wcm90b3R5cGUuX3Bhbj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fdXBkYXRlKHQuZGVsdGFYLHQuZGVsdGFZKSx0aGlzLnBsb3Rfdmlldy5pbnRlcmFjdGl2ZV90aW1lc3RhbXA9RGF0ZS5ub3coKSxudWxsfSxlLnByb3RvdHlwZS5fcGFuX2VuZD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5wbG90X3ZpZXcucHVzaF9zdGF0ZSgicmVzaXplIix7ZGltZW5zaW9uczp7d2lkdGg6dGhpcy5wbG90X3ZpZXcuY2FudmFzLmdldCgid2lkdGgiKSxoZWlnaHQ6dGhpcy5wbG90X3ZpZXcuY2FudmFzLmdldCgiaGVpZ2h0Iil9fSl9LGUucHJvdG90eXBlLl91cGRhdGU9ZnVuY3Rpb24odCxlKXt2YXIgcixuO249dGhpcy5jdyt0LHI9dGhpcy5jdytlLG48MTAwfHxyPDEwMHx8dGhpcy5wbG90X3ZpZXcudXBkYXRlX2RpbWVuc2lvbnMobixyKX0sZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWksZS5wcm90b3R5cGUudHlwZT0iUmVzaXplVG9vbCIsZS5wcm90b3R5cGUudG9vbF9uYW1lPSJSZXNpemUiLGUucHJvdG90eXBlLmljb249ImJrLXRvb2wtaWNvbi1yZXNpemUiLGUucHJvdG90eXBlLmV2ZW50X3R5cGU9InBhbiIsZS5wcm90b3R5cGUuZGVmYXVsdF9vcmRlcj00MCxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm8sVmlldzppfX0seyIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuL2dlc3R1cmVfdG9vbCI6Im1vZGVscy90b29scy9nZXN0dXJlcy9nZXN0dXJlX3Rvb2wiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90b29scy9nZXN0dXJlcy9zZWxlY3RfdG9vbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7YT10KCJ1bmRlcnNjb3JlIiksbj10KCIuL2dlc3R1cmVfdG9vbCIpLG89dCgiLi4vLi4vcmVuZGVyZXJzL2dseXBoX3JlbmRlcmVyIiksbD10KCIuLi8uLi8uLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIsdT10KCIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBoKGUsdCksZS5wcm90b3R5cGUuX2tleXVwPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhO2lmKDI3PT09dC5rZXlDb2RlKXtmb3IoaT10aGlzLm1nZXQoImNvbXB1dGVkX3JlbmRlcmVycyIpLHM9W10scj0wLG49aS5sZW5ndGg7cjxuO3IrKylvPWlbcl0sZT1vLmdldCgiZGF0YV9zb3VyY2UiKSxhPWUuZ2V0KCJzZWxlY3Rpb25fbWFuYWdlciIpLHMucHVzaChhLmNsZWFyKCkpO3JldHVybiBzfX0sZS5wcm90b3R5cGUuX3NhdmVfZ2VvbWV0cnk9ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLHUsaCxjLHA7aWYobj1hLmNsb25lKHQpLGM9dGhpcy5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJ4X21hcHBlcnMiKVsiZGVmYXVsdCJdLHA9dGhpcy5wbG90X3ZpZXcuZnJhbWUuZ2V0KCJ5X21hcHBlcnMiKVsiZGVmYXVsdCJdLCJwb2ludCI9PT1uLnR5cGUpbi54PWMubWFwX2Zyb21fdGFyZ2V0KG4udngpLG4ueT1wLm1hcF9mcm9tX3RhcmdldChuLnZ5KTtlbHNlIGlmKCJyZWN0Ij09PW4udHlwZSluLngwPWMubWFwX2Zyb21fdGFyZ2V0KG4udngwKSxuLnkwPXAubWFwX2Zyb21fdGFyZ2V0KG4udnkwKSxuLngxPWMubWFwX2Zyb21fdGFyZ2V0KG4udngxKSxuLnkxPXAubWFwX2Zyb21fdGFyZ2V0KG4udnkxKTtlbHNlIGlmKCJwb2x5Ij09PW4udHlwZSlmb3Iobi54PW5ldyBBcnJheShuLnZ4Lmxlbmd0aCksbi55PW5ldyBBcnJheShuLnZ5Lmxlbmd0aCksaT1zPTAsdT1uLnZ4Lmxlbmd0aDswPD11P3M8dTpzPnU7aT0wPD11PysrczotLXMpbi54W2ldPWMubWFwX2Zyb21fdGFyZ2V0KG4udnhbaV0pLG4ueVtpXT1wLm1hcF9mcm9tX3RhcmdldChuLnZ5W2ldKTtlbHNlIGwuZGVidWcoIlVucmVjb2duaXplZCBzZWxlY3Rpb24gZ2VvbWV0cnkgdHlwZTogJyIrbi50eXBlKyInIik7cmV0dXJuIGUmJihoPXRoaXMucGxvdF9tb2RlbC5wbG90LnRvb2xfZXZlbnRzLHI/KG89aC5nZXQoImdlb21ldHJpZXMiKSxvLnB1c2gobikpOm89W25dLGguc2V0KCJnZW9tZXRyaWVzIixvKSksbnVsbH0sZX0obi5WaWV3KSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBoKGUsdCksZS5kZWZpbmUoe3JlbmRlcmVyczpbdS5BcnJheSxbXV0sbmFtZXM6W3UuQXJyYXksW11dfSksZS5pbnRlcm5hbCh7bXVsdGlfc2VsZWN0X21vZGlmaWVyOlt1LlN0cmluZywic2hpZnQiXX0pLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgiY29tcHV0ZWRfcmVuZGVyZXJzIixmdW5jdGlvbigpe3ZhciB0LGUscixuO3JldHVybiBuPXRoaXMuZ2V0KCJyZW5kZXJlcnMiKSxlPXRoaXMuZ2V0KCJuYW1lcyIpLDA9PT1uLmxlbmd0aCYmKHQ9dGhpcy5nZXQoInBsb3QiKS5nZXQoInJlbmRlcmVycyIpLG49ZnVuY3Rpb24oKXt2YXIgZSxuLGk7Zm9yKGk9W10sZT0wLG49dC5sZW5ndGg7ZTxuO2UrKylyPXRbZV0sciBpbnN0YW5jZW9mIG8uTW9kZWwmJmkucHVzaChyKTtyZXR1cm4gaX0oKSksZS5sZW5ndGg+MCYmKG49ZnVuY3Rpb24oKXt2YXIgdCxvLGk7Zm9yKGk9W10sdD0wLG89bi5sZW5ndGg7dDxvO3QrKylyPW5bdF0sZS5pbmRleE9mKHIuZ2V0KCJuYW1lIikpPj0wJiZpLnB1c2gocik7cmV0dXJuIGl9KCkpLG59LCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoImNvbXB1dGVkX3JlbmRlcmVycyIsdGhpcyxbInJlbmRlcmVycyIsIm5hbWVzIiwicGxvdCJdKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoImNvbXB1dGVkX3JlbmRlcmVycyIsdGhpcy5nZXQoInBsb3QiKSxbInJlbmRlcmVycyJdKSxudWxsfSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOmksVmlldzpzfX0seyIuLi8uLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi9yZW5kZXJlcnMvZ2x5cGhfcmVuZGVyZXIiOiJtb2RlbHMvcmVuZGVyZXJzL2dseXBoX3JlbmRlcmVyIiwiLi9nZXN0dXJlX3Rvb2wiOiJtb2RlbHMvdG9vbHMvZ2VzdHVyZXMvZ2VzdHVyZV90b29sIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdG9vbHMvZ2VzdHVyZXMvdGFwX3Rvb2wiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSl1LmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LHU9e30uaGFzT3duUHJvcGVydHk7cz10KCJ1bmRlcnNjb3JlIiksbj10KCIuL3NlbGVjdF90b29sIiksYT10KCIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxpPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuX3RhcD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpO3JldHVybiByPXRoaXMucGxvdF92aWV3LmNhbnZhcyxvPXIuc3hfdG9fdngodC5ib2tlaC5zeCksaT1yLnN5X3RvX3Z5KHQuYm9rZWguc3kpLGU9bnVsbCE9KG49dC5zcmNFdmVudC5zaGlmdEtleSkmJm4sdGhpcy5fc2VsZWN0KG8saSwhMCxlKX0sZS5wcm90b3R5cGUuX3NlbGVjdD1mdW5jdGlvbih0LGUscixuKXt2YXIgbyxpLGEsbCx1LGgsYyxwLF8sZCxmO2Zvcih1PXt0eXBlOiJwb2ludCIsdng6dCx2eTplfSxvPXRoaXMubWdldCgiY2FsbGJhY2siKSx0aGlzLl9zYXZlX2dlb21ldHJ5KHUscixuKSxpPXtnZW9tZXRyaWVzOnRoaXMucGxvdF9tb2RlbC5wbG90LnRvb2xfZXZlbnRzLmdldCgiZ2VvbWV0cmllcyIpfSxfPXRoaXMubWdldCgiY29tcHV0ZWRfcmVuZGVyZXJzIiksaD0wLGM9Xy5sZW5ndGg7aDxjO2grKylwPV9baF0sbD1wLmdldCgiZGF0YV9zb3VyY2UiKSxkPWwuZ2V0KCJzZWxlY3Rpb25fbWFuYWdlciIpLGY9dGhpcy5wbG90X3ZpZXcucmVuZGVyZXJfdmlld3NbcC5pZF0sYT0ic2VsZWN0Ij09PXRoaXMubW9kZWwuYmVoYXZpb3I/ZC5zZWxlY3QodGhpcyxmLHUscixuKTpkLmluc3BlY3QodGhpcyxmLHUse2dlb21ldHJ5OnV9KSxhJiZudWxsIT1vJiYocy5pc0Z1bmN0aW9uKG8pP28obCxpKTpvLmV4ZWN1dGUobCxpKSk7cmV0dXJuInNlbGVjdCI9PT10aGlzLm1vZGVsLmJlaGF2aW9yJiZ0aGlzLnBsb3Rfdmlldy5wdXNoX3N0YXRlKCJ0YXAiLHtzZWxlY3Rpb246dGhpcy5wbG90X3ZpZXcuZ2V0X3NlbGVjdGlvbigpfSksbnVsbH0sZX0obi5WaWV3KSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PWksZS5wcm90b3R5cGUudHlwZT0iVGFwVG9vbCIsZS5wcm90b3R5cGUudG9vbF9uYW1lPSJUYXAiLGUucHJvdG90eXBlLmljb249ImJrLXRvb2wtaWNvbi10YXAtc2VsZWN0IixlLnByb3RvdHlwZS5ldmVudF90eXBlPSJ0YXAiLGUucHJvdG90eXBlLmRlZmF1bHRfb3JkZXI9MTAsZS5kZWZpbmUoe2JlaGF2aW9yOlthLlN0cmluZywic2VsZWN0Il0sY2FsbGJhY2s6W2EuQW55XX0pLGV9KG4uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3Oml9fSx7Ii4uLy4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vc2VsZWN0X3Rvb2wiOiJtb2RlbHMvdG9vbHMvZ2VzdHVyZXMvc2VsZWN0X3Rvb2wiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90b29scy9nZXN0dXJlcy93aGVlbF96b29tX3Rvb2wiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHU9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWguY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0saD17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxuPXQoIi4vZ2VzdHVyZV90b29sIiksbD10KCIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSwidW5kZWZpbmVkIiE9dHlwZW9mIGEmJm51bGwhPT1hfHwoYT17fSksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLl9waW5jaD1mdW5jdGlvbih0KXt2YXIgZTtyZXR1cm4gZT10LnNjYWxlPj0xPzIwKih0LnNjYWxlLTEpOi0yMC90LnNjYWxlLHQuYm9rZWguZGVsdGE9ZSx0aGlzLl9zY3JvbGwodCl9LGUucHJvdG90eXBlLl9zY3JvbGw9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTLHosUCxFLEE7aT10aGlzLnBsb3RfbW9kZWwuZ2V0KCJmcmFtZSIpLGE9aS5nZXQoImhfcmFuZ2UiKSx3PWkuZ2V0KCJ2X3JhbmdlIiksTT10aGlzLnBsb3Rfdmlldy5jYW52YXMuc3hfdG9fdngodC5ib2tlaC5zeCksVD10aGlzLnBsb3Rfdmlldy5jYW52YXMuc3lfdG9fdnkodC5ib2tlaC5zeSksKE08YS5nZXQoInN0YXJ0Iil8fE0+YS5nZXQoImVuZCIpKSYmKHg9ITApLChUPHcuZ2V0KCJzdGFydCIpfHxUPncuZ2V0KCJlbmQiKSkmJihzPSEwKSx1PW5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKS5pbmRleE9mKCJmaXJlZm94Iik+LTE/MjA6MSxlPW51bGwhPShudWxsIT0oYz10Lm9yaWdpbmFsRXZlbnQpP2MuZGVsdGFZOnZvaWQgMCk/LXQub3JpZ2luYWxFdmVudC5kZWx0YVkqdTp0LmJva2VoLmRlbHRhLG89dGhpcy5tZ2V0KCJzcGVlZCIpKmUsbz4uOT9vPS45Om88LS45JiYobz0tLjkpLGo9YS5nZXQoInN0YXJ0Iiksaz1hLmdldCgiZW5kIiksej13LmdldCgic3RhcnQiKSxTPXcuZ2V0KCJlbmQiKSxyPXRoaXMubWdldCgiZGltZW5zaW9ucyIpLHIuaW5kZXhPZigid2lkdGgiKT4tMSYmIXg/KGc9ai0oai1NKSpvLHk9ay0oay1NKSpvKTooZz1qLHk9ayksci5pbmRleE9mKCJoZWlnaHQiKT4tMSYmIXM/KHY9ei0oei1UKSpvLGI9Uy0oUy1UKSpvKToodj16LGI9UyksUD17fSxwPWkuZ2V0KCJ4X21hcHBlcnMiKTtmb3IoaCBpbiBwKWw9cFtoXSxfPWwudl9tYXBfZnJvbV90YXJnZXQoW2cseV0sITApLG09X1swXSxuPV9bMV0sUFtoXT17c3RhcnQ6bSxlbmQ6bn07RT17fSxkPWkuZ2V0KCJ5X21hcHBlcnMiKTtmb3IoaCBpbiBkKWw9ZFtoXSxmPWwudl9tYXBfZnJvbV90YXJnZXQoW3YsYl0sITApLG09ZlswXSxuPWZbMV0sRVtoXT17c3RhcnQ6bSxlbmQ6bn07cmV0dXJuIEE9e3hyczpQLHlyczpFLGZhY3RvcjpvfSx0aGlzLnBsb3Rfdmlldy5wdXNoX3N0YXRlKCJ3aGVlbF96b29tIix7cmFuZ2U6QX0pLHRoaXMucGxvdF92aWV3LnVwZGF0ZV9yYW5nZShBLCExLCEwKSx0aGlzLnBsb3Rfdmlldy5pbnRlcmFjdGl2ZV90aW1lc3RhbXA9RGF0ZS5ub3coKSxudWxsfSxlfShuLlZpZXcpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHUoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9aSxlLnByb3RvdHlwZS50eXBlPSJXaGVlbFpvb21Ub29sIixlLnByb3RvdHlwZS50b29sX25hbWU9IldoZWVsIFpvb20iLGUucHJvdG90eXBlLmljb249ImJrLXRvb2wtaWNvbi13aGVlbC16b29tIixlLnByb3RvdHlwZS5ldmVudF90eXBlPSJvbnRvdWNoc3RhcnQiaW4gd2luZG93fHxuYXZpZ2F0b3IubWF4VG91Y2hQb2ludHM+MD8icGluY2giOiJzY3JvbGwiLGUucHJvdG90eXBlLmRlZmF1bHRfb3JkZXI9MTAsZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0LHIpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0LHIpLHRoaXMub3ZlcnJpZGVfY29tcHV0ZWRfcHJvcGVydHkoInRvb2x0aXAiLGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2dldF9kaW1fdG9vbHRpcCh0aGlzLnRvb2xfbmFtZSx0aGlzLl9jaGVja19kaW1zKHRoaXMuZ2V0KCJkaW1lbnNpb25zIiksIndoZWVsIHpvb20gdG9vbCIpKX0sITEpLHRoaXMuYWRkX2RlcGVuZGVuY2llcygidG9vbHRpcCIsdGhpcyxbImRpbWVuc2lvbnMiXSl9LGUuZGVmaW5lKHtkaW1lbnNpb25zOltsLkFycmF5LFsid2lkdGgiLCJoZWlnaHQiXV19KSxlLmludGVybmFsKHtzcGVlZDpbbC5OdW1iZXIsMS82MDBdfSksZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvLFZpZXc6aX19LHsiLi4vLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi9nZXN0dXJlX3Rvb2wiOiJtb2RlbHMvdG9vbHMvZ2VzdHVyZXMvZ2VzdHVyZV90b29sIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdG9vbHMvaW5zcGVjdG9ycy9jcm9zc2hhaXJfdG9vbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdT1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpaC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxoPXt9Lmhhc093blByb3BlcnR5O2E9dCgidW5kZXJzY29yZSIpLGk9dCgiLi9pbnNwZWN0X3Rvb2wiKSxzPXQoIi4uLy4uL2Fubm90YXRpb25zL3NwYW4iKSxsPXQoIi4uLy4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHUoZSx0KSxlLnByb3RvdHlwZS5fbW92ZT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsLHUsaDtpZih0aGlzLm1nZXQoImFjdGl2ZSIpKXtmb3Iobj10aGlzLnBsb3RfbW9kZWwuZ2V0KCJmcmFtZSIpLGU9dGhpcy5wbG90X21vZGVsLmdldCgiY2FudmFzIiksdT1lLnN4X3RvX3Z4KHQuYm9rZWguc3gpLGg9ZS5zeV90b192eSh0LmJva2VoLnN5KSxzPXRoaXMubWdldCgiZGltZW5zaW9ucyIpLGE9W10sbz0wLGk9cy5sZW5ndGg7bzxpO28rKylyPXNbb10sbD10aGlzLm1nZXQoInNwYW5zIilbcl0sbi5jb250YWlucyh1LGgpPyJ3aWR0aCI9PT1yP2EucHVzaChsLnNldCgiY29tcHV0ZWRfbG9jYXRpb24iLGgpKTphLnB1c2gobC5zZXQoImNvbXB1dGVkX2xvY2F0aW9uIix1KSk6YS5wdXNoKGwudW5zZXQoImNvbXB1dGVkX2xvY2F0aW9uIikpO3JldHVybiBhfX0sZS5wcm90b3R5cGUuX21vdmVfZXhpdD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHM7Zm9yKG89dGhpcy5tZ2V0KCJkaW1lbnNpb25zIiksaT1bXSxyPTAsbj1vLmxlbmd0aDtyPG47cisrKWU9b1tyXSxzPXRoaXMubWdldCgic3BhbnMiKVtlXSxpLnB1c2gocy51bnNldCgiY29tcHV0ZWRfbG9jYXRpb24iKSk7cmV0dXJuIGl9LGV9KGkuVmlldyksbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdShlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1vLGUucHJvdG90eXBlLnR5cGU9IkNyb3NzaGFpclRvb2wiLGUucHJvdG90eXBlLnRvb2xfbmFtZT0iQ3Jvc3NoYWlyIixlLmRlZmluZSh7ZGltZW5zaW9uczpbbC5BcnJheSxbIndpZHRoIiwiaGVpZ2h0Il1dLGxpbmVfY29sb3I6W2wuQ29sb3IsImJsYWNrIl0sbGluZV93aWR0aDpbbC5OdW1iZXIsMV0sbGluZV9hbHBoYTpbbC5OdW1iZXIsMV19KSxlLmludGVybmFsKHtsb2NhdGlvbl91bml0czpbbC5TcGF0aWFsVW5pdHMsInNjcmVlbiJdLHJlbmRlcl9tb2RlOltsLlJlbmRlck1vZGUsImNzcyJdLHNwYW5zOltsLkFueV19KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5vdmVycmlkZV9jb21wdXRlZF9wcm9wZXJ0eSgidG9vbHRpcCIsZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZ2V0X2RpbV90b29sdGlwKCJDcm9zc2hhaXIiLHRoaXMuX2NoZWNrX2RpbXModGhpcy5nZXQoImRpbWVuc2lvbnMiKSwiY3Jvc3NoYWlyIHRvb2wiKSl9LCExKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoInRvb2x0aXAiLHRoaXMsWyJkaW1lbnNpb25zIl0pLHRoaXMuc3BhbnM9e3dpZHRoOm5ldyBzLk1vZGVsKHtmb3JfaG92ZXI6ITAsZGltZW5zaW9uOiJ3aWR0aCIscmVuZGVyX21vZGU6dGhpcy5nZXQoInJlbmRlcl9tb2RlIiksbG9jYXRpb25fdW5pdHM6dGhpcy5nZXQoImxvY2F0aW9uX3VuaXRzIiksbGluZV9jb2xvcjp0aGlzLmdldCgibGluZV9jb2xvciIpLGxpbmVfd2lkdGg6dGhpcy5nZXQoImxpbmVfd2lkdGgiKSxsaW5lX2FscGhhOnRoaXMuZ2V0KCJsaW5lX2FscGhhIil9KSxoZWlnaHQ6bmV3IHMuTW9kZWwoe2Zvcl9ob3ZlcjohMCxkaW1lbnNpb246ImhlaWdodCIscmVuZGVyX21vZGU6dGhpcy5nZXQoInJlbmRlcl9tb2RlIiksbG9jYXRpb25fdW5pdHM6dGhpcy5nZXQoImxvY2F0aW9uX3VuaXRzIiksbGluZV9jb2xvcjp0aGlzLmdldCgibGluZV9jb2xvciIpLGxpbmVfd2lkdGg6dGhpcy5nZXQoImxpbmVfd2lkdGgiKSxsaW5lX2FscGhhOnRoaXMuZ2V0KCJsaW5lX2FscGhhIil9KX0sdGhpcy5vdmVycmlkZV9jb21wdXRlZF9wcm9wZXJ0eSgic3ludGhldGljX3JlbmRlcmVycyIsZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGEudmFsdWVzKHQuZ2V0KCJzcGFucyIpKX19KHRoaXMpLCEwKX0sZX0oaS5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpuLFZpZXc6b319LHsiLi4vLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vYW5ub3RhdGlvbnMvc3BhbiI6Im1vZGVscy9hbm5vdGF0aW9ucy9zcGFuIiwiLi9pbnNwZWN0X3Rvb2wiOiJtb2RlbHMvdG9vbHMvaW5zcGVjdG9ycy9pbnNwZWN0X3Rvb2wiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90b29scy9pbnNwZWN0b3JzL2hvdmVyX3Rvb2wiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGY9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKW0uY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbT17fS5oYXNPd25Qcm9wZXJ0eTtoPXQoInVuZGVyc2NvcmUiKSxuPXQoImpxdWVyeSIpLGE9dCgiLi9pbnNwZWN0X3Rvb2wiKSxsPXQoIi4uLy4uL2Fubm90YXRpb25zL3Rvb2x0aXAiKSxvPXQoIi4uLy4uL3JlbmRlcmVycy9nbHlwaF9yZW5kZXJlciIpLHA9dCgiLi4vLi4vLi4vY29tbW9uL2hpdHRlc3QiKSxfPXQoIi4uLy4uLy4uL2NvcmUvbG9nZ2luZyIpLmxvZ2dlcixkPXQoIi4uLy4uLy4uL2NvcmUvcHJvcGVydGllcyIpLHU9dCgiLi4vLi4vLi4vdXRpbC91dGlsIiksYz1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpO3JldHVybiIjIj09PXQuc3Vic3RyKDAsMSk/dDoocj0vKC4qPylyZ2JcKChcZCspLCAoXGQrKSwgKFxkKylcKS8uZXhlYyh0KSxvPXBhcnNlSW50KHJbMl0pLG49cGFyc2VJbnQoclszXSksZT1wYXJzZUludChyWzRdKSxpPWV8bjw8OHxvPDwxNixyWzFdKyIjIitpLnRvU3RyaW5nKDE2KSl9LHM9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGYoZSx0KSxlLnByb3RvdHlwZS5iaW5kX2Jva2VoX2V2ZW50cz1mdW5jdGlvbigpe3ZhciB0LGUscixuO2ZvcihuPXRoaXMubWdldCgiY29tcHV0ZWRfcmVuZGVyZXJzIiksdD0wLGU9bi5sZW5ndGg7dDxlO3QrKylyPW5bdF0sdGhpcy5saXN0ZW5UbyhyLmRhdGFfc291cmNlLCJpbnNwZWN0Iix0aGlzLl91cGRhdGUpO3JldHVybiB0aGlzLnBsb3Rfdmlldy5jYW52YXNfdmlldy4kZWwuY3NzKCJjdXJzb3IiLCJjcm9zc2hhaXIiKX0sZS5wcm90b3R5cGUuX2NsZWFyPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47dGhpcy5faW5zcGVjdCgxLzAsMS8wKSx0PXRoaXMubWdldCgidHRtb2RlbHMiKSxlPVtdO2ZvcihyIGluIHQpbj10W3JdLGUucHVzaChuLmNsZWFyKCkpO3JldHVybiBlfSxlLnByb3RvdHlwZS5fbW92ZT1mdW5jdGlvbih0KXt2YXIgZSxyLG47aWYodGhpcy5tZ2V0KCJhY3RpdmUiKSlyZXR1cm4gZT10aGlzLnBsb3Rfdmlldy5jYW52YXMscj1lLnN4X3RvX3Z4KHQuYm9rZWguc3gpLG49ZS5zeV90b192eSh0LmJva2VoLnN5KSx0aGlzLnBsb3Rfdmlldy5mcmFtZS5jb250YWlucyhyLG4pP3RoaXMuX2luc3BlY3QocixuKTp0aGlzLl9jbGVhcigpfSxlLnByb3RvdHlwZS5fbW92ZV9leGl0PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NsZWFyKCl9LGUucHJvdG90eXBlLl9pbnNwZWN0PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoO2ZvcihuPXt0eXBlOiJwb2ludCIsdng6dCx2eTplfSwibW91c2UiPT09dGhpcy5tb2RlbC5tb2RlP24udHlwZT0icG9pbnQiOihuLnR5cGU9InNwYW4iLCJ2bGluZSI9PT10aGlzLm1vZGVsLm1vZGU/bi5kaXJlY3Rpb249ImgiOm4uZGlyZWN0aW9uPSJ2Iiksbz1bXSxpPVtdLHU9dGhpcy5tZ2V0KCJjb21wdXRlZF9yZW5kZXJlcnMiKSxzPTAsYT11Lmxlbmd0aDtzPGE7cysrKWw9dVtzXSxoPWwuZGF0YV9zb3VyY2UuZ2V0KCJzZWxlY3Rpb25fbWFuYWdlciIpLGguaW5zcGVjdCh0aGlzLHRoaXMucGxvdF92aWV3LnJlbmRlcmVyX3ZpZXdzW2wuaWRdLG4se2dlb21ldHJ5Om59KTtudWxsIT10aGlzLm1nZXQoImNhbGxiYWNrIikmJnRoaXMuX2VtaXRfY2FsbGJhY2sobil9LGUucHJvdG90eXBlLl91cGRhdGU9ZnVuY3Rpb24odCxlLHIsbixvKXt2YXIgaSxzLGEsbCx1LGMsXyxkLGYsbSxnLHksdixiLHgsdyxNLGssaixULFMseixQLEUsQSxDLE4sTyxxLEQsSSxSLEYsQixMLEcsVixVLFksSCxYLCQsVyxKLFEsSyxaLHR0LGV0LHJ0LG50O2lmKGc9by5nZW9tZXRyeSxKPW51bGwhPSh6PXRoaXMubWdldCgidHRtb2RlbHMiKVtyLm1vZGVsLmlkXSk/ejpudWxsLG51bGwhPUomJihKLmNsZWFyKCksbnVsbCE9PXRbIjBkIl0uZ2x5cGh8fDAhPT10WyIxZCJdLmluZGljZXMubGVuZ3RoKSl7Zm9yKEs9Zy52eCxaPWcudnksaT10aGlzLnBsb3RfbW9kZWwuZ2V0KCJjYW52YXMiKSxtPXRoaXMucGxvdF9tb2RlbC5nZXQoImZyYW1lIiksJD1pLnZ4X3RvX3N4KEspLFc9aS52eV90b19zeShaKSxldD1tLmdldCgieF9tYXBwZXJzIilbci5tZ2V0KCJ4X3JhbmdlX25hbWUiKV0sbnQ9bS5nZXQoInlfbWFwcGVycyIpW3IubWdldCgieV9yYW5nZV9uYW1lIildLHR0PWV0Lm1hcF9mcm9tX3RhcmdldChLKSxydD1udC5tYXBfZnJvbV90YXJnZXQoWiksUD10WyIwZCJdLmluZGljZXMsYj0wLHc9UC5sZW5ndGg7Yjx3O2IrKyl5PVBbYl0sYz1yLmdseXBoLl94W3krMV0sXz1yLmdseXBoLl95W3krMV0sImludGVycCI9PT10aGlzLm1vZGVsLmxpbmVfcG9saWN5PyhEPXIuZ2x5cGguZ2V0X2ludGVycG9sYXRpb25faGl0KHksZyksYz1EWzBdLF89RFsxXSxVPWV0Lm1hcF90b190YXJnZXQoYyksWT1udC5tYXBfdG9fdGFyZ2V0KF8pKToicHJldiI9PT10aGlzLm1vZGVsLmxpbmVfcG9saWN5PyhVPWkuc3hfdG9fdngoci5nbHlwaC5zeFt5XSksWT1pLnN5X3RvX3Z5KHIuZ2x5cGguc3lbeV0pKToibmV4dCI9PT10aGlzLm1vZGVsLmxpbmVfcG9saWN5PyhVPWkuc3hfdG9fdngoci5nbHlwaC5zeFt5KzFdKSxZPWkuc3lfdG9fdnkoci5nbHlwaC5zeVt5KzFdKSk6Im5lYXJlc3QiPT09dGhpcy5tb2RlbC5saW5lX3BvbGljeT8ocz1yLmdseXBoLnN4W3ldLGE9ci5nbHlwaC5zeVt5XSxkPXAuZGlzdF8yX3B0cyhzLGEsJCxXKSxsPXIuZ2x5cGguc3hbeSsxXSx1PXIuZ2x5cGguc3lbeSsxXSxmPXAuZGlzdF8yX3B0cyhsLHUsJCxXKSxkPGY/KEk9W3MsYV0sSD1JWzBdLFg9SVsxXSk6KFI9W2wsdV0sSD1SWzBdLFg9UlsxXSx5Kz0xKSxjPXIuZ2x5cGguX3hbeV0sXz1yLmdseXBoLl95W3ldLFU9aS5zeF90b192eChIKSxZPWkuc3lfdG9fdnkoWCkpOihGPVtLLFpdLFU9RlswXSxZPUZbMV0pLFE9e2luZGV4OnkseDp0dCx5OnJ0LHZ4Okssdnk6WixzeDokLHN5OlcsZGF0YV94OmMsZGF0YV95Ol8scng6VSxyeTpZfSxKLmFkZChVLFksdGhpcy5fcmVuZGVyX3Rvb2x0aXBzKG4seSxRKSk7Zm9yKEI9dFsiMWQiXS5pbmRpY2VzLHg9MCxNPUIubGVuZ3RoO3g8TTt4KyspaWYoeT1CW3hdLGguaXNFbXB0eSh0WyIyZCJdKSljPW51bGwhPShDPXIuZ2x5cGguX3gpP0NbeV06dm9pZCAwLF89bnVsbCE9KE49ci5nbHlwaC5feSk/Tlt5XTp2b2lkIDAsInNuYXBfdG9fZGF0YSI9PT10aGlzLm1vZGVsLnBvaW50X3BvbGljeT8oUz1yLmdseXBoLmdldF9hbmNob3JfcG9pbnQodGhpcy5tb2RlbC5hbmNob3IseSxbJCxXXSksbnVsbCE9Uz8odHQ9Uy54LHJ0PVMueSk6KE89ci5nbHlwaC5nZXRfYW5jaG9yX3BvaW50KCJjZW50ZXIiLHksWyQsV10pLHR0PU8ueCxydD1PLnkpLFU9aS5zeF90b192eCh0dCksWT1pLnN5X3RvX3Z5KHJ0KSk6KHE9W0ssWl0sVT1xWzBdLFk9cVsxXSksUT17aW5kZXg6eSx4OnR0LHk6cnQsdng6Syx2eTpaLHN4OiQsc3k6VyxkYXRhX3g6YyxkYXRhX3k6X30sSi5hZGQoVSxZLHRoaXMuX3JlbmRlcl90b29sdGlwcyhuLHksUSkpO2Vsc2UgZm9yKEw9aC5wYWlycyh0WyIyZCJdKSxqPTAsaz1MLmxlbmd0aDtqPGs7aisrKVQ9TFtqXSxHPVtUWzBdLFRbMV1bMF1dLHk9R1swXSx2PUdbMV0sYz1yLmdseXBoLl94c1t5XVt2XSxfPXIuZ2x5cGguX3lzW3ldW3ZdLCJpbnRlcnAiPT09dGhpcy5tb2RlbC5saW5lX3BvbGljeT8oVj1yLmdseXBoLmdldF9pbnRlcnBvbGF0aW9uX2hpdCh5LHYsZyksYz1WWzBdLF89VlsxXSxVPWV0Lm1hcF90b190YXJnZXQoYyksWT1udC5tYXBfdG9fdGFyZ2V0KF8pKToicHJldiI9PT10aGlzLm1vZGVsLmxpbmVfcG9saWN5PyhVPWkuc3hfdG9fdngoci5nbHlwaC5zeHNbeV1bdl0pLFk9aS5zeV90b192eShyLmdseXBoLnN5c1t5XVt2XSkpOiJuZXh0Ij09PXRoaXMubW9kZWwubGluZV9wb2xpY3k/KFU9aS5zeF90b192eChyLmdseXBoLnN4c1t5XVt2KzFdKSxZPWkuc3lfdG9fdnkoci5nbHlwaC5zeXNbeV1bdisxXSkpOiJuZWFyZXN0Ij09PXRoaXMubW9kZWwubGluZV9wb2xpY3kmJihzPXIuZ2x5cGguc3hbeV1bdl0sYT1yLmdseXBoLnN5W3ldW3ZdLGQ9cC5kaXN0XzJfcHRzKHMsYSwkLFcpLGw9ci5nbHlwaC5zeFt5XVt2KzFdLHU9ci5nbHlwaC5zeVt5XVt2KzFdLGY9cC5kaXN0XzJfcHRzKGwsdSwkLFcpLGQ8Zj8oRT1bcyxhXSxIPUVbMF0sWD1FWzFdKTooQT1bbCx1XSxIPUFbMF0sWD1BWzFdLHYrPTEpLGM9ci5nbHlwaC5feFt5XVt2XSxfPXIuZ2x5cGguX3lbeV1bdl0sVT1pLnN4X3RvX3Z4KEgpLFk9aS5zeV90b192eShYKSksUT17aW5kZXg6eSxzZWdtZW50X2luZGV4OnYseDp0dCx5OnJ0LHZ4Okssdnk6WixzeDokLHN5OlcsZGF0YV94OmMsZGF0YV95Ol8KfSxKLmFkZChVLFksdGhpcy5fcmVuZGVyX3Rvb2x0aXBzKG4seSxRKSk7cmV0dXJuIG51bGx9fSxlLnByb3RvdHlwZS5fZW1pdF9jYWxsYmFjaz1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsLHUsYzthPXRoaXMubWdldCgiY29tcHV0ZWRfcmVuZGVyZXJzIilbMF0saT10aGlzLnBsb3Rfdmlldy5yZW5kZXJlcl92aWV3c1thLmlkXS5oaXRfdGVzdCh0KSxyPXRoaXMucGxvdF9tb2RlbC5jYW52YXMsbz10aGlzLnBsb3RfbW9kZWwuZnJhbWUsdC5zeD1yLnZ4X3RvX3N4KHQudngpLHQuc3k9ci52eV90b19zeSh0LnZ5KSx1PW8uZ2V0KCJ4X21hcHBlcnMiKVthLmdldCgieF9yYW5nZV9uYW1lIildLGM9by5nZXQoInlfbWFwcGVycyIpW2EuZ2V0KCJ5X3JhbmdlX25hbWUiKV0sdC54PXUubWFwX2Zyb21fdGFyZ2V0KHQudngpLHQueT1jLm1hcF9mcm9tX3RhcmdldCh0LnZ5KSxlPXRoaXMubW9kZWwuY2FsbGJhY2ssbD1bZSx7aW5kZXg6aSxnZW9tZXRyeTp0fV0scz1sWzBdLG49bFsxXSxoLmlzRnVuY3Rpb24oZSk/ZShzLG4pOmUuZXhlY3V0ZShzLG4pfSxlLnByb3RvdHlwZS5fcmVuZGVyX3Rvb2x0aXBzPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbyxpLHMsYSxsLHAsXyxkLGYsbSxnLHksdixiLHgsdyxNLGs7aWYoTT10aGlzLm1nZXQoInRvb2x0aXBzIiksaC5pc1N0cmluZyhNKSlyZXR1cm4gbigiPGRpdj4iKS5odG1sKHUucmVwbGFjZV9wbGFjZWhvbGRlcnMoTSx0LGUscikpO2lmKGguaXNGdW5jdGlvbihNKSlyZXR1cm4gTSh0LHIpO2Zvcih4PW4oIjx0YWJsZT48L3RhYmxlPiIpLGw9MCxfPU0ubGVuZ3RoO2w8XztsKyspe2lmKG09TVtsXSxwPW1bMF0saz1tWzFdLHk9bigiPHRyPjwvdHI+IikseS5hcHBlbmQobigiPHRkIGNsYXNzPSdiay10b29sdGlwLXJvdy1sYWJlbCc+IikudGV4dChwKyI6ICIpKSx3PW4oIjx0ZCBjbGFzcz0nYmstdG9vbHRpcC1yb3ctdmFsdWUnPjwvdGQ+Iiksay5pbmRleE9mKCIkY29sb3IiKT49MCl7aWYoZz1rLm1hdGNoKC9cJGNvbG9yKFxbLipcXSk/OihcdyopLyksZD1nWzBdLGY9Z1sxXSxvPWdbMl0scz10LmdldF9jb2x1bW4obyksbnVsbD09cyl7dj1uKCI8c3Bhbj4iKS50ZXh0KG8rIiB1bmtub3duIiksdy5hcHBlbmQodik7Y29udGludWV9aWYoYT0obnVsbCE9Zj9mLmluZGV4T2YoImhleCIpOnZvaWQgMCk+PTAsYj0obnVsbCE9Zj9mLmluZGV4T2YoInN3YXRjaCIpOnZvaWQgMCk+PTAsaT1zW2VdLG51bGw9PWkpe3Y9bigiPHNwYW4+KG51bGwpPC9zcGFuPiIpLHcuYXBwZW5kKHYpO2NvbnRpbnVlfWEmJihpPWMoaSkpLHY9bigiPHNwYW4+IikudGV4dChpKSx3LmFwcGVuZCh2KSxiJiYodj1uKCI8c3BhbiBjbGFzcz0nYmstdG9vbHRpcC1jb2xvci1ibG9jayc+IDwvc3Bhbj4iKSx2LmNzcyh7YmFja2dyb3VuZENvbG9yOml9KSksdy5hcHBlbmQodil9ZWxzZSBrPWsucmVwbGFjZSgiJH4iLCIkZGF0YV8iKSxrPXUucmVwbGFjZV9wbGFjZWhvbGRlcnMoayx0LGUsciksdy5hcHBlbmQobigiPHNwYW4+IikuaHRtbChrKSk7eS5hcHBlbmQodykseC5hcHBlbmQoeSl9cmV0dXJuIHh9LGV9KGEuVmlldyksaT1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gZihlLHQpLGUucHJvdG90eXBlLmRlZmF1bHRfdmlldz1zLGUucHJvdG90eXBlLnR5cGU9IkhvdmVyVG9vbCIsZS5wcm90b3R5cGUudG9vbF9uYW1lPSJIb3ZlciBUb29sIixlLnByb3RvdHlwZS5pY29uPSJiay10b29sLWljb24taG92ZXIiLGUuZGVmaW5lKHt0b29sdGlwczpbZC5BbnksW1siaW5kZXgiLCIkaW5kZXgiXSxbImRhdGEgKHgsIHkpIiwiKCR4LCAkeSkiXSxbImNhbnZhcyAoeCwgeSkiLCIoJHN4LCAkc3kpIl1dXSxyZW5kZXJlcnM6W2QuQXJyYXksW11dLG5hbWVzOltkLkFycmF5LFtdXSxtb2RlOltkLlN0cmluZywibW91c2UiXSxwb2ludF9wb2xpY3k6W2QuU3RyaW5nLCJzbmFwX3RvX2RhdGEiXSxsaW5lX3BvbGljeTpbZC5TdHJpbmcsInByZXYiXSxzaG93X2Fycm93OltkLkJvb2xlYW4sITBdLGFuY2hvcjpbZC5TdHJpbmcsImNlbnRlciJdLGF0dGFjaG1lbnQ6W2QuU3RyaW5nLCJob3Jpem9udGFsIl0sY2FsbGJhY2s6W2QuQW55XX0pLGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgiY29tcHV0ZWRfcmVuZGVyZXJzIixmdW5jdGlvbigpe3ZhciB0LGUscixuO3JldHVybiBuPXRoaXMuZ2V0KCJyZW5kZXJlcnMiKSxlPXRoaXMuZ2V0KCJuYW1lcyIpLDA9PT1uLmxlbmd0aCYmKHQ9dGhpcy5nZXQoInBsb3QiKS5nZXQoInJlbmRlcmVycyIpLG49ZnVuY3Rpb24oKXt2YXIgZSxuLGk7Zm9yKGk9W10sZT0wLG49dC5sZW5ndGg7ZTxuO2UrKylyPXRbZV0sciBpbnN0YW5jZW9mIG8uTW9kZWwmJmkucHVzaChyKTtyZXR1cm4gaX0oKSksZS5sZW5ndGg+MCYmKG49ZnVuY3Rpb24oKXt2YXIgdCxvLGk7Zm9yKGk9W10sdD0wLG89bi5sZW5ndGg7dDxvO3QrKylyPW5bdF0sZS5pbmRleE9mKHIuZ2V0KCJuYW1lIikpPj0wJiZpLnB1c2gocik7cmV0dXJuIGl9KCkpLG59LCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoImNvbXB1dGVkX3JlbmRlcmVycyIsdGhpcyxbInJlbmRlcmVycyIsIm5hbWVzIiwicGxvdCJdKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoImNvbXB1dGVkX3JlbmRlcmVycyIsdGhpcy5nZXQoInBsb3QiKSxbInJlbmRlcmVycyJdKSx0aGlzLmRlZmluZV9jb21wdXRlZF9wcm9wZXJ0eSgidHRtb2RlbHMiLGZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLHM7aWYocz17fSxpPXRoaXMuZ2V0KCJ0b29sdGlwcyIpLG51bGwhPWkpZm9yKG49dGhpcy5nZXQoImNvbXB1dGVkX3JlbmRlcmVycyIpLHQ9MCxlPW4ubGVuZ3RoO3Q8ZTt0Kyspcj1uW3RdLG89bmV3IGwuTW9kZWwoe2N1c3RvbTpoLmlzU3RyaW5nKGkpfHxoLmlzRnVuY3Rpb24oaSksYXR0YWNobWVudDp0aGlzLmF0dGFjaG1lbnQsc2hvd19hcnJvdzp0aGlzLnNob3dfYXJyb3d9KSxzW3IuaWRdPW87cmV0dXJuIHN9LCEwKSx0aGlzLmFkZF9kZXBlbmRlbmNpZXMoInR0bW9kZWxzIix0aGlzLFsiY29tcHV0ZWRfcmVuZGVyZXJzIiwidG9vbHRpcHMiXSksdGhpcy5vdmVycmlkZV9jb21wdXRlZF9wcm9wZXJ0eSgic3ludGhldGljX3JlbmRlcmVycyIsZnVuY3Rpb24oKXtyZXR1cm4gaC52YWx1ZXModGhpcy5nZXQoInR0bW9kZWxzIikpfSwhMCksdGhpcy5hZGRfZGVwZW5kZW5jaWVzKCJzeW50aGV0aWNfcmVuZGVyZXJzIix0aGlzLFsidHRtb2RlbHMiXSl9LGV9KGEuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6aSxWaWV3OnN9fSx7Ii4uLy4uLy4uL2NvbW1vbi9oaXR0ZXN0IjoiY29tbW9uL2hpdHRlc3QiLCIuLi8uLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi8uLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi8uLi91dGlsL3V0aWwiOiJ1dGlsL3V0aWwiLCIuLi8uLi9hbm5vdGF0aW9ucy90b29sdGlwIjoibW9kZWxzL2Fubm90YXRpb25zL3Rvb2x0aXAiLCIuLi8uLi9yZW5kZXJlcnMvZ2x5cGhfcmVuZGVyZXIiOiJtb2RlbHMvcmVuZGVyZXJzL2dseXBoX3JlbmRlcmVyIiwiLi9pbnNwZWN0X3Rvb2wiOiJtb2RlbHMvdG9vbHMvaW5zcGVjdG9ycy9pbnNwZWN0X3Rvb2wiLGpxdWVyeToianF1ZXJ5Iix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdG9vbHMvaW5zcGVjdG9ycy9pbnNwZWN0X3Rvb2wiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaD1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYy5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxjPXt9Lmhhc093blByb3BlcnR5O2w9dCgidW5kZXJzY29yZSIpLG49dCgiYmFja2JvbmUiKSxhPXQoIi4uL3Rvb2wiKSx1PXQoIi4vaW5zcGVjdF90b29sX2xpc3RfaXRlbV90ZW1wbGF0ZSIpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5jbGFzc05hbWU9ImJrLXRvb2xiYXItaW5zcGVjdG9yIixlLnByb3RvdHlwZS50ZW1wbGF0ZT11LGUucHJvdG90eXBlLmV2ZW50cz17J2NsaWNrIFt0eXBlPSJjaGVja2JveCJdJzoiX2NsaWNrZWQifSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmxpc3RlblRvKHRoaXMubW9kZWwsImNoYW5nZTphY3RpdmUiLHRoaXMucmVuZGVyKSx0aGlzLnJlbmRlcigpfSxlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4kZWwuaHRtbCh0aGlzLnRlbXBsYXRlKHttb2RlbDp0aGlzLm1vZGVsfSkpLHRoaXN9LGUucHJvdG90eXBlLl9jbGlja2VkPWZ1bmN0aW9uKHQpe3ZhciBlO3JldHVybiBlPXRoaXMubW9kZWwuZ2V0KCJhY3RpdmUiKSx0aGlzLm1vZGVsLnNldCgiYWN0aXZlIiwhZSl9LGV9KG4uVmlldykscz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGV9KGEuVmlldyksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gaChlLHQpLGUucHJvdG90eXBlLmV2ZW50X3R5cGU9Im1vdmUiLGUub3ZlcnJpZGUoe2FjdGl2ZTohMH0pLGUucHJvdG90eXBlLmJpbmRfYm9rZWhfZXZlbnRzPWZ1bmN0aW9uKCl7cmV0dXJuIGUuX19zdXBlcl9fLmJpbmRfYm9rZWhfZXZlbnRzLmNhbGwodGhpcyksdGhpcy5saXN0ZW5UbyhldmVudHMsIm1vdmUiLHRoaXMuX2luc3BlY3QpfSxlLnByb3RvdHlwZS5faW5zcGVjdD1mdW5jdGlvbih0LGUscil7fSxlLnByb3RvdHlwZS5fZXhpdF9pbm5lcj1mdW5jdGlvbigpe30sZS5wcm90b3R5cGUuX2V4aXRfb3V0ZXI9ZnVuY3Rpb24oKXt9LGV9KGEuTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6byxWaWV3OnMsTGlzdEl0ZW1WaWV3Oml9fSx7Ii4uL3Rvb2wiOiJtb2RlbHMvdG9vbHMvdG9vbCIsIi4vaW5zcGVjdF90b29sX2xpc3RfaXRlbV90ZW1wbGF0ZSI6Im1vZGVscy90b29scy9pbnNwZWN0b3JzL2luc3BlY3RfdG9vbF9saXN0X2l0ZW1fdGVtcGxhdGUiLGJhY2tib25lOiJiYWNrYm9uZSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3Rvb2xzL2luc3BlY3RvcnMvaW5zcGVjdF90b29sX2xpc3RfaXRlbV90ZW1wbGF0ZSI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9ZnVuY3Rpb24odCl7dHx8KHQ9e30pO3ZhciBlPVtdLHI9ZnVuY3Rpb24odCl7cmV0dXJuIHQmJnQuZWNvU2FmZT90OiJ1bmRlZmluZWQiIT10eXBlb2YgdCYmbnVsbCE9dD9uKHQpOiIifSxuPWZ1bmN0aW9uKHQpe3JldHVybigiIit0KS5yZXBsYWNlKC8mL2csIiZhbXA7IikucmVwbGFjZSgvPC9nLCImbHQ7IikucmVwbGFjZSgvPi9nLCImZ3Q7IikucmVwbGFjZSgvIi9nLCImcXVvdDsiKX07cmV0dXJuIGZ1bmN0aW9uKCl7KGZ1bmN0aW9uKCl7ZS5wdXNoKCc8aW5wdXQgdHlwZT0iY2hlY2tib3giICcpLHRoaXMubW9kZWwuYWN0aXZlJiZlLnB1c2goImNoZWNrZWQiKSxlLnB1c2goIj4iKSxlLnB1c2gocih0aGlzLm1vZGVsLnRvb2xfbmFtZSkpLGUucHVzaCgiPC9pbnB1dD5cbiIpfSkuY2FsbCh0aGlzKX0uY2FsbCh0KSxlLmpvaW4oIiIpfX0se31dLCJtb2RlbHMvdG9vbHMvdG9vbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSljLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LGM9e30uaGFzT3duUHJvcGVydHk7YT10KCJ1bmRlcnNjb3JlIiksbz10KCIuLi9yZW5kZXJlcnMvcmVuZGVyZXIiKSxsPXQoIi4uLy4uL2NvcmUvbG9nZ2luZyIpLmxvZ2dlcix1PXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG49dCgiLi4vLi4vbW9kZWwiKSxzPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBoKGUsdCksZS5wcm90b3R5cGUuYmluZF9ib2tlaF9ldmVudHM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5saXN0ZW5Ubyh0aGlzLm1vZGVsLCJjaGFuZ2U6YWN0aXZlIixmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdC5tZ2V0KCJhY3RpdmUiKT90LmFjdGl2YXRlKCk6dC5kZWFjdGl2YXRlKCl9fSh0aGlzKSl9LGUucHJvdG90eXBlLmFjdGl2YXRlPWZ1bmN0aW9uKCl7fSxlLnByb3RvdHlwZS5kZWFjdGl2YXRlPWZ1bmN0aW9uKCl7fSxlfShvLlZpZXcpLGk9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGgoZSx0KSxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQscil7cmV0dXJuIGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQsciksdGhpcy5kZWZpbmVfY29tcHV0ZWRfcHJvcGVydHkoInN5bnRoZXRpY19yZW5kZXJlcnMiLGZ1bmN0aW9uKCl7cmV0dXJuW119LCEwKX0sZS5kZWZpbmUoe3Bsb3Q6W3UuSW5zdGFuY2VdfSksZS5pbnRlcm5hbCh7bGV2ZWw6W3UuUmVuZGVyTGV2ZWwsIm92ZXJsYXkiXSxhY3RpdmU6W3UuQm9vbGVhbiwhMV19KSxlLnByb3RvdHlwZS5fY2hlY2tfZGltcz1mdW5jdGlvbih0LGUpe3ZhciByLG4sbztyZXR1cm4gbj1bITEsITFdLG89blswXSxyPW5bMV0sMD09PXQubGVuZ3RoP2wud2FybihlKyIgZ2l2ZW4gZW1wdHkgZGltZW5zaW9ucyIpOjE9PT10Lmxlbmd0aD8id2lkdGgiIT09dFswXSYmImhlaWdodCIhPT10WzBdJiZsLndhcm4oZSsiIGdpdmVuIHVucmVjb2duaXplZCBkaW1lbnNpb25zOiAiK3QpOjI9PT10Lmxlbmd0aD8odC5pbmRleE9mKCJ3aWR0aCIpPDB8fHQuaW5kZXhPZigiaGVpZ2h0Iik8MCkmJmwud2FybihlKyIgZ2l2ZW4gdW5yZWNvZ25pemVkIGRpbWVuc2lvbnM6ICIrdCk6bC53YXJuKGUrIiBnaXZlbiBtb3JlIHRoYW4gdHdvIGRpbWVuc2lvbnM6ICIrdCksdC5pbmRleE9mKCJ3aWR0aCIpPj0wJiYobz0hMCksdC5pbmRleE9mKCJoZWlnaHQiKT49MCYmKHI9ITApLFtvLHJdfSxlLnByb3RvdHlwZS5fZ2V0X2RpbV90b29sdGlwPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbjtyZXR1cm4gbj1lWzBdLHI9ZVsxXSxuJiYhcj90KyIgKHgtYXhpcykiOnImJiFuP3QrIiAoeS1heGlzKSI6dH0sZS5wcm90b3R5cGUuX2dldF9kaW1fbGltaXRzPWZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBvLGkscyxsLHUsaCxjLHA7cmV0dXJuIHM9dFswXSxoPXRbMV0sbD1lWzBdLGM9ZVsxXSxvPXIuZ2V0KCJoX3JhbmdlIiksbi5pbmRleE9mKCJ3aWR0aCIpPj0wPyh1PVthLm1pbihbcyxsXSksYS5tYXgoW3MsbF0pXSx1PVthLm1heChbdVswXSxvLmdldCgibWluIildKSxhLm1pbihbdVsxXSxvLmdldCgibWF4IildKV0pOnU9W28uZ2V0KCJtaW4iKSxvLmdldCgibWF4IildLGk9ci5nZXQoInZfcmFuZ2UiKSxuLmluZGV4T2YoImhlaWdodCIpPj0wPyhwPVthLm1pbihbaCxjXSksYS5tYXgoW2gsY10pXSxwPVthLm1heChbcFswXSxpLmdldCgibWluIildKSxhLm1pbihbcFsxXSxpLmdldCgibWF4IildKV0pOnA9W2kuZ2V0KCJtaW4iKSxpLmdldCgibWF4IildLFt1LHBdfSxlfShuKSxlLmV4cG9ydHM9e01vZGVsOmksVmlldzpzfX0seyIuLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi8uLi9tb2RlbCI6Im1vZGVsIiwiLi4vcmVuZGVyZXJzL3JlbmRlcmVyIjoibW9kZWxzL3JlbmRlcmVycy9yZW5kZXJlciIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3Rvb2xzL3Rvb2xfcHJveHkiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHM9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWEuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sYT17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoIi4uLy4uL2NvcmUvcHJvcGVydGllcyIpLG49dCgiLi4vLi4vbW9kZWwiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBzKGUsdCksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy5saXN0ZW5Ubyh0aGlzLCJkbyIsdGhpc1siZG8iXSksdGhpcy5saXN0ZW5Ubyh0aGlzLCJjaGFuZ2U6YWN0aXZlIix0aGlzLnNldF9hY3RpdmUpfSxlLnByb3RvdHlwZVsiZG8iXT1mdW5jdGlvbigpe3ZhciB0LGUscixuO2ZvcihyPXRoaXMudG9vbHMsdD0wLGU9ci5sZW5ndGg7dDxlO3QrKyluPXJbdF0sbi50cmlnZ2VyKCJkbyIpO3JldHVybiBudWxsfSxlLnByb3RvdHlwZS5zZXRfYWN0aXZlPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG47Zm9yKHI9dGhpcy50b29scyx0PTAsZT1yLmxlbmd0aDt0PGU7dCsrKW49clt0XSxuLmFjdGl2ZT10aGlzLmFjdGl2ZTtyZXR1cm4gbnVsbH0sZS5kZWZpbmUoe3Rvb2xzOltpLkFycmF5LFtdXSxhY3RpdmU6W2kuQm9vbCwhMV0sdG9vbHRpcDpbaS5TdHJpbmddLHRvb2xfbmFtZTpbaS5TdHJpbmddLGRpc2FibGVkOltpLkJvb2wsITFdLGV2ZW50X3R5cGU6W2kuU3RyaW5nXSxpY29uOltpLlN0cmluZ119KSxlLnByb3RvdHlwZS5fY2xpY2tlZD1mdW5jdGlvbigpe3ZhciB0O3JldHVybiB0PXRoaXMubW9kZWwuZ2V0KCJhY3RpdmUiKSx0aGlzLm1vZGVsLnNldCgiYWN0aXZlIiwhdCl9LGV9KG4pLGUuZXhwb3J0cz17VG9vbFByb3h5Om99fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4uLy4uL21vZGVsIjoibW9kZWwifV0sIm1vZGVscy90b29scy90b29sYmFyIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYz1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpcC5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxwPXt9Lmhhc093blByb3BlcnR5O3U9dCgidW5kZXJzY29yZSIpLGg9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksbj10KCIuL2FjdGlvbnMvYWN0aW9uX3Rvb2wiKSxpPXQoIi4vYWN0aW9ucy9oZWxwX3Rvb2wiKSxvPXQoIi4vZ2VzdHVyZXMvZ2VzdHVyZV90b29sIikscz10KCIuL2luc3BlY3RvcnMvaW5zcGVjdF90b29sIiksbD10KCIuL3Rvb2xiYXJfYmFzZSIpLGE9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGMoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJUb29sYmFyIixlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9bC5WaWV3LGUucHJvdG90eXBlLmluaXRpYWxpemU9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCxyKSx0aGlzLmxpc3RlblRvKHRoaXMsImNoYW5nZTp0b29scyIsdGhpcy5faW5pdF90b29scyksdGhpcy5faW5pdF90b29scygpfSxlLnByb3RvdHlwZS5faW5pdF90b29scz1mdW5jdGlvbigpe3ZhciB0LGUscixhLGwsaCxjO2ZvcihhPXRoaXMuZ2V0KCJ0b29scyIpLGU9MCxyPWEubGVuZ3RoO2U8cjtlKyspaWYoaD1hW2VdLGggaW5zdGFuY2VvZiBzLk1vZGVsKXUuc29tZSh0aGlzLmluc3BlY3RvcnMsZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkPT09aC5pZH19KHRoaXMpKXx8KHRoaXMuaW5zcGVjdG9ycz10aGlzLmluc3BlY3RvcnMuY29uY2F0KFtoXSkpO2Vsc2UgaWYoaCBpbnN0YW5jZW9mIGkuTW9kZWwpdS5zb21lKHRoaXMuaGVscCxmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24odCl7cmV0dXJuIHQuaWQ9PT1oLmlkfX0odGhpcykpfHwodGhpcy5oZWxwPXRoaXMuaGVscC5jb25jYXQoW2hdKSk7ZWxzZSBpZihoIGluc3RhbmNlb2Ygbi5Nb2RlbCl1LnNvbWUodGhpcy5hY3Rpb25zLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbih0KXtyZXR1cm4gdC5pZD09PWguaWR9fSh0aGlzKSl8fCh0aGlzLmFjdGlvbnM9dGhpcy5hY3Rpb25zLmNvbmNhdChbaF0pKTtlbHNlIGlmKGggaW5zdGFuY2VvZiBvLk1vZGVsKXtpZih0PWguZXZlbnRfdHlwZSwhKHQgaW4gdGhpcy5nZXN0dXJlcykpe2xvZ2dlci53YXJuKCJUb29sYmFyOiB1bmtub3duIGV2ZW50IHR5cGUgJyIrdCsiJyBmb3IgdG9vbDogIitoLnR5cGUrIiAoIitoLmlkKyIpIik7Y29udGludWV9dS5zb21lKHRoaXMuZ2VzdHVyZXNbdF0udG9vbHMsZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkPT09aC5pZH19KHRoaXMpKXx8KHRoaXMuZ2VzdHVyZXNbdF0udG9vbHM9dGhpcy5nZXN0dXJlc1t0XS50b29scy5jb25jYXQoW2hdKSksdGhpcy5saXN0ZW5UbyhoLCJjaGFuZ2U6YWN0aXZlIix1LmJpbmQodGhpcy5fYWN0aXZlX2NoYW5nZSxoKSl9bD1bXTtmb3IodCBpbiB0aGlzLmdlc3R1cmVzKWlmKGM9dGhpcy5nZXN0dXJlc1t0XS50b29scywwIT09Yy5sZW5ndGgpe2lmKHRoaXMuZ2VzdHVyZXNbdF0udG9vbHM9dS5zb3J0QnkoYyxmdW5jdGlvbih0KXtyZXR1cm4gdC5kZWZhdWx0X29yZGVyfSksInRhcCI9PT10KXtpZihudWxsPT09dGhpcy5hY3RpdmVfdGFwKWNvbnRpbnVlOyJhdXRvIj09PXRoaXMuYWN0aXZlX3RhcD90aGlzLmdlc3R1cmVzW3RdLnRvb2xzWzBdLmFjdGl2ZT0hMDp0aGlzLmFjdGl2ZV90YXAuYWN0aXZlPSEwfWlmKCJwYW4iPT09dCl7aWYobnVsbD09PXRoaXMuYWN0aXZlX2RyYWcpY29udGludWU7ImF1dG8iPT09dGhpcy5hY3RpdmVfZHJhZz90aGlzLmdlc3R1cmVzW3RdLnRvb2xzWzBdLmFjdGl2ZT0hMDp0aGlzLmFjdGl2ZV9kcmFnLmFjdGl2ZT0hMH1pZigicGluY2giPT09dHx8InNjcm9sbCI9PT10KXtpZihudWxsPT09dGhpcy5hY3RpdmVfc2Nyb2xsfHwiYXV0byI9PT10aGlzLmFjdGl2ZV9zY3JvbGwpY29udGludWU7bC5wdXNoKHRoaXMuYWN0aXZlX3Njcm9sbC5hY3RpdmU9ITApfWVsc2UgbC5wdXNoKHZvaWQgMCl9cmV0dXJuIGx9LGUuZGVmaW5lKHthY3RpdmVfZHJhZzpbaC5BbnksImF1dG8iXSxhY3RpdmVfc2Nyb2xsOltoLkFueSwiYXV0byJdLGFjdGl2ZV90YXA6W2guQW55LCJhdXRvIl19KSxlfShsLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOmF9fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vYWN0aW9ucy9hY3Rpb25fdG9vbCI6Im1vZGVscy90b29scy9hY3Rpb25zL2FjdGlvbl90b29sIiwiLi9hY3Rpb25zL2hlbHBfdG9vbCI6Im1vZGVscy90b29scy9hY3Rpb25zL2hlbHBfdG9vbCIsIi4vZ2VzdHVyZXMvZ2VzdHVyZV90b29sIjoibW9kZWxzL3Rvb2xzL2dlc3R1cmVzL2dlc3R1cmVfdG9vbCIsIi4vaW5zcGVjdG9ycy9pbnNwZWN0X3Rvb2wiOiJtb2RlbHMvdG9vbHMvaW5zcGVjdG9ycy9pbnNwZWN0X3Rvb2wiLCIuL3Rvb2xiYXJfYmFzZSI6Im1vZGVscy90b29scy90b29sYmFyX2Jhc2UiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90b29scy90b29sYmFyX2Jhc2UiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdj1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYi5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxiPXt9Lmhhc093blByb3BlcnR5LHg9ZnVuY3Rpb24odCxlKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdC5hcHBseShlLGFyZ3VtZW50cyl9fTtkPXQoInVuZGVyc2NvcmUiKSxuPXQoImpxdWVyeSIpLG89dCgiYm9vdHN0cmFwL2Ryb3Bkb3duIiksZj10KCIuLi8uLi9jb3JlL2xvZ2dpbmciKS5sb2dnZXIsZz10KCIuLi8uLi9jb3JlL2xheW91dC9zb2x2ZXIiKSxzPWcuRVEsXz1nLlZhcmlhYmxlLG09dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksaD10KCIuLi9sYXlvdXRzL2xheW91dF9kb20iKSxpPXQoIi4vYWN0aW9ucy9hY3Rpb25fdG9vbCIpLGw9dCgiLi9hY3Rpb25zL2hlbHBfdG9vbCIpLGE9dCgiLi9nZXN0dXJlcy9nZXN0dXJlX3Rvb2wiKSx1PXQoIi4vaW5zcGVjdG9ycy9pbnNwZWN0X3Rvb2wiKSx5PXQoIi4vdG9vbGJhcl90ZW1wbGF0ZSIpLHA9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIHYoZSx0KSxlLnByb3RvdHlwZS5jbGFzc05hbWU9ImJrLXRvb2xiYXItd3JhcHBlciIsZS5wcm90b3R5cGUudGVtcGxhdGU9eSxlLnByb3RvdHlwZS5yZW5kZXI9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbyxzLGwsaCxjOyJmaXhlZCIhPT10aGlzLm1vZGVsLnNpemluZ19tb2RlJiZ0aGlzLiRlbC5jc3Moe2xlZnQ6dGhpcy5tb2RlbC5fZG9tX2xlZnQuX3ZhbHVlLHRvcDp0aGlzLm1vZGVsLl9kb21fdG9wLl92YWx1ZSx3aWR0aDp0aGlzLm1vZGVsLl93aWR0aC5fdmFsdWUsaGVpZ2h0OnRoaXMubW9kZWwuX2hlaWdodC5fdmFsdWV9KSxsPW51bGwhPXRoaXMubW9kZWwudG9vbGJhcl9sb2NhdGlvbj90aGlzLm1vZGVsLnRvb2xiYXJfbG9jYXRpb246ImFib3ZlIixoPXRoaXMubW9kZWwudG9vbGJhcl9zdGlja3k9PT0hMD8ic3RpY2t5Ijoibm90LXN0aWNreSIsdGhpcy4kZWwuaHRtbCh0aGlzLnRlbXBsYXRlKHtsb2dvOnRoaXMubWdldCgibG9nbyIpLGxvY2F0aW9uOmwsc3RpY2t5Omh9KSkscz10aGlzLm1vZGVsLmdldCgiaW5zcGVjdG9ycyIpLGU9dGhpcy4kKCIuYmstYnMtZHJvcGRvd25bdHlwZT0naW5zcGVjdG9ycyddIiksMD09PXMubGVuZ3RoP2UuaGlkZSgpOih0PW4oJzxhIGhyZWY9IiMiIGRhdGEtYmstYnMtdG9nZ2xlPSJkcm9wZG93biIgY2xhc3M9ImJrLWJzLWRyb3Bkb3duLXRvZ2dsZSI+aW5zcGVjdCA8c3BhbiBjbGFzcz0iYmstYnMtY2FyZXQiPjwvYT4nKSx0LmFwcGVuZFRvKGUpLGM9bignPHVsIGNsYXNzPSJiay1icy1kcm9wZG93bi1tZW51IiAvPicpLGQuZWFjaChzLGZ1bmN0aW9uKHQpe3ZhciBlO3JldHVybiBlPW4oIjxsaSAvPiIpLGUuYXBwZW5kKG5ldyB1Lkxpc3RJdGVtVmlldyh7bW9kZWw6dH0pLmVsKSxlLmFwcGVuZFRvKGMpfSksYy5vbigiY2xpY2siLGZ1bmN0aW9uKHQpe3JldHVybiB0LnN0b3BQcm9wYWdhdGlvbigpfSksYy5hcHBlbmRUbyhlKSx0LmRyb3Bkb3duKCkpLGU9dGhpcy4kKCIuYmstYnV0dG9uLWJhci1saXN0W3R5cGU9J2hlbHAnXSIpLGQuZWFjaCh0aGlzLm1vZGVsLmdldCgiaGVscCIpLGZ1bmN0aW9uKHQpe3JldHVybiBlLmFwcGVuZChuZXcgaS5CdXR0b25WaWV3KHttb2RlbDp0fSkuZWwpfSksZT10aGlzLiQoIi5iay1idXR0b24tYmFyLWxpc3RbdHlwZT0nYWN0aW9ucyddIiksZC5lYWNoKHRoaXMubW9kZWwuZ2V0KCJhY3Rpb25zIiksZnVuY3Rpb24odCl7cmV0dXJuIGUuYXBwZW5kKG5ldyBpLkJ1dHRvblZpZXcoe21vZGVsOnR9KS5lbCl9KSxvPXRoaXMubW9kZWwuZ2V0KCJnZXN0dXJlcyIpO2ZvcihyIGluIG8pZT10aGlzLiQoIi5iay1idXR0b24tYmFyLWxpc3RbdHlwZT0nIityKyInXSIpLGQuZWFjaChvW3JdLnRvb2xzLGZ1bmN0aW9uKHQpe3JldHVybiBlLmFwcGVuZChuZXcgYS5CdXR0b25WaWV3KHttb2RlbDp0fSkuZWwpfSk7cmV0dXJuIHRoaXN9LGV9KGguVmlldyksYz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIHRoaXMuX2FjdGl2ZV9jaGFuZ2U9eCh0aGlzLl9hY3RpdmVfY2hhbmdlLHRoaXMpLGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gdihlLHQpLGUucHJvdG90eXBlLnR5cGU9IlRvb2xiYXJCYXNlIixlLnByb3RvdHlwZS5kZWZhdWx0X3ZpZXc9cCxlLnByb3RvdHlwZS5fYWN0aXZlX2NoYW5nZT1mdW5jdGlvbih0KXt2YXIgZSxyLG47cmV0dXJuIHI9dC5ldmVudF90eXBlLG49dGhpcy5nZXQoImdlc3R1cmVzIiksZT1uW3JdLmFjdGl2ZSxudWxsIT1lJiZlIT09dCYmKGYuZGVidWcoIlRvb2xiYXI6IGRlYWN0aXZhdGluZyB0b29sOiAiK2UudHlwZSsiICgiK2UuaWQrIikgZm9yIGV2ZW50IHR5cGUgJyIrcisiJyIpLGUuc2V0KCJhY3RpdmUiLCExKSksbltyXS5hY3RpdmU9dCx0aGlzLnNldCgiZ2VzdHVyZXMiLG4pLGYuZGVidWcoIlRvb2xiYXI6IGFjdGl2YXRpbmcgdG9vbDogIit0LnR5cGUrIiAoIit0LmlkKyIpIGZvciBldmVudCB0eXBlICciK3IrIiciKSxudWxsfSxlLnByb3RvdHlwZS5nZXRfY29uc3RyYWludHM9ZnVuY3Rpb24oKXt2YXIgdDtyZXR1cm4gdD1lLl9fc3VwZXJfXy5nZXRfY29uc3RyYWludHMuY2FsbCh0aGlzKSx0LnB1c2gocyh0aGlzLl9zaXplYWJsZSwtMzApKSx0fSxlLmRlZmluZSh7dG9vbHM6W20uQXJyYXksW11dLGxvZ286W20uU3RyaW5nLCJub3JtYWwiXX0pLGUuaW50ZXJuYWwoe2dlc3R1cmVzOlttLkFueSxmdW5jdGlvbigpe3JldHVybntwYW46e3Rvb2xzOltdLGFjdGl2ZTpudWxsfSx0YXA6e3Rvb2xzOltdLGFjdGl2ZTpudWxsfSxkb3VibGV0YXA6e3Rvb2xzOltdLGFjdGl2ZTpudWxsfSxzY3JvbGw6e3Rvb2xzOltdLGFjdGl2ZTpudWxsfSxwaW5jaDp7dG9vbHM6W10sYWN0aXZlOm51bGx9LHByZXNzOnt0b29sczpbXSxhY3RpdmU6bnVsbH0scm90YXRlOnt0b29sczpbXSxhY3RpdmU6bnVsbH19fV0sYWN0aW9uczpbbS5BcnJheSxbXV0saW5zcGVjdG9yczpbbS5BcnJheSxbXV0saGVscDpbbS5BcnJheSxbXV0sdG9vbGJhcl9sb2NhdGlvbjpbbS5Mb2NhdGlvbiwicmlnaHQiXSx0b29sYmFyX3N0aWNreTpbbS5Cb29sXX0pLGUub3ZlcnJpZGUoe3NpemluZ19tb2RlOm51bGx9KSxlfShoLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOmMsVmlldzpwfX0seyIuLi8uLi9jb3JlL2xheW91dC9zb2x2ZXIiOiJjb3JlL2xheW91dC9zb2x2ZXIiLCIuLi8uLi9jb3JlL2xvZ2dpbmciOiJjb3JlL2xvZ2dpbmciLCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiOiJjb3JlL3Byb3BlcnRpZXMiLCIuLi9sYXlvdXRzL2xheW91dF9kb20iOiJtb2RlbHMvbGF5b3V0cy9sYXlvdXRfZG9tIiwiLi9hY3Rpb25zL2FjdGlvbl90b29sIjoibW9kZWxzL3Rvb2xzL2FjdGlvbnMvYWN0aW9uX3Rvb2wiLCIuL2FjdGlvbnMvaGVscF90b29sIjoibW9kZWxzL3Rvb2xzL2FjdGlvbnMvaGVscF90b29sIiwiLi9nZXN0dXJlcy9nZXN0dXJlX3Rvb2wiOiJtb2RlbHMvdG9vbHMvZ2VzdHVyZXMvZ2VzdHVyZV90b29sIiwiLi9pbnNwZWN0b3JzL2luc3BlY3RfdG9vbCI6Im1vZGVscy90b29scy9pbnNwZWN0b3JzL2luc3BlY3RfdG9vbCIsIi4vdG9vbGJhcl90ZW1wbGF0ZSI6Im1vZGVscy90b29scy90b29sYmFyX3RlbXBsYXRlIiwiYm9vdHN0cmFwL2Ryb3Bkb3duIjoiYm9vdHN0cmFwL2Ryb3Bkb3duIixqcXVlcnk6ImpxdWVyeSIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwibW9kZWxzL3Rvb2xzL3Rvb2xiYXJfYm94IjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGEsbCx1LGgsYyxwLF8sZCxmPWZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSltLmNhbGwoZSxuKSYmKHRbbl09ZVtuXSk7cmV0dXJuIHIucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByLHQuX19zdXBlcl9fPWUucHJvdG90eXBlLHR9LG09e30uaGFzT3duUHJvcGVydHk7Xz10KCJ1bmRlcnNjb3JlIiksZD10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxuPXQoIi4vYWN0aW9ucy9hY3Rpb25fdG9vbCIpLHM9dCgiLi9hY3Rpb25zL2hlbHBfdG9vbCIpLGk9dCgiLi9nZXN0dXJlcy9nZXN0dXJlX3Rvb2wiKSxhPXQoIi4vaW5zcGVjdG9ycy9pbnNwZWN0X3Rvb2wiKSx1PXQoIi4vdG9vbGJhcl9iYXNlIiksbD10KCIuL3Rvb2xfcHJveHkiKS5Ub29sUHJveHksbz10KCIuLi9sYXlvdXRzL2JveCIpLGM9ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGYoZSx0KSxlLnByb3RvdHlwZS50eXBlPSJUb29sYmFyQm94VG9vbGJhciIsZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PXUuVmlldyxlLnByb3RvdHlwZS5pbml0aWFsaXplPWZ1bmN0aW9uKHQpe2lmKGUuX19zdXBlcl9fLmluaXRpYWxpemUuY2FsbCh0aGlzLHQpLHRoaXMuX2luaXRfdG9vbHMoKSx0aGlzLm1lcmdlX3Rvb2xzPT09ITApcmV0dXJuIHRoaXMuX21lcmdlX3Rvb2xzKCl9LGUuZGVmaW5lKHttZXJnZV90b29sczpbZC5Cb29sLCEwXX0pLGUucHJvdG90eXBlLl9pbml0X3Rvb2xzPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG8sbCx1O2ZvcihvPXRoaXMuZ2V0KCJ0b29scyIpLGw9W10sZT0wLHI9by5sZW5ndGg7ZTxyO2UrKyl1PW9bZV0sdSBpbnN0YW5jZW9mIGEuTW9kZWw/Xy5zb21lKHRoaXMuaW5zcGVjdG9ycyxmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24odCl7cmV0dXJuIHQuaWQ9PT11LmlkfX0odGhpcykpP2wucHVzaCh2b2lkIDApOmwucHVzaCh0aGlzLmluc3BlY3RvcnM9dGhpcy5pbnNwZWN0b3JzLmNvbmNhdChbdV0pKTp1IGluc3RhbmNlb2Ygcy5Nb2RlbD9fLnNvbWUodGhpcy5oZWxwLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbih0KXtyZXR1cm4gdC5pZD09PXUuaWR9fSh0aGlzKSk/bC5wdXNoKHZvaWQgMCk6bC5wdXNoKHRoaXMuaGVscD10aGlzLmhlbHAuY29uY2F0KFt1XSkpOnUgaW5zdGFuY2VvZiBuLk1vZGVsP18uc29tZSh0aGlzLmFjdGlvbnMsZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiB0LmlkPT09dS5pZH19KHRoaXMpKT9sLnB1c2godm9pZCAwKTpsLnB1c2godGhpcy5hY3Rpb25zPXRoaXMuYWN0aW9ucy5jb25jYXQoW3VdKSk6dSBpbnN0YW5jZW9mIGkuTW9kZWw/KHQ9dS5ldmVudF90eXBlLF8uc29tZSh0aGlzLmdlc3R1cmVzW3RdLnRvb2xzLGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbih0KXtyZXR1cm4gdC5pZD09PXUuaWR9fSh0aGlzKSk/bC5wdXNoKHZvaWQgMCk6bC5wdXNoKHRoaXMuZ2VzdHVyZXNbdF0udG9vbHM9dGhpcy5nZXN0dXJlc1t0XS50b29scy5jb25jYXQoW3VdKSkpOmwucHVzaCh2b2lkIDApO3JldHVybiBsfSxlLnByb3RvdHlwZS5fbWVyZ2VfdG9vbHM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLHUsaCxjLHAsZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTLHosUCxFLEE7Zm9yKHU9e30sdD17fSxvPXt9LHY9W10sYj1bXSx3PXRoaXMuaGVscCxzPTAsZD13Lmxlbmd0aDtzPGQ7cysrKWk9d1tzXSxfLmNvbnRhaW5zKGIsaS5yZWRpcmVjdCl8fCh2LnB1c2goaSksYi5wdXNoKGkucmVkaXJlY3QpKTt0aGlzLmhlbHA9dixNPXRoaXMuZ2VzdHVyZXM7Zm9yKG4gaW4gTSl7YT1NW25dLG4gaW4gb3x8KG9bbl09e30pLGs9YS50b29scztmb3IoaD0wLGY9ay5sZW5ndGg7aDxmO2grKylQPWtbaF0sUC50eXBlIGluIG9bbl18fChvW25dW1AudHlwZV09W10pLG9bbl1bUC50eXBlXS5wdXNoKFApfWZvcihqPXRoaXMuaW5zcGVjdG9ycyxjPTAsbT1qLmxlbmd0aDtjPG07YysrKVA9altjXSxQLnR5cGUgaW4gdXx8KHVbUC50eXBlXT1bXSksdVtQLnR5cGVdLnB1c2goUCk7Zm9yKFQ9dGhpcy5hY3Rpb25zLHA9MCxnPVQubGVuZ3RoO3A8ZztwKyspUD1UW3BdLFAudHlwZSBpbiB0fHwodFtQLnR5cGVdPVtdKSx0W1AudHlwZV0ucHVzaChQKTt5PWZ1bmN0aW9uKHQsZSl7cmV0dXJuIG51bGw9PWUmJihlPSExKSxuZXcgbCh7dG9vbHM6dCxldmVudF90eXBlOnRbMF0uZXZlbnRfdHlwZSx0b29sdGlwOnRbMF0udG9vbF9uYW1lLHRvb2xfbmFtZTp0WzBdLnRvb2xfbmFtZSxpY29uOnRbMF0uaWNvbixhY3RpdmU6ZX0pfTtmb3IobiBpbiBvKXt0aGlzLmdlc3R1cmVzW25dLnRvb2xzPVtdLFM9b1tuXTtmb3IoRSBpbiBTKUE9U1tFXSxBLmxlbmd0aD4wJiYoeD15KEEpLHRoaXMuZ2VzdHVyZXNbbl0udG9vbHMucHVzaCh4KSx0aGlzLmxpc3RlblRvKHgsImNoYW5nZTphY3RpdmUiLF8uYmluZCh0aGlzLl9hY3RpdmVfY2hhbmdlLHgpKSl9dGhpcy5hY3Rpb25zPVtdO2ZvcihFIGluIHQpQT10W0VdLEEubGVuZ3RoPjAmJnRoaXMuYWN0aW9ucy5wdXNoKHkoQSkpO3RoaXMuaW5zcGVjdG9ycz1bXTtmb3IoRSBpbiB1KUE9dVtFXSxBLmxlbmd0aD4wJiZ0aGlzLmluc3BlY3RvcnMucHVzaCh5KEEsZT0hMCkpO3o9W107Zm9yKHIgaW4gdGhpcy5nZXN0dXJlcylBPXRoaXMuZ2VzdHVyZXNbcl0udG9vbHMsMCE9PUEubGVuZ3RoJiYodGhpcy5nZXN0dXJlc1tyXS50b29scz1fLnNvcnRCeShBLGZ1bmN0aW9uKHQpe3JldHVybiB0LmRlZmF1bHRfb3JkZXJ9KSwicGluY2giIT09ciYmInNjcm9sbCIhPT1yP3oucHVzaCh0aGlzLmdlc3R1cmVzW3JdLnRvb2xzWzBdLnNldCgiYWN0aXZlIiwhMCkpOnoucHVzaCh2b2lkIDApKTtyZXR1cm4gen0sZX0odS5Nb2RlbCkscD1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gZihlLHQpLGUucHJvdG90eXBlLmNsYXNzTmFtZT0iYmstdG9vbGJhci1ib3giLGUucHJvdG90eXBlLmdldF93aWR0aD1mdW5jdGlvbigpe3JldHVybiB0aGlzLm1vZGVsLl9ob3Jpem9udGFsPT09ITA/MzA6bnVsbH0sZS5wcm90b3R5cGUuZ2V0X2hlaWdodD1mdW5jdGlvbigpe3JldHVybiAzMH0sZX0oby5WaWV3KSxoPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBmKGUsdCksZS5wcm90b3R5cGUudHlwZT0iVG9vbGJhckJveCIsZS5wcm90b3R5cGUuZGVmYXVsdF92aWV3PXAsZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0KXt2YXIgcjtyZXR1cm4gZS5fX3N1cGVyX18uaW5pdGlhbGl6ZS5jYWxsKHRoaXMsdCksdGhpcy5fdG9vbGJhcj1uZXcgYyh0KSwibGVmdCI9PT0ocj10aGlzLnRvb2xiYXJfbG9jYXRpb24pfHwicmlnaHQiPT09cj8odGhpcy5faG9yaXpvbnRhbD0hMCx0aGlzLl90b29sYmFyLl9zaXplYWJsZT10aGlzLl90b29sYmFyLl93aWR0aCk6KHRoaXMuX2hvcml6b250YWw9ITEsdGhpcy5fdG9vbGJhci5fc2l6ZWFibGU9dGhpcy5fdG9vbGJhci5faGVpZ2h0KX0sZS5wcm90b3R5cGUuX2RvY19hdHRhY2hlZD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl90b29sYmFyLmF0dGFjaF9kb2N1bWVudCh0aGlzLmRvY3VtZW50KX0sZS5wcm90b3R5cGUuZ2V0X2xheW91dGFibGVfY2hpbGRyZW49ZnVuY3Rpb24oKXtyZXR1cm5bdGhpcy5fdG9vbGJhcl19LGUuZGVmaW5lKHt0b29sYmFyX2xvY2F0aW9uOltkLkxvY2F0aW9uLCJyaWdodCJdLG1lcmdlX3Rvb2xzOltkLkJvb2wsITBdLHRvb2xzOltkLkFueSxbXV0sbG9nbzpbZC5TdHJpbmcsIm5vcm1hbCJdfSksZX0oby5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpoLFZpZXc6cH19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vbGF5b3V0cy9ib3giOiJtb2RlbHMvbGF5b3V0cy9ib3giLCIuL2FjdGlvbnMvYWN0aW9uX3Rvb2wiOiJtb2RlbHMvdG9vbHMvYWN0aW9ucy9hY3Rpb25fdG9vbCIsIi4vYWN0aW9ucy9oZWxwX3Rvb2wiOiJtb2RlbHMvdG9vbHMvYWN0aW9ucy9oZWxwX3Rvb2wiLCIuL2dlc3R1cmVzL2dlc3R1cmVfdG9vbCI6Im1vZGVscy90b29scy9nZXN0dXJlcy9nZXN0dXJlX3Rvb2wiLCIuL2luc3BlY3RvcnMvaW5zcGVjdF90b29sIjoibW9kZWxzL3Rvb2xzL2luc3BlY3RvcnMvaW5zcGVjdF90b29sIiwiLi90b29sX3Byb3h5IjoibW9kZWxzL3Rvb2xzL3Rvb2xfcHJveHkiLCIuL3Rvb2xiYXJfYmFzZSI6Im1vZGVscy90b29scy90b29sYmFyX2Jhc2UiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90b29scy90b29sYmFyX3RlbXBsYXRlIjpbZnVuY3Rpb24odCxlLHIpe2UuZXhwb3J0cz1mdW5jdGlvbih0KXt0fHwodD17fSk7dmFyIGU9W10scj1mdW5jdGlvbih0KXtyZXR1cm4gdCYmdC5lY29TYWZlP3Q6InVuZGVmaW5lZCIhPXR5cGVvZiB0JiZudWxsIT10P24odCk6IiJ9LG49ZnVuY3Rpb24odCl7cmV0dXJuKCIiK3QpLnJlcGxhY2UoLyYvZywiJmFtcDsiKS5yZXBsYWNlKC88L2csIiZsdDsiKS5yZXBsYWNlKC8+L2csIiZndDsiKS5yZXBsYWNlKC8iL2csIiZxdW90OyIpfTtyZXR1cm4gZnVuY3Rpb24oKXsoZnVuY3Rpb24oKXtlLnB1c2goJzxkaXYgY2xhc3M9ImJrLXRvb2xiYXItJyksZS5wdXNoKHIodGhpcy5sb2NhdGlvbikpLGUucHVzaCgiIGJrLXBsb3QtIiksZS5wdXNoKHIodGhpcy5sb2NhdGlvbikpLGUucHVzaCgiIGJrLXRvb2xiYXItIiksZS5wdXNoKHIodGhpcy5zdGlja3kpKSxlLnB1c2goJyBiay10b29sYmFyLWFjdGl2ZSI+XG4gICcpLG51bGwhPXRoaXMubG9nbyYmImdyZXkiPT09dGhpcy5sb2dvP2UucHVzaCgiXG4gICAgPGEgaHJlZj0naHR0cDovL2Jva2VoLnB5ZGF0YS5vcmcvJyB0YXJnZXQ9J19ibGFuaycgY2xhc3M9J2JrLWxvZ28gYmstbG9nby1zbWFsbCBncmV5Jz48L2E+XG4gICIpOm51bGwhPXRoaXMubG9nbyYmZS5wdXNoKCJcbiAgPGEgaHJlZj0naHR0cDovL2Jva2VoLnB5ZGF0YS5vcmcvJyB0YXJnZXQ9J19ibGFuaycgY2xhc3M9J2JrLWxvZ28gYmstbG9nby1zbWFsbCc+PC9hPlxuICAiKSxlLnB1c2goIlxuICA8ZGl2IGNsYXNzPSdiay1idXR0b24tYmFyJz5cbiAgICA8dWwgY2xhc3M9J2JrLWJ1dHRvbi1iYXItbGlzdCcgdHlwZT1cInBhblwiIC8+XG4gICAgPHVsIGNsYXNzPSdiay1idXR0b24tYmFyLWxpc3QnIHR5cGU9XCJzY3JvbGxcIiAvPlxuICAgIDx1bCBjbGFzcz0nYmstYnV0dG9uLWJhci1saXN0JyB0eXBlPVwicGluY2hcIiAvPlxuICAgIDx1bCBjbGFzcz0nYmstYnV0dG9uLWJhci1saXN0JyB0eXBlPVwidGFwXCIgLz5cbiAgICA8dWwgY2xhc3M9J2JrLWJ1dHRvbi1iYXItbGlzdCcgdHlwZT1cInByZXNzXCIgLz5cbiAgICA8dWwgY2xhc3M9J2JrLWJ1dHRvbi1iYXItbGlzdCcgdHlwZT1cInJvdGF0ZVwiIC8+XG4gICAgPHVsIGNsYXNzPSdiay1idXR0b24tYmFyLWxpc3QnIHR5cGU9XCJhY3Rpb25zXCIgLz5cbiAgICA8ZGl2IGNsYXNzPSdiay1idXR0b24tYmFyLWxpc3QgYmstYnMtZHJvcGRvd24nIHR5cGU9XCJpbnNwZWN0b3JzXCIgLz5cbiAgICA8dWwgY2xhc3M9J2JrLWJ1dHRvbi1iYXItbGlzdCcgdHlwZT1cImhlbHBcIiAvPlxuICA8L2Rpdj5cbjwvZGl2PlxuIil9KS5jYWxsKHRoaXMpfS5jYWxsKHQpLGUuam9pbigiIil9fSx7fV0sIm1vZGVscy90cmFuc2Zvcm1zL2ludGVycG9sYXRvciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXUuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sdT17fS5oYXNPd25Qcm9wZXJ0eSxoPVtdLmluZGV4T2Z8fGZ1bmN0aW9uKHQpe2Zvcih2YXIgZT0wLHI9dGhpcy5sZW5ndGg7ZTxyO2UrKylpZihlIGluIHRoaXMmJnRoaXNbZV09PT10KXJldHVybiBlO3JldHVybi0xfTtpPXQoInVuZGVyc2NvcmUiKSxvPXQoIi4vdHJhbnNmb3JtIiksYT10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxzPXQoIi4uLy4uL2NvcmUvbG9nZ2luZyIpLmxvZ2dlcixuPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBsKGUsdCksZS5wcm90b3R5cGUuaW5pdGlhbGl6ZT1mdW5jdGlvbih0LHIpe3JldHVybiBlLl9fc3VwZXJfXy5pbml0aWFsaXplLmNhbGwodGhpcyx0LHIpLHRoaXMuX3hfc29ydGVkPVtdLHRoaXMuX3lfc29ydGVkPVtdLHRoaXMuX3NvcnRlZF9kaXJ0eT0hMCx0aGlzLmJpbmQoImNoYW5nZSIsZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc29ydGVkX2RpcnR5PSEwfSl9LGUuZGVmaW5lKHt4OlthLkFueV0seTpbYS5BbnldLGRhdGE6W2EuQW55XSxjbGlwOlthLkJvb2wsITBdfSksZS5wcm90b3R5cGUuc29ydD1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsLHUsYyxwO2lmKG51bGw9PXQmJih0PSExKSx0eXBlb2YgdGhpcy5nZXQoIngiKSE9dHlwZW9mIHRoaXMuZ2V0KCJ5IikpdGhyb3cgRXJyb3IoIlRoZSBwYXJhbWV0ZXJzIGZvciB4IGFuZCB5IG11c3QgYmUgb2YgdGhlIHNhbWUgdHlwZSwgZWl0aGVyIGJvdGggc3RyaW5ncyB3aGljaCBkZWZpbmUgYSBjb2x1bW4gaW4gdGhlIGRhdGEgc291cmNlIG9yIGJvdGggYXJyYXlzIG9mIHRoZSBzYW1lIGxlbmd0aCIpO2lmKCJzdHJpbmciPT10eXBlb2YgdGhpcy5nZXQoIngiKSYmbnVsbD09PXRoaXMuZ2V0KCJkYXRhIikpdGhyb3cgRXJyb3IoIklmIHRoZSB4IGFuZCB5IHBhcmFtZXRlcnMgYXJlIG5vdCBzcGVjaWZpZWQgYXMgYW4gYXJyYXksIHRoZSBkYXRhIHBhcmFtZXRlciBpcyByZXFpcmVkLiIpO2lmKHRoaXMuX3NvcnRlZF9kaXJ0eSE9PSExKXtpZihjPVtdLHA9W10sInN0cmluZyI9PXR5cGVvZiB0aGlzLmdldCgieCIpKXtpZihyPXRoaXMuZ2V0KCJkYXRhIiksZT1yLmNvbHVtbnMoKSxhPXRoaXMuZ2V0KCJ4IiksaC5jYWxsKGUsYSk8MCl0aHJvdyBFcnJvcigiVGhlIHggcGFyYW1ldGVyIGRvZXMgbm90IGNvcnJlc3BvbmQgdG8gYSB2YWxpZCBjb2x1bW4gbmFtZSBkZWZpbmVkIGluIHRoZSBkYXRhIHBhcmFtZXRlciIpO2lmKGw9dGhpcy5nZXQoInkiKSxoLmNhbGwoZSxsKTwwKXRocm93IEVycm9yKCJUaGUgeCBwYXJhbWV0ZXIgZG9lcyBub3QgY29ycmVzcG9uZCB0byBhIHZhbGlkIGNvbHVtbiBuYW1lIGRlZmluZWQgaW4gdGhlIGRhdGEgcGFyYW1ldGVyIik7Yz1yLmdldF9jb2x1bW4odGhpcy5nZXQoIngiKSkscD1yLmdldF9jb2x1bW4odGhpcy5nZXQoInkiKSl9ZWxzZSBjPXRoaXMuZ2V0KCJ4IikscD10aGlzLmdldCgieSIpO2lmKGMubGVuZ3RoIT09cC5sZW5ndGgpdGhyb3cgRXJyb3IoIlRoZSBsZW5ndGggZm9yIHggYW5kIHkgZG8gbm90IG1hdGNoIik7aWYoYy5sZW5ndGg8Mil0aHJvdyBFcnJvcigieCBhbmQgeSBtdXN0IGhhdmUgYXQgbGVhc3QgdHdvIGVsZW1lbnRzIHRvIHN1cHBvcnQgaW50ZXJwb2xhdGlvbiIpO3M9W107Zm9yKG8gaW4gYylzLnB1c2goe3g6Y1tvXSx5OnBbb119KTtmb3IodD09PSEwP3Muc29ydChmdW5jdGlvbih0LGUpe3ZhciByLG47cmV0dXJuIG51bGwhPShyPXQueDxlLngpP3I6LXsxOm51bGwhPShuPXQueD09PWUueCk/bjp7MDoxfX19KTpzLnNvcnQoZnVuY3Rpb24odCxlKXt2YXIgcixuO3JldHVybiBudWxsIT0ocj10Lng+ZS54KT9yOi17MTpudWxsIT0obj10Lng9PT1lLngpP246ezA6MX19fSksaT1uPTAsdT1zLmxlbmd0aC0xOzA8PXU/bjw9dTpuPj11O2k9MDw9dT8rK246LS1uKXRoaXMuX3hfc29ydGVkW2ldPXNbaV0ueCx0aGlzLl95X3NvcnRlZFtpXT1zW2ldLnk7cmV0dXJuIHRoaXMuX3NvcnRlZF9kaXJ0eT0hMX19LGV9KG8uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29yZS9sb2dnaW5nIjoiY29yZS9sb2dnaW5nIiwiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi90cmFuc2Zvcm0iOiJtb2RlbHMvdHJhbnNmb3Jtcy90cmFuc2Zvcm0iLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90cmFuc2Zvcm1zL2ppdHRlciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXUuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sdT17fS5oYXNPd25Qcm9wZXJ0eTtpPXQoInVuZGVyc2NvcmUiKSxvPXQoIi4vdHJhbnNmb3JtIiksYT10KCIuLi8uLi9jb3JlL3Byb3BlcnRpZXMiKSxzPXQoIi4uLy4uL2NvcmUvdXRpbC9tYXRoIiksbj1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUuZGVmaW5lKHttZWFuOlthLk51bWJlciwwXSx3aWR0aDpbYS5OdW1iZXIsMV0sZGlzdHJpYnV0aW9uOlthLkRpc3RyaWJ1dGlvbiwidW5pZm9ybSJdfSksZS5wcm90b3R5cGUuY29tcHV0ZT1mdW5jdGlvbih0KXtyZXR1cm4idW5pZm9ybSI9PT10aGlzLmdldCgiZGlzdHJpYnV0aW9uIik/dCt0aGlzLmdldCgibWVhbiIpKyhzLnJhbmRvbSgpLS41KSp0aGlzLmdldCgid2lkdGgiKToibm9ybWFsIj09PXRoaXMuZ2V0KCJkaXN0cmlidXRpb24iKT90K3Mucm5vcm0odGhpcy5nZXQoIm1lYW4iKSx0aGlzLmdldCgid2lkdGgiKSk6dm9pZCAwfSxlLnByb3RvdHlwZS52X2NvbXB1dGU9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saTtmb3Iobz1uZXcgRmxvYXQ2NEFycmF5KHQubGVuZ3RoKSxyPWU9MCxuPXQubGVuZ3RoO2U8bjtyPSsrZSlpPXRbcl0sb1tyXT10aGlzLmNvbXB1dGUoaSk7cmV0dXJuIG99LGV9KG8uTW9kZWwpLGUuZXhwb3J0cz17TW9kZWw6bn19LHsiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIjoiY29yZS9wcm9wZXJ0aWVzIiwiLi4vLi4vY29yZS91dGlsL21hdGgiOiJjb3JlL3V0aWwvbWF0aCIsIi4vdHJhbnNmb3JtIjoibW9kZWxzL3RyYW5zZm9ybXMvdHJhbnNmb3JtIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdHJhbnNmb3Jtcy9saW5lYXJfaW50ZXJwb2xhdG9yIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWwuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sbD17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxpPXQoIi4vdHJhbnNmb3JtIiksbj10KCIuL2ludGVycG9sYXRvciIpLG89ZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSgpe3JldHVybiBlLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9cmV0dXJuIGEoZSx0KSxlLnByb3RvdHlwZS5kZWZhdWx0cz1mdW5jdGlvbigpe3JldHVybiBzLmV4dGVuZCh7fSxlLl9fc3VwZXJfXy5kZWZhdWx0cy5jYWxsKHRoaXMpKX0sZS5wcm90b3R5cGUuY29tcHV0ZT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLGEsbDtpZih0aGlzLnNvcnQoZT0hMSksdGhpcy5jbGlwPT09ITApe2lmKHQ8dGhpcy5feF9zb3J0ZWRbMF18fHQ+dGhpcy5feF9zb3J0ZWRbdGhpcy5feF9zb3J0ZWQubGVuZ3RoLTFdKXJldHVybiBudWxsfWVsc2V7aWYodDx0aGlzLl94X3NvcnRlZFswXSlyZXR1cm4gdGhpcy5feV9zb3J0ZWRbMF07aWYodD50aGlzLl94X3NvcnRlZFt0aGlzLl94X3NvcnRlZC5sZW5ndGgtMV0pcmV0dXJuIHRoaXMuX3lfc29ydGVkW3RoaXMuX3lfc29ydGVkLmxlbmd0aC0xXX1yZXR1cm4gcj1zLmZpbmRMYXN0SW5kZXgodGhpcy5feF9zb3J0ZWQsZnVuY3Rpb24oZSl7cmV0dXJuIHQ+PWV9KSxvPXRoaXMuX3hfc29ydGVkW3JdLGk9dGhpcy5feF9zb3J0ZWRbcisxXSxhPXRoaXMuX3lfc29ydGVkW3JdLGw9dGhpcy5feV9zb3J0ZWRbcisxXSxuPWErKHQtbykvKGktbykqKGwtYSl9LGUucHJvdG90eXBlLnZfY29tcHV0ZT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpO2ZvcihvPW5ldyBGbG9hdDY0QXJyYXkodC5sZW5ndGgpLHI9ZT0wLG49dC5sZW5ndGg7ZTxuO3I9KytlKWk9dFtyXSxvW3JdPXRoaXMuY29tcHV0ZShpKTtyZXR1cm4gb30sZX0obi5Nb2RlbCksZS5leHBvcnRzPXtNb2RlbDpvfX0seyIuL2ludGVycG9sYXRvciI6Im1vZGVscy90cmFuc2Zvcm1zL2ludGVycG9sYXRvciIsIi4vdHJhbnNmb3JtIjoibW9kZWxzL3RyYW5zZm9ybXMvdHJhbnNmb3JtIix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLCJtb2RlbHMvdHJhbnNmb3Jtcy9zdGVwX2ludGVycG9sYXRvciI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKXUuY2FsbChlLG4pJiYodFtuXT1lW25dKTtyZXR1cm4gci5wcm90b3R5cGU9ZS5wcm90b3R5cGUsdC5wcm90b3R5cGU9bmV3IHIsdC5fX3N1cGVyX189ZS5wcm90b3R5cGUsdH0sdT17fS5oYXNPd25Qcm9wZXJ0eTtzPXQoInVuZGVyc2NvcmUiKSxpPXQoIi4vdHJhbnNmb3JtIiksbj10KCIuL2ludGVycG9sYXRvciIpLGE9dCgiLi4vLi4vY29yZS9wcm9wZXJ0aWVzIiksbz1mdW5jdGlvbih0KXtmdW5jdGlvbiBlKCl7cmV0dXJuIGUuX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gbChlLHQpLGUuZGVmaW5lKHttb2RlOlthLlRyYW5zZm9ybVN0ZXBNb2RlLCJhZnRlciJdfSksZS5wcm90b3R5cGUuY29tcHV0ZT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLGE7aWYodGhpcy5zb3J0KGU9ITEpLHRoaXMuY2xpcD09PSEwKXtpZih0PHRoaXMuX3hfc29ydGVkWzBdfHx0PnRoaXMuX3hfc29ydGVkW3RoaXMuX3hfc29ydGVkLmxlbmd0aC0xXSlyZXR1cm4gbnVsbH1lbHNle2lmKHQ8dGhpcy5feF9zb3J0ZWRbMF0pcmV0dXJuIHRoaXMuX3lfc29ydGVkWzBdO2lmKHQ+dGhpcy5feF9zb3J0ZWRbdGhpcy5feF9zb3J0ZWQubGVuZ3RoLTFdKXJldHVybiB0aGlzLl95X3NvcnRlZFt0aGlzLl95X3NvcnRlZC5sZW5ndGgtMV19cmV0dXJuIG49LTEsImFmdGVyIj09PXRoaXMuZ2V0KCJtb2RlIikmJihuPXMuZmluZExhc3RJbmRleCh0aGlzLl94X3NvcnRlZCxmdW5jdGlvbihlKXtyZXR1cm4gdD49ZX0pKSwiYmVmb3JlIj09PXRoaXMuZ2V0KCJtb2RlIikmJihuPXMuZmluZEluZGV4KHRoaXMuX3hfc29ydGVkLGZ1bmN0aW9uKGUpe3JldHVybiB0PD1lfSkpLCJjZW50ZXIiPT09dGhpcy5nZXQoIm1vZGUiKSYmKHI9ZnVuY3Rpb24oKXt2YXIgZSxyLG4sbztmb3Iobj10aGlzLl94X3NvcnRlZCxvPVtdLGU9MCxyPW4ubGVuZ3RoO2U8cjtlKyspYT1uW2VdLG8ucHVzaChNYXRoLmFicyhhLXQpKTtyZXR1cm4gb30uY2FsbCh0aGlzKSxvPXMubWluKHIpLG49cy5maW5kSW5kZXgocixmdW5jdGlvbih0KXtyZXR1cm4gbz09PXR9KSksaT1uIT09LTE/dGhpcy5feV9zb3J0ZWRbbl06bnVsbH0sZS5wcm90b3R5cGUudl9jb21wdXRlPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGk7Zm9yKG89bmV3IEZsb2F0NjRBcnJheSh0Lmxlbmd0aCkscj1lPTAsbj10Lmxlbmd0aDtlPG47cj0rK2UpaT10W3JdLG9bcl09dGhpcy5jb21wdXRlKGkpO3JldHVybiBvfSxlfShuLk1vZGVsKSxlLmV4cG9ydHM9e01vZGVsOm99fSx7Ii4uLy4uL2NvcmUvcHJvcGVydGllcyI6ImNvcmUvcHJvcGVydGllcyIsIi4vaW50ZXJwb2xhdG9yIjoibW9kZWxzL3RyYW5zZm9ybXMvaW50ZXJwb2xhdG9yIiwiLi90cmFuc2Zvcm0iOiJtb2RlbHMvdHJhbnNmb3Jtcy90cmFuc2Zvcm0iLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sIm1vZGVscy90cmFuc2Zvcm1zL3RyYW5zZm9ybSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscz1mdW5jdGlvbih0LGUpe2Z1bmN0aW9uIHIoKXt0aGlzLmNvbnN0cnVjdG9yPXR9Zm9yKHZhciBuIGluIGUpYS5jYWxsKGUsbikmJih0W25dPWVbbl0pO3JldHVybiByLnByb3RvdHlwZT1lLnByb3RvdHlwZSx0LnByb3RvdHlwZT1uZXcgcix0Ll9fc3VwZXJfXz1lLnByb3RvdHlwZSx0fSxhPXt9Lmhhc093blByb3BlcnR5O2k9dCgidW5kZXJzY29yZSIpLG49dCgiLi4vLi4vbW9kZWwiKSxvPWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoKXtyZXR1cm4gZS5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcyxhcmd1bWVudHMpfXJldHVybiBzKGUsdCksZS5wcm90b3R5cGUuZGVmYXVsdHM9ZnVuY3Rpb24oKXtyZXR1cm4gaS5leHRlbmQoe30sZS5fX3N1cGVyX18uZGVmYXVsdHMuY2FsbCh0aGlzKSl9LGV9KG4pLGUuZXhwb3J0cz17TW9kZWw6b319LHsiLi4vLi4vbW9kZWwiOiJtb2RlbCIsdW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwicGFsZXR0ZXMvcGFsZXR0ZXMiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbztuPXQoInVuZGVyc2NvcmUiKSxvPXtZbEduOntZbEduMzpbMzI1MzA3NiwxMTM5NDQ0NiwxNjI1MjA4OV0sWWxHbjQ6WzIzMjc2MTksNzkxNTEyOSwxMjc3MzAxNywxNjc3NzE2NF0sWWxHbjU6WzI2Njc5LDMyNTMwNzYsNzkxNTEyOSwxMjc3MzAxNywxNjc3NzE2NF0sWWxHbjY6WzI2Njc5LDMyNTMwNzYsNzkxNTEyOSwxMTM5NDQ0NiwxNDI4MjkxNSwxNjc3NzE2NF0sWWxHbjc6WzIzMDkwLDIzMjc2MTksNDMwMzcwOSw3OTE1MTI5LDExMzk0NDQ2LDE0MjgyOTE1LDE2Nzc3MTY0XSxZbEduODpbMjMwOTAsMjMyNzYxOSw0MzAzNzA5LDc5MTUxMjksMTEzOTQ0NDYsMTQyODI5MTUsMTYyNTIwODksMTY3NzcxODldLFlsR245OlsxNzcwNSwyNjY3OSwyMzI3NjE5LDQzMDM3MDksNzkxNTEyOSwxMTM5NDQ0NiwxNDI4MjkxNSwxNjI1MjA4OSwxNjc3NzE4OV19LFlsR25CdTp7WWxHbkJ1MzpbMjkxNjI4MCw4Mzc1NzM5LDE1NTk1Njk3XSxZbEduQnU0OlsyMjUyNDU2LDQzMDY2MjgsMTA2MDcyODQsMTY3NzcxNjRdLFlsR25CdTU6WzI0MzgyOTIsMjkxNjI4MCw0MzA2NjI4LDEwNjA3Mjg0LDE2Nzc3MTY0XSxZbEduQnU2OlsyNDM4MjkyLDI5MTYyODAsNDMwNjYyOCw4Mzc1NzM5LDEzMTAxNDkyLDE2Nzc3MTY0XSxZbEduQnU3Ols3OTc4MjgsMjI1MjQ1NiwxOTM3ODU2LDQzMDY2MjgsODM3NTczOSwxMzEwMTQ5MiwxNjc3NzE2NF0sWWxHbkJ1ODpbNzk3ODI4LDIyNTI0NTYsMTkzNzg1Niw0MzA2NjI4LDgzNzU3MzksMTMxMDE0OTIsMTU1OTU2OTcsMTY3NzcxNzddLFlsR25CdTk6WzUzMTgwMCwyNDM4MjkyLDIyNTI0NTYsMTkzNzg1Niw0MzA2NjI4LDgzNzU3MzksMTMxMDE0OTIsMTU1OTU2OTcsMTY3NzcxNzddfSxHbkJ1OntHbkJ1MzpbNDQzMjU4NiwxMTA2NjgwNSwxNDc0MjQ5MV0sR25CdTQ6WzI4NTQwNzgsODExMzM0OCwxMjI0ODI1MiwxNTc5MjYxNl0sR25CdTU6WzU1MTA4NCw0NDMyNTg2LDgxMTMzNDgsMTIyNDgyNTIsMTU3OTI2MTZdLEduQnU2Ols1NTEwODQsNDQzMjU4Niw4MTEzMzQ4LDExMDY2ODA1LDEzNDI5NzAxLDE1NzkyNjE2XSxHbkJ1NzpbNTQ2OTc0LDI4NTQwNzgsNTE1Nzg0Myw4MTEzMzQ4LDExMDY2ODA1LDEzNDI5NzAxLDE1NzkyNjE2XSxHbkJ1ODpbNTQ2OTc0LDI4NTQwNzgsNTE1Nzg0Myw4MTEzMzQ4LDExMDY2ODA1LDEzNDI5NzAxLDE0NzQyNDkxLDE2MjUyMTQ0XSxHbkJ1OTpbNTQwODAxLDU1MTA4NCwyODU0MDc4LDUxNTc4NDMsODExMzM0OCwxMTA2NjgwNSwxMzQyOTcwMSwxNDc0MjQ5MSwxNjI1MjE0NF19LEJ1R246e0J1R24zOlsyOTI1MTUxLDEwMDgyNTA1LDE1MDcwNzEzXSxCdUduNDpbMjMyOTQxMyw2NzM0NTAwLDExNzIzNDkwLDE1NTk1NzcxXSxCdUduNTpbMjc5NDgsMjkyNTE1MSw2NzM0NTAwLDExNzIzNDkwLDE1NTk1NzcxXSxCdUduNjpbMjc5NDgsMjkyNTE1MSw2NzM0NTAwLDEwMDgyNTA1LDEzNDI5OTkwLDE1NTk1NzcxXSxCdUduNzpbMjI1NjQsMjMyOTQxMyw0MzA0NTAyLDY3MzQ1MDAsMTAwODI1MDUsMTM0Mjk5OTAsMTU1OTU3NzFdLEJ1R244OlsyMjU2NCwyMzI5NDEzLDQzMDQ1MDIsNjczNDUwMCwxMDA4MjUwNSwxMzQyOTk5MCwxNTA3MDcxMywxNjI1MjE1N10sQnVHbjk6WzE3NDM1LDI3OTQ4LDIzMjk0MTMsNDMwNDUwMiw2NzM0NTAwLDEwMDgyNTA1LDEzNDI5OTkwLDE1MDcwNzEzLDE2MjUyMTU3XX0sUHVCdUduOntQdUJ1R24zOlsxODcyMDI1LDEwOTI3NTc5LDE1NTI0NTkyXSxQdUJ1R240OlsxNjQyMzQsNjc5MzY3OSwxMjQzNzk4NSwxNjE4MzI4N10sUHVCdUduNTpbOTMyNzMsMTg3MjAyNSw2NzkzNjc5LDEyNDM3OTg1LDE2MTgzMjg3XSxQdUJ1R242Ols5MzI3MywxODcyMDI1LDY3OTM2NzksMTA5Mjc1NzksMTM2ODUyMjIsMTYxODMyODddLFB1QnVHbjc6WzkxMjE2LDE2NDIzNCwzNTc2ZTMsNjc5MzY3OSwxMDkyNzU3OSwxMzY4NTIyMiwxNjE4MzI4N10sUHVCdUduODpbOTEyMTYsMTY0MjM0LDM1NzZlMyw2NzkzNjc5LDEwOTI3NTc5LDEzNjg1MjIyLDE1NTI0NTkyLDE2Nzc1MTYzXSxQdUJ1R245Ols4MzUxMCw5MzI3MywxNjQyMzQsMzU3NmUzLDY3OTM2NzksMTA5Mjc1NzksMTM2ODUyMjIsMTU1MjQ1OTIsMTY3NzUxNjNdfSxQdUJ1OntQdUJ1MzpbMjg1NDA3OCwxMDkyNzU3OSwxNTUyNTg3NF0sUHVCdTQ6WzM1NjUyOCw3NjQ1NjQ3LDEyNDM3OTg1LDE1ODU1MzUwXSxQdUJ1NTpbMjg1MzI1LDI4NTQwNzgsNzY0NTY0NywxMjQzNzk4NSwxNTg1NTM1MF0sUHVCdTY6WzI4NTMyNSwyODU0MDc4LDc2NDU2NDcsMTA5Mjc1NzksMTM2ODUyMjIsMTU4NTUzNTBdLFB1QnU3OlsyMTY2OTksMzU2NTI4LDM1NzZlMyw3NjQ1NjQ3LDEwOTI3NTc5LDEzNjg1MjIyLDE1ODU1MzUwXSxQdUJ1ODpbMjE2Njk5LDM1NjUyOCwzNTc2ZTMsNzY0NTY0NywxMDkyNzU3OSwxMzY4NTIyMiwxNTUyNTg3NCwxNjc3NTE2M10sUHVCdTk6WzE0NTQ5NiwyODUzMjUsMzU2NTI4LDM1NzZlMyw3NjQ1NjQ3LDEwOTI3NTc5LDEzNjg1MjIyLDE1NTI1ODc0LDE2Nzc1MTYzXX0sQnVQdTp7QnVQdTM6Wzg5MzUwNzksMTA0MDMwMzQsMTQ3NDA3MjRdLEJ1UHU0Ols4OTI5NjkzLDkyMTM2MzgsMTE3ODM2NTEsMTU1OTU3NzFdLEJ1UHU1Ols4NDU4MTA4LDg5MzUwNzksOTIxMzYzOCwxMTc4MzY1MSwxNTU5NTc3MV0sQnVQdTY6Wzg0NTgxMDgsODkzNTA3OSw5MjEzNjM4LDEwNDAzMDM0LDEyNTcxNjIyLDE1NTk1NzcxXSxCdVB1NzpbNzIwOTMyMyw4OTI5NjkzLDkyMDI2MDksOTIxMzYzOCwxMDQwMzAzNCwxMjU3MTYyMiwxNTU5NTc3MV0sQnVQdTg6WzcyMDkzMjMsODkyOTY5Myw5MjAyNjA5LDkyMTM2MzgsMTA0MDMwMzQsMTI1NzE2MjIsMTQ3NDA3MjQsMTYyNTIxNTddLEJ1UHU5Ols1MDQ2MzQ3LDg0NTgxMDgsODkyOTY5Myw5MjAyNjA5LDkyMTM2MzgsMTA0MDMwMzQsMTI1NzE2MjIsMTQ3NDA3MjQsMTYyNTIxNTddfSxSZFB1OntSZFB1MzpbMTI5MTc2NDIsMTY0MjQ4ODUsMTY2MzgxNzNdLFJkUHU0OlsxMTQwMzY0NiwxNjIxNDE3NywxNjQ5NTgwMSwxNjcwNjUzMF0sUmRQdTU6Wzc5OTU3NjcsMTI5MTc2NDIsMTYyMTQxNzcsMTY0OTU4MDEsMTY3MDY1MzBdLFJkUHU2Ols3OTk1NzY3LDEyOTE3NjQyLDE2MjE0MTc3LDE2NDI0ODg1LDE2NTY1Njk2LDE2NzA2NTMwXSxSZFB1NzpbNzk5NTc2NywxMTQwMzY0NiwxNDQ5NjkxOSwxNjIxNDE3NywxNjQyNDg4NSwxNjU2NTY5NiwxNjcwNjUzMF0sUmRQdTg6Wzc5OTU3NjcsMTE0MDM2NDYsMTQ0OTY5MTksMTYyMTQxNzcsMTY0MjQ4ODUsMTY1NjU2OTYsMTY2MzgxNzMsMTY3NzUxNTVdLFJkUHU5Ols0Nzg0MjM0LDc5OTU3NjcsMTE0MDM2NDYsMTQ0OTY5MTksMTYyMTQxNzcsMTY0MjQ4ODUsMTY1NjU2OTYsMTY2MzgxNzMsMTY3NzUxNTVdCn0sUHVSZDp7UHVSZDM6WzE0NDkwNzQzLDEzMjEwODIzLDE1MTk2NjU1XSxQdVJkNDpbMTM1MDUxMTAsMTQ2NDA1NjAsMTQxMzY3OTIsMTU4NTUzNTBdLFB1UmQ1Ols5OTYxNTM5LDE0NDkwNzQzLDE0NjQwNTYwLDE0MTM2NzkyLDE1ODU1MzUwXSxQdVJkNjpbOTk2MTUzOSwxNDQ5MDc0MywxNDY0MDU2MCwxMzIxMDgyMywxMzk0MTIxMCwxNTg1NTM1MF0sUHVSZDc6Wzk1MDI3ODMsMTM1MDUxMTAsMTUxNDk0NTAsMTQ2NDA1NjAsMTMyMTA4MjMsMTM5NDEyMTAsMTU4NTUzNTBdLFB1UmQ4Ols5NTAyNzgzLDEzNTA1MTEwLDE1MTQ5NDUwLDE0NjQwNTYwLDEzMjEwODIzLDEzOTQxMjEwLDE1MTk2NjU1LDE2MjUwMTA1XSxQdVJkOTpbNjc1MDIzOSw5OTYxNTM5LDEzNTA1MTEwLDE1MTQ5NDUwLDE0NjQwNTYwLDEzMjEwODIzLDEzOTQxMjEwLDE1MTk2NjU1LDE2MjUwMTA1XX0sT3JSZDp7T3JSZDM6WzE0ODk1NjY3LDE2NjI4NjEyLDE2NzA1NzM2XSxPclJkNDpbMTQxMDI1NTksMTY1NTEyNTcsMTY2MzI5NzAsMTY3MDc4MDFdLE9yUmQ1OlsxMTczMDk0NCwxNDg5NTY2NywxNjU1MTI1NywxNjYzMjk3MCwxNjcwNzgwMV0sT3JSZDY6WzExNzMwOTQ0LDE0ODk1NjY3LDE2NTUxMjU3LDE2NjI4NjEyLDE2NjM1MDM4LDE2NzA3ODAxXSxPclJkNzpbMTAwMjcwMDgsMTQxMDI1NTksMTU2ODkwMzIsMTY1NTEyNTcsMTY2Mjg2MTIsMTY2MzUwMzgsMTY3MDc4MDFdLE9yUmQ4OlsxMDAyNzAwOCwxNDEwMjU1OSwxNTY4OTAzMiwxNjU1MTI1NywxNjYyODYxMiwxNjYzNTAzOCwxNjcwNTczNiwxNjc3NTE0OF0sT3JSZDk6WzgzMjMwNzIsMTE3MzA5NDQsMTQxMDI1NTksMTU2ODkwMzIsMTY1NTEyNTcsMTY2Mjg2MTIsMTY2MzUwMzgsMTY3MDU3MzYsMTY3NzUxNDhdfSxZbE9yUmQ6e1lsT3JSZDM6WzE1NzQzNzc2LDE2NjkxNzg4LDE2NzcyNTEyXSxZbE9yUmQ0OlsxNDg4MzM1NiwxNjYxNjc2NCwxNjY5ODQ2MCwxNjc3NzEzOF0sWWxPclJkNTpbMTIzODYzNDIsMTU3NDM3NzYsMTY2MTY3NjQsMTY2OTg0NjAsMTY3NzcxMzhdLFlsT3JSZDY6WzEyMzg2MzQyLDE1NzQzNzc2LDE2NjE2NzY0LDE2NjkxNzg4LDE2NzAxODE0LDE2Nzc3MTM4XSxZbE9yUmQ3OlsxMTU5OTkxMCwxNDg4MzM1NiwxNjUzNTA4MiwxNjYxNjc2NCwxNjY5MTc4OCwxNjcwMTgxNCwxNjc3NzEzOF0sWWxPclJkODpbMTE1OTk5MTAsMTQ4ODMzNTYsMTY1MzUwODIsMTY2MTY3NjQsMTY2OTE3ODgsMTY3MDE4MTQsMTY3NzI1MTIsMTY3NzcxNjRdLFlsT3JSZDk6WzgzODg2NDYsMTIzODYzNDIsMTQ4ODMzNTYsMTY1MzUwODIsMTY2MTY3NjQsMTY2OTE3ODgsMTY3MDE4MTQsMTY3NzI1MTIsMTY3NzcxNjRdfSxZbE9yQnI6e1lsT3JCcjM6WzE0MjQ1NjQ2LDE2Njk2Mzk5LDE2Nzc1MTAwXSxZbE9yQnI0OlsxMzM4ODgwMiwxNjY4NTM1MywxNjcwMTgzOCwxNjc3NzE3Ml0sWWxPckJyNTpbMTAwNDAzMjQsMTQyNDU2NDYsMTY2ODUzNTMsMTY3MDE4MzgsMTY3NzcxNzJdLFlsT3JCcjY6WzEwMDQwMzI0LDE0MjQ1NjQ2LDE2Njg1MzUzLDE2Njk2Mzk5LDE2NzA0NDAxLDE2Nzc3MTcyXSxZbE9yQnI3Ols5MTg2NTY0LDEzMzg4ODAyLDE1NDk1MTg4LDE2Njg1MzUzLDE2Njk2Mzk5LDE2NzA0NDAxLDE2Nzc3MTcyXSxZbE9yQnI4Ols5MTg2NTY0LDEzMzg4ODAyLDE1NDk1MTg4LDE2Njg1MzUzLDE2Njk2Mzk5LDE2NzA0NDAxLDE2Nzc1MTAwLDE2Nzc3MTg5XSxZbE9yQnI5Ols2Njk0MTUwLDEwMDQwMzI0LDEzMzg4ODAyLDE1NDk1MTg4LDE2Njg1MzUzLDE2Njk2Mzk5LDE2NzA0NDAxLDE2Nzc1MTAwLDE2Nzc3MTg5XX0sUHVycGxlczp7UHVycGxlczM6Wzc2OTUyODEsMTIzNjkzNzIsMTU3MjQwMjFdLFB1cnBsZXM0Ols2OTY3NzE1LDEwMzk0MzEyLDEzMzU1NDkwLDE1OTIxMzk5XSxQdXJwbGVzNTpbNTUxNTE1MSw3Njk1MjgxLDEwMzk0MzEyLDEzMzU1NDkwLDE1OTIxMzk5XSxQdXJwbGVzNjpbNTUxNTE1MSw3Njk1MjgxLDEwMzk0MzEyLDEyMzY5MzcyLDE0MzQyODkxLDE1OTIxMzk5XSxQdXJwbGVzNzpbNDg1NDkxOCw2OTY3NzE1LDg0MjA3OTQsMTAzOTQzMTIsMTIzNjkzNzIsMTQzNDI4OTEsMTU5MjEzOTldLFB1cnBsZXM4Ols0ODU0OTE4LDY5Njc3MTUsODQyMDc5NCwxMDM5NDMxMiwxMjM2OTM3MiwxNDM0Mjg5MSwxNTcyNDAyMSwxNjU3OTU4MV0sUHVycGxlczk6WzQxMjg4OTMsNTUxNTE1MSw2OTY3NzE1LDg0MjA3OTQsMTAzOTQzMTIsMTIzNjkzNzIsMTQzNDI4OTEsMTU3MjQwMjEsMTY1Nzk1ODFdfSxCbHVlczp7Qmx1ZXMzOlszMjQ0NzMzLDEwNDA2NjI1LDE0NjA5Mzk5XSxCbHVlczQ6WzIxOTE3OTcsNzA1NzExMCwxMjQ0MTU3NSwxNTcyNTU2N10sQmx1ZXM1Ols1NDUxODAsMzI0NDczMyw3MDU3MTEwLDEyNDQxNTc1LDE1NzI1NTY3XSxCbHVlczY6WzU0NTE4MCwzMjQ0NzMzLDcwNTcxMTAsMTA0MDY2MjUsMTMwMzI0MzEsMTU3MjU1NjddLEJsdWVzNzpbNTQyMTAwLDIxOTE3OTcsNDM2Mjk1MCw3MDU3MTEwLDEwNDA2NjI1LDEzMDMyNDMxLDE1NzI1NTY3XSxCbHVlczg6WzU0MjEwMCwyMTkxNzk3LDQzNjI5NTAsNzA1NzExMCwxMDQwNjYyNSwxMzAzMjQzMSwxNDYwOTM5OSwxNjI1MTkwM10sQmx1ZXM5Ols1MzY2ODMsNTQ1MTgwLDIxOTE3OTcsNDM2Mjk1MCw3MDU3MTEwLDEwNDA2NjI1LDEzMDMyNDMxLDE0NjA5Mzk5LDE2MjUxOTAzXX0sR3JlZW5zOntHcmVlbnMzOlszMjUzMDc2LDEwNjA3MDAzLDE1MDcwNjg4XSxHcmVlbnM0OlsyMzI5NDEzLDc2NTI0NzAsMTIyNDgyNDMsMTU1OTU3NTNdLEdyZWVuczU6WzI3OTQ4LDMyNTMwNzYsNzY1MjQ3MCwxMjI0ODI0MywxNTU5NTc1M10sR3JlZW5zNjpbMjc5NDgsMzI1MzA3Niw3NjUyNDcwLDEwNjA3MDAzLDEzMTAxNTA0LDE1NTk1NzUzXSxHcmVlbnM3OlsyMzA5MCwyMzI5NDEzLDQzMDM3MDksNzY1MjQ3MCwxMDYwNzAwMywxMzEwMTUwNCwxNTU5NTc1M10sR3JlZW5zODpbMjMwOTAsMjMyOTQxMyw0MzAzNzA5LDc2NTI0NzAsMTA2MDcwMDMsMTMxMDE1MDQsMTUwNzA2ODgsMTYyNTIxNDldLEdyZWVuczk6WzE3NDM1LDI3OTQ4LDIzMjk0MTMsNDMwMzcwOSw3NjUyNDcwLDEwNjA3MDAzLDEzMTAxNTA0LDE1MDcwNjg4LDE2MjUyMTQ5XX0sT3Jhbmdlczp7T3JhbmdlczM6WzE1MDk1MDUzLDE2NjI1MjU5LDE2NzA1MjMwXSxPcmFuZ2VzNDpbMTQyMzk0ODksMTY2MTY3NjQsMTY2MjkzODEsMTY3MDcwMzhdLE9yYW5nZXM1OlsxMDg5MjgwMywxNTA5NTA1MywxNjYxNjc2NCwxNjYyOTM4MSwxNjcwNzAzOF0sT3JhbmdlczY6WzEwODkyODAzLDE1MDk1MDUzLDE2NjE2NzY0LDE2NjI1MjU5LDE2NjM0MDE4LDE2NzA3MDM4XSxPcmFuZ2VzNzpbOTE4NjU2NCwxNDIzOTc0NSwxNTgyMTA3NSwxNjYxNjc2NCwxNjYyNTI1OSwxNjYzNDAxOCwxNjcwNzAzOF0sT3Jhbmdlczg6WzkxODY1NjQsMTQyMzk3NDUsMTU4MjEwNzUsMTY2MTY3NjQsMTY2MjUyNTksMTY2MzQwMTgsMTY3MDUyMzAsMTY3NzQ2MzVdLE9yYW5nZXM5Ols4MzMzMDYwLDEwODkyODAzLDE0MjM5NzQ1LDE1ODIxMDc1LDE2NjE2NzY0LDE2NjI1MjU5LDE2NjM0MDE4LDE2NzA1MjMwLDE2Nzc0NjM1XX0sUmVkczp7UmVkczM6WzE0NTYwNTUwLDE2NTUyNTYyLDE2NzAzNjk4XSxSZWRzNDpbMTMzMDk5ODEsMTY0NzY3NDYsMTY1NTk3NjEsMTY3MDQ5ODVdLFJlZHM1OlsxMDgxNzMwMSwxNDU2MDU1MCwxNjQ3Njc0NiwxNjU1OTc2MSwxNjcwNDk4NV0sUmVkczY6WzEwODE3MzAxLDE0NTYwNTUwLDE2NDc2NzQ2LDE2NTUyNTYyLDE2NTYzMTA1LDE2NzA0OTg1XSxSZWRzNzpbMTAwMjcwMjEsMTMzMDk5ODEsMTU2NzgyNTIsMTY0NzY3NDYsMTY1NTI1NjIsMTY1NjMxMDUsMTY3MDQ5ODVdLFJlZHM4OlsxMDAyNzAyMSwxMzMwOTk4MSwxNTY3ODI1MiwxNjQ3Njc0NiwxNjU1MjU2MiwxNjU2MzEwNSwxNjcwMzY5OCwxNjc3NDY0MF0sUmVkczk6WzY3NTAyMjEsMTA4MTczMDEsMTMzMDk5ODEsMTU2NzgyNTIsMTY0NzY3NDYsMTY1NTI1NjIsMTY1NjMxMDUsMTY3MDM2OTgsMTY3NzQ2NDBdfSxHcmV5czp7R3JleXMzOls2NTEzNTA3LDEyNDM0ODc3LDE1NzkwMzIwXSxHcmV5czQ6WzUzOTUwMjYsOTg2ODk1MCwxMzQyMTc3MiwxNjI1MDg3MV0sR3JleXM1OlsyNDM0MzQxLDY1MTM1MDcsOTg2ODk1MCwxMzQyMTc3MiwxNjI1MDg3MV0sR3JleXM2OlsyNDM0MzQxLDY1MTM1MDcsOTg2ODk1MCwxMjQzNDg3NywxNDI3NzA4MSwxNjI1MDg3MV0sR3JleXM3OlsyNDM0MzQxLDUzOTUwMjYsNzU2NjE5NSw5ODY4OTUwLDEyNDM0ODc3LDE0Mjc3MDgxLDE2MjUwODcxXSxHcmV5czg6WzI0MzQzNDEsNTM5NTAyNiw3NTY2MTk1LDk4Njg5NTAsMTI0MzQ4NzcsMTQyNzcwODEsMTU3OTAzMjAsMTY3NzcyMTVdLEdyZXlzOTpbMCwyNDM0MzQxLDUzOTUwMjYsNzU2NjE5NSw5ODY4OTUwLDEyNDM0ODc3LDE0Mjc3MDgxLDE1NzkwMzIwLDE2Nzc3MjE1XSxHcmV5czEwOlswLDE4NDIyMDQsMzY4NDQwOCw1NTkyNDA1LDc0MzQ2MDksOTI3NjgxMywxMTE4NDgxMCwxMzAyNzAxNCwxNDg2OTIxOCwxNjc3NzIxNV0sR3JleXMxMTpbMCwxNjQ0ODI1LDMzNTU0NDMsNTAwMDI2OCw2NzEwODg2LDgzNTU3MTEsMTAwNjYzMjksMTE3MTExNTQsMTM0MjE3NzIsMTUwNjY1OTcsMTY3NzcyMTVdLEdyZXlzMjU2OlswLDY1NzkzLDEzMTU4NiwxOTczNzksMjYzMTcyLDMyODk2NSwzOTQ3NTgsNDYwNTUxLDUyNjM0NCw1OTIxMzcsNjU3OTMwLDcyMzcyMyw3ODk1MTYsODU1MzA5LDkyMTEwMiw5ODY4OTUsMTA1MjY4OCwxMTE4NDgxLDExODQyNzQsMTI1MDA2NywxMzE1ODYwLDEzODE2NTMsMTQ0NzQ0NiwxNTEzMjM5LDE1NzkwMzIsMTY0NDgyNSwxNzEwNjE4LDE3NzY0MTEsMTg0MjIwNCwxOTA3OTk3LDE5NzM3OTAsMjAzOTU4MywyMTA1Mzc2LDIxNzExNjksMjIzNjk2MiwyMzAyNzU1LDIzNjg1NDgsMjQzNDM0MSwyNTAwMTM0LDI1NjU5MjcsMjYzMTcyMCwyNjk3NTEzLDI3NjMzMDYsMjgyOTA5OSwyODk0ODkyLDI5NjA2ODUsMzAyNjQ3OCwzMDkyMjcxLDMxNTgwNjQsMzIyMzg1NywzMjg5NjUwLDMzNTU0NDMsMzQyMTIzNiwzNDg3MDI5LDM1NTI4MjIsMzYxODYxNSwzNjg0NDA4LDM3NTAyMDEsMzgxNTk5NCwzODgxNzg3LDM5NDc1ODAsNDAxMzM3Myw0MDc5MTY2LDQxNDQ5NTksNDIxMDc1Miw0Mjc2NTQ1LDQzNDIzMzgsNDQwODEzMSw0NDczOTI0LDQ1Mzk3MTcsNDYwNTUxMCw0NjcxMzAzLDQ3MzcwOTYsNDgwMjg4OSw0ODY4NjgyLDQ5MzQ0NzUsNTAwMDI2OCw1MDY2MDYxLDUxMzE4NTQsNTE5NzY0Nyw1MjYzNDQwLDUzMjkyMzMsNTM5NTAyNiw1NDYwODE5LDU1MjY2MTIsNTU5MjQwNSw1NjU4MTk4LDU3MjM5OTEsNTc4OTc4NCw1ODU1NTc3LDU5MjEzNzAsNTk4NzE2Myw2MDUyOTU2LDYxMTg3NDksNjE4NDU0Miw2MjUwMzM1LDYzMTYxMjgsNjM4MTkyMSw2NDQ3NzE0LDY1MTM1MDcsNjU3OTMwMCw2NjQ1MDkzLDY3MTA4ODYsNjc3NjY3OSw2ODQyNDcyLDY5MDgyNjUsNjk3NDA1OCw3MDM5ODUxLDcxMDU2NDQsNzE3MTQzNyw3MjM3MjMwLDczMDMwMjMsNzM2ODgxNiw3NDM0NjA5LDc1MDA0MDIsNzU2NjE5NSw3NjMxOTg4LDc2OTc3ODEsNzc2MzU3NCw3ODI5MzY3LDc4OTUxNjAsNzk2MDk1Myw4MDI2NzQ2LDgwOTI1MzksODE1ODMzMiw4MjI0MTI1LDgyODk5MTgsODM1NTcxMSw4NDIxNTA0LDg0ODcyOTcsODU1MzA5MCw4NjE4ODgzLDg2ODQ2NzYsODc1MDQ2OSw4ODE2MjYyLDg4ODIwNTUsODk0Nzg0OCw5MDEzNjQxLDkwNzk0MzQsOTE0NTIyNyw5MjExMDIwLDkyNzY4MTMsOTM0MjYwNiw5NDA4Mzk5LDk0NzQxOTIsOTUzOTk4NSw5NjA1Nzc4LDk2NzE1NzEsOTczNzM2NCw5ODAzMTU3LDk4Njg5NTAsOTkzNDc0MywxMDAwMDUzNiwxMDA2NjMyOSwxMDEzMjEyMiwxMDE5NzkxNSwxMDI2MzcwOCwxMDMyOTUwMSwxMDM5NTI5NCwxMDQ2MTA4NywxMDUyNjg4MCwxMDU5MjY3MywxMDY1ODQ2NiwxMDcyNDI1OSwxMDc5MDA1MiwxMDg1NTg0NSwxMDkyMTYzOCwxMDk4NzQzMSwxMTA1MzIyNCwxMTExOTAxNywxMTE4NDgxMCwxMTI1MDYwMywxMTMxNjM5NiwxMTM4MjE4OSwxMTQ0Nzk4MiwxMTUxMzc3NSwxMTU3OTU2OCwxMTY0NTM2MSwxMTcxMTE1NCwxMTc3Njk0NywxMTg0Mjc0MCwxMTkwODUzMywxMTk3NDMyNiwxMjA0MDExOSwxMjEwNTkxMiwxMjE3MTcwNSwxMjIzNzQ5OCwxMjMwMzI5MSwxMjM2OTA4NCwxMjQzNDg3NywxMjUwMDY3MCwxMjU2NjQ2MywxMjYzMjI1NiwxMjY5ODA0OSwxMjc2Mzg0MiwxMjgyOTYzNSwxMjg5NTQyOCwxMjk2MTIyMSwxMzAyNzAxNCwxMzA5MjgwNywxMzE1ODYwMCwxMzIyNDM5MywxMzI5MDE4NiwxMzM1NTk3OSwxMzQyMTc3MiwxMzQ4NzU2NSwxMzU1MzM1OCwxMzYxOTE1MSwxMzY4NDk0NCwxMzc1MDczNywxMzgxNjUzMCwxMzg4MjMyMywxMzk0ODExNiwxNDAxMzkwOSwxNDA3OTcwMiwxNDE0NTQ5NSwxNDIxMTI4OCwxNDI3NzA4MSwxNDM0Mjg3NCwxNDQwODY2NywxNDQ3NDQ2MCwxNDU0MDI1MywxNDYwNjA0NiwxNDY3MTgzOSwxNDczNzYzMiwxNDgwMzQyNSwxNDg2OTIxOCwxNDkzNTAxMSwxNTAwMDgwNCwxNTA2NjU5NywxNTEzMjM5MCwxNTE5ODE4MywxNTI2Mzk3NiwxNTMyOTc2OSwxNTM5NTU2MiwxNTQ2MTM1NSwxNTUyNzE0OCwxNTU5Mjk0MSwxNTY1ODczNCwxNTcyNDUyNywxNTc5MDMyMCwxNTg1NjExMywxNTkyMTkwNiwxNTk4NzY5OSwxNjA1MzQ5MiwxNjExOTI4NSwxNjE4NTA3OCwxNjI1MDg3MSwxNjMxNjY2NCwxNjM4MjQ1NywxNjQ0ODI1MCwxNjUxNDA0MywxNjU3OTgzNiwxNjY0NTYyOSwxNjcxMTQyMiwxNjc3NzIxNV19LFB1T3I6e1B1T3IzOlsxMDA2MzU1NSwxNjI1MDg3MSwxNTgzNTk2OF0sUHVPcjQ6WzYxNzU4OTcsMTE3MDkzOTQsMTY2Mjc4MTEsMTUwOTgxMTNdLFB1T3I1Ols2MTc1ODk3LDExNzA5Mzk0LDE2MjUwODcxLDE2NjI3ODExLDE1MDk4MTEzXSxQdU9yNjpbNTUxNTE0NCwxMDA2MzU1NSwxNDIxMTgxOSwxNjcwMzY3MCwxNTgzNTk2OCwxMTc1MzQ3OF0sUHVPcjc6WzU1MTUxNDQsMTAwNjM1NTUsMTQyMTE4MTksMTYyNTA4NzEsMTY3MDM2NzAsMTU4MzU5NjgsMTE3NTM0NzhdLFB1T3I4Ols1NTE1MTQ0LDg0MTgyMjAsMTE3MDkzOTQsMTQyMTE4MTksMTY3MDM2NzAsMTY2Mjc4MTEsMTQ3MTMzNjQsMTE3NTM0NzhdLFB1T3I5Ols1NTE1MTQ0LDg0MTgyMjAsMTE3MDkzOTQsMTQyMTE4MTksMTYyNTA4NzEsMTY3MDM2NzAsMTY2Mjc4MTEsMTQ3MTMzNjQsMTE3NTM0NzhdLFB1T3IxMDpbMjk0OTE5NSw1NTE1MTQ0LDg0MTgyMjAsMTE3MDkzOTQsMTQyMTE4MTksMTY3MDM2NzAsMTY2Mjc4MTEsMTQ3MTMzNjQsMTE3NTM0NzgsODMzODE4NF0sUHVPcjExOlsyOTQ5MTk1LDU1MTUxNDQsODQxODIyMCwxMTcwOTM5NCwxNDIxMTgxOSwxNjI1MDg3MSwxNjcwMzY3MCwxNjYyNzgxMSwxNDcxMzM2NCwxMTc1MzQ3OCw4MzM4MTg0XX0sQnJCRzp7QnJCRzM6WzU5NDQ0OTIsMTYxMTkyODUsMTQyMDE3MDFdLEJyQkc0Ols5OTY5Nyw4NDQxMjgxLDE0NjY0MzE3LDEwOTAzODM0XSxCckJHNTpbOTk2OTcsODQ0MTI4MSwxNjExOTI4NSwxNDY2NDMxNywxMDkwMzgzNF0sQnJCRzY6WzkxNzQyLDU5NDQ0OTIsMTMxMDE3OTcsMTYxODE0NDMsMTQyMDE3MDEsOTE5NTc4Nl0sQnJCRzc6WzkxNzQyLDU5NDQ0OTIsMTMxMDE3OTcsMTYxMTkyODUsMTYxODE0NDMsMTQyMDE3MDEsOTE5NTc4Nl0sQnJCRzg6WzkxNzQyLDM1MTIyMDcsODQ0MTI4MSwxMzEwMTc5NywxNjE4MTQ0MywxNDY2NDMxNywxMjU1MDQ0NSw5MTk1Nzg2XSxCckJHOTpbOTE3NDIsMzUxMjIwNyw4NDQxMjgxLDEzMTAxNzk3LDE2MTE5Mjg1LDE2MTgxNDQzLDE0NjY0MzE3LDEyNTUwNDQ1LDkxOTU3ODZdLEJyQkcxMDpbMTU0MDgsOTE3NDIsMzUxMjIwNyw4NDQxMjgxLDEzMTAxNzk3LDE2MTgxNDQzLDE0NjY0MzE3LDEyNTUwNDQ1LDkxOTU3ODYsNTUxNzMxN10sQnJCRzExOlsxNTQwOCw5MTc0MiwzNTEyMjA3LDg0NDEyODEsMTMxMDE3OTcsMTYxMTkyODUsMTYxODE0NDMsMTQ2NjQzMTcsMTI1NTA0NDUsOTE5NTc4Niw1NTE3MzE3XX0sUFJHbjp7UFJHbjM6WzgzNzIwOTEsMTYyNTA4NzEsMTE1MDUwOTFdLFBSR240OlszNDg3MSwxMDkzNTIwMCwxMjc1NjQzMSw4MDczODc2XSxQUkduNTpbMzQ4NzEsMTA5MzUyMDAsMTYyNTA4NzEsMTI3NTY0MzEsODA3Mzg3Nl0sUFJHbjY6WzE4MDAyNDcsODM3MjA5MSwxNDI4Mjk2MywxNTE5MzMyMCwxMTUwNTA5MSw3NzQ0MTMxXSxQUkduNzpbMTgwMDI0Nyw4MzcyMDkxLDE0MjgyOTYzLDE2MjUwODcxLDE1MTkzMzIwLDExNTA1MDkxLDc3NDQxMzFdLFBSR244OlsxODAwMjQ3LDU5NDI4ODEsMTA5MzUyMDAsMTQyODI5NjMsMTUxOTMzMjAsMTI3NTY0MzEsMTAwNTU4NTEsNzc0NDEzMV0sUFJHbjk6WzE4MDAyNDcsNTk0Mjg4MSwxMDkzNTIwMCwxNDI4Mjk2MywxNjI1MDg3MSwxNTE5MzMyMCwxMjc1NjQzMSwxMDA1NTg1MSw3NzQ0MTMxXSxQUkduMTA6WzE3NDM1LDE4MDAyNDcsNTk0Mjg4MSwxMDkzNTIwMCwxNDI4Mjk2MywxNTE5MzMyMCwxMjc1NjQzMSwxMDA1NTg1MSw3NzQ0MTMxLDQxOTQzNzldLFBSR24xMTpbMTc0MzUsMTgwMDI0Nyw1OTQyODgxLDEwOTM1MjAwLDE0MjgyOTYzLDE2MjUwODcxLDE1MTkzMzIwLDEyNzU2NDMxLDEwMDU1ODUxLDc3NDQxMzEsNDE5NDM3OV19LFBpWUc6e1BpWUczOlsxMDYwNjQ0MiwxNjI1MDg3MSwxNTMxMTgxN10sUGlZRzQ6WzUwOTAzNDIsMTIxMTYzNTgsMTU4NDA5ODYsMTM2Mzg3OTVdLFBpWUc1Ols1MDkwMzQyLDEyMTE2MzU4LDE2MjUwODcxLDE1ODQwOTg2LDEzNjM4Nzk1XSxQaVlHNjpbNTA4MzY4MSwxMDYwNjQ0MiwxNTEzNjIwOCwxNjYzODE5MSwxNTMxMTgxNywxMjkxNzYyOV0sUGlZRzc6WzUwODM2ODEsMTA2MDY0NDIsMTUxMzYyMDgsMTYyNTA4NzEsMTY2MzgxOTEsMTUzMTE4MTcsMTI5MTc2MjldLFBpWUc4Ols1MDgzNjgxLDgzNzEyNjUsMTIxMTYzNTgsMTUxMzYyMDgsMTY2MzgxOTEsMTU4NDA5ODYsMTQ1Nzk2MzAsMTI5MTc2MjldLFBpWUc5Ols1MDgzNjgxLDgzNzEyNjUsMTIxMTYzNTgsMTUxMzYyMDgsMTYyNTA4NzEsMTY2MzgxOTEsMTU4NDA5ODYsMTQ1Nzk2MzAsMTI5MTc2MjldLFBpWUcxMDpbMjU4MTUyOSw1MDgzNjgxLDgzNzEyNjUsMTIxMTYzNTgsMTUxMzYyMDgsMTY2MzgxOTEsMTU4NDA5ODYsMTQ1Nzk2MzAsMTI5MTc2MjksOTMwNjQ1MF0sUGlZRzExOlsyNTgxNTI5LDUwODM2ODEsODM3MTI2NSwxMjExNjM1OCwxNTEzNjIwOCwxNjI1MDg3MSwxNjYzODE5MSwxNTg0MDk4NiwxNDU3OTYzMCwxMjkxNzYyOSw5MzA2NDUwXX0sUmRCdTp7UmRCdTM6WzY3OTM2NzksMTYyNTA4NzEsMTU2OTg1MzBdLFJkQnU0OlszNTY3ODQsOTYxODkxMCwxNjAzMzE1NCwxMzIzODMwNF0sUmRCdTU6WzM1Njc4NCw5NjE4OTEwLDE2MjUwODcxLDE2MDMzMTU0LDEzMjM4MzA0XSxSZEJ1NjpbMjE4ODk3Miw2NzkzNjc5LDEzNzU1ODg4LDE2NjM2ODcxLDE1Njk4NTMwLDExNjcxNTk1XSxSZEJ1NzpbMjE4ODk3Miw2NzkzNjc5LDEzNzU1ODg4LDE2MjUwODcxLDE2NjM2ODcxLDE1Njk4NTMwLDExNjcxNTk1XSxSZEJ1ODpbMjE4ODk3Miw0NDI4NzM5LDk2MTg5MTAsMTM3NTU4ODgsMTY2MzY4NzEsMTYwMzMxNTQsMTQwNDkzNTcsMTE2NzE1OTVdLFJkQnU5OlsyMTg4OTcyLDQ0Mjg3MzksOTYxODkxMCwxMzc1NTg4OCwxNjI1MDg3MSwxNjYzNjg3MSwxNjAzMzE1NCwxNDA0OTM1NywxMTY3MTU5NV0sUmRCdTEwOlszNDAwNjUsMjE4ODk3Miw0NDI4NzM5LDk2MTg5MTAsMTM3NTU4ODgsMTY2MzY4NzEsMTYwMzMxNTQsMTQwNDkzNTcsMTE2NzE1OTUsNjc1MDIzOV0sUmRCdTExOlszNDAwNjUsMjE4ODk3Miw0NDI4NzM5LDk2MTg5MTAsMTM3NTU4ODgsMTYyNTA4NzEsMTY2MzY4NzEsMTYwMzMxNTQsMTQwNDkzNTcsMTE2NzE1OTUsNjc1MDIzOV19LFJkR3k6e1JkR3kzOlsxMDA2NjMyOSwxNjc3NzIxNSwxNTY5ODUzMF0sUmRHeTQ6WzQyMTA3NTIsMTIyMzc0OTgsMTYwMzMxNTQsMTMyMzgzMDRdLFJkR3k1Ols0MjEwNzUyLDEyMjM3NDk4LDE2Nzc3MjE1LDE2MDMzMTU0LDEzMjM4MzA0XSxSZEd5NjpbNTA2NjA2MSwxMDA2NjMyOSwxNDczNzYzMiwxNjYzNjg3MSwxNTY5ODUzMCwxMTY3MTU5NV0sUmRHeTc6WzUwNjYwNjEsMTAwNjYzMjksMTQ3Mzc2MzIsMTY3NzcyMTUsMTY2MzY4NzEsMTU2OTg1MzAsMTE2NzE1OTVdLFJkR3k4Ols1MDY2MDYxLDg4ODIwNTUsMTIyMzc0OTgsMTQ3Mzc2MzIsMTY2MzY4NzEsMTYwMzMxNTQsMTQwNDkzNTcsMTE2NzE1OTVdLFJkR3k5Ols1MDY2MDYxLDg4ODIwNTUsMTIyMzc0OTgsMTQ3Mzc2MzIsMTY3NzcyMTUsMTY2MzY4NzEsMTYwMzMxNTQsMTQwNDkzNTcsMTE2NzE1OTVdLFJkR3kxMDpbMTcxMDYxOCw1MDY2MDYxLDg4ODIwNTUsMTIyMzc0OTgsMTQ3Mzc2MzIsMTY2MzY4NzEsMTYwMzMxNTQsMTQwNDkzNTcsMTE2NzE1OTUsNjc1MDIzOV0sUmRHeTExOlsxNzEwNjE4LDUwNjYwNjEsODg4MjA1NSwxMjIzNzQ5OCwxNDczNzYzMiwxNjc3NzIxNSwxNjYzNjg3MSwxNjAzMzE1NCwxNDA0OTM1NywxMTY3MTU5NSw2NzUwMjM5XX0sUmRZbEJ1OntSZFlsQnUzOls5NTUxODM1LDE2Nzc3MTUxLDE2NTUxMjU3XSxSZFlsQnU0OlsyOTE1MjU0LDExMjYyNDQxLDE2NjI1MjQ5LDE0MDk2NjY4XSxSZFlsQnU1OlsyOTE1MjU0LDExMjYyNDQxLDE2Nzc3MTUxLDE2NjI1MjQ5LDE0MDk2NjY4XSxSZFlsQnU2Ols0NTUyMTE2LDk1NTE4MzUsMTQ3NDI1MjAsMTY3MDM2MzIsMTY1NTEyNTcsMTQxMDI1NjddLFJkWWxCdTc6WzQ1NTIxMTYsOTU1MTgzNSwxNDc0MjUyMCwxNjc3NzE1MSwxNjcwMzYzMiwxNjU1MTI1NywxNDEwMjU2N10sUmRZbEJ1ODpbNDU1MjExNiw3NjQ2NjczLDExMjYyNDQxLDE0NzQyNTIwLDE2NzAzNjMyLDE2NjI1MjQ5LDE2MDE4NzU1LDE0MTAyNTY3XSxSZFlsQnU5Ols0NTUyMTE2LDc2NDY2NzMsMTEyNjI0NDEsMTQ3NDI1MjAsMTY3NzcxNTEsMTY3MDM2MzIsMTY2MjUyNDksMTYwMTg3NTUsMTQxMDI1NjddLFJkWWxCdTEwOlszMjI1MjM3LDQ1NTIxMTYsNzY0NjY3MywxMTI2MjQ0MSwxNDc0MjUyMCwxNjcwMzYzMiwxNjYyNTI0OSwxNjAxODc1NSwxNDEwMjU2NywxMDgxMzQ3OF0sUmRZbEJ1MTE6WzMyMjUyMzcsNDU1MjExNiw3NjQ2NjczLDExMjYyNDQxLDE0NzQyNTIwLDE2Nzc3MTUxLDE2NzAzNjMyLDE2NjI1MjQ5LDE2MDE4NzU1LDE0MTAyNTY3LDEwODEzNDc4XX0sU3BlY3RyYWw6e1NwZWN0cmFsMzpbMTAwODE2ODQsMTY3NzcxNTEsMTY1NTEyNTddLFNwZWN0cmFsNDpbMjg1MTc3MCwxMTI2MzM5NiwxNjYyNTI0OSwxNDA5NjY2OF0sU3BlY3RyYWw1OlsyODUxNzcwLDExMjYzMzk2LDE2Nzc3MTUxLDE2NjI1MjQ5LDE0MDk2NjY4XSxTcGVjdHJhbDY6WzMzMTE4MDUsMTAwODE2ODQsMTUxMzYxNTIsMTY3MDM2MjcsMTY1NTEyNTcsMTM5NzUxMTldLFNwZWN0cmFsNzpbMzMxMTgwNSwxMDA4MTY4NCwxNTEzNjE1MiwxNjc3NzE1MSwxNjcwMzYyNywxNjU1MTI1NywxMzk3NTExOV0sU3BlY3RyYWw4OlszMzExODA1LDY3MzQ1MDEsMTEyNjMzOTYsMTUxMzYxNTIsMTY3MDM2MjcsMTY2MjUyNDksMTYwMTg3NTUsMTM5NzUxMTldLFNwZWN0cmFsOTpbMzMxMTgwNSw2NzM0NTAxLDExMjYzMzk2LDE1MTM2MTUyLDE2Nzc3MTUxLDE2NzAzNjI3LDE2NjI1MjQ5LDE2MDE4NzU1LDEzOTc1MTE5XSxTcGVjdHJhbDEwOls2MTgwNzcwLDMzMTE4MDUsNjczNDUwMSwxMTI2MzM5NiwxNTEzNjE1MiwxNjcwMzYyNywxNjYyNTI0OSwxNjAxODc1NSwxMzk3NTExOSwxMDM1NTAxMF0sU3BlY3RyYWwxMTpbNjE4MDc3MCwzMzExODA1LDY3MzQ1MDEsMTEyNjMzOTYsMTUxMzYxNTIsMTY3NzcxNTEsMTY3MDM2MjcsMTY2MjUyNDksMTYwMTg3NTUsMTM5NzUxMTksMTAzNTUwMTBdfSxSZFlsR246e1JkWWxHbjM6Wzk1NTU4MDgsMTY3NzcxNTEsMTY1NTEyNTddLFJkWWxHbjQ6WzE3NDI0MDEsMTA5MzQ2MzQsMTY2MjUyNDksMTQwOTY2NjhdLFJkWWxHbjU6WzE3NDI0MDEsMTA5MzQ2MzQsMTY3NzcxNTEsMTY2MjUyNDksMTQwOTY2NjhdLFJkWWxHbjY6WzE3NDI5MjgsOTU1NTgwOCwxNDI4MjYzNSwxNjcwMzYyNywxNjU1MTI1NywxNDEwMjU2N10sUmRZbEduNzpbMTc0MjkyOCw5NTU1ODA4LDE0MjgyNjM1LDE2Nzc3MTUxLDE2NzAzNjI3LDE2NTUxMjU3LDE0MTAyNTY3XSxSZFlsR244OlsxNzQyOTI4LDY3MzMxNTUsMTA5MzQ2MzQsMTQyODI2MzUsMTY3MDM2MjcsMTY2MjUyNDksMTYwMTg3NTUsMTQxMDI1NjddLFJkWWxHbjk6WzE3NDI5MjgsNjczMzE1NSwxMDkzNDYzNCwxNDI4MjYzNSwxNjc3NzE1MSwxNjcwMzYyNywxNjYyNTI0OSwxNjAxODc1NSwxNDEwMjU2N10sUmRZbEduMTA6WzI2Njc5LDE3NDI5MjgsNjczMzE1NSwxMDkzNDYzNCwxNDI4MjYzNSwxNjcwMzYyNywxNjYyNTI0OSwxNjAxODc1NSwxNDEwMjU2NywxMDgxMzQ3OF0sUmRZbEduMTE6WzI2Njc5LDE3NDI5MjgsNjczMzE1NSwxMDkzNDYzNCwxNDI4MjYzNSwxNjc3NzE1MSwxNjcwMzYyNywxNjYyNTI0OSwxNjAxODc1NSwxNDEwMjU2NywxMDgxMzQ3OF19LEluZmVybm86e0luZmVybm8zOls0NDU2Nzg4LDIxMzM5MDAsMTY2Mzk3ODBdLEluZmVybm80OlszLDc4NzE1OTcsMTU1NTg2OTMsMTY1ODAyNjBdLEluZmVybm81OlszLDU1NzQ1MDksMTIyMDM2MDUsMTYzNTQzMTMsMTY1ODAyNjBdLEluZmVybm82OlszLDQyNjIyNDcsOTY0MzM2NywxNDQzODQ1NywxNjQ5MTUzMCwxNjU4MDI2MF0sSW5mZXJubzc6WzMsMzI3OTE5Nyw3ODcxNTk3LDEyMjAzNjA1LDE1NTU4NjkzLDE2NDk1Mzg0LDE2NTgwMjYwXSxJbmZlcm5vODpbMywyNTU4ODAyLDY0OTMyOTQsMTAzNjUyODMsMTM3ODA4MDIsMTYwODgwODUsMTY0MzI5MzMsMTY1ODAyNjBdLEluZmVybm85OlszLDIwMzQ3NTksNTU3NDUwOSw4OTIxNDUwLDEyMjAzNjA1LDE0ODk5MjUwLDE2MzU0MzEzLDE2MzA0NDMzLDE2NTgwMjYwXSxJbmZlcm5vMTA6WzMsMTcwNjgxNiw0ODUyNTg2LDc4NzE1OTcsMTA3NTkyNjQsMTM0NTE4NDcsMTU1NTg2OTMsMTY0ODg3MTAsMTYyNDA0NDIsMTY1ODAyNjBdLEluZmVybm8xMTpbMywxNDQ0NjY1LDQyNjIyNDcsNjk1MjgxNCw5NjQzMzY3LDEyMjAzNjA1LDE0NDM4NDU3LDE1ODg5NjkwLDE2NDkxNTMwLDE2MTc2NDUwLDE2NTgwMjYwXSxJbmZlcm5vMjU2OlszLDQsNiw2NTU0Myw2NTgwMSw2NTgwMywxMzEzNDIsMTMxNjAwLDE5NzEzOCwyNjI5MzIsMjYyOTM0LDMyODcyOCwzOTQyNjcsNDYwMDYxLDUyNTg1NSw1OTEzOTMsNjU3MTg3LDcyMjcyNiw4NTQwNTYsOTE5NTk0LDk4NTM4OSwxMDUwOTI3LDExODIyNTgsMTI0Nzc5NiwxMzEzNTkwLDE0NDQ2NjUsMTUxMDIwMywxNjQxMjc4LDE3MDY4MTYsMTgzODE0NywxOTAzNjg1LDIwMzQ3NTksMjEwMDI5OCwyMjMxMTE2LDIzNjIxOTAsMjQ5MzI2NCwyNTU4ODAyLDI2ODk4NzYsMjgyMDY5NCwyOTUxNzY4LDMwMTczMDYsMzE0ODM4MCwzMjc5MTk3LDM0MTAyNzEsMzQ3NTgwOCwzNjA2ODgxLDM3Mzc5NTQsMzg2OTAyOCwzOTM0NTY1LDQwNjU2MzgsNDE5NjcxMCw0MjYyMjQ3LDQzOTM1NzYsNDUyNDY0OSw0NTkwMTg1LDQ3MjE1MTQsNDg1MjU4Niw0OTE4Mzc5LDUwNDk0NTEsNTE4MDc4MCw1MjQ2MzE2LDUzNzc2NDQsNTQ0MzE4MSw1NTc0NTA5LDU3MDU1ODEsNTc3MTM3Myw1OTAyNzAxLDU5NjgyMzgsNjA5OTU2Niw2MjMwNjM4LDYyOTY0MzAsNjQyNzc1OCw2NDkzMjk0LDY2MjQ2MjIsNjY5MDE1OCw2ODIxNDg2LDY5NTI4MTQsNzAxODM1MCw3MTQ5Njc4LDcyMTUyMTQsNzM0NjU0Miw3NDc3NjEzLDc1NDM0MDUsNzY3NDczMyw3NzQwMjY5LDc4NzE1OTcsODAwMjY2OSw4MDY4NDYwLDgxOTk1MzIsODI2NTMyNCw4Mzk2NjUxLDg0NjIxODcsODU5MzUxNSw4NzI0NTg2LDg3OTAzNzgsODkyMTQ1MCw4OTg3MjQxLDkxMTgzMTMsOTI0OTY0MSw5MzE1NDMyLDk0NDY1MDQsOTUxMjI5NSw5NjQzMzY3LDk3NzQ2OTQsOTg0MDIzMCw5OTcxNTU3LDEwMDM3MzQ4LDEwMTY4NDIwLDEwMjM0MjExLDEwMzY1MjgzLDEwNDk2NjEwLDEwNTYyNDAxLDEwNjkzNDczLDEwNzU5MjY0LDEwODkwMzM1LDEwOTU2MTI3LDExMDg3NDU0LDExMjE4NTI1LDExMjg0MzE2LDExNDE1NjQzLDExNDgxNDM1LDExNjEyNTA2LDExNjc4Mjk3LDExODA5NjI0LDExODc1MTU5LDEyMDA2NDg2LDEyMDcyMjc4LDEyMjAzNjA1LDEyMjY5Mzk2LDEyNDAwNDY3LDEyNDY2MjU4LDEyNTMyMDQ5LDEyNjYzMzc2LDEyNzI5MTY3LDEyODYwNDk0LDEyOTI2Mjg1LDEzMDU3NjEyLDEzMTIzMTQ3LDEzMTg4OTM4LDEzMzIwMjY1LDEzMzg2MDU2LDEzNDUxODQ3LDEzNTgzNDMwLDEzNjQ5MjIwLDEzNzE1MDExLDEzNzgwODAyLDEzOTEyMTI5LDEzOTc3OTIwLDE0MDQzNzExLDE0MTA5NTAyLDE0MjQxMDg1LDE0MzA2ODc1LDE0MzcyNjY2LDE0NDM4NDU3LDE0NTA0NTA0LDE0NTcwMjk1LDE0NjM2MDg2LDE0NzAyMTMyLDE0ODMzNDU5LDE0ODk5MjUwLDE0OTY1Mjk3LDE1MDMxMDg4LDE1MDk2ODc4LDE1MDk3Mzg5LDE1MTYzMTgwLDE1MjI5MjI3LDE1Mjk1MDE4LDE1MzYxMDY0LDE1NDI2ODU1LDE1NDkyOTAyLDE1NTU4NjkzLDE1NTU5MjAzLDE1NjI1MjUwLDE1NjkxMDQxLDE1NzU3MDg3LDE1NzU3MzQyLDE1ODIzMzg5LDE1ODg5NDM2LDE1ODg5NjkwLDE1OTU1NzM3LDE1OTU2MjQ4LDE2MDIyMDM4LDE2MDg4MDg1LDE2MDg4NTk2LDE2MTU0NjQyLDE2MTU0ODk3LDE2MjIwOTQ0LDE2MjIxNDU0LDE2Mjg3NTAxLDE2Mjg3NzU2LDE2Mjg4MjY3LDE2MzU0MzEzLDE2MzU0ODI0LDE2MzU1MzM2LDE2NDIxMTI3LDE2NDIxNjM4LDE2NDIyMTUwLDE2NDIyNjYyLDE2NDg4NzEwLDE2NDg5MjIyLDE2NDg5NzM0LDE2NDg5OTkxLDE2NDkwNTAzLDE2NDkxMDE2LDE2NDkxNTMwLDE2NDkyMDQzLDE2NDkyNTU3LDE2NDkzMDcwLDE2NDkzNTg0LDE2NDk0MDk4LDE2NDk0NjEyLDE2NDk0ODcwLDE2NDk1Mzg0LDE2NDk1ODk4LDE2NDk2NDEyLDE2NDk2OTI2LDE2NDMxOTA1LDE2NDMyNDE5LDE2NDMyOTMzLDE2NDMzNDQ4LDE2MzY4NDI2LDE2MzY4OTQwLDE2MzY5NDU1LDE2MzA0NDMzLDE2MzA0OTQ4LDE2MzA1NDYzLDE2MjQwNDQyLDE2MjQwOTU2LDE2MTc1OTM1LDE2MTc2NDUwLDE2MTExNDI5LDE2MTExOTQ0LDE2MDQ2OTIzLDE2MDQ3MTgzLDE1OTgyMTYyLDE1OTgyNjc4LDE1OTgzMTkzLDE1OTE4MTczLDE1OTE4Njg4LDE1ODUzNjY4LDE1ODUzOTI4LDE1ODU0NDQ0LDE1ODU0OTYwLDE1ODU1MjIwLDE1ODU1NzM3LDE1ODU2MjUzLDE1OTIyMDQ5LDE1OTIyMzA5LDE1OTg4MzYxLDE2MDU0MTU3LDE2MTE5OTUzLDE2MTg2MDA1LDE2MjUxODAxLDE2MzgzMTMzLDE2NDQ4OTI4LDE2NTgwMjYwXX0sTWFnbWE6e01hZ21hMzpbMywxMTg3NTk2MSwxNjUxNDIzOV0sTWFnbWE0OlszLDc0MTM2MzMsMTU3NTMzMDksMTY1MTQyMzldLE1hZ21hNTpbMyw1MTgxODE5LDExODc1OTYxLDE2NDgzOTM2LDE2NTE0MjM5XSxNYWdtYTY6WzMsMzg3MDU3NSw5MTg1NjY0LDE0NTAyMjQ4LDE2NjIxNDIwLDE2NTE0MjM5XSxNYWdtYTc6WzMsMjgyMjQ5NCw3NDEzNjMzLDExODc1OTYxLDE1NzUzMzA5LDE2NjkwODA2LDE2NTE0MjM5XSxNYWdtYTg6WzMsMjIzMjY1Niw2MTAwODYyLDk5MDczMjcsMTM3MTQwMzAsMTYyODI5NzIsMTY2OTM2MzEsMTY1MTQyMzldLE1hZ21hOTpbMywxNzczNjM2LDUxODE4MTksODQ2Mzc0NSwxMTg3NTk2MSwxNTAyODMyMywxNjQ4MzkzNiwxNjY5NTk0MiwxNjUxNDIzOV0sTWFnbWExMDpbMywxNTExMjI4LDQzOTQ4NjksNzQxMzYzMywxMDM2NjU5MCwxMzMxOTc5MywxNTc1MzMwOSwxNjU1MjgwNiwxNjY5NzIyNywxNjUxNDIzOV0sTWFnbWExMTpbMywxMzE0MTAxLDM4NzA1NzUsNjQ5NDU5MSw5MTg1NjY0LDExODc1OTYxLDE0NTAyMjQ4LDE2MTUwMTA3LDE2NjIxNDIwLDE2NjMzMjMyLDE2NTE0MjM5XSxNYWdtYTI1NjpbMyw0LDYsNjU1NDMsNjU4MDEsNjU4MDMsMTMxNTk3LDEzMTU5OSwxOTczOTMsMjYyOTMxLDI2MzE4OSwzMjg3MjcsMzk0NTIxLDQ2MDA1OSw1MjU4NTMsNTkxNjQ3LDY1NzE4Niw3MjI5ODAsNzg4Nzc0LDg1NDU2OCw5MjAxMDYsOTg1OTAwLDEwNTE2OTUsMTExNzIzMywxMTgzMDI3LDEzMTQxMDEsMTM3OTg5NiwxNDQ1NDM0LDE1MTEyMjgsMTU3Njc2NywxNzA4MDk3LDE3NzM2MzYsMTgzOTE3NCwxOTcwMjQ5LDIwMzYwNDMsMjEwMTU4MSwyMjMyNjU2LDIyOTgxOTQsMjQyOTI2OSwyNDk0ODA3LDI2MjU4ODEsMjc1Njk1NiwyODIyNDk0LDI5NTMzMTIsMzA4NDM4NiwzMTQ5OTI1LDMyODA5OTksMzQxMjA3MiwzNDc3MzU0LDM2MDg0MjgsMzczOTUwMiwzODcwNTc1LDM5MzYxMTMsNDA2NzE4Niw0MTk4MjU5LDQzMjkzMzIsNDM5NDg2OSw0NTI1OTQyLDQ2NTcwMTUsNDcyMjgwOCw0ODUzODgxLDQ5MTk0MTcsNTA1MDc0Niw1MTgxODE5LDUyNDc2MTEsNTM3ODY4NCw1NDQ0NDc2LDU1NzU1NDksNTcwNjg3Nyw1NzcyNjcwLDU5MDM3NDIsNTk2OTUzNCw2MTAwODYyLDYxNjYzOTksNjI5NzcyNyw2MzYzMjYzLDY0OTQ1OTEsNjYyNTkyMCw2NjkxNDU2LDY4MjI3ODQsNjg4ODU3Niw3MDE5NjQ4LDcwODU0NDAsNzIxNjc2OSw3MjgyMzA1LDc0MTM2MzMsNzU0NDcwNSw3NjEwNDk3LDc3NDE4MjUsNzgwNzM2MSw3OTM4Njg5LDgwMDQyMjUsODEzNTU1Myw4MjY2ODgxLDgzMzI0MTcsODQ2Mzc0NSw4NTI5MjgxLDg2NjA2MDksODcyNjE0NSw4ODU3NDczLDg5ODg4MDEsOTA1NDMzNyw5MTg1NjY0LDkyNTEyMDAsOTM4MjUyOCw5NTEzNjAwLDk1NzkzOTIsOTcxMDQ2NCw5Nzc2MjU2LDk5MDczMjcsMTAwMzg2NTUsMTAxMDQxOTEsMTAyMzU1MTksMTAzNjY1OTAsMTA0MzIzODIsMTA1NjM0NTQsMTA2OTQ3ODIsMTA3NjAzMTcsMTA4OTE2NDUsMTA5NTcxODEsMTEwODg1MDgsMTEyMTk4MzYsMTEyODUzNzEsMTE0MTY2OTksMTE1NDc3NzEsMTE2MTM1NjIsMTE3NDQ2MzQsMTE4NzU5NjEsMTE5NDE0OTcsMTIwNzI4MjQsMTIxMzgzNjAsMTIyNjk2ODcsMTI0MDEwMTUsMTI0NjY1NTAsMTI1OTc4NzcsMTI3Mjg5NDksMTI3OTQ3NDAsMTI5MjYwNjgsMTI5OTE2MDMsMTMxMjI5MzAsMTMyNTQyNTgsMTMzMTk3OTMsMTM0NTExMjAsMTM1MTY5MTIsMTM2NDgyMzksMTM3MTQwMzAsMTM4NDUxMDEsMTM5MTA4OTMsMTQwNDIyMjAsMTQxMDgwMTEsMTQyMzkzMzgsMTQzMDUxMjksMTQ0MzY0NTcsMTQ1MDIyNDgsMTQ1NjgwMzksMTQ2OTkzNjYsMTQ3NjUxNTgsMTQ4MzA5NDksMTQ5NjIyNzYsMTUwMjgzMjMsMTUwOTQxMTQsMTUxNTk5MDYsMTUyMjU5NTMsMTUzNTcyODAsMTU0MjMwNzIsMTU0ODkxMTksMTU1NTQ5MTEsMTU2MjA5NTgsMTU2MjE0NjksMTU2ODcyNjEsMTU3NTMzMDksMTU4MTkxMDAsMTU4ODUxNDgsMTU5NTExOTYsMTU5NTE3MDcsMTYwMTc0OTksMTYwODM1NDcsMTYwODQwNTksMTYxNTAxMDcsMTYxNTA2MTksMTYyMTY0MTEsMTYyMTY5MjQsMTYyODI5NzIsMTYyODM0ODQsMTYzNDk1MzIsMTYzNTAwNDUsMTYzNTA1NTcsMTY0MTY2MDYsMTY0MTY4NjIsMTY0MTczNzUsMTY0ODM0MjQsMTY0ODM5MzYsMTY0ODQ0NDksMTY0ODQ5NjIsMTY1NTEwMTEsMTY1NTE1MjMsMTY1NTIwMzYsMTY1NTI1NDksMTY1NTI4MDYsMTY2MTg4NTUsMTY2MTkzNjgsMTY2MTk4ODEsMTY2MjAzOTQsMTY2MjA5MDcsMTY2MjE0MjAsMTY2MjE5MzQsMTY2MjIxOTEsMTY2MjI3MDQsMTY2ODg3NTMsMTY2ODkyNjcsMTY2ODk3ODAsMTY2OTAyOTMsMTY2OTA4MDYsMTY2OTEwNjQsMTY2OTE1NzcsMTY2OTIwOTEsMTY2OTI2MDQsMTY2OTMxMTcsMTY2OTM2MzEsMTY2OTQxNDQsMTY2OTQ0MDIsMTY2OTQ5MTUsMTY2OTU0MjksMTY2OTU5NDIsMTY2OTY0NTYsMTY2OTY5NjksMTY2OTcyMjcsMTY2OTc3NDEsMTY2OTgyNTQsMTY2MzMyMzIsMTY2MzM3NDYsMTY2MzQyNTksMTY2MzQ1MTcsMTY2MzUwMzEsMTY2MzU1NDQsMTY2MzYwNTgsMTY2MzY1NzIsMTY2MzcwODUsMTY2MzczNDMsMTY2Mzc4NTcsMTY2MzgzNzEsMTY1NzMzNDksMTY1NzM4NjIsMTY1NzQxMjAsMTY1NzQ2MzQsMTY1NzUxNDgsMTY1NzU2NjIsMTY1NzYxNzYsMTY1NzY2ODksMTY1NzY5NDcsMTY1Nzc0NjEsMTY1Nzc5NzUsMTY1MTI5NTMsMTY1MTM0NjcsMTY1MTM3MjUsMTY1MTQyMzldfSxQbGFzbWE6e1BsYXNtYTM6Wzc4ODM1OCwxMzI1NjMxMiwxNTcyNjYyNV0sUGxhc21hNDpbNzg4MzU4LDEwMTY0MTI2LDE1NDk3Mjk5LDE1NzI2NjI1XSxQbGFzbWE1Ols3ODgzNTgsODEyNzE0MywxMzI1NjMxMiwxNjIyNTA4OSwxNTcyNjYyNV0sUGxhc21hNjpbNzg4MzU4LDY5NDY5ODMsMTE1NDUyMzEsMTQ3MDU3NjEsMTY1NTc2MjEsMTU3MjY2MjVdLFBsYXNtYTc6Wzc4ODM1OCw2MDI5NDc3LDEwMTY0MTI2LDEzMjU2MzEyLDE1NDk3Mjk5LDE2NjI2MjIzLDE1NzI2NjI1XSxQbGFzbWE4Ols3ODgzNTgsNTM3NDM3MSw4OTgwNjQ1LDEyMDcxNTYxLDE0MzA5OTkyLDE1OTU5ODgwLDE2NjI4NTIzLDE1NzI2NjI1XSxQbGFzbWE5Ols3ODgzNTgsNDg1MDMzNiw4MTI3MTQzLDExMDE4OTAyLDEzMjU2MzEyLDE1MDM1MjI4LDE2MjI1MDg5LDE2NjMwNTY4LDE1NzI2NjI1XSxQbGFzbWExMDpbNzg4MzU4LDQ1MjI5MTAsNzQ3MTI3MiwxMDE2NDEyNiwxMjMzNDcyNSwxNDExMjM2NCwxNTQ5NzI5OSwxNjQyNDI1MCwxNjU2NjA1NCwxNTcyNjYyNV0sUGxhc21hMTE6Wzc4ODM1OCw0MTk1MjI4LDY5NDY5ODMsOTM3NTEzOSwxMTU0NTIzMSwxMzI1NjMxMiwxNDcwNTc2MSwxNTgyNzUzMiwxNjU1NzYyMSwxNjU2NzMzMywxNTcyNjYyNV0sUGxhc21hMjU2Ols3ODgzNTgsMTA1MDUwMywxMjQ2ODU3LDEzNzc5MzAsMTU3NDUzOSwxNzcxMTQ4LDE5MDIyMjEsMjAzMzAzOCwyMTY0MTExLDIyOTUxODQsMjQyNjI1NywyNTU3MzMwLDI2ODg0MDMsMjgxOTQ3NiwyOTUwMjkyLDMwODEzNjUsMzIxMjQzOCwzMzQzNTExLDM0MDkwNDgsMzU0MDEyMCwzNjcxMTkzLDM4MDIyNjYsMzg2NzU0NiwzOTk4NjE5LDQxMjk2OTIsNDE5NTIyOCw0MzI2MzAxLDQ0NTczNzQsNDUyMjkxMCw0NjUzNzI3LDQ3ODQ3OTksNDg1MDMzNiw0OTgxNDA5LDUxMTI0ODEsNTE3ODAxOCw1MzA4ODM0LDUzNzQzNzEsNTUwNTQ0Myw1NjM2NTE1LDU3MDIwNTIsNTgzMzEyNCw1ODk4NDA1LDYwMjk0NzcsNjE2MDU0OSw2MjI2MDg2LDYzNTcxNTgsNjQyMjY5NCw2NTUzNzY3LDY2MTkzMDMsNjc1MDM3NSw2ODE1OTExLDY5NDY5ODMsNzA3ODA1Niw3MTQzNTkyLDcyNzQ2NjQsNzM0MDIwMCw3NDcxMjcyLDc1MzY4MDgsNzY2Nzg4MCw3NzMzNjcyLDc4NjQ3NDQsNzkzMDI4MCw4MDYxNjA4LDgxMjcxNDMsODI1ODQ3MSw4MzI0MDA3LDg0NTUzMzUsODUyMDg3MSw4NjUyMTk4LDg3MTc5OTAsODc4Mzc4Miw4OTE0ODUzLDg5ODA2NDUsOTExMTk3Miw5MTc3NzY0LDkzMDkzNDgsOTM3NTEzOSw5NDQwOTMxLDk1NzIyNTgsOTYzODA0OSw5NzY5Mzc3LDk4MzUxNjgsOTkwMDk2MCwxMDAzMjI4NywxMDA5ODA3OCwxMDE2NDEyNiwxMDI5NTQ1MywxMDM2MTI0NCwxMDQyNzAzNSwxMDQ5MjgyNywxMDYyNDE1NCwxMDY4OTk0NSwxMDc1NTczNiwxMDgyMTUyNywxMDk1MzExMSwxMTAxODkwMiwxMTA4NDY5MywxMTE1MDQ4NCwxMTI4MTgxMSwxMTM0NzYwMiwxMTQxMzM5MywxMTQ3OTE4NCwxMTU0NTIzMSwxMTYxMTAyMywxMTY3NjgxNCwxMTgwODE0MSwxMTg3MzkzMiwxMTkzOTcyMywxMjAwNTUxNCwxMjA3MTU2MSwxMjEzNzM1MiwxMjIwMzE0MywxMjI2ODkzNCwxMjMzNDcyNSwxMjQwMDUxNiwxMjQ2NjMwNywxMjUzMjA5OCwxMjU5ODE0NSwxMjY2MzkzNiwxMjcyOTcyOCwxMjc5NTUxOSwxMjg2MTMxMCwxMjkyNzEwMSwxMjk5Mjg5MiwxMzA1ODY4MywxMzEyNDczMCwxMzE5MDUyMSwxMzI1NjMxMiwxMzMyMjEwMywxMzM4Nzg5NCwxMzQ1MzY4NSwxMzUxOTQ3NywxMzU4NTI2OCwxMzY1MTMxNSwxMzcxNzEwNiwxMzcxNzM2MSwxMzc4MzE1MiwxMzg0ODk0MywxMzkxNDczNCwxMzk4MDUyNSwxNDA0NjU3MywxNDExMjM2NCwxNDExMjYxOSwxNDE3ODQxMCwxNDI0NDIwMSwxNDMwOTk5MiwxNDM3NTc4MywxNDQ0MTgzMCwxNDQ0MjA4NiwxNDUwNzg3NywxNDU3MzY2OCwxNDYzOTQ1OSwxNDYzOTcxNCwxNDcwNTc2MSwxNDc3MTU1MiwxNDgzNzM0NCwxNDkwMzEzNSwxNDkwMzM5MCwxNDk2OTQzNywxNTAzNTIyOCwxNTAzNTQ4MywxNTEwMTI3NCwxNTE2NzA2NiwxNTIzMzExMywxNTIzMzM2OCwxNTI5OTE1OSwxNTM2NDk1MCwxNTM2NTIwNSwxNTQzMTI1MiwxNTQ5NzA0NCwxNTQ5NzI5OSwxNTU2MzA5MCwxNTU2MzYwMSwxNTYyOTM5MiwxNTY5NTE4MywxNTY5NTQzOCwxNTc2MTQ4NSwxNTc2MTc0MSwxNTgyNzUzMiwxNTg5MzU3OSwxNTg5MzgzNCwxNTk1OTYyNSwxNTk1OTg4MCwxNjAyNTkyNywxNjAyNjE4MywxNjA5MTk3NCwxNjA5MjQ4NSwxNjE1ODI3NiwxNjE1ODUzMSwxNjE1OTA0MiwxNjIyNDgzMywxNjIyNTA4OSwxNjI5MTEzNiwxNjI5MTM5MSwxNjI5MTkwMiwxNjM1NzY5MywxNjM1Nzk0OCwxNjQyMzk5NSwxNjQyNDI1MCwxNjQyNDc2MiwxNjQyNTAxNywxNjQ5MTA2NCwxNjQ5MTMxOSwxNjQ5MTU3NCwxNjU1NzYyMSwxNjU1Nzg3NywxNjU1ODM4OCwxNjU1ODY0MywxNjU1OTE1NCwxNjU1OTQwOSwxNjYyNTQ1NywxNjYyNTcxMiwxNjYyNjIyMywxNjYyNjQ3OCwxNjYyNjk4OSwxNjYyNzI0NSwxNjYyNzc1NiwxNjYyODAxMSwxNjYyODUyMywxNjYyODc3OCwxNjYyOTI4OSwxNjYyOTgwMSwxNjYzMDA1NiwxNjYzMDU2OCwxNjYzMDgyMywxNjYzMTMzNCwxNjU2NjA1NCwxNjU2NjU2NiwxNjU2NzA3NywxNjU2NzMzMywxNjU2Nzg0NSwxNjUwMjgyMCwxNjUwMzA3NiwxNjUwMzU4OCwxNjQzODU2NCwxNjQzODgyMCwxNjQzOTMzMiwxNjM3NDA1MiwxNjM3NDU2NCwxNjMwOTU0MCwxNjMxMDA1MiwxNjI0NDc3MiwxNjI0NTI4NSwxNjE4MDI2MSwxNjE4MDUxNywxNjExNTQ5NCwxNjExNjAwNiwxNjA1MDcyNiwxNTk4NTcwMiwxNTk4NjIxNCwxNTkyMTE5MCwxNTkyMTQ0NiwxNTg1NjQyMiwxNTc5MTM5NywxNTc5MTY1MSwxNTcyNjYyNV19LFZpcmlkaXM6e1ZpcmlkaXMzOls0NDU2Nzg4LDIxMzM5MDAsMTY2Mzk3ODBdLFZpcmlkaXM0Ols0NDU2Nzg4LDMxNzIyMzcsMzUyMDM3NiwxNjYzOTc4MF0sVmlyaWRpczU6WzQ0NTY3ODgsMzg4NzQ5OCwyMTMzOTAwLDYwMTUwNzQsMTY2Mzk3ODBdLFZpcmlkaXM2Ols0NDU2Nzg4LDQyMTE1OTEsMjcxNzgzOCwyMjcxMTA4LDc5ODM0NDEsMTY2Mzk3ODBdLFZpcmlkaXM3Ols0NDU2Nzg4LDQ0NzExNzAsMzE3MjIzNywyMTMzOTAwLDM1MjAzNzYsOTI5NTQyOCwxNjYzOTc4MF0sVmlyaWRpczg6WzQ0NTY3ODgsNDYwMDE5MCwzNTYyMTI0LDI1ODgzMDIsMjAwNzE3NSw0ODMzNjQ1LDEwMzQ0NzYyLDE2NjM5NzgwXSxWaXJpZGlzOTpbNDQ1Njc4OCw0NjY0MTg2LDM4ODc0OTgsMjkxMjY1NCwyMTMzOTAwLDI2MDAzMjAsNjAxNTA3NCwxMTE5NzIzNCwxNjYzOTc4MF0sVmlyaWRpczEwOls0NDU2Nzg4LDQ2NjMxNTksNDA4MjA1NywzMTcyMjM3LDI0NTgyNTQsMjAwNjE1MywzNTIwMzc2LDcwNjQ5MjEsMTE3MjIwMjgsMTY2Mzk3ODBdLFZpcmlkaXMxMTpbNDQ1Njc4OCw0NzI3NjY4LDQyMTE1OTEsMzQzMjA3NywyNzE3ODM4LDIxMzM5MDAsMjI3MTEwOCw0Mzc0MTI5LDc5ODM0NDEsMTIyNDY1NjcsMTY2Mzk3ODBdLFZpcmlkaXMyNTY6WzQ0NTY3ODgsNDQ1NzA0NSw0NDU3MzAzLDQ1MjMzNTIsNDUyMzYxMCw0NTI0MTIzLDQ1ODk5MTYsNDU5MDQzMCw0NTkwNjg3LDQ1OTEyMDEsNDY1Njk5NCw0NjU3NTA3LDQ2NTc3NjUsNDY1ODI3OCw0NjU4NTM1LDQ2NTg3OTMsNDY1OTMwNiw0NzI1MDk5LDQ3MjUzNTYsNDcyNTg3MCw0NzI2MTI3LDQ3MjYzODQsNDcyNjg5Nyw0NzI3MTU0LDQ3Mjc0MTEsNDcyNzY2OCw0NjYyNjQ1LDQ2NjI5MDIsNDY2MzE1OSw0NjYzNDE2LDQ2NjM5MjksNDY2NDE4Niw0NjY0NDQzLDQ1OTkxNjQsNDU5OTY3Niw0NTk5OTMzLDQ2MDAxOTAsNDUzNDkxMSw0NTM1NDIzLDQ1MzU2ODAsNDUzNTkzNyw0NDcwNjU3LDQ0NzExNzAsNDQwNTg5MSw0NDA2MTQ3LDQ0MDY0MDQsNDM0MTEyNCw0MzQxMzgxLDQzNDE4OTMsNDI3NjYxNCw0Mjc2ODcwLDQyMTE1OTEsNDIxMTg0Nyw0MTQ2NTY3LDQxNDcwODAsNDA4MTgwMCw0MDgyMDU3LDQwMTY3NzcsNDAxNzAzMyw0MDE3Mjg5LDM5NTIwMTAsMzk1MjI2NiwzODg3MjQyLDM4ODc0OTgsMzgyMjIxOSwzODIyNDc1LDM3NTcxOTUsMzc1NzQ1MSwzNjkyMTcxLDM2OTI0MjgsMzYyNzE0OCwzNjI3NDA0LDM1NjIxMjQsMzU2MjM4MCwzNDk3MTAwLDM0OTczNTYsMzQzMjA3NywzNDMyMzMzLDMzNjcwNTMsMzM2NzMwOSwzMzAyMDI5LDMzMDIyODUsMzIzNzAwNSwzMjM3MjYxLDMyMzc1MTcsMzE3MjIzNywzMTcyNDkzLDMxMDcyMTMsMzEwNzQ2OSwzMDQyMTkwLDMwNDI0NDYsMzA0MjcwMiwyOTc3NDIyLDI5Nzc2NzgsMjkxMjM5OCwyOTEyNjU0LDI5MTI5MTAsMjg0NzYzMCwyODQ3ODg2LDI3ODI2MDYsMjc4Mjg2MiwyNzgzMTE4LDI3MTc4MzgsMjcxODA5NCwyNjUyODE0LDI2NTI4MTQsMjY1MzA3MCwyNTg3NzkwLDI1ODgwNDYsMjU4ODMwMiwyNTIzMDIyLDI1MjMyNzgsMjUyMzUzNCwyNDU4MjU0LDI0NTg1MDksMjM5MzIyOSwyMzkzNDg1LDIzOTM3NDEsMjMyODQ2MSwyMzI4NzE3LDIzMjg5NzMsMjI2MzQzNywyMjYzNjkzLDIyNjM5NDksMjE5ODY2OSwyMTk4OTI0LDIxOTkxODAsMjEzMzkwMCwyMTM0MTU2LDIxMzQ0MTIsMjA2OTEzMiwyMDY5Mzg3LDIwNjk2NDMsMjA2OTg5OSwyMDcwMTU1LDIwMDQ4NzQsMjAwNTEzMCwyMDA1Mzg2LDIwMDUzODYsMjAwNTY0MSwyMDA1ODk3LDIwMDYxNTMsMjAwNjQwOCwyMDA2NjY0LDIwMDY5MjAsMjAwNzE3NSwyMDcyOTY3LDIwNzMyMjIsMjA3MzQ3OCwyMTM5MjY5LDIxMzk1MjUsMjIwNTMxNywyMjA1NTcyLDIyNzExMDgsMjMzNjg5OSwyMzM3MTU0LDI0MDI5NDYsMjQ2ODczNywyNTM0NTI5LDI2MDAzMjAsMjY2NjExMSwyNzMxOTAzLDI3OTc2OTQsMjg2MzQ4NSwyOTI5MDIxLDMwNjAzNDgsMzEyNjEzOSwzMTkxOTMwLDMzMjMyNTgsMzM4OTA0OSwzNTIwMzc2LDM1ODYxNjcsMzcxNzQ5NCwzNzgzMDMwLDM5MTQzNTcsNDA0NTY4NCw0MTExNDc1LDQyNDI4MDIsNDM3NDEyOSw0NTA1MjAwLDQ1NzA5OTEsNDcwMjMxOCw0ODMzNjQ1LDQ5NjQ5NzIsNTA5NjA0Myw1MjI3MzY5LDUzNTg2OTYsNTQ5MDAyMyw1NjIxMzUwLDU3NTI0MjEsNTg4Mzc0OCw2MDE1MDc0LDYyMTE5MzcsNjM0MzAwOCw2NDc0MzM1LDY2MDU2NjEsNjgwMjUyNCw2OTMzNTk1LDcwNjQ5MjEsNzE5NjI0OCw3MzkyODU0LDc1MjQxODEsNzY1NTUwOCw3ODUyMTE0LDc5ODM0NDEsODE4MDMwMyw4MzExMzc0LDg1MDgyMzYsODYzOTMwNyw4ODM2MTY5LDg5Njc0OTUsOTE2NDEwMiw5Mjk1NDI4LDk0OTIwMzUsOTYyMzM2MSw5ODE5OTY3LDk5NTEyOTQsMTAxNDc5MDAsMTAzNDQ3NjIsMTA0NzU4MzIsMTA2NzI2OTUsMTA4NjkzMDEsMTEwMDA2MjcsMTExOTcyMzQsMTEzOTQwOTYsMTE1MjUxNjYsMTE3MjIwMjgsMTE5MTg2MzUsMTIwNDk3MDUsMTIyNDY1NjcsMTI0NDMxNzQsMTI1NzQ1MDAsMTI3NzExMDYsMTI5Njc3MTMsMTMwOTkwMzksMTMyOTU2NDYsMTM0OTIyNTMsMTM2MjM1ODAsMTM4MjAxODcsMTM5NTEyNTgsMTQxNDgxMjEsMTQzNDQ3MjgsMTQ0NzU4MDAsMTQ2NzI2NjQsMTQ4MDM3MzYsMTUwMDAzNDQsMTUxOTcyMDksMTUzMjgyODEsMTU1MjQ4OTAsMTU2NTYyMTksMTU4NTI4MjgsMTU5ODM5MDIsMTYxODA3NjcsMTYzMTE4NDEsMTY0NDI5MTQsMTY2Mzk3ODBdfSxBY2NlbnQ6e0FjY2VudDM6WzgzNzQ2NTUsMTI0OTY1OTYsMTY2Mjk4OTRdLEFjY2VudDQ6WzgzNzQ2NTUsMTI0OTY1OTYsMTY2Mjk4OTQsMTY3NzcxMTNdLEFjY2VudDU6WzgzNzQ2NTUsMTI0OTY1OTYsMTY2Mjk4OTQsMTY3NzcxMTMsMzY5Nzg0MF0sQWNjZW50NjpbODM3NDY1NSwxMjQ5NjU5NiwxNjYyOTg5NCwxNjc3NzExMywzNjk3ODQwLDE1NzI5Mjc5XSxBY2NlbnQ3Ols4Mzc0NjU1LDEyNDk2NTk2LDE2NjI5ODk0LDE2Nzc3MTEzLDM2OTc4NDAsMTU3MjkyNzksMTI1NDA2OTVdLEFjY2VudDg6WzgzNzQ2NTUsMTI0OTY1OTYsMTY2Mjk4OTQsMTY3NzcxMTMsMzY5Nzg0MCwxNTcyOTI3OSwxMjU0MDY5NSw2NzEwODg2XX0sRGFyazI6e0RhcmsyXzM6WzE4MTAwMzksMTQyNDU2MzQsNzY5NjU2M10sRGFyazJfNDpbMTgxMDAzOSwxNDI0NTYzNCw3Njk2NTYzLDE1MTQ5NDUwXSxEYXJrMl81OlsxODEwMDM5LDE0MjQ1NjM0LDc2OTY1NjMsMTUxNDk0NTAsNjcyNzE5OF0sRGFyazJfNjpbMTgxMDAzOSwxNDI0NTYzNCw3Njk2NTYzLDE1MTQ5NDUwLDY3MjcxOTgsMTUxMTcwNThdLERhcmsyXzc6WzE4MTAwMzksMTQyNDU2MzQsNzY5NjU2MywxNTE0OTQ1MCw2NzI3MTk4LDE1MTE3MDU4LDEwOTA5MjEzXSxEYXJrMl84OlsxODEwMDM5LDE0MjQ1NjM0LDc2OTY1NjMsMTUxNDk0NTAsNjcyNzE5OCwxNTExNzA1OCwxMDkwOTIxMyw2NzEwODg2XX0sUGFpcmVkOntQYWlyZWQzOlsxMDkzMTkzOSwyMDYyNTE2LDExNzIyNjM0XSxQYWlyZWQ0OlsxMDkzMTkzOSwyMDYyNTE2LDExNzIyNjM0LDMzODMzNDBdLFBhaXJlZDU6WzEwOTMxOTM5LDIwNjI1MTYsMTE3MjI2MzQsMzM4MzM0MCwxNjQ4OTExM10sUGFpcmVkNjpbMTA5MzE5MzksMjA2MjUxNiwxMTcyMjYzNCwzMzgzMzQwLDE2NDg5MTEzLDE0ODgzMzU2XSxQYWlyZWQ3OlsxMDkzMTkzOSwyMDYyNTE2LDExNzIyNjM0LDMzODMzNDAsMTY0ODkxMTMsMTQ4ODMzNTYsMTY2Mjk2MTVdLFBhaXJlZDg6WzEwOTMxOTM5LDIwNjI1MTYsMTE3MjI2MzQsMzM4MzM0MCwxNjQ4OTExMywxNDg4MzM1NiwxNjYyOTYxNSwxNjc0NDE5Ml0sUGFpcmVkOTpbMTA5MzE5MzksMjA2MjUxNiwxMTcyMjYzNCwzMzgzMzQwLDE2NDg5MTEzLDE0ODgzMzU2LDE2NjI5NjE1LDE2NzQ0MTkyLDEzMjg0MDU0XSxQYWlyZWQxMDpbMTA5MzE5MzksMjA2MjUxNiwxMTcyMjYzNCwzMzgzMzQwLDE2NDg5MTEzLDE0ODgzMzU2LDE2NjI5NjE1LDE2NzQ0MTkyLDEzMjg0MDU0LDY5NjI1ODZdLFBhaXJlZDExOlsxMDkzMTkzOSwyMDYyNTE2LDExNzIyNjM0LDMzODMzNDAsMTY0ODkxMTMsMTQ4ODMzNTYsMTY2Mjk2MTUsMTY3NDQxOTIsMTMyODQwNTQsNjk2MjU4NiwxNjc3NzExM10sUGFpcmVkMTI6WzEwOTMxOTM5LDIwNjI1MTYsMTE3MjI2MzQsMzM4MzM0MCwxNjQ4OTExMywxNDg4MzM1NiwxNjYyOTYxNSwxNjc0NDE5MiwxMzI4NDA1NCw2OTYyNTg2LDE2Nzc3MTEzLDExNjIyNjk2XX0sUGFzdGVsMTp7UGFzdGVsMV8zOlsxNjQ5NTc5MCwxMTc4MzY1MSwxMzQyOTcwMV0sUGFzdGVsMV80OlsxNjQ5NTc5MCwxMTc4MzY1MSwxMzQyOTcwMSwxNDYwMTE4OF0sUGFzdGVsMV81OlsxNjQ5NTc5MCwxMTc4MzY1MSwxMzQyOTcwMSwxNDYwMTE4OCwxNjcwMTg2Ml0sUGFzdGVsMV82OlsxNjQ5NTc5MCwxMTc4MzY1MSwxMzQyOTcwMSwxNDYwMTE4OCwxNjcwMTg2MiwxNjc3NzE2NF0sUGFzdGVsMV83OlsxNjQ5NTc5MCwxMTc4MzY1MSwxMzQyOTcwMSwxNDYwMTE4OCwxNjcwMTg2MiwxNjc3NzE2NCwxNTA2MzIyOV0sUGFzdGVsMV84OlsxNjQ5NTc5MCwxMTc4MzY1MSwxMzQyOTcwMSwxNDYwMTE4OCwxNjcwMTg2MiwxNjc3NzE2NCwxNTA2MzIyOSwxNjYzNjY1Ml0sUGFzdGVsMV85OlsxNjQ5NTc5MCwxMTc4MzY1MSwxMzQyOTcwMSwxNDYwMTE4OCwxNjcwMTg2MiwxNjc3NzE2NCwxNTA2MzIyOSwxNjYzNjY1MiwxNTkyMTkwNl19LFBhc3RlbDI6e1Bhc3RlbDJfMzpbMTE3ODkwMDUsMTY2MzMyNjAsMTMzNTg1NjhdLFBhc3RlbDJfNDpbMTE3ODkwMDUsMTY2MzMyNjAsMTMzNTg1NjgsMTYwNDI3MjRdLFBhc3RlbDJfNTpbMTE3ODkwMDUsMTY2MzMyNjAsMTMzNTg1NjgsMTYwNDI3MjQsMTUxMzYyMDFdLFBhc3RlbDJfNjpbMTE3ODkwMDUsMTY2MzMyNjAsMTMzNTg1NjgsMTYwNDI3MjQsMTUxMzYyMDEsMTY3NzM4MDZdLFBhc3RlbDJfNzpbMTE3ODkwMDUsMTY2MzMyNjAsMTMzNTg1NjgsMTYwNDI3MjQsMTUxMzYyMDEsMTY3NzM4MDYsMTU4NTIyMzZdLFBhc3RlbDJfODpbMTE3ODkwMDUsMTY2MzMyNjAsMTMzNTg1NjgsMTYwNDI3MjQsMTUxMzYyMDEsMTY3NzM4MDYsMTU4NTIyMzYsMTM0MjE3NzJdfSxTZXQxOntTZXQxXzM6WzE0OTQ4ODkyLDM2MzY5MjAsNTA5MTE0Nl0sU2V0MV80OlsxNDk0ODg5MiwzNjM2OTIwLDUwOTExNDYsOTk4MTYwM10sU2V0MV81OlsxNDk0ODg5MiwzNjM2OTIwLDUwOTExNDYsOTk4MTYwMywxNjc0NDE5Ml0sU2V0MV82OlsxNDk0ODg5MiwzNjM2OTIwLDUwOTExNDYsOTk4MTYwMywxNjc0NDE5MiwxNjc3NzAxMV0sU2V0MV83OlsxNDk0ODg5MiwzNjM2OTIwLDUwOTExNDYsOTk4MTYwMywxNjc0NDE5MiwxNjc3NzAxMSwxMDkwMTAzMl0sU2V0MV84OlsxNDk0ODg5MiwzNjM2OTIwLDUwOTExNDYsOTk4MTYwMywxNjc0NDE5MiwxNjc3NzAxMSwxMDkwMTAzMiwxNjIyMDYwN10sU2V0MV85OlsxNDk0ODg5MiwzNjM2OTIwLDUwOTExNDYsOTk4MTYwMywxNjc0NDE5MiwxNjc3NzAxMSwxMDkwMTAzMiwxNjIyMDYwNywxMDA2NjMyOV19LFNldDI6e1NldDJfMzpbNjczNDUwMSwxNjU1MTI2Niw5MjgxNzM5XSxTZXQyXzQ6WzY3MzQ1MDEsMTY1NTEyNjYsOTI4MTczOSwxNTE3NDMzOV0sU2V0Ml81Ols2NzM0NTAxLDE2NTUxMjY2LDkyODE3MzksMTUxNzQzMzksMTA5MzQzNTZdLFNldDJfNjpbNjczNDUwMSwxNjU1MTI2Niw5MjgxNzM5LDE1MTc0MzM5LDEwOTM0MzU2LDE2NzY3Mjc5XSxTZXQyXzc6WzY3MzQ1MDEsMTY1NTEyNjYsOTI4MTczOSwxNTE3NDMzOSwxMDkzNDM1NiwxNjc2NzI3OSwxNTA1ODA2OF0sU2V0Ml84Ols2NzM0NTAxLDE2NTUxMjY2LDkyODE3MzksMTUxNzQzMzksMTA5MzQzNTYsMTY3NjcyNzksMTUwNTgwNjgsMTE3NzY5NDddfSxTZXQzOntTZXQzXzM6WzkyOTQ3OTEsMTY3NzcxMzksMTI0OTk2NzRdLFNldDNfNDpbOTI5NDc5MSwxNjc3NzEzOSwxMjQ5OTY3NCwxNjQ4MjQxOF0sU2V0M181Ols5Mjk0NzkxLDE2Nzc3MTM5LDEyNDk5Njc0LDE2NDgyNDE4LDg0MzQxMzFdLFNldDNfNjpbOTI5NDc5MSwxNjc3NzEzOSwxMjQ5OTY3NCwxNjQ4MjQxOCw4NDM0MTMxLDE2NjI2Nzg2XSxTZXQzXzc6WzkyOTQ3OTEsMTY3NzcxMzksMTI0OTk2NzQsMTY0ODI0MTgsODQzNDEzMSwxNjYyNjc4NiwxMTc4Nzg4MV0sU2V0M184Ols5Mjk0NzkxLDE2Nzc3MTM5LDEyNDk5Njc0LDE2NDgyNDE4LDg0MzQxMzEsMTY2MjY3ODYsMTE3ODc4ODEsMTY1Njc3ODFdLFNldDNfOTpbOTI5NDc5MSwxNjc3NzEzOSwxMjQ5OTY3NCwxNjQ4MjQxOCw4NDM0MTMxLDE2NjI2Nzg2LDExNzg3ODgxLDE2NTY3NzgxLDE0Mjc3MDgxXSxTZXQzXzEwOls5Mjk0NzkxLDE2Nzc3MTM5LDEyNDk5Njc0LDE2NDgyNDE4LDg0MzQxMzEsMTY2MjY3ODYsMTE3ODc4ODEsMTY1Njc3ODEsMTQyNzcwODEsMTIzNTM3MjVdLFNldDNfMTE6WzkyOTQ3OTEsMTY3NzcxMzksMTI0OTk2NzQsMTY0ODI0MTgsODQzNDEzMSwxNjYyNjc4NiwxMTc4Nzg4MSwxNjU2Nzc4MSwxNDI3NzA4MSwxMjM1MzcyNSwxMzQyOTcwMV0sU2V0M18xMjpbOTI5NDc5MSwxNjc3NzEzOSwxMjQ5OTY3NCwxNjQ4MjQxOCw4NDM0MTMxLDE2NjI2Nzg2LDExNzg3ODgxLDE2NTY3NzgxLDE0Mjc3MDgxLDEyMzUzNzI1LDEzNDI5NzAxLDE2NzcyNDYzXX19LC8qIExpY2Vuc2UgcmVnYXJkaW5nIHRoZSBWaXJpZGlzLCBNYWdtYSwgUGxhc21hIGFuZCBJbmZlcm5vIGNvbG9yIG1hcHMgKi8KZS5leHBvcnRzPW4uZXh0ZW5kKHt9LG8sby5ZbEduLG8uWWxHbkJ1LG8uR25CdSxvLkJ1R24sby5QdUJ1R24sby5QdUJ1LG8uQnVQdSxvLlJkUHUsby5QdVJkLG8uT3JSZCxvLllsT3JSZCxvLllsT3JCcixvLlB1cnBsZXMsby5CbHVlcyxvLkdyZWVucyxvLk9yYW5nZXMsby5SZWRzLG8uR3JleXMsby5QdU9yLG8uQnJCRyxvLlBSR24sby5QaVlHLG8uUmRCdSxvLlJkR3ksby5SZFlsQnUsby5TcGVjdHJhbCxvLlJkWWxHbixvLkluZmVybm8sby5NYWdtYSxvLlBsYXNtYSxvLlZpcmlkaXMpfSx7dW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSxzYWZlbHk6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvO249ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzO3JldHVybiByPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpLHIuc3R5bGVbImJhY2tncm91bmQtY29sb3IiXT0iI2YyZGVkZSIsci5zdHlsZS5ib3JkZXI9IjFweCBzb2xpZCAjYTk0NDQyIixyLnN0eWxlWyJib3JkZXItcmFkaXVzIl09IjRweCIsci5zdHlsZS5kaXNwbGF5PSJpbmxpbmUtYmxvY2siLHIuc3R5bGVbImZvbnQtZmFtaWx5Il09InNhbnMtc2VyaWYiLHIuc3R5bGVbIm1hcmdpbi10b3AiXT0iNXB4IixyLnN0eWxlWyJtaW4td2lkdGgiXT0iMjAwcHgiLHIuc3R5bGUucGFkZGluZz0iNXB4IDVweCA1cHggMTBweCIsbj1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJzcGFuIiksbi5zdHlsZVsiYmFja2dyb3VuZC1jb2xvciJdPSIjYTk0NDQyIixuLnN0eWxlWyJib3JkZXItcmFkaXVzIl09IjBweCA0cHggMHB4IDBweCIsbi5zdHlsZS5jb2xvcj0id2hpdGUiLG4uc3R5bGUuY3Vyc29yPSJwb2ludGVyIixuLnN0eWxlWyJmbG9hdCJdPSJyaWdodCIsbi5zdHlsZVsiZm9udC1zaXplIl09IjAuOGVtIixuLnN0eWxlLm1hcmdpbj0iLTZweCAtNnB4IDBweCAwcHgiLG4uc3R5bGUucGFkZGluZz0iMnB4IDVweCA0cHggNXB4IixuLnRpdGxlPSJjbG9zZSIsbi5zZXRBdHRyaWJ1dGUoImFyaWEtbGFiZWwiLCJjbG9zZSIpLG4uYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoIngiKSksbi5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsZnVuY3Rpb24oKXtyZXR1cm4gZS5yZW1vdmVDaGlsZChyKX0pLHM9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiaDMiKSxzLnN0eWxlLmNvbG9yPSIjYTk0NDQyIixzLnN0eWxlLm1hcmdpbj0iOHB4IDBweCAwcHggMHB4IixzLnN0eWxlLnBhZGRpbmc9IjBweCIscy5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgiQm9rZWggRXJyb3IiKSksbz1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJwcmUiKSxvLnN0eWxlWyJ3aGl0ZS1zcGFjZSJdPSJ1bnNldCIsby5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShudWxsIT0oaT10Lm1lc3NhZ2UpP2k6dCkpLHIuYXBwZW5kQ2hpbGQobiksci5hcHBlbmRDaGlsZChzKSxyLmFwcGVuZENoaWxkKG8pLGU9ZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImJvZHkiKVswXSxlLmluc2VydEJlZm9yZShyLGUuZmlyc3RDaGlsZCl9LG89ZnVuY3Rpb24odCxlKXt2YXIgcixvO251bGw9PWUmJihlPSExKTt0cnl7cmV0dXJuIHQoKX1jYXRjaChvKXtpZihyPW8sbihyKSwhZSl0aHJvdyByfX0sZS5leHBvcnRzPW99LHt9XSwidXRpbC9iZXppZXIiOltmdW5jdGlvbih0LGUscil7dmFyIG4sbztvPWZ1bmN0aW9uKHQsZSxyLG4sbyxpLHMsYSl7dmFyIGwsdSxoLGMscCxfLGQsZixtLGcseSx2O3JldHVybiBsPWEqbyx1PS1zKmksaD1zKm8sYz1hKmksXz0uNSoobi1yKSxwPTgvMypNYXRoLnNpbiguNSpfKSpNYXRoLnNpbiguNSpfKS9NYXRoLnNpbihfKSxkPXQrTWF0aC5jb3MociktcCpNYXRoLnNpbihyKSxnPWUrTWF0aC5zaW4ocikrcCpNYXRoLmNvcyhyKSxtPXQrTWF0aC5jb3Mobiksdj1lK01hdGguc2luKG4pLGY9bStwKk1hdGguc2luKG4pLHk9di1wKk1hdGguY29zKG4pLFtsKmQrdSpnLGgqZCtjKmcsbCpmK3UqeSxoKmYrYyp5LGwqbSt1KnYsaCptK2Mqdl19LG49ZnVuY3Rpb24odCxlLHIsbixpLHMsYSxsLHUpe3ZhciBoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE0sayxqLFQsUyx6LFAsRSxBLEMsTixPLHEsRCxJLFI7cmV0dXJuIFM9aSooTWF0aC5QSS8xODApLFQ9TWF0aC5zaW4oUyksZD1NYXRoLmNvcyhTKSx4PU1hdGguYWJzKHIpLHc9TWF0aC5hYnMobikseT1kKih0LWwpKi41K1QqKGUtdSkqLjUsdj1kKihlLXUpKi41LVQqKHQtbCkqLjUsZz15KnkvKHgqeCkrdip2Lyh3KncpLGc+MSYmKGc9TWF0aC5zcXJ0KGcpLHgqPWcsdyo9ZyksaD1kL3gsYz1UL3gscD0tVC93LF89ZC93LE49aCp0K2MqZSxEPXAqdCtfKmUsTz1oKmwrYyp1LEk9cCpsK18qdSxmPShPLU4pKihPLU4pKyhJLUQpKihJLUQpLGo9MS9mLS4yNSxqPDAmJihqPTApLGs9TWF0aC5zcXJ0KGopLGE9PT1zJiYoaz0taykscT0uNSooTitPKS1rKihJLUQpLFI9LjUqKEQrSSkrayooTy1OKSx6PU1hdGguYXRhbjIoRC1SLE4tcSksUD1NYXRoLmF0YW4yKEktUixPLXEpLEM9UC16LEM8MCYmMT09PWE/Qys9MipNYXRoLlBJOkM+MCYmMD09PWEmJihDLT0yKk1hdGguUEkpLE09TWF0aC5jZWlsKE1hdGguYWJzKEMvKC41Kk1hdGguUEkrLjAwMSkpKSxiPWZ1bmN0aW9uKCl7dmFyIHQsZSxyO2ZvcihyPVtdLG09dD0wLGU9TTswPD1lP3Q8ZTp0PmU7bT0wPD1lPysrdDotLXQpRT16K20qQy9NLEE9eisobSsxKSpDL00sci5wdXNoKG8ocSxSLEUsQSx4LHcsVCxkKSk7cmV0dXJuIHJ9KCl9LGUuZXhwb3J0cz17YXJjX3RvX2JlemllcjpuLHNlZ21lbnRfdG9fYmV6aWVyOm99fSx7fV0sInV0aWwvdXRpbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw7aT10KCJ1bmRlcnNjb3JlIiksbz10KCJzcHJpbnRmIiksbj10KCJudW1icm8iKSxzPWZ1bmN0aW9uKHQpe3ZhciBlO3JldHVybiBpLmlzTnVtYmVyKHQpPyhlPWZ1bmN0aW9uKCl7c3dpdGNoKCExKXtjYXNlIE1hdGguZmxvb3IodCkhPT10OnJldHVybiIlZCI7Y2FzZSEoTWF0aC5hYnModCk+LjEmJk1hdGguYWJzKHQpPDFlMyk6cmV0dXJuIiUwLjNmIjtkZWZhdWx0OnJldHVybiIlMC4zZSJ9fSgpLG8uc3ByaW50ZihlLHQpKToiIit0fSxsPWZ1bmN0aW9uKHQsZSxyLG8pe3JldHVybiBudWxsPT1vJiYobz17fSksdD10LnJlcGxhY2UoLyhefFteXCRdKVwkKFx3KykvZyxmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24odCxlLHIpe3JldHVybiBlKyJAJCIrcn19KHRoaXMpKSx0PXQucmVwbGFjZSgvKF58W15AXSlAKD86KFwkP1x3Kyl8eyhbXnt9XSspfSkoPzp7KFtee31dKyl9KT8vZyxmdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24odCxhLGwsdSxoKXt2YXIgYyxwLF87cmV0dXJuIGw9bnVsbCE9dT91OmwsXz0iJCI9PT1sWzBdP29bbC5zdWJzdHJpbmcoMSldOm51bGwhPShjPWUuZ2V0X2NvbHVtbihsKSk/Y1tyXTp2b2lkIDAscD1udWxsPT1fPyI/Pz8iOm51bGwhPWg/bi5mb3JtYXQoXyxoKTpzKF8pLCIiK2EraS5lc2NhcGUocCl9fSh0aGlzKSl9LGE9ZnVuY3Rpb24odCl7dmFyIGU7cmV0dXJuIGU9dC5nZXQoInNlbGVjdGVkIiksZVsiMGQiXS5nbHlwaD9lWyIwZCJdLmluZGljZXM6ZVsiMWQiXS5pbmRpY2VzLmxlbmd0aD4wP2VbIjFkIl0uaW5kaWNlczplWyIyZCJdLmluZGljZXMubGVuZ3RoPjA/ZVsiMmQiXS5pbmRpY2VzOltdfSxlLmV4cG9ydHM9e3JlcGxhY2VfcGxhY2Vob2xkZXJzOmwsZ2V0X2luZGljZXM6YX19LHtudW1icm86Im51bWJyby9udW1icm8iLHNwcmludGY6InNwcmludGYiLHVuZGVyc2NvcmU6InVuZGVyc2NvcmUifV0sdmVyc2lvbjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuO249IjAuMTIuMiIsZS5leHBvcnRzPW59LHt9XSxiYWNrYm9uZTpbZnVuY3Rpb24oZSxyLG4peyhmdW5jdGlvbihyKXsKLy8gICAgIChjKSAyMDEwLTIwMTYgSmVyZW15IEFzaGtlbmFzLCBEb2N1bWVudENsb3VkIGFuZCBJbnZlc3RpZ2F0aXZlIFJlcG9ydGVycyAmIEVkaXRvcnMKLy8gICAgIEJhY2tib25lIG1heSBiZSBmcmVlbHkgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlLgohZnVuY3Rpb24obyl7dmFyIGk9Im9iamVjdCI9PXR5cGVvZiBzZWxmJiZzZWxmLnNlbGY9PT1zZWxmJiZzZWxmfHwib2JqZWN0Ij09dHlwZW9mIHImJnIuZ2xvYmFsPT09ciYmcjtpZigiZnVuY3Rpb24iPT10eXBlb2YgdCYmdC5hbWQpdChbInVuZGVyc2NvcmUiLCJqcXVlcnkiLCJleHBvcnRzIl0sZnVuY3Rpb24odCxlLHIpe2kuQmFja2JvbmU9byhpLHIsdCxlKX0pO2Vsc2UgaWYoInVuZGVmaW5lZCIhPXR5cGVvZiBuKXt2YXIgcyxhPWUoInVuZGVyc2NvcmUiKTt0cnl7cz1lKCJqcXVlcnkiKX1jYXRjaChsKXt9byhpLG4sYSxzKX1lbHNlIGkuQmFja2JvbmU9byhpLHt9LGkuXyxpLmpRdWVyeXx8aS5aZXB0b3x8aS5lbmRlcnx8aS4kKX0oZnVuY3Rpb24odCxlLHIsbil7dmFyIG89dC5CYWNrYm9uZSxpPUFycmF5LnByb3RvdHlwZS5zbGljZTtlLlZFUlNJT049IjEuMy4zIixlLiQ9bixlLm5vQ29uZmxpY3Q9ZnVuY3Rpb24oKXtyZXR1cm4gdC5CYWNrYm9uZT1vLHRoaXN9LGUuZW11bGF0ZUhUVFA9ITEsZS5lbXVsYXRlSlNPTj0hMTt2YXIgcz1mdW5jdGlvbih0LGUsbil7c3dpdGNoKHQpe2Nhc2UgMTpyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gcltlXSh0aGlzW25dKX07Y2FzZSAyOnJldHVybiBmdW5jdGlvbih0KXtyZXR1cm4gcltlXSh0aGlzW25dLHQpfTtjYXNlIDM6cmV0dXJuIGZ1bmN0aW9uKHQsbyl7cmV0dXJuIHJbZV0odGhpc1tuXSxsKHQsdGhpcyksbyl9O2Nhc2UgNDpyZXR1cm4gZnVuY3Rpb24odCxvLGkpe3JldHVybiByW2VdKHRoaXNbbl0sbCh0LHRoaXMpLG8saSl9O2RlZmF1bHQ6cmV0dXJuIGZ1bmN0aW9uKCl7dmFyIHQ9aS5jYWxsKGFyZ3VtZW50cyk7cmV0dXJuIHQudW5zaGlmdCh0aGlzW25dKSxyW2VdLmFwcGx5KHIsdCl9fX0sYT1mdW5jdGlvbih0LGUsbil7ci5lYWNoKGUsZnVuY3Rpb24oZSxvKXtyW29dJiYodC5wcm90b3R5cGVbb109cyhlLG8sbikpfSl9LGw9ZnVuY3Rpb24odCxlKXtyZXR1cm4gci5pc0Z1bmN0aW9uKHQpP3Q6ci5pc09iamVjdCh0KSYmIWUuX2lzTW9kZWwodCk/dSh0KTpyLmlzU3RyaW5nKHQpP2Z1bmN0aW9uKGUpe3JldHVybiBlLmdldCh0KX06dH0sdT1mdW5jdGlvbih0KXt2YXIgZT1yLm1hdGNoZXModCk7cmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiBlKHQuYXR0cmlidXRlcyl9fSxoPWUuRXZlbnRzPXt9LGM9L1xzKy8scD1mdW5jdGlvbih0LGUsbixvLGkpe3ZhciBzLGE9MDtpZihuJiYib2JqZWN0Ij09dHlwZW9mIG4pe3ZvaWQgMCE9PW8mJiJjb250ZXh0ImluIGkmJnZvaWQgMD09PWkuY29udGV4dCYmKGkuY29udGV4dD1vKTtmb3Iocz1yLmtleXMobik7YTxzLmxlbmd0aDthKyspZT1wKHQsZSxzW2FdLG5bc1thXV0saSl9ZWxzZSBpZihuJiZjLnRlc3QobikpZm9yKHM9bi5zcGxpdChjKTthPHMubGVuZ3RoO2ErKyllPXQoZSxzW2FdLG8saSk7ZWxzZSBlPXQoZSxuLG8saSk7cmV0dXJuIGV9O2gub249ZnVuY3Rpb24odCxlLHIpe3JldHVybiBfKHRoaXMsdCxlLHIpfTt2YXIgXz1mdW5jdGlvbih0LGUscixuLG8pe2lmKHQuX2V2ZW50cz1wKGQsdC5fZXZlbnRzfHx7fSxlLHIse2NvbnRleHQ6bixjdHg6dCxsaXN0ZW5pbmc6b30pLG8pe3ZhciBpPXQuX2xpc3RlbmVyc3x8KHQuX2xpc3RlbmVycz17fSk7aVtvLmlkXT1vfXJldHVybiB0fTtoLmxpc3RlblRvPWZ1bmN0aW9uKHQsZSxuKXtpZighdClyZXR1cm4gdGhpczt2YXIgbz10Ll9saXN0ZW5JZHx8KHQuX2xpc3RlbklkPXIudW5pcXVlSWQoImwiKSksaT10aGlzLl9saXN0ZW5pbmdUb3x8KHRoaXMuX2xpc3RlbmluZ1RvPXt9KSxzPWlbb107aWYoIXMpe3ZhciBhPXRoaXMuX2xpc3RlbklkfHwodGhpcy5fbGlzdGVuSWQ9ci51bmlxdWVJZCgibCIpKTtzPWlbb109e29iajp0LG9iaklkOm8saWQ6YSxsaXN0ZW5pbmdUbzppLGNvdW50OjB9fXJldHVybiBfKHQsZSxuLHRoaXMscyksdGhpc307dmFyIGQ9ZnVuY3Rpb24odCxlLHIsbil7aWYocil7dmFyIG89dFtlXXx8KHRbZV09W10pLGk9bi5jb250ZXh0LHM9bi5jdHgsYT1uLmxpc3RlbmluZzthJiZhLmNvdW50Kyssby5wdXNoKHtjYWxsYmFjazpyLGNvbnRleHQ6aSxjdHg6aXx8cyxsaXN0ZW5pbmc6YX0pfXJldHVybiB0fTtoLm9mZj1mdW5jdGlvbih0LGUscil7cmV0dXJuIHRoaXMuX2V2ZW50cz8odGhpcy5fZXZlbnRzPXAoZix0aGlzLl9ldmVudHMsdCxlLHtjb250ZXh0OnIsbGlzdGVuZXJzOnRoaXMuX2xpc3RlbmVyc30pLHRoaXMpOnRoaXN9LGguc3RvcExpc3RlbmluZz1mdW5jdGlvbih0LGUsbil7dmFyIG89dGhpcy5fbGlzdGVuaW5nVG87aWYoIW8pcmV0dXJuIHRoaXM7Zm9yKHZhciBpPXQ/W3QuX2xpc3RlbklkXTpyLmtleXMobykscz0wO3M8aS5sZW5ndGg7cysrKXt2YXIgYT1vW2lbc11dO2lmKCFhKWJyZWFrO2Eub2JqLm9mZihlLG4sdGhpcyl9cmV0dXJuIHRoaXN9O3ZhciBmPWZ1bmN0aW9uKHQsZSxuLG8pe2lmKHQpe3ZhciBpLHM9MCxhPW8uY29udGV4dCxsPW8ubGlzdGVuZXJzO2lmKGV8fG58fGEpe2Zvcih2YXIgdT1lP1tlXTpyLmtleXModCk7czx1Lmxlbmd0aDtzKyspe2U9dVtzXTt2YXIgaD10W2VdO2lmKCFoKWJyZWFrO2Zvcih2YXIgYz1bXSxwPTA7cDxoLmxlbmd0aDtwKyspe3ZhciBfPWhbcF07biYmbiE9PV8uY2FsbGJhY2smJm4hPT1fLmNhbGxiYWNrLl9jYWxsYmFja3x8YSYmYSE9PV8uY29udGV4dD9jLnB1c2goXyk6KGk9Xy5saXN0ZW5pbmcsaSYmMD09PS0taS5jb3VudCYmKGRlbGV0ZSBsW2kuaWRdLGRlbGV0ZSBpLmxpc3RlbmluZ1RvW2kub2JqSWRdKSl9Yy5sZW5ndGg/dFtlXT1jOmRlbGV0ZSB0W2VdfXJldHVybiB0fWZvcih2YXIgZD1yLmtleXMobCk7czxkLmxlbmd0aDtzKyspaT1sW2Rbc11dLGRlbGV0ZSBsW2kuaWRdLGRlbGV0ZSBpLmxpc3RlbmluZ1RvW2kub2JqSWRdfX07aC5vbmNlPWZ1bmN0aW9uKHQsZSxuKXt2YXIgbz1wKG0se30sdCxlLHIuYmluZCh0aGlzLm9mZix0aGlzKSk7cmV0dXJuInN0cmluZyI9PXR5cGVvZiB0JiZudWxsPT1uJiYoZT12b2lkIDApLHRoaXMub24obyxlLG4pfSxoLmxpc3RlblRvT25jZT1mdW5jdGlvbih0LGUsbil7dmFyIG89cChtLHt9LGUsbixyLmJpbmQodGhpcy5zdG9wTGlzdGVuaW5nLHRoaXMsdCkpO3JldHVybiB0aGlzLmxpc3RlblRvKHQsbyl9O3ZhciBtPWZ1bmN0aW9uKHQsZSxuLG8pe2lmKG4pe3ZhciBpPXRbZV09ci5vbmNlKGZ1bmN0aW9uKCl7byhlLGkpLG4uYXBwbHkodGhpcyxhcmd1bWVudHMpfSk7aS5fY2FsbGJhY2s9bn1yZXR1cm4gdH07aC50cmlnZ2VyPWZ1bmN0aW9uKHQpe2lmKCF0aGlzLl9ldmVudHMpcmV0dXJuIHRoaXM7Zm9yKHZhciBlPU1hdGgubWF4KDAsYXJndW1lbnRzLmxlbmd0aC0xKSxyPUFycmF5KGUpLG49MDtuPGU7bisrKXJbbl09YXJndW1lbnRzW24rMV07cmV0dXJuIHAoZyx0aGlzLl9ldmVudHMsdCx2b2lkIDAsciksdGhpc307dmFyIGc9ZnVuY3Rpb24odCxlLHIsbil7aWYodCl7dmFyIG89dFtlXSxpPXQuYWxsO28mJmkmJihpPWkuc2xpY2UoKSksbyYmeShvLG4pLGkmJnkoaSxbZV0uY29uY2F0KG4pKX1yZXR1cm4gdH0seT1mdW5jdGlvbih0LGUpe3ZhciByLG49LTEsbz10Lmxlbmd0aCxpPWVbMF0scz1lWzFdLGE9ZVsyXTtzd2l0Y2goZS5sZW5ndGgpe2Nhc2UgMDpmb3IoOysrbjxvOykocj10W25dKS5jYWxsYmFjay5jYWxsKHIuY3R4KTtyZXR1cm47Y2FzZSAxOmZvcig7KytuPG87KShyPXRbbl0pLmNhbGxiYWNrLmNhbGwoci5jdHgsaSk7cmV0dXJuO2Nhc2UgMjpmb3IoOysrbjxvOykocj10W25dKS5jYWxsYmFjay5jYWxsKHIuY3R4LGkscyk7cmV0dXJuO2Nhc2UgMzpmb3IoOysrbjxvOykocj10W25dKS5jYWxsYmFjay5jYWxsKHIuY3R4LGkscyxhKTtyZXR1cm47ZGVmYXVsdDpmb3IoOysrbjxvOykocj10W25dKS5jYWxsYmFjay5hcHBseShyLmN0eCxlKTtyZXR1cm59fTtoLmJpbmQ9aC5vbixoLnVuYmluZD1oLm9mZixyLmV4dGVuZChlLGgpO3ZhciB2PWUuTW9kZWw9ZnVuY3Rpb24odCxlKXt2YXIgbj10fHx7fTtlfHwoZT17fSksdGhpcy5jaWQ9ci51bmlxdWVJZCh0aGlzLmNpZFByZWZpeCksdGhpcy5hdHRyaWJ1dGVzPXt9LGUuY29sbGVjdGlvbiYmKHRoaXMuY29sbGVjdGlvbj1lLmNvbGxlY3Rpb24pLGUucGFyc2UmJihuPXRoaXMucGFyc2UobixlKXx8e30pO3ZhciBvPXIucmVzdWx0KHRoaXMsImRlZmF1bHRzIik7bj1yLmRlZmF1bHRzKHIuZXh0ZW5kKHt9LG8sbiksbyksdGhpcy5zZXQobixlKSx0aGlzLmNoYW5nZWQ9e30sdGhpcy5pbml0aWFsaXplLmFwcGx5KHRoaXMsYXJndW1lbnRzKX07ci5leHRlbmQodi5wcm90b3R5cGUsaCx7Y2hhbmdlZDpudWxsLHZhbGlkYXRpb25FcnJvcjpudWxsLGlkQXR0cmlidXRlOiJpZCIsY2lkUHJlZml4OiJjIixpbml0aWFsaXplOmZ1bmN0aW9uKCl7fSx0b0pTT046ZnVuY3Rpb24odCl7cmV0dXJuIHIuY2xvbmUodGhpcy5hdHRyaWJ1dGVzKX0sc3luYzpmdW5jdGlvbigpe3JldHVybiBlLnN5bmMuYXBwbHkodGhpcyxhcmd1bWVudHMpfSxnZXQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuYXR0cmlidXRlc1t0XX0sZXNjYXBlOmZ1bmN0aW9uKHQpe3JldHVybiByLmVzY2FwZSh0aGlzLmdldCh0KSl9LGhhczpmdW5jdGlvbih0KXtyZXR1cm4gbnVsbCE9dGhpcy5nZXQodCl9LG1hdGNoZXM6ZnVuY3Rpb24odCl7cmV0dXJuISFyLml0ZXJhdGVlKHQsdGhpcykodGhpcy5hdHRyaWJ1dGVzKX0sc2V0OmZ1bmN0aW9uKHQsZSxuKXtpZihudWxsPT10KXJldHVybiB0aGlzO3ZhciBvO2lmKCJvYmplY3QiPT10eXBlb2YgdD8obz10LG49ZSk6KG89e30pW3RdPWUsbnx8KG49e30pLCF0aGlzLl92YWxpZGF0ZShvLG4pKXJldHVybiExO3ZhciBpPW4udW5zZXQscz1uLnNpbGVudCxhPVtdLGw9dGhpcy5fY2hhbmdpbmc7dGhpcy5fY2hhbmdpbmc9ITAsbHx8KHRoaXMuX3ByZXZpb3VzQXR0cmlidXRlcz1yLmNsb25lKHRoaXMuYXR0cmlidXRlcyksdGhpcy5jaGFuZ2VkPXt9KTt2YXIgdT10aGlzLmF0dHJpYnV0ZXMsaD10aGlzLmNoYW5nZWQsYz10aGlzLl9wcmV2aW91c0F0dHJpYnV0ZXM7Zm9yKHZhciBwIGluIG8pZT1vW3BdLHIuaXNFcXVhbCh1W3BdLGUpfHxhLnB1c2gocCksci5pc0VxdWFsKGNbcF0sZSk/ZGVsZXRlIGhbcF06aFtwXT1lLGk/ZGVsZXRlIHVbcF06dVtwXT1lO2lmKHRoaXMuaWRBdHRyaWJ1dGUgaW4gbyYmKHRoaXMuaWQ9dGhpcy5nZXQodGhpcy5pZEF0dHJpYnV0ZSkpLCFzKXthLmxlbmd0aCYmKHRoaXMuX3BlbmRpbmc9bik7Zm9yKHZhciBfPTA7XzxhLmxlbmd0aDtfKyspdGhpcy50cmlnZ2VyKCJjaGFuZ2U6IithW19dLHRoaXMsdVthW19dXSxuKX1pZihsKXJldHVybiB0aGlzO2lmKCFzKWZvcig7dGhpcy5fcGVuZGluZzspbj10aGlzLl9wZW5kaW5nLHRoaXMuX3BlbmRpbmc9ITEsdGhpcy50cmlnZ2VyKCJjaGFuZ2UiLHRoaXMsbik7cmV0dXJuIHRoaXMuX3BlbmRpbmc9ITEsdGhpcy5fY2hhbmdpbmc9ITEsdGhpc30sdW5zZXQ6ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5zZXQodCx2b2lkIDAsci5leHRlbmQoe30sZSx7dW5zZXQ6ITB9KSl9LGNsZWFyOmZ1bmN0aW9uKHQpe3ZhciBlPXt9O2Zvcih2YXIgbiBpbiB0aGlzLmF0dHJpYnV0ZXMpZVtuXT12b2lkIDA7cmV0dXJuIHRoaXMuc2V0KGUsci5leHRlbmQoe30sdCx7dW5zZXQ6ITB9KSl9LGhhc0NoYW5nZWQ6ZnVuY3Rpb24odCl7cmV0dXJuIG51bGw9PXQ/IXIuaXNFbXB0eSh0aGlzLmNoYW5nZWQpOnIuaGFzKHRoaXMuY2hhbmdlZCx0KX0sY2hhbmdlZEF0dHJpYnV0ZXM6ZnVuY3Rpb24odCl7aWYoIXQpcmV0dXJuISF0aGlzLmhhc0NoYW5nZWQoKSYmci5jbG9uZSh0aGlzLmNoYW5nZWQpO3ZhciBlPXRoaXMuX2NoYW5naW5nP3RoaXMuX3ByZXZpb3VzQXR0cmlidXRlczp0aGlzLmF0dHJpYnV0ZXMsbj17fTtmb3IodmFyIG8gaW4gdCl7dmFyIGk9dFtvXTtyLmlzRXF1YWwoZVtvXSxpKXx8KG5bb109aSl9cmV0dXJuISFyLnNpemUobikmJm59LHByZXZpb3VzOmZ1bmN0aW9uKHQpe3JldHVybiBudWxsIT10JiZ0aGlzLl9wcmV2aW91c0F0dHJpYnV0ZXM/dGhpcy5fcHJldmlvdXNBdHRyaWJ1dGVzW3RdOm51bGx9LHByZXZpb3VzQXR0cmlidXRlczpmdW5jdGlvbigpe3JldHVybiByLmNsb25lKHRoaXMuX3ByZXZpb3VzQXR0cmlidXRlcyl9LGZldGNoOmZ1bmN0aW9uKHQpe3Q9ci5leHRlbmQoe3BhcnNlOiEwfSx0KTt2YXIgZT10aGlzLG49dC5zdWNjZXNzO3JldHVybiB0LnN1Y2Nlc3M9ZnVuY3Rpb24ocil7dmFyIG89dC5wYXJzZT9lLnBhcnNlKHIsdCk6cjtyZXR1cm4hIWUuc2V0KG8sdCkmJihuJiZuLmNhbGwodC5jb250ZXh0LGUscix0KSx2b2lkIGUudHJpZ2dlcigic3luYyIsZSxyLHQpKX0sTCh0aGlzLHQpLHRoaXMuc3luYygicmVhZCIsdGhpcyx0KX0sc2F2ZTpmdW5jdGlvbih0LGUsbil7dmFyIG87bnVsbD09dHx8Im9iamVjdCI9PXR5cGVvZiB0PyhvPXQsbj1lKToobz17fSlbdF09ZSxuPXIuZXh0ZW5kKHt2YWxpZGF0ZTohMCxwYXJzZTohMH0sbik7dmFyIGk9bi53YWl0O2lmKG8mJiFpKXtpZighdGhpcy5zZXQobyxuKSlyZXR1cm4hMX1lbHNlIGlmKCF0aGlzLl92YWxpZGF0ZShvLG4pKXJldHVybiExO3ZhciBzPXRoaXMsYT1uLnN1Y2Nlc3MsbD10aGlzLmF0dHJpYnV0ZXM7bi5zdWNjZXNzPWZ1bmN0aW9uKHQpe3MuYXR0cmlidXRlcz1sO3ZhciBlPW4ucGFyc2U/cy5wYXJzZSh0LG4pOnQ7cmV0dXJuIGkmJihlPXIuZXh0ZW5kKHt9LG8sZSkpLCEoZSYmIXMuc2V0KGUsbikpJiYoYSYmYS5jYWxsKG4uY29udGV4dCxzLHQsbiksdm9pZCBzLnRyaWdnZXIoInN5bmMiLHMsdCxuKSl9LEwodGhpcyxuKSxvJiZpJiYodGhpcy5hdHRyaWJ1dGVzPXIuZXh0ZW5kKHt9LGwsbykpO3ZhciB1PXRoaXMuaXNOZXcoKT8iY3JlYXRlIjpuLnBhdGNoPyJwYXRjaCI6InVwZGF0ZSI7InBhdGNoIiE9PXV8fG4uYXR0cnN8fChuLmF0dHJzPW8pO3ZhciBoPXRoaXMuc3luYyh1LHRoaXMsbik7cmV0dXJuIHRoaXMuYXR0cmlidXRlcz1sLGh9LGRlc3Ryb3k6ZnVuY3Rpb24odCl7dD10P3IuY2xvbmUodCk6e307dmFyIGU9dGhpcyxuPXQuc3VjY2VzcyxvPXQud2FpdCxpPWZ1bmN0aW9uKCl7ZS5zdG9wTGlzdGVuaW5nKCksZS50cmlnZ2VyKCJkZXN0cm95IixlLGUuY29sbGVjdGlvbix0KX07dC5zdWNjZXNzPWZ1bmN0aW9uKHIpe28mJmkoKSxuJiZuLmNhbGwodC5jb250ZXh0LGUscix0KSxlLmlzTmV3KCl8fGUudHJpZ2dlcigic3luYyIsZSxyLHQpfTt2YXIgcz0hMTtyZXR1cm4gdGhpcy5pc05ldygpP3IuZGVmZXIodC5zdWNjZXNzKTooTCh0aGlzLHQpLHM9dGhpcy5zeW5jKCJkZWxldGUiLHRoaXMsdCkpLG98fGkoKSxzfSx1cmw6ZnVuY3Rpb24oKXt2YXIgdD1yLnJlc3VsdCh0aGlzLCJ1cmxSb290Iil8fHIucmVzdWx0KHRoaXMuY29sbGVjdGlvbiwidXJsIil8fEIoKTtpZih0aGlzLmlzTmV3KCkpcmV0dXJuIHQ7dmFyIGU9dGhpcy5nZXQodGhpcy5pZEF0dHJpYnV0ZSk7cmV0dXJuIHQucmVwbGFjZSgvW15cL10kLywiJCYvIikrZW5jb2RlVVJJQ29tcG9uZW50KGUpfSxwYXJzZTpmdW5jdGlvbih0LGUpe3JldHVybiB0fSxjbG9uZTpmdW5jdGlvbigpe3JldHVybiBuZXcgdGhpcy5jb25zdHJ1Y3Rvcih0aGlzLmF0dHJpYnV0ZXMpfSxpc05ldzpmdW5jdGlvbigpe3JldHVybiF0aGlzLmhhcyh0aGlzLmlkQXR0cmlidXRlKX0saXNWYWxpZDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5fdmFsaWRhdGUoe30sci5leHRlbmQoe30sdCx7dmFsaWRhdGU6ITB9KSl9LF92YWxpZGF0ZTpmdW5jdGlvbih0LGUpe2lmKCFlLnZhbGlkYXRlfHwhdGhpcy52YWxpZGF0ZSlyZXR1cm4hMDt0PXIuZXh0ZW5kKHt9LHRoaXMuYXR0cmlidXRlcyx0KTt2YXIgbj10aGlzLnZhbGlkYXRpb25FcnJvcj10aGlzLnZhbGlkYXRlKHQsZSl8fG51bGw7cmV0dXJuIW58fCh0aGlzLnRyaWdnZXIoImludmFsaWQiLHRoaXMsbixyLmV4dGVuZChlLHt2YWxpZGF0aW9uRXJyb3I6bn0pKSwhMSl9fSk7dmFyIGI9e2tleXM6MSx2YWx1ZXM6MSxwYWlyczoxLGludmVydDoxLHBpY2s6MCxvbWl0OjAsY2hhaW46MSxpc0VtcHR5OjF9O2EodixiLCJhdHRyaWJ1dGVzIik7dmFyIHg9ZS5Db2xsZWN0aW9uPWZ1bmN0aW9uKHQsZSl7ZXx8KGU9e30pLGUubW9kZWwmJih0aGlzLm1vZGVsPWUubW9kZWwpLHZvaWQgMCE9PWUuY29tcGFyYXRvciYmKHRoaXMuY29tcGFyYXRvcj1lLmNvbXBhcmF0b3IpLHRoaXMuX3Jlc2V0KCksdGhpcy5pbml0aWFsaXplLmFwcGx5KHRoaXMsYXJndW1lbnRzKSx0JiZ0aGlzLnJlc2V0KHQsci5leHRlbmQoe3NpbGVudDohMH0sZSkpfSx3PXthZGQ6ITAscmVtb3ZlOiEwLG1lcmdlOiEwfSxNPXthZGQ6ITAscmVtb3ZlOiExfSxrPWZ1bmN0aW9uKHQsZSxyKXtyPU1hdGgubWluKE1hdGgubWF4KHIsMCksdC5sZW5ndGgpO3ZhciBuLG89QXJyYXkodC5sZW5ndGgtciksaT1lLmxlbmd0aDtmb3Iobj0wO248by5sZW5ndGg7bisrKW9bbl09dFtuK3JdO2ZvcihuPTA7bjxpO24rKyl0W24rcl09ZVtuXTtmb3Iobj0wO248by5sZW5ndGg7bisrKXRbbitpK3JdPW9bbl19O3IuZXh0ZW5kKHgucHJvdG90eXBlLGgse21vZGVsOnYsaW5pdGlhbGl6ZTpmdW5jdGlvbigpe30sdG9KU09OOmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLm1hcChmdW5jdGlvbihlKXtyZXR1cm4gZS50b0pTT04odCl9KX0sc3luYzpmdW5jdGlvbigpe3JldHVybiBlLnN5bmMuYXBwbHkodGhpcyxhcmd1bWVudHMpfSxhZGQ6ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5zZXQodCxyLmV4dGVuZCh7bWVyZ2U6ITF9LGUsTSkpfSxyZW1vdmU6ZnVuY3Rpb24odCxlKXtlPXIuZXh0ZW5kKHt9LGUpO3ZhciBuPSFyLmlzQXJyYXkodCk7dD1uP1t0XTp0LnNsaWNlKCk7dmFyIG89dGhpcy5fcmVtb3ZlTW9kZWxzKHQsZSk7cmV0dXJuIWUuc2lsZW50JiZvLmxlbmd0aCYmKGUuY2hhbmdlcz17YWRkZWQ6W10sbWVyZ2VkOltdLHJlbW92ZWQ6b30sdGhpcy50cmlnZ2VyKCJ1cGRhdGUiLHRoaXMsZSkpLG4/b1swXTpvfSxzZXQ6ZnVuY3Rpb24odCxlKXtpZihudWxsIT10KXtlPXIuZXh0ZW5kKHt9LHcsZSksZS5wYXJzZSYmIXRoaXMuX2lzTW9kZWwodCkmJih0PXRoaXMucGFyc2UodCxlKXx8W10pO3ZhciBuPSFyLmlzQXJyYXkodCk7dD1uP1t0XTp0LnNsaWNlKCk7dmFyIG89ZS5hdDtudWxsIT1vJiYobz0rbyksbz50aGlzLmxlbmd0aCYmKG89dGhpcy5sZW5ndGgpLG88MCYmKG8rPXRoaXMubGVuZ3RoKzEpO3ZhciBpLHMsYT1bXSxsPVtdLHU9W10saD1bXSxjPXt9LHA9ZS5hZGQsXz1lLm1lcmdlLGQ9ZS5yZW1vdmUsZj0hMSxtPXRoaXMuY29tcGFyYXRvciYmbnVsbD09byYmZS5zb3J0IT09ITEsZz1yLmlzU3RyaW5nKHRoaXMuY29tcGFyYXRvcik/dGhpcy5jb21wYXJhdG9yOm51bGw7Zm9yKHM9MDtzPHQubGVuZ3RoO3MrKyl7aT10W3NdO3ZhciB5PXRoaXMuZ2V0KGkpO2lmKHkpe2lmKF8mJmkhPT15KXt2YXIgdj10aGlzLl9pc01vZGVsKGkpP2kuYXR0cmlidXRlczppO2UucGFyc2UmJih2PXkucGFyc2UodixlKSkseS5zZXQodixlKSx1LnB1c2goeSksbSYmIWYmJihmPXkuaGFzQ2hhbmdlZChnKSl9Y1t5LmNpZF18fChjW3kuY2lkXT0hMCxhLnB1c2goeSkpLHRbc109eX1lbHNlIHAmJihpPXRbc109dGhpcy5fcHJlcGFyZU1vZGVsKGksZSksaSYmKGwucHVzaChpKSx0aGlzLl9hZGRSZWZlcmVuY2UoaSxlKSxjW2kuY2lkXT0hMCxhLnB1c2goaSkpKX1pZihkKXtmb3Iocz0wO3M8dGhpcy5sZW5ndGg7cysrKWk9dGhpcy5tb2RlbHNbc10sY1tpLmNpZF18fGgucHVzaChpKTtoLmxlbmd0aCYmdGhpcy5fcmVtb3ZlTW9kZWxzKGgsZSl9dmFyIGI9ITEseD0hbSYmcCYmZDtpZihhLmxlbmd0aCYmeD8oYj10aGlzLmxlbmd0aCE9PWEubGVuZ3RofHxyLnNvbWUodGhpcy5tb2RlbHMsZnVuY3Rpb24odCxlKXtyZXR1cm4gdCE9PWFbZV19KSx0aGlzLm1vZGVscy5sZW5ndGg9MCxrKHRoaXMubW9kZWxzLGEsMCksdGhpcy5sZW5ndGg9dGhpcy5tb2RlbHMubGVuZ3RoKTpsLmxlbmd0aCYmKG0mJihmPSEwKSxrKHRoaXMubW9kZWxzLGwsbnVsbD09bz90aGlzLmxlbmd0aDpvKSx0aGlzLmxlbmd0aD10aGlzLm1vZGVscy5sZW5ndGgpLGYmJnRoaXMuc29ydCh7c2lsZW50OiEwfSksIWUuc2lsZW50KXtmb3Iocz0wO3M8bC5sZW5ndGg7cysrKW51bGwhPW8mJihlLmluZGV4PW8rcyksaT1sW3NdLGkudHJpZ2dlcigiYWRkIixpLHRoaXMsZSk7KGZ8fGIpJiZ0aGlzLnRyaWdnZXIoInNvcnQiLHRoaXMsZSksKGwubGVuZ3RofHxoLmxlbmd0aHx8dS5sZW5ndGgpJiYoZS5jaGFuZ2VzPXthZGRlZDpsLHJlbW92ZWQ6aCxtZXJnZWQ6dX0sdGhpcy50cmlnZ2VyKCJ1cGRhdGUiLHRoaXMsZSkpfXJldHVybiBuP3RbMF06dH19LHJlc2V0OmZ1bmN0aW9uKHQsZSl7ZT1lP3IuY2xvbmUoZSk6e307Zm9yKHZhciBuPTA7bjx0aGlzLm1vZGVscy5sZW5ndGg7bisrKXRoaXMuX3JlbW92ZVJlZmVyZW5jZSh0aGlzLm1vZGVsc1tuXSxlKTtyZXR1cm4gZS5wcmV2aW91c01vZGVscz10aGlzLm1vZGVscyx0aGlzLl9yZXNldCgpLHQ9dGhpcy5hZGQodCxyLmV4dGVuZCh7c2lsZW50OiEwfSxlKSksZS5zaWxlbnR8fHRoaXMudHJpZ2dlcigicmVzZXQiLHRoaXMsZSksdH0scHVzaDpmdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmFkZCh0LHIuZXh0ZW5kKHthdDp0aGlzLmxlbmd0aH0sZSkpfSxwb3A6ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5hdCh0aGlzLmxlbmd0aC0xKTtyZXR1cm4gdGhpcy5yZW1vdmUoZSx0KX0sdW5zaGlmdDpmdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmFkZCh0LHIuZXh0ZW5kKHthdDowfSxlKSl9LHNoaWZ0OmZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuYXQoMCk7cmV0dXJuIHRoaXMucmVtb3ZlKGUsdCl9LHNsaWNlOmZ1bmN0aW9uKCl7cmV0dXJuIGkuYXBwbHkodGhpcy5tb2RlbHMsYXJndW1lbnRzKX0sZ2V0OmZ1bmN0aW9uKHQpe2lmKG51bGwhPXQpcmV0dXJuIHRoaXMuX2J5SWRbdF18fHRoaXMuX2J5SWRbdGhpcy5tb2RlbElkKHQuYXR0cmlidXRlc3x8dCldfHx0LmNpZCYmdGhpcy5fYnlJZFt0LmNpZF19LGhhczpmdW5jdGlvbih0KXtyZXR1cm4gbnVsbCE9dGhpcy5nZXQodCl9LGF0OmZ1bmN0aW9uKHQpe3JldHVybiB0PDAmJih0Kz10aGlzLmxlbmd0aCksdGhpcy5tb2RlbHNbdF19LHdoZXJlOmZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXNbZT8iZmluZCI6ImZpbHRlciJdKHQpfSxmaW5kV2hlcmU6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMud2hlcmUodCwhMCl9LHNvcnQ6ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5jb21wYXJhdG9yO2lmKCFlKXRocm93IG5ldyBFcnJvcigiQ2Fubm90IHNvcnQgYSBzZXQgd2l0aG91dCBhIGNvbXBhcmF0b3IiKTt0fHwodD17fSk7dmFyIG49ZS5sZW5ndGg7cmV0dXJuIHIuaXNGdW5jdGlvbihlKSYmKGU9ci5iaW5kKGUsdGhpcykpLDE9PT1ufHxyLmlzU3RyaW5nKGUpP3RoaXMubW9kZWxzPXRoaXMuc29ydEJ5KGUpOnRoaXMubW9kZWxzLnNvcnQoZSksdC5zaWxlbnR8fHRoaXMudHJpZ2dlcigic29ydCIsdGhpcyx0KSx0aGlzfSxwbHVjazpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5tYXAodCsiIil9LGZldGNoOmZ1bmN0aW9uKHQpe3Q9ci5leHRlbmQoe3BhcnNlOiEwfSx0KTt2YXIgZT10LnN1Y2Nlc3Msbj10aGlzO3JldHVybiB0LnN1Y2Nlc3M9ZnVuY3Rpb24ocil7dmFyIG89dC5yZXNldD8icmVzZXQiOiJzZXQiO25bb10ocix0KSxlJiZlLmNhbGwodC5jb250ZXh0LG4scix0KSxuLnRyaWdnZXIoInN5bmMiLG4scix0KX0sTCh0aGlzLHQpLHRoaXMuc3luYygicmVhZCIsdGhpcyx0KX0sY3JlYXRlOmZ1bmN0aW9uKHQsZSl7ZT1lP3IuY2xvbmUoZSk6e307dmFyIG49ZS53YWl0O2lmKHQ9dGhpcy5fcHJlcGFyZU1vZGVsKHQsZSksIXQpcmV0dXJuITE7bnx8dGhpcy5hZGQodCxlKTt2YXIgbz10aGlzLGk9ZS5zdWNjZXNzO3JldHVybiBlLnN1Y2Nlc3M9ZnVuY3Rpb24odCxlLHIpe24mJm8uYWRkKHQsciksaSYmaS5jYWxsKHIuY29udGV4dCx0LGUscil9LHQuc2F2ZShudWxsLGUpLHR9LHBhcnNlOmZ1bmN0aW9uKHQsZSl7cmV0dXJuIHR9LGNsb25lOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyB0aGlzLmNvbnN0cnVjdG9yKHRoaXMubW9kZWxzLHttb2RlbDp0aGlzLm1vZGVsLGNvbXBhcmF0b3I6dGhpcy5jb21wYXJhdG9yfSl9LG1vZGVsSWQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRbdGhpcy5tb2RlbC5wcm90b3R5cGUuaWRBdHRyaWJ1dGV8fCJpZCJdfSxfcmVzZXQ6ZnVuY3Rpb24oKXt0aGlzLmxlbmd0aD0wLHRoaXMubW9kZWxzPVtdLHRoaXMuX2J5SWQ9e319LF9wcmVwYXJlTW9kZWw6ZnVuY3Rpb24odCxlKXtpZih0aGlzLl9pc01vZGVsKHQpKXJldHVybiB0LmNvbGxlY3Rpb258fCh0LmNvbGxlY3Rpb249dGhpcyksdDtlPWU/ci5jbG9uZShlKTp7fSxlLmNvbGxlY3Rpb249dGhpczt2YXIgbj1uZXcgdGhpcy5tb2RlbCh0LGUpO3JldHVybiBuLnZhbGlkYXRpb25FcnJvcj8odGhpcy50cmlnZ2VyKCJpbnZhbGlkIix0aGlzLG4udmFsaWRhdGlvbkVycm9yLGUpLCExKTpufSxfcmVtb3ZlTW9kZWxzOmZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPVtdLG49MDtuPHQubGVuZ3RoO24rKyl7dmFyIG89dGhpcy5nZXQodFtuXSk7aWYobyl7dmFyIGk9dGhpcy5pbmRleE9mKG8pO3RoaXMubW9kZWxzLnNwbGljZShpLDEpLHRoaXMubGVuZ3RoLS0sZGVsZXRlIHRoaXMuX2J5SWRbby5jaWRdO3ZhciBzPXRoaXMubW9kZWxJZChvLmF0dHJpYnV0ZXMpO251bGwhPXMmJmRlbGV0ZSB0aGlzLl9ieUlkW3NdLGUuc2lsZW50fHwoZS5pbmRleD1pLG8udHJpZ2dlcigicmVtb3ZlIixvLHRoaXMsZSkpLHIucHVzaChvKSx0aGlzLl9yZW1vdmVSZWZlcmVuY2UobyxlKX19cmV0dXJuIHJ9LF9pc01vZGVsOmZ1bmN0aW9uKHQpe3JldHVybiB0IGluc3RhbmNlb2Ygdn0sX2FkZFJlZmVyZW5jZTpmdW5jdGlvbih0LGUpe3RoaXMuX2J5SWRbdC5jaWRdPXQ7dmFyIHI9dGhpcy5tb2RlbElkKHQuYXR0cmlidXRlcyk7bnVsbCE9ciYmKHRoaXMuX2J5SWRbcl09dCksdC5vbigiYWxsIix0aGlzLl9vbk1vZGVsRXZlbnQsdGhpcyl9LF9yZW1vdmVSZWZlcmVuY2U6ZnVuY3Rpb24odCxlKXtkZWxldGUgdGhpcy5fYnlJZFt0LmNpZF07dmFyIHI9dGhpcy5tb2RlbElkKHQuYXR0cmlidXRlcyk7bnVsbCE9ciYmZGVsZXRlIHRoaXMuX2J5SWRbcl0sdGhpcz09PXQuY29sbGVjdGlvbiYmZGVsZXRlIHQuY29sbGVjdGlvbix0Lm9mZigiYWxsIix0aGlzLl9vbk1vZGVsRXZlbnQsdGhpcyl9LF9vbk1vZGVsRXZlbnQ6ZnVuY3Rpb24odCxlLHIsbil7aWYoZSl7aWYoKCJhZGQiPT09dHx8InJlbW92ZSI9PT10KSYmciE9PXRoaXMpcmV0dXJuO2lmKCJkZXN0cm95Ij09PXQmJnRoaXMucmVtb3ZlKGUsbiksImNoYW5nZSI9PT10KXt2YXIgbz10aGlzLm1vZGVsSWQoZS5wcmV2aW91c0F0dHJpYnV0ZXMoKSksaT10aGlzLm1vZGVsSWQoZS5hdHRyaWJ1dGVzKTtvIT09aSYmKG51bGwhPW8mJmRlbGV0ZSB0aGlzLl9ieUlkW29dLG51bGwhPWkmJih0aGlzLl9ieUlkW2ldPWUpKX19dGhpcy50cmlnZ2VyLmFwcGx5KHRoaXMsYXJndW1lbnRzKX19KTt2YXIgaj17Zm9yRWFjaDozLGVhY2g6MyxtYXA6Myxjb2xsZWN0OjMscmVkdWNlOjAsZm9sZGw6MCxpbmplY3Q6MCxyZWR1Y2VSaWdodDowLGZvbGRyOjAsZmluZDozLGRldGVjdDozLGZpbHRlcjozLHNlbGVjdDozLHJlamVjdDozLGV2ZXJ5OjMsYWxsOjMsc29tZTozLGFueTozLGluY2x1ZGU6MyxpbmNsdWRlczozLGNvbnRhaW5zOjMsaW52b2tlOjAsbWF4OjMsbWluOjMsdG9BcnJheToxLHNpemU6MSxmaXJzdDozLGhlYWQ6Myx0YWtlOjMsaW5pdGlhbDozLHJlc3Q6Myx0YWlsOjMsZHJvcDozLGxhc3Q6Myx3aXRob3V0OjAsZGlmZmVyZW5jZTowLGluZGV4T2Y6MyxzaHVmZmxlOjEsbGFzdEluZGV4T2Y6Myxpc0VtcHR5OjEsY2hhaW46MSxzYW1wbGU6MyxwYXJ0aXRpb246Myxncm91cEJ5OjMsY291bnRCeTozLHNvcnRCeTozLGluZGV4Qnk6MyxmaW5kSW5kZXg6MyxmaW5kTGFzdEluZGV4OjN9O2EoeCxqLCJtb2RlbHMiKTt2YXIgVD1lLlZpZXc9ZnVuY3Rpb24odCl7dGhpcy5jaWQ9ci51bmlxdWVJZCgidmlldyIpLHIuZXh0ZW5kKHRoaXMsci5waWNrKHQseikpLHRoaXMuX2Vuc3VyZUVsZW1lbnQoKSx0aGlzLmluaXRpYWxpemUuYXBwbHkodGhpcyxhcmd1bWVudHMpfSxTPS9eKFxTKylccyooLiopJC8sej1bIm1vZGVsIiwiY29sbGVjdGlvbiIsImVsIiwiaWQiLCJhdHRyaWJ1dGVzIiwiY2xhc3NOYW1lIiwidGFnTmFtZSIsImV2ZW50cyJdO3IuZXh0ZW5kKFQucHJvdG90eXBlLGgse3RhZ05hbWU6ImRpdiIsJDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy4kZWwuZmluZCh0KX0saW5pdGlhbGl6ZTpmdW5jdGlvbigpe30scmVuZGVyOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9LHJlbW92ZTpmdW5jdGlvbigpe3JldHVybiB0aGlzLl9yZW1vdmVFbGVtZW50KCksdGhpcy5zdG9wTGlzdGVuaW5nKCksdGhpc30sX3JlbW92ZUVsZW1lbnQ6ZnVuY3Rpb24oKXt0aGlzLiRlbC5yZW1vdmUoKX0sc2V0RWxlbWVudDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy51bmRlbGVnYXRlRXZlbnRzKCksdGhpcy5fc2V0RWxlbWVudCh0KSx0aGlzLmRlbGVnYXRlRXZlbnRzKCksdGhpc30sX3NldEVsZW1lbnQ6ZnVuY3Rpb24odCl7dGhpcy4kZWw9dCBpbnN0YW5jZW9mIGUuJD90OmUuJCh0KSx0aGlzLmVsPXRoaXMuJGVsWzBdfSxkZWxlZ2F0ZUV2ZW50czpmdW5jdGlvbih0KXtpZih0fHwodD1yLnJlc3VsdCh0aGlzLCJldmVudHMiKSksIXQpcmV0dXJuIHRoaXM7dGhpcy51bmRlbGVnYXRlRXZlbnRzKCk7Zm9yKHZhciBlIGluIHQpe3ZhciBuPXRbZV07aWYoci5pc0Z1bmN0aW9uKG4pfHwobj10aGlzW25dKSxuKXt2YXIgbz1lLm1hdGNoKFMpO3RoaXMuZGVsZWdhdGUob1sxXSxvWzJdLHIuYmluZChuLHRoaXMpKX19cmV0dXJuIHRoaXN9LGRlbGVnYXRlOmZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gdGhpcy4kZWwub24odCsiLmRlbGVnYXRlRXZlbnRzIit0aGlzLmNpZCxlLHIpLHRoaXN9LHVuZGVsZWdhdGVFdmVudHM6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4kZWwmJnRoaXMuJGVsLm9mZigiLmRlbGVnYXRlRXZlbnRzIit0aGlzLmNpZCksdGhpc30sdW5kZWxlZ2F0ZTpmdW5jdGlvbih0LGUscil7cmV0dXJuIHRoaXMuJGVsLm9mZih0KyIuZGVsZWdhdGVFdmVudHMiK3RoaXMuY2lkLGUsciksdGhpc30sX2NyZWF0ZUVsZW1lbnQ6ZnVuY3Rpb24odCl7cmV0dXJuIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodCl9LF9lbnN1cmVFbGVtZW50OmZ1bmN0aW9uKCl7aWYodGhpcy5lbCl0aGlzLnNldEVsZW1lbnQoci5yZXN1bHQodGhpcywiZWwiKSk7ZWxzZXt2YXIgdD1yLmV4dGVuZCh7fSxyLnJlc3VsdCh0aGlzLCJhdHRyaWJ1dGVzIikpO3RoaXMuaWQmJih0LmlkPXIucmVzdWx0KHRoaXMsImlkIikpLHRoaXMuY2xhc3NOYW1lJiYodFsiY2xhc3MiXT1yLnJlc3VsdCh0aGlzLCJjbGFzc05hbWUiKSksdGhpcy5zZXRFbGVtZW50KHRoaXMuX2NyZWF0ZUVsZW1lbnQoci5yZXN1bHQodGhpcywidGFnTmFtZSIpKSksdGhpcy5fc2V0QXR0cmlidXRlcyh0KX19LF9zZXRBdHRyaWJ1dGVzOmZ1bmN0aW9uKHQpe3RoaXMuJGVsLmF0dHIodCl9fSksZS5zeW5jPWZ1bmN0aW9uKHQsbixvKXt2YXIgaT1QW3RdO3IuZGVmYXVsdHMob3x8KG89e30pLHtlbXVsYXRlSFRUUDplLmVtdWxhdGVIVFRQLGVtdWxhdGVKU09OOmUuZW11bGF0ZUpTT059KTt2YXIgcz17dHlwZTppLGRhdGFUeXBlOiJqc29uIn07aWYoby51cmx8fChzLnVybD1yLnJlc3VsdChuLCJ1cmwiKXx8QigpKSxudWxsIT1vLmRhdGF8fCFufHwiY3JlYXRlIiE9PXQmJiJ1cGRhdGUiIT09dCYmInBhdGNoIiE9PXR8fChzLmNvbnRlbnRUeXBlPSJhcHBsaWNhdGlvbi9qc29uIixzLmRhdGE9SlNPTi5zdHJpbmdpZnkoby5hdHRyc3x8bi50b0pTT04obykpKSxvLmVtdWxhdGVKU09OJiYocy5jb250ZW50VHlwZT0iYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIixzLmRhdGE9cy5kYXRhP3ttb2RlbDpzLmRhdGF9Ont9KSxvLmVtdWxhdGVIVFRQJiYoIlBVVCI9PT1pfHwiREVMRVRFIj09PWl8fCJQQVRDSCI9PT1pKSl7cy50eXBlPSJQT1NUIixvLmVtdWxhdGVKU09OJiYocy5kYXRhLl9tZXRob2Q9aSk7dmFyIGE9by5iZWZvcmVTZW5kO28uYmVmb3JlU2VuZD1mdW5jdGlvbih0KXtpZih0LnNldFJlcXVlc3RIZWFkZXIoIlgtSFRUUC1NZXRob2QtT3ZlcnJpZGUiLGkpLGEpcmV0dXJuIGEuYXBwbHkodGhpcyxhcmd1bWVudHMpfX0iR0VUIj09PXMudHlwZXx8by5lbXVsYXRlSlNPTnx8KHMucHJvY2Vzc0RhdGE9ITEpO3ZhciBsPW8uZXJyb3I7by5lcnJvcj1mdW5jdGlvbih0LGUscil7by50ZXh0U3RhdHVzPWUsby5lcnJvclRocm93bj1yLGwmJmwuY2FsbChvLmNvbnRleHQsdCxlLHIpfTt2YXIgdT1vLnhocj1lLmFqYXgoci5leHRlbmQocyxvKSk7cmV0dXJuIG4udHJpZ2dlcigicmVxdWVzdCIsbix1LG8pLHV9O3ZhciBQPXtjcmVhdGU6IlBPU1QiLHVwZGF0ZToiUFVUIixwYXRjaDoiUEFUQ0giLCJkZWxldGUiOiJERUxFVEUiLHJlYWQ6IkdFVCJ9O2UuYWpheD1mdW5jdGlvbigpe3JldHVybiBlLiQuYWpheC5hcHBseShlLiQsYXJndW1lbnRzKX07dmFyIEU9ZS5Sb3V0ZXI9ZnVuY3Rpb24odCl7dHx8KHQ9e30pLHQucm91dGVzJiYodGhpcy5yb3V0ZXM9dC5yb3V0ZXMpLHRoaXMuX2JpbmRSb3V0ZXMoKSx0aGlzLmluaXRpYWxpemUuYXBwbHkodGhpcyxhcmd1bWVudHMpfSxBPS9cKCguKj8pXCkvZyxDPS8oXChcPyk/Olx3Ky9nLE49L1wqXHcrL2csTz0vW1wte31cW1xdKz8uLFxcXF4kfCNcc10vZztyLmV4dGVuZChFLnByb3RvdHlwZSxoLHtpbml0aWFsaXplOmZ1bmN0aW9uKCl7fSxyb3V0ZTpmdW5jdGlvbih0LG4sbyl7ci5pc1JlZ0V4cCh0KXx8KHQ9dGhpcy5fcm91dGVUb1JlZ0V4cCh0KSksci5pc0Z1bmN0aW9uKG4pJiYobz1uLG49IiIpLG98fChvPXRoaXNbbl0pO3ZhciBpPXRoaXM7cmV0dXJuIGUuaGlzdG9yeS5yb3V0ZSh0LGZ1bmN0aW9uKHIpe3ZhciBzPWkuX2V4dHJhY3RQYXJhbWV0ZXJzKHQscik7aS5leGVjdXRlKG8scyxuKSE9PSExJiYoaS50cmlnZ2VyLmFwcGx5KGksWyJyb3V0ZToiK25dLmNvbmNhdChzKSksaS50cmlnZ2VyKCJyb3V0ZSIsbixzKSxlLmhpc3RvcnkudHJpZ2dlcigicm91dGUiLGksbixzKSl9KSx0aGlzfSxleGVjdXRlOmZ1bmN0aW9uKHQsZSxyKXt0JiZ0LmFwcGx5KHRoaXMsZSl9LG5hdmlnYXRlOmZ1bmN0aW9uKHQscil7cmV0dXJuIGUuaGlzdG9yeS5uYXZpZ2F0ZSh0LHIpLHRoaXN9LF9iaW5kUm91dGVzOmZ1bmN0aW9uKCl7aWYodGhpcy5yb3V0ZXMpe3RoaXMucm91dGVzPXIucmVzdWx0KHRoaXMsInJvdXRlcyIpO2Zvcih2YXIgdCxlPXIua2V5cyh0aGlzLnJvdXRlcyk7bnVsbCE9KHQ9ZS5wb3AoKSk7KXRoaXMucm91dGUodCx0aGlzLnJvdXRlc1t0XSl9fSxfcm91dGVUb1JlZ0V4cDpmdW5jdGlvbih0KXtyZXR1cm4gdD10LnJlcGxhY2UoTywiXFwkJiIpLnJlcGxhY2UoQSwiKD86JDEpPyIpLnJlcGxhY2UoQyxmdW5jdGlvbih0LGUpe3JldHVybiBlP3Q6IihbXi8/XSspIn0pLnJlcGxhY2UoTiwiKFteP10qPykiKSxuZXcgUmVnRXhwKCJeIit0KyIoPzpcXD8oW1xcc1xcU10qKSk/JCIpfSxfZXh0cmFjdFBhcmFtZXRlcnM6ZnVuY3Rpb24odCxlKXt2YXIgbj10LmV4ZWMoZSkuc2xpY2UoMSk7cmV0dXJuIHIubWFwKG4sZnVuY3Rpb24odCxlKXtyZXR1cm4gZT09PW4ubGVuZ3RoLTE/dHx8bnVsbDp0P2RlY29kZVVSSUNvbXBvbmVudCh0KTpudWxsfSl9fSk7dmFyIHE9ZS5IaXN0b3J5PWZ1bmN0aW9uKCl7dGhpcy5oYW5kbGVycz1bXSx0aGlzLmNoZWNrVXJsPXIuYmluZCh0aGlzLmNoZWNrVXJsLHRoaXMpLCJ1bmRlZmluZWQiIT10eXBlb2Ygd2luZG93JiYodGhpcy5sb2NhdGlvbj13aW5kb3cubG9jYXRpb24sdGhpcy5oaXN0b3J5PXdpbmRvdy5oaXN0b3J5KX0sRD0vXlsjXC9dfFxzKyQvZyxJPS9eXC8rfFwvKyQvZyxSPS8jLiokLztxLnN0YXJ0ZWQ9ITEsci5leHRlbmQocS5wcm90b3R5cGUsaCx7aW50ZXJ2YWw6NTAsYXRSb290OmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5sb2NhdGlvbi5wYXRobmFtZS5yZXBsYWNlKC9bXlwvXSQvLCIkJi8iKTtyZXR1cm4gdD09PXRoaXMucm9vdCYmIXRoaXMuZ2V0U2VhcmNoKCl9LG1hdGNoUm9vdDpmdW5jdGlvbigpe3ZhciB0PXRoaXMuZGVjb2RlRnJhZ21lbnQodGhpcy5sb2NhdGlvbi5wYXRobmFtZSksZT10LnNsaWNlKDAsdGhpcy5yb290Lmxlbmd0aC0xKSsiLyI7cmV0dXJuIGU9PT10aGlzLnJvb3R9LGRlY29kZUZyYWdtZW50OmZ1bmN0aW9uKHQpe3JldHVybiBkZWNvZGVVUkkodC5yZXBsYWNlKC8lMjUvZywiJTI1MjUiKSl9LGdldFNlYXJjaDpmdW5jdGlvbigpe3ZhciB0PXRoaXMubG9jYXRpb24uaHJlZi5yZXBsYWNlKC8jLiovLCIiKS5tYXRjaCgvXD8uKy8pO3JldHVybiB0P3RbMF06IiJ9LGdldEhhc2g6ZnVuY3Rpb24odCl7dmFyIGU9KHR8fHRoaXMpLmxvY2F0aW9uLmhyZWYubWF0Y2goLyMoLiopJC8pO3JldHVybiBlP2VbMV06IiJ9LGdldFBhdGg6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmRlY29kZUZyYWdtZW50KHRoaXMubG9jYXRpb24ucGF0aG5hbWUrdGhpcy5nZXRTZWFyY2goKSkuc2xpY2UodGhpcy5yb290Lmxlbmd0aC0xKTtyZXR1cm4iLyI9PT10LmNoYXJBdCgwKT90LnNsaWNlKDEpOnR9LGdldEZyYWdtZW50OmZ1bmN0aW9uKHQpe3JldHVybiBudWxsPT10JiYodD10aGlzLl91c2VQdXNoU3RhdGV8fCF0aGlzLl93YW50c0hhc2hDaGFuZ2U/dGhpcy5nZXRQYXRoKCk6dGhpcy5nZXRIYXNoKCkpLHQucmVwbGFjZShELCIiKX0sc3RhcnQ6ZnVuY3Rpb24odCl7aWYocS5zdGFydGVkKXRocm93IG5ldyBFcnJvcigiQmFja2JvbmUuaGlzdG9yeSBoYXMgYWxyZWFkeSBiZWVuIHN0YXJ0ZWQiKTtpZihxLnN0YXJ0ZWQ9ITAsdGhpcy5vcHRpb25zPXIuZXh0ZW5kKHtyb290OiIvIn0sdGhpcy5vcHRpb25zLHQpLHRoaXMucm9vdD10aGlzLm9wdGlvbnMucm9vdCx0aGlzLl93YW50c0hhc2hDaGFuZ2U9dGhpcy5vcHRpb25zLmhhc2hDaGFuZ2UhPT0hMSx0aGlzLl9oYXNIYXNoQ2hhbmdlPSJvbmhhc2hjaGFuZ2UiaW4gd2luZG93JiYodm9pZCAwPT09ZG9jdW1lbnQuZG9jdW1lbnRNb2RlfHxkb2N1bWVudC5kb2N1bWVudE1vZGU+NyksdGhpcy5fdXNlSGFzaENoYW5nZT10aGlzLl93YW50c0hhc2hDaGFuZ2UmJnRoaXMuX2hhc0hhc2hDaGFuZ2UsdGhpcy5fd2FudHNQdXNoU3RhdGU9ISF0aGlzLm9wdGlvbnMucHVzaFN0YXRlLHRoaXMuX2hhc1B1c2hTdGF0ZT0hKCF0aGlzLmhpc3Rvcnl8fCF0aGlzLmhpc3RvcnkucHVzaFN0YXRlKSx0aGlzLl91c2VQdXNoU3RhdGU9dGhpcy5fd2FudHNQdXNoU3RhdGUmJnRoaXMuX2hhc1B1c2hTdGF0ZSx0aGlzLmZyYWdtZW50PXRoaXMuZ2V0RnJhZ21lbnQoKSx0aGlzLnJvb3Q9KCIvIit0aGlzLnJvb3QrIi8iKS5yZXBsYWNlKEksIi8iKSx0aGlzLl93YW50c0hhc2hDaGFuZ2UmJnRoaXMuX3dhbnRzUHVzaFN0YXRlKXtpZighdGhpcy5faGFzUHVzaFN0YXRlJiYhdGhpcy5hdFJvb3QoKSl7dmFyIGU9dGhpcy5yb290LnNsaWNlKDAsLTEpfHwiLyI7cmV0dXJuIHRoaXMubG9jYXRpb24ucmVwbGFjZShlKyIjIit0aGlzLmdldFBhdGgoKSksITB9dGhpcy5faGFzUHVzaFN0YXRlJiZ0aGlzLmF0Um9vdCgpJiZ0aGlzLm5hdmlnYXRlKHRoaXMuZ2V0SGFzaCgpLHtyZXBsYWNlOiEwfSl9aWYoIXRoaXMuX2hhc0hhc2hDaGFuZ2UmJnRoaXMuX3dhbnRzSGFzaENoYW5nZSYmIXRoaXMuX3VzZVB1c2hTdGF0ZSl7dGhpcy5pZnJhbWU9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiaWZyYW1lIiksdGhpcy5pZnJhbWUuc3JjPSJqYXZhc2NyaXB0OjAiLHRoaXMuaWZyYW1lLnN0eWxlLmRpc3BsYXk9Im5vbmUiLHRoaXMuaWZyYW1lLnRhYkluZGV4PS0xO3ZhciBuPWRvY3VtZW50LmJvZHksbz1uLmluc2VydEJlZm9yZSh0aGlzLmlmcmFtZSxuLmZpcnN0Q2hpbGQpLmNvbnRlbnRXaW5kb3c7by5kb2N1bWVudC5vcGVuKCksby5kb2N1bWVudC5jbG9zZSgpLG8ubG9jYXRpb24uaGFzaD0iIyIrdGhpcy5mcmFnbWVudH12YXIgaT13aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcnx8ZnVuY3Rpb24odCxlKXtyZXR1cm4gYXR0YWNoRXZlbnQoIm9uIit0LGUpfTtpZih0aGlzLl91c2VQdXNoU3RhdGU/aSgicG9wc3RhdGUiLHRoaXMuY2hlY2tVcmwsITEpOnRoaXMuX3VzZUhhc2hDaGFuZ2UmJiF0aGlzLmlmcmFtZT9pKCJoYXNoY2hhbmdlIix0aGlzLmNoZWNrVXJsLCExKTp0aGlzLl93YW50c0hhc2hDaGFuZ2UmJih0aGlzLl9jaGVja1VybEludGVydmFsPXNldEludGVydmFsKHRoaXMuY2hlY2tVcmwsdGhpcy5pbnRlcnZhbCkpLCF0aGlzLm9wdGlvbnMuc2lsZW50KXJldHVybiB0aGlzLmxvYWRVcmwoKX0sc3RvcDpmdW5jdGlvbigpe3ZhciB0PXdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyfHxmdW5jdGlvbih0LGUpe3JldHVybiBkZXRhY2hFdmVudCgib24iK3QsZSl9O3RoaXMuX3VzZVB1c2hTdGF0ZT90KCJwb3BzdGF0ZSIsdGhpcy5jaGVja1VybCwhMSk6dGhpcy5fdXNlSGFzaENoYW5nZSYmIXRoaXMuaWZyYW1lJiZ0KCJoYXNoY2hhbmdlIix0aGlzLmNoZWNrVXJsLCExKSx0aGlzLmlmcmFtZSYmKGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQodGhpcy5pZnJhbWUpLHRoaXMuaWZyYW1lPW51bGwpLHRoaXMuX2NoZWNrVXJsSW50ZXJ2YWwmJmNsZWFySW50ZXJ2YWwodGhpcy5fY2hlY2tVcmxJbnRlcnZhbCkscS5zdGFydGVkPSExfSxyb3V0ZTpmdW5jdGlvbih0LGUpe3RoaXMuaGFuZGxlcnMudW5zaGlmdCh7cm91dGU6dCxjYWxsYmFjazplfSl9LGNoZWNrVXJsOmZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuZ2V0RnJhZ21lbnQoKTtyZXR1cm4gZT09PXRoaXMuZnJhZ21lbnQmJnRoaXMuaWZyYW1lJiYoZT10aGlzLmdldEhhc2godGhpcy5pZnJhbWUuY29udGVudFdpbmRvdykpLGUhPT10aGlzLmZyYWdtZW50JiYodGhpcy5pZnJhbWUmJnRoaXMubmF2aWdhdGUoZSksdm9pZCB0aGlzLmxvYWRVcmwoKSl9LGxvYWRVcmw6ZnVuY3Rpb24odCl7cmV0dXJuISF0aGlzLm1hdGNoUm9vdCgpJiYodD10aGlzLmZyYWdtZW50PXRoaXMuZ2V0RnJhZ21lbnQodCksci5zb21lKHRoaXMuaGFuZGxlcnMsZnVuY3Rpb24oZSl7aWYoZS5yb3V0ZS50ZXN0KHQpKXJldHVybiBlLmNhbGxiYWNrKHQpLCEwfSkpfSxuYXZpZ2F0ZTpmdW5jdGlvbih0LGUpe2lmKCFxLnN0YXJ0ZWQpcmV0dXJuITE7ZSYmZSE9PSEwfHwoZT17dHJpZ2dlcjohIWV9KSx0PXRoaXMuZ2V0RnJhZ21lbnQodHx8IiIpO3ZhciByPXRoaXMucm9vdDsiIiE9PXQmJiI/IiE9PXQuY2hhckF0KDApfHwocj1yLnNsaWNlKDAsLTEpfHwiLyIpO3ZhciBuPXIrdDtpZih0PXRoaXMuZGVjb2RlRnJhZ21lbnQodC5yZXBsYWNlKFIsIiIpKSx0aGlzLmZyYWdtZW50IT09dCl7aWYodGhpcy5mcmFnbWVudD10LHRoaXMuX3VzZVB1c2hTdGF0ZSl0aGlzLmhpc3RvcnlbZS5yZXBsYWNlPyJyZXBsYWNlU3RhdGUiOiJwdXNoU3RhdGUiXSh7fSxkb2N1bWVudC50aXRsZSxuKTtlbHNle2lmKCF0aGlzLl93YW50c0hhc2hDaGFuZ2UpcmV0dXJuIHRoaXMubG9jYXRpb24uYXNzaWduKG4pO2lmKHRoaXMuX3VwZGF0ZUhhc2godGhpcy5sb2NhdGlvbix0LGUucmVwbGFjZSksdGhpcy5pZnJhbWUmJnQhPT10aGlzLmdldEhhc2godGhpcy5pZnJhbWUuY29udGVudFdpbmRvdykpe3ZhciBvPXRoaXMuaWZyYW1lLmNvbnRlbnRXaW5kb3c7ZS5yZXBsYWNlfHwoby5kb2N1bWVudC5vcGVuKCksby5kb2N1bWVudC5jbG9zZSgpKSx0aGlzLl91cGRhdGVIYXNoKG8ubG9jYXRpb24sdCxlLnJlcGxhY2UpfX1yZXR1cm4gZS50cmlnZ2VyP3RoaXMubG9hZFVybCh0KTp2b2lkIDB9fSxfdXBkYXRlSGFzaDpmdW5jdGlvbih0LGUscil7aWYocil7dmFyIG49dC5ocmVmLnJlcGxhY2UoLyhqYXZhc2NyaXB0OnwjKS4qJC8sIiIpO3QucmVwbGFjZShuKyIjIitlKX1lbHNlIHQuaGFzaD0iIyIrZX19KSxlLmhpc3Rvcnk9bmV3IHE7dmFyIEY9ZnVuY3Rpb24odCxlKXt2YXIgbixvPXRoaXM7cmV0dXJuIG49dCYmci5oYXModCwiY29uc3RydWN0b3IiKT90LmNvbnN0cnVjdG9yOmZ1bmN0aW9uKCl7cmV0dXJuIG8uYXBwbHkodGhpcyxhcmd1bWVudHMpfSxyLmV4dGVuZChuLG8sZSksbi5wcm90b3R5cGU9ci5jcmVhdGUoby5wcm90b3R5cGUsdCksbi5wcm90b3R5cGUuY29uc3RydWN0b3I9bixuLl9fc3VwZXJfXz1vLnByb3RvdHlwZSxufTt2LmV4dGVuZD14LmV4dGVuZD1FLmV4dGVuZD1ULmV4dGVuZD1xLmV4dGVuZD1GO3ZhciBCPWZ1bmN0aW9uKCl7dGhyb3cgbmV3IEVycm9yKCdBICJ1cmwiIHByb3BlcnR5IG9yIGZ1bmN0aW9uIG11c3QgYmUgc3BlY2lmaWVkJyl9LEw9ZnVuY3Rpb24odCxlKXt2YXIgcj1lLmVycm9yO2UuZXJyb3I9ZnVuY3Rpb24obil7ciYmci5jYWxsKGUuY29udGV4dCx0LG4sZSksdC50cmlnZ2VyKCJlcnJvciIsdCxuLGUpfX07cmV0dXJuIGV9KX0pLmNhbGwodGhpcywidW5kZWZpbmVkIiE9dHlwZW9mIGdsb2JhbD9nbG9iYWw6InVuZGVmaW5lZCIhPXR5cGVvZiBzZWxmP3NlbGY6InVuZGVmaW5lZCIhPXR5cGVvZiB3aW5kb3c/d2luZG93Ont9KX0se2pxdWVyeToianF1ZXJ5Iix1bmRlcnNjb3JlOiJ1bmRlcnNjb3JlIn1dLF9wcm9jZXNzOltmdW5jdGlvbih0LGUscil7ZnVuY3Rpb24gbigpe3Rocm93IG5ldyBFcnJvcigic2V0VGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCIpfWZ1bmN0aW9uIG8oKXt0aHJvdyBuZXcgRXJyb3IoImNsZWFyVGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCIpfWZ1bmN0aW9uIGkodCl7aWYoYz09PXNldFRpbWVvdXQpcmV0dXJuIHNldFRpbWVvdXQodCwwKTtpZigoYz09PW58fCFjKSYmc2V0VGltZW91dClyZXR1cm4gYz1zZXRUaW1lb3V0LHNldFRpbWVvdXQodCwwKTt0cnl7cmV0dXJuIGModCwwKX1jYXRjaChlKXt0cnl7cmV0dXJuIGMuY2FsbChudWxsLHQsMCl9Y2F0Y2goZSl7cmV0dXJuIGMuY2FsbCh0aGlzLHQsMCl9fX1mdW5jdGlvbiBzKHQpe2lmKHA9PT1jbGVhclRpbWVvdXQpcmV0dXJuIGNsZWFyVGltZW91dCh0KTtpZigocD09PW98fCFwKSYmY2xlYXJUaW1lb3V0KXJldHVybiBwPWNsZWFyVGltZW91dCxjbGVhclRpbWVvdXQodCk7dHJ5e3JldHVybiBwKHQpfWNhdGNoKGUpe3RyeXtyZXR1cm4gcC5jYWxsKG51bGwsdCl9Y2F0Y2goZSl7cmV0dXJuIHAuY2FsbCh0aGlzLHQpfX19ZnVuY3Rpb24gYSgpe20mJmQmJihtPSExLGQubGVuZ3RoP2Y9ZC5jb25jYXQoZik6Zz0tMSxmLmxlbmd0aCYmbCgpKX1mdW5jdGlvbiBsKCl7aWYoIW0pe3ZhciB0PWkoYSk7bT0hMDtmb3IodmFyIGU9Zi5sZW5ndGg7ZTspe2ZvcihkPWYsZj1bXTsrK2c8ZTspZCYmZFtnXS5ydW4oKTtnPS0xLGU9Zi5sZW5ndGh9ZD1udWxsLG09ITEscyh0KX19ZnVuY3Rpb24gdSh0LGUpe3RoaXMuZnVuPXQsdGhpcy5hcnJheT1lfWZ1bmN0aW9uIGgoKXt9dmFyIGMscCxfPWUuZXhwb3J0cz17fTshZnVuY3Rpb24oKXt0cnl7Yz0iZnVuY3Rpb24iPT10eXBlb2Ygc2V0VGltZW91dD9zZXRUaW1lb3V0Om59Y2F0Y2godCl7Yz1ufXRyeXtwPSJmdW5jdGlvbiI9PXR5cGVvZiBjbGVhclRpbWVvdXQ/Y2xlYXJUaW1lb3V0Om99Y2F0Y2godCl7cD1vfX0oKTt2YXIgZCxmPVtdLG09ITEsZz0tMTtfLm5leHRUaWNrPWZ1bmN0aW9uKHQpe3ZhciBlPW5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoLTEpO2lmKGFyZ3VtZW50cy5sZW5ndGg+MSlmb3IodmFyIHI9MTtyPGFyZ3VtZW50cy5sZW5ndGg7cisrKWVbci0xXT1hcmd1bWVudHNbcl07Zi5wdXNoKG5ldyB1KHQsZSkpLDEhPT1mLmxlbmd0aHx8bXx8aShsKX0sdS5wcm90b3R5cGUucnVuPWZ1bmN0aW9uKCl7dGhpcy5mdW4uYXBwbHkobnVsbCx0aGlzLmFycmF5KX0sXy50aXRsZT0iYnJvd3NlciIsXy5icm93c2VyPSEwLF8uZW52PXt9LF8uYXJndj1bXSxfLnZlcnNpb249IiIsXy52ZXJzaW9ucz17fSxfLm9uPWgsXy5hZGRMaXN0ZW5lcj1oLF8ub25jZT1oLF8ub2ZmPWgsXy5yZW1vdmVMaXN0ZW5lcj1oLF8ucmVtb3ZlQWxsTGlzdGVuZXJzPWgsXy5lbWl0PWgsXy5iaW5kaW5nPWZ1bmN0aW9uKHQpe3Rocm93IG5ldyBFcnJvcigicHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQiKX0sXy5jd2Q9ZnVuY3Rpb24oKXtyZXR1cm4iLyJ9LF8uY2hkaXI9ZnVuY3Rpb24odCl7dGhyb3cgbmV3IEVycm9yKCJwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQiKX0sXy51bWFzaz1mdW5jdGlvbigpe3JldHVybiAwfX0se31dLCJlczYtcHJvbWlzZSI6W2Z1bmN0aW9uKGUscixuKXsoZnVuY3Rpb24obixvKXsvKiEKICogQG92ZXJ2aWV3IGVzNi1wcm9taXNlIC0gYSB0aW55IGltcGxlbWVudGF0aW9uIG9mIFByb21pc2VzL0ErLgogKiBAY29weXJpZ2h0IENvcHlyaWdodCAoYykgMjAxNCBZZWh1ZGEgS2F0eiwgVG9tIERhbGUsIFN0ZWZhbiBQZW5uZXIgYW5kIGNvbnRyaWJ1dG9ycyAoQ29udmVyc2lvbiB0byBFUzYgQVBJIGJ5IEpha2UgQXJjaGliYWxkKQogKiBAbGljZW5zZSAgIExpY2Vuc2VkIHVuZGVyIE1JVCBsaWNlbnNlCiAqICAgICAgICAgICAgU2VlIGh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9qYWtlYXJjaGliYWxkL2VzNi1wcm9taXNlL21hc3Rlci9MSUNFTlNFCiAqIEB2ZXJzaW9uICAgMy4wLjIKICovCihmdW5jdGlvbigpeyJ1c2Ugc3RyaWN0IjtmdW5jdGlvbiBpKHQpe3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiB0fHwib2JqZWN0Ij09dHlwZW9mIHQmJm51bGwhPT10fWZ1bmN0aW9uIHModCl7cmV0dXJuImZ1bmN0aW9uIj09dHlwZW9mIHR9ZnVuY3Rpb24gYSh0KXtyZXR1cm4ib2JqZWN0Ij09dHlwZW9mIHQmJm51bGwhPT10fWZ1bmN0aW9uIGwodCl7SD10fWZ1bmN0aW9uIHUodCl7Sj10fWZ1bmN0aW9uIGgoKXtyZXR1cm4gZnVuY3Rpb24oKXtuLm5leHRUaWNrKGYpfX1mdW5jdGlvbiBjKCl7cmV0dXJuIGZ1bmN0aW9uKCl7WShmKX19ZnVuY3Rpb24gcCgpe3ZhciB0PTAsZT1uZXcgWihmKSxyPWRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCIiKTtyZXR1cm4gZS5vYnNlcnZlKHIse2NoYXJhY3RlckRhdGE6ITB9KSxmdW5jdGlvbigpe3IuZGF0YT10PSsrdCUyfX1mdW5jdGlvbiBfKCl7dmFyIHQ9bmV3IE1lc3NhZ2VDaGFubmVsO3JldHVybiB0LnBvcnQxLm9ubWVzc2FnZT1mLGZ1bmN0aW9uKCl7dC5wb3J0Mi5wb3N0TWVzc2FnZSgwKX19ZnVuY3Rpb24gZCgpe3JldHVybiBmdW5jdGlvbigpe3NldFRpbWVvdXQoZiwxKX19ZnVuY3Rpb24gZigpe2Zvcih2YXIgdD0wO3Q8Vzt0Kz0yKXt2YXIgZT1ydFt0XSxyPXJ0W3QrMV07ZShyKSxydFt0XT12b2lkIDAscnRbdCsxXT12b2lkIDB9Vz0wfWZ1bmN0aW9uIG0oKXt0cnl7dmFyIHQ9ZSxyPXQoInZlcnR4Iik7cmV0dXJuIFk9ci5ydW5Pbkxvb3B8fHIucnVuT25Db250ZXh0LGMoKX1jYXRjaChuKXtyZXR1cm4gZCgpfX1mdW5jdGlvbiBnKCl7fWZ1bmN0aW9uIHkoKXtyZXR1cm4gbmV3IFR5cGVFcnJvcigiWW91IGNhbm5vdCByZXNvbHZlIGEgcHJvbWlzZSB3aXRoIGl0c2VsZiIpfWZ1bmN0aW9uIHYoKXtyZXR1cm4gbmV3IFR5cGVFcnJvcigiQSBwcm9taXNlcyBjYWxsYmFjayBjYW5ub3QgcmV0dXJuIHRoYXQgc2FtZSBwcm9taXNlLiIpfWZ1bmN0aW9uIGIodCl7dHJ5e3JldHVybiB0LnRoZW59Y2F0Y2goZSl7cmV0dXJuIHN0LmVycm9yPWUsc3R9fWZ1bmN0aW9uIHgodCxlLHIsbil7dHJ5e3QuY2FsbChlLHIsbil9Y2F0Y2gobyl7cmV0dXJuIG99fWZ1bmN0aW9uIHcodCxlLHIpe0ooZnVuY3Rpb24odCl7dmFyIG49ITEsbz14KHIsZSxmdW5jdGlvbihyKXtufHwobj0hMCxlIT09cj9qKHQscik6Uyh0LHIpKX0sZnVuY3Rpb24oZSl7bnx8KG49ITAseih0LGUpKX0sIlNldHRsZTogIisodC5fbGFiZWx8fCIgdW5rbm93biBwcm9taXNlIikpOyFuJiZvJiYobj0hMCx6KHQsbykpfSx0KX1mdW5jdGlvbiBNKHQsZSl7ZS5fc3RhdGU9PT1vdD9TKHQsZS5fcmVzdWx0KTplLl9zdGF0ZT09PWl0P3oodCxlLl9yZXN1bHQpOlAoZSx2b2lkIDAsZnVuY3Rpb24oZSl7aih0LGUpfSxmdW5jdGlvbihlKXt6KHQsZSl9KX1mdW5jdGlvbiBrKHQsZSl7aWYoZS5jb25zdHJ1Y3Rvcj09PXQuY29uc3RydWN0b3IpTSh0LGUpO2Vsc2V7dmFyIHI9YihlKTtyPT09c3Q/eih0LHN0LmVycm9yKTp2b2lkIDA9PT1yP1ModCxlKTpzKHIpP3codCxlLHIpOlModCxlKX19ZnVuY3Rpb24gaih0LGUpe3Q9PT1lP3oodCx5KCkpOmkoZSk/ayh0LGUpOlModCxlKX1mdW5jdGlvbiBUKHQpe3QuX29uZXJyb3ImJnQuX29uZXJyb3IodC5fcmVzdWx0KSxFKHQpfWZ1bmN0aW9uIFModCxlKXt0Ll9zdGF0ZT09PW50JiYodC5fcmVzdWx0PWUsdC5fc3RhdGU9b3QsMCE9PXQuX3N1YnNjcmliZXJzLmxlbmd0aCYmSihFLHQpKX1mdW5jdGlvbiB6KHQsZSl7dC5fc3RhdGU9PT1udCYmKHQuX3N0YXRlPWl0LHQuX3Jlc3VsdD1lLEooVCx0KSl9ZnVuY3Rpb24gUCh0LGUscixuKXt2YXIgbz10Ll9zdWJzY3JpYmVycyxpPW8ubGVuZ3RoO3QuX29uZXJyb3I9bnVsbCxvW2ldPWUsb1tpK290XT1yLG9baStpdF09biwwPT09aSYmdC5fc3RhdGUmJkooRSx0KX1mdW5jdGlvbiBFKHQpe3ZhciBlPXQuX3N1YnNjcmliZXJzLHI9dC5fc3RhdGU7aWYoMCE9PWUubGVuZ3RoKXtmb3IodmFyIG4sbyxpPXQuX3Jlc3VsdCxzPTA7czxlLmxlbmd0aDtzKz0zKW49ZVtzXSxvPWVbcytyXSxuP04ocixuLG8saSk6byhpKTt0Ll9zdWJzY3JpYmVycy5sZW5ndGg9MH19ZnVuY3Rpb24gQSgpe3RoaXMuZXJyb3I9bnVsbH1mdW5jdGlvbiBDKHQsZSl7dHJ5e3JldHVybiB0KGUpfWNhdGNoKHIpe3JldHVybiBhdC5lcnJvcj1yLGF0fX1mdW5jdGlvbiBOKHQsZSxyLG4pe3ZhciBvLGksYSxsLHU9cyhyKTtpZih1KXtpZihvPUMocixuKSxvPT09YXQ/KGw9ITAsaT1vLmVycm9yLG89bnVsbCk6YT0hMCxlPT09bylyZXR1cm4gdm9pZCB6KGUsdigpKX1lbHNlIG89bixhPSEwO2UuX3N0YXRlIT09bnR8fCh1JiZhP2ooZSxvKTpsP3ooZSxpKTp0PT09b3Q/UyhlLG8pOnQ9PT1pdCYmeihlLG8pKX1mdW5jdGlvbiBPKHQsZSl7dHJ5e2UoZnVuY3Rpb24oZSl7aih0LGUpfSxmdW5jdGlvbihlKXt6KHQsZSl9KX1jYXRjaChyKXt6KHQscil9fWZ1bmN0aW9uIHEodCxlKXt2YXIgcj10aGlzO3IuX2luc3RhbmNlQ29uc3RydWN0b3I9dCxyLnByb21pc2U9bmV3IHQoZyksci5fdmFsaWRhdGVJbnB1dChlKT8oci5faW5wdXQ9ZSxyLmxlbmd0aD1lLmxlbmd0aCxyLl9yZW1haW5pbmc9ZS5sZW5ndGgsci5faW5pdCgpLDA9PT1yLmxlbmd0aD9TKHIucHJvbWlzZSxyLl9yZXN1bHQpOihyLmxlbmd0aD1yLmxlbmd0aHx8MCxyLl9lbnVtZXJhdGUoKSwwPT09ci5fcmVtYWluaW5nJiZTKHIucHJvbWlzZSxyLl9yZXN1bHQpKSk6eihyLnByb21pc2Usci5fdmFsaWRhdGlvbkVycm9yKCkpfWZ1bmN0aW9uIEQodCl7cmV0dXJuIG5ldyBsdCh0aGlzLHQpLnByb21pc2V9ZnVuY3Rpb24gSSh0KXtmdW5jdGlvbiBlKHQpe2oobyx0KX1mdW5jdGlvbiByKHQpe3oobyx0KX12YXIgbj10aGlzLG89bmV3IG4oZyk7aWYoISQodCkpcmV0dXJuIHoobyxuZXcgVHlwZUVycm9yKCJZb3UgbXVzdCBwYXNzIGFuIGFycmF5IHRvIHJhY2UuIikpLG87Zm9yKHZhciBpPXQubGVuZ3RoLHM9MDtvLl9zdGF0ZT09PW50JiZzPGk7cysrKVAobi5yZXNvbHZlKHRbc10pLHZvaWQgMCxlLHIpO3JldHVybiBvfWZ1bmN0aW9uIFIodCl7dmFyIGU9dGhpcztpZih0JiYib2JqZWN0Ij09dHlwZW9mIHQmJnQuY29uc3RydWN0b3I9PT1lKXJldHVybiB0O3ZhciByPW5ldyBlKGcpO3JldHVybiBqKHIsdCkscn1mdW5jdGlvbiBGKHQpe3ZhciBlPXRoaXMscj1uZXcgZShnKTtyZXR1cm4geihyLHQpLHJ9ZnVuY3Rpb24gQigpe3Rocm93IG5ldyBUeXBlRXJyb3IoIllvdSBtdXN0IHBhc3MgYSByZXNvbHZlciBmdW5jdGlvbiBhcyB0aGUgZmlyc3QgYXJndW1lbnQgdG8gdGhlIHByb21pc2UgY29uc3RydWN0b3IiKX1mdW5jdGlvbiBMKCl7dGhyb3cgbmV3IFR5cGVFcnJvcigiRmFpbGVkIHRvIGNvbnN0cnVjdCAnUHJvbWlzZSc6IFBsZWFzZSB1c2UgdGhlICduZXcnIG9wZXJhdG9yLCB0aGlzIG9iamVjdCBjb25zdHJ1Y3RvciBjYW5ub3QgYmUgY2FsbGVkIGFzIGEgZnVuY3Rpb24uIil9ZnVuY3Rpb24gRyh0KXt0aGlzLl9pZD1fdCsrLHRoaXMuX3N0YXRlPXZvaWQgMCx0aGlzLl9yZXN1bHQ9dm9pZCAwLHRoaXMuX3N1YnNjcmliZXJzPVtdLGchPT10JiYocyh0KXx8QigpLHRoaXMgaW5zdGFuY2VvZiBHfHxMKCksTyh0aGlzLHQpKX1mdW5jdGlvbiBWKCl7dmFyIHQ7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiBvKXQ9bztlbHNlIGlmKCJ1bmRlZmluZWQiIT10eXBlb2Ygc2VsZil0PXNlbGY7ZWxzZSB0cnl7dD1GdW5jdGlvbigicmV0dXJuIHRoaXMiKSgpfWNhdGNoKGUpe3Rocm93IG5ldyBFcnJvcigicG9seWZpbGwgZmFpbGVkIGJlY2F1c2UgZ2xvYmFsIG9iamVjdCBpcyB1bmF2YWlsYWJsZSBpbiB0aGlzIGVudmlyb25tZW50Iil9dmFyIHI9dC5Qcm9taXNlO3ImJiJbb2JqZWN0IFByb21pc2VdIj09PU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChyLnJlc29sdmUoKSkmJiFyLmNhc3R8fCh0LlByb21pc2U9ZHQpfXZhciBVO1U9QXJyYXkuaXNBcnJheT9BcnJheS5pc0FycmF5OmZ1bmN0aW9uKHQpe3JldHVybiJbb2JqZWN0IEFycmF5XSI9PT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodCl9O3ZhciBZLEgsWCwkPVUsVz0wLEo9KHt9LnRvU3RyaW5nLGZ1bmN0aW9uKHQsZSl7cnRbV109dCxydFtXKzFdPWUsVys9MiwyPT09VyYmKEg/SChmKTpYKCkpfSksUT0idW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdz93aW5kb3c6dm9pZCAwLEs9UXx8e30sWj1LLk11dGF0aW9uT2JzZXJ2ZXJ8fEsuV2ViS2l0TXV0YXRpb25PYnNlcnZlcix0dD0idW5kZWZpbmVkIiE9dHlwZW9mIG4mJiJbb2JqZWN0IHByb2Nlc3NdIj09PXt9LnRvU3RyaW5nLmNhbGwobiksZXQ9InVuZGVmaW5lZCIhPXR5cGVvZiBVaW50OENsYW1wZWRBcnJheSYmInVuZGVmaW5lZCIhPXR5cGVvZiBpbXBvcnRTY3JpcHRzJiYidW5kZWZpbmVkIiE9dHlwZW9mIE1lc3NhZ2VDaGFubmVsLHJ0PW5ldyBBcnJheSgxZTMpO1g9dHQ/aCgpOlo/cCgpOmV0P18oKTp2b2lkIDA9PT1RJiYiZnVuY3Rpb24iPT10eXBlb2YgZT9tKCk6ZCgpO3ZhciBudD12b2lkIDAsb3Q9MSxpdD0yLHN0PW5ldyBBLGF0PW5ldyBBO3EucHJvdG90eXBlLl92YWxpZGF0ZUlucHV0PWZ1bmN0aW9uKHQpe3JldHVybiAkKHQpfSxxLnByb3RvdHlwZS5fdmFsaWRhdGlvbkVycm9yPWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBFcnJvcigiQXJyYXkgTWV0aG9kcyBtdXN0IGJlIHByb3ZpZGVkIGFuIEFycmF5Iil9LHEucHJvdG90eXBlLl9pbml0PWZ1bmN0aW9uKCl7dGhpcy5fcmVzdWx0PW5ldyBBcnJheSh0aGlzLmxlbmd0aCl9O3ZhciBsdD1xO3EucHJvdG90eXBlLl9lbnVtZXJhdGU9ZnVuY3Rpb24oKXtmb3IodmFyIHQ9dGhpcyxlPXQubGVuZ3RoLHI9dC5wcm9taXNlLG49dC5faW5wdXQsbz0wO3IuX3N0YXRlPT09bnQmJm88ZTtvKyspdC5fZWFjaEVudHJ5KG5bb10sbyl9LHEucHJvdG90eXBlLl9lYWNoRW50cnk9ZnVuY3Rpb24odCxlKXt2YXIgcj10aGlzLG49ci5faW5zdGFuY2VDb25zdHJ1Y3RvcjthKHQpP3QuY29uc3RydWN0b3I9PT1uJiZ0Ll9zdGF0ZSE9PW50Pyh0Ll9vbmVycm9yPW51bGwsci5fc2V0dGxlZEF0KHQuX3N0YXRlLGUsdC5fcmVzdWx0KSk6ci5fd2lsbFNldHRsZUF0KG4ucmVzb2x2ZSh0KSxlKTooci5fcmVtYWluaW5nLS0sci5fcmVzdWx0W2VdPXQpfSxxLnByb3RvdHlwZS5fc2V0dGxlZEF0PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj10aGlzLG89bi5wcm9taXNlO28uX3N0YXRlPT09bnQmJihuLl9yZW1haW5pbmctLSx0PT09aXQ/eihvLHIpOm4uX3Jlc3VsdFtlXT1yKSwwPT09bi5fcmVtYWluaW5nJiZTKG8sbi5fcmVzdWx0KX0scS5wcm90b3R5cGUuX3dpbGxTZXR0bGVBdD1mdW5jdGlvbih0LGUpe3ZhciByPXRoaXM7UCh0LHZvaWQgMCxmdW5jdGlvbih0KXtyLl9zZXR0bGVkQXQob3QsZSx0KX0sZnVuY3Rpb24odCl7ci5fc2V0dGxlZEF0KGl0LGUsdCl9KX07dmFyIHV0PUQsaHQ9SSxjdD1SLHB0PUYsX3Q9MCxkdD1HO0cuYWxsPXV0LEcucmFjZT1odCxHLnJlc29sdmU9Y3QsRy5yZWplY3Q9cHQsRy5fc2V0U2NoZWR1bGVyPWwsRy5fc2V0QXNhcD11LEcuX2FzYXA9SixHLnByb3RvdHlwZT17Y29uc3RydWN0b3I6Ryx0aGVuOmZ1bmN0aW9uKHQsZSl7dmFyIHI9dGhpcyxuPXIuX3N0YXRlO2lmKG49PT1vdCYmIXR8fG49PT1pdCYmIWUpcmV0dXJuIHRoaXM7dmFyIG89bmV3IHRoaXMuY29uc3RydWN0b3IoZyksaT1yLl9yZXN1bHQ7aWYobil7dmFyIHM9YXJndW1lbnRzW24tMV07SihmdW5jdGlvbigpe04obixvLHMsaSl9KX1lbHNlIFAocixvLHQsZSk7cmV0dXJuIG99LCJjYXRjaCI6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMudGhlbihudWxsLHQpfX07dmFyIGZ0PVYsbXQ9e1Byb21pc2U6ZHQscG9seWZpbGw6ZnR9OyJmdW5jdGlvbiI9PXR5cGVvZiB0JiZ0LmFtZD90KGZ1bmN0aW9uKCl7cmV0dXJuIG10fSk6InVuZGVmaW5lZCIhPXR5cGVvZiByJiZyLmV4cG9ydHM/ci5leHBvcnRzPW10OiJ1bmRlZmluZWQiIT10eXBlb2YgdGhpcyYmKHRoaXMuRVM2UHJvbWlzZT1tdCksZnQoKX0pLmNhbGwodGhpcyl9KS5jYWxsKHRoaXMsZSgiX3Byb2Nlc3MiKSwidW5kZWZpbmVkIiE9dHlwZW9mIGdsb2JhbD9nbG9iYWw6InVuZGVmaW5lZCIhPXR5cGVvZiBzZWxmP3NlbGY6InVuZGVmaW5lZCIhPXR5cGVvZiB3aW5kb3c/d2luZG93Ont9KX0se19wcm9jZXNzOiJfcHJvY2VzcyJ9XSwiaGFtbWVyanMvaGFtbWVyIjpbZnVuY3Rpb24oZSxyLG4pey8qISBIYW1tZXIuSlMgLSB2Mi4wLjcgLSAyMDE2LTA0LTIyCiAqIGh0dHA6Ly9oYW1tZXJqcy5naXRodWIuaW8vCiAqCiAqIENvcHlyaWdodCAoYykgMjAxNiBKb3JpayBUYW5nZWxkZXI7CiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSAqLwohZnVuY3Rpb24oZSxuLG8saSl7InVzZSBzdHJpY3QiO2Z1bmN0aW9uIHModCxlLHIpe3JldHVybiBzZXRUaW1lb3V0KGModCxyKSxlKX1mdW5jdGlvbiBhKHQsZSxyKXtyZXR1cm4hIUFycmF5LmlzQXJyYXkodCkmJihsKHQscltlXSxyKSwhMCl9ZnVuY3Rpb24gbCh0LGUscil7dmFyIG47aWYodClpZih0LmZvckVhY2gpdC5mb3JFYWNoKGUscik7ZWxzZSBpZih0Lmxlbmd0aCE9PWkpZm9yKG49MDtuPHQubGVuZ3RoOyllLmNhbGwocix0W25dLG4sdCksbisrO2Vsc2UgZm9yKG4gaW4gdCl0Lmhhc093blByb3BlcnR5KG4pJiZlLmNhbGwocix0W25dLG4sdCl9ZnVuY3Rpb24gdSh0LHIsbil7dmFyIG89IkRFUFJFQ0FURUQgTUVUSE9EOiAiK3IrIlxuIituKyIgQVQgXG4iO3JldHVybiBmdW5jdGlvbigpe3ZhciByPW5ldyBFcnJvcigiZ2V0LXN0YWNrLXRyYWNlIiksbj1yJiZyLnN0YWNrP3Iuc3RhY2sucmVwbGFjZSgvXlteXChdKz9bXG4kXS9nbSwiIikucmVwbGFjZSgvXlxzK2F0XHMrL2dtLCIiKS5yZXBsYWNlKC9eT2JqZWN0Ljxhbm9ueW1vdXM+XHMqXCgvZ20sInthbm9ueW1vdXN9KClAIik6IlVua25vd24gU3RhY2sgVHJhY2UiLGk9ZS5jb25zb2xlJiYoZS5jb25zb2xlLndhcm58fGUuY29uc29sZS5sb2cpO3JldHVybiBpJiZpLmNhbGwoZS5jb25zb2xlLG8sbiksdC5hcHBseSh0aGlzLGFyZ3VtZW50cyl9fWZ1bmN0aW9uIGgodCxlLHIpe3ZhciBuLG89ZS5wcm90b3R5cGU7bj10LnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKG8pLG4uY29uc3RydWN0b3I9dCxuLl9zdXBlcj1vLHImJl90KG4scil9ZnVuY3Rpb24gYyh0LGUpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiB0LmFwcGx5KGUsYXJndW1lbnRzKX19ZnVuY3Rpb24gcCh0LGUpe3JldHVybiB0eXBlb2YgdD09bXQ/dC5hcHBseShlP2VbMF18fGk6aSxlKTp0fWZ1bmN0aW9uIF8odCxlKXtyZXR1cm4gdD09PWk/ZTp0fWZ1bmN0aW9uIGQodCxlLHIpe2woeShlKSxmdW5jdGlvbihlKXt0LmFkZEV2ZW50TGlzdGVuZXIoZSxyLCExKX0pfWZ1bmN0aW9uIGYodCxlLHIpe2woeShlKSxmdW5jdGlvbihlKXt0LnJlbW92ZUV2ZW50TGlzdGVuZXIoZSxyLCExKX0pfWZ1bmN0aW9uIG0odCxlKXtmb3IoO3Q7KXtpZih0PT1lKXJldHVybiEwO3Q9dC5wYXJlbnROb2RlfXJldHVybiExfWZ1bmN0aW9uIGcodCxlKXtyZXR1cm4gdC5pbmRleE9mKGUpPi0xfWZ1bmN0aW9uIHkodCl7cmV0dXJuIHQudHJpbSgpLnNwbGl0KC9ccysvZyl9ZnVuY3Rpb24gdih0LGUscil7aWYodC5pbmRleE9mJiYhcilyZXR1cm4gdC5pbmRleE9mKGUpO2Zvcih2YXIgbj0wO248dC5sZW5ndGg7KXtpZihyJiZ0W25dW3JdPT1lfHwhciYmdFtuXT09PWUpcmV0dXJuIG47bisrfXJldHVybi0xfWZ1bmN0aW9uIGIodCl7cmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHQsMCl9ZnVuY3Rpb24geCh0LGUscil7Zm9yKHZhciBuPVtdLG89W10saT0wO2k8dC5sZW5ndGg7KXt2YXIgcz1lP3RbaV1bZV06dFtpXTt2KG8scyk8MCYmbi5wdXNoKHRbaV0pLG9baV09cyxpKyt9cmV0dXJuIHImJihuPWU/bi5zb3J0KGZ1bmN0aW9uKHQscil7cmV0dXJuIHRbZV0+cltlXX0pOm4uc29ydCgpKSxufWZ1bmN0aW9uIHcodCxlKXtmb3IodmFyIHIsbixvPWVbMF0udG9VcHBlckNhc2UoKStlLnNsaWNlKDEpLHM9MDtzPGR0Lmxlbmd0aDspe2lmKHI9ZHRbc10sbj1yP3IrbzplLG4gaW4gdClyZXR1cm4gbjtzKyt9cmV0dXJuIGl9ZnVuY3Rpb24gTSgpe3JldHVybiB3dCsrfWZ1bmN0aW9uIGsodCl7dmFyIHI9dC5vd25lckRvY3VtZW50fHx0O3JldHVybiByLmRlZmF1bHRWaWV3fHxyLnBhcmVudFdpbmRvd3x8ZX1mdW5jdGlvbiBqKHQsZSl7dmFyIHI9dGhpczt0aGlzLm1hbmFnZXI9dCx0aGlzLmNhbGxiYWNrPWUsdGhpcy5lbGVtZW50PXQuZWxlbWVudCx0aGlzLnRhcmdldD10Lm9wdGlvbnMuaW5wdXRUYXJnZXQsdGhpcy5kb21IYW5kbGVyPWZ1bmN0aW9uKGUpe3AodC5vcHRpb25zLmVuYWJsZSxbdF0pJiZyLmhhbmRsZXIoZSl9LHRoaXMuaW5pdCgpfWZ1bmN0aW9uIFQodCl7dmFyIGUscj10Lm9wdGlvbnMuaW5wdXRDbGFzcztyZXR1cm4gbmV3KGU9cj9yOmp0P0I6VHQ/VjprdD9ZOkYpKHQsUyl9ZnVuY3Rpb24gUyh0LGUscil7dmFyIG49ci5wb2ludGVycy5sZW5ndGgsbz1yLmNoYW5nZWRQb2ludGVycy5sZW5ndGgsaT1lJkN0JiZuLW89PT0wLHM9ZSYoT3R8cXQpJiZuLW89PT0wO3IuaXNGaXJzdD0hIWksci5pc0ZpbmFsPSEhcyxpJiYodC5zZXNzaW9uPXt9KSxyLmV2ZW50VHlwZT1lLHoodCxyKSx0LmVtaXQoImhhbW1lci5pbnB1dCIsciksdC5yZWNvZ25pemUociksdC5zZXNzaW9uLnByZXZJbnB1dD1yfWZ1bmN0aW9uIHoodCxlKXt2YXIgcj10LnNlc3Npb24sbj1lLnBvaW50ZXJzLG89bi5sZW5ndGg7ci5maXJzdElucHV0fHwoci5maXJzdElucHV0PUEoZSkpLG8+MSYmIXIuZmlyc3RNdWx0aXBsZT9yLmZpcnN0TXVsdGlwbGU9QShlKToxPT09byYmKHIuZmlyc3RNdWx0aXBsZT0hMSk7dmFyIGk9ci5maXJzdElucHV0LHM9ci5maXJzdE11bHRpcGxlLGE9cz9zLmNlbnRlcjppLmNlbnRlcixsPWUuY2VudGVyPUMobik7ZS50aW1lU3RhbXA9dnQoKSxlLmRlbHRhVGltZT1lLnRpbWVTdGFtcC1pLnRpbWVTdGFtcCxlLmFuZ2xlPUQoYSxsKSxlLmRpc3RhbmNlPXEoYSxsKSxQKHIsZSksZS5vZmZzZXREaXJlY3Rpb249TyhlLmRlbHRhWCxlLmRlbHRhWSk7dmFyIHU9TihlLmRlbHRhVGltZSxlLmRlbHRhWCxlLmRlbHRhWSk7ZS5vdmVyYWxsVmVsb2NpdHlYPXUueCxlLm92ZXJhbGxWZWxvY2l0eVk9dS55LGUub3ZlcmFsbFZlbG9jaXR5PXl0KHUueCk+eXQodS55KT91Lng6dS55LGUuc2NhbGU9cz9SKHMucG9pbnRlcnMsbik6MSxlLnJvdGF0aW9uPXM/SShzLnBvaW50ZXJzLG4pOjAsZS5tYXhQb2ludGVycz1yLnByZXZJbnB1dD9lLnBvaW50ZXJzLmxlbmd0aD5yLnByZXZJbnB1dC5tYXhQb2ludGVycz9lLnBvaW50ZXJzLmxlbmd0aDpyLnByZXZJbnB1dC5tYXhQb2ludGVyczplLnBvaW50ZXJzLmxlbmd0aCxFKHIsZSk7dmFyIGg9dC5lbGVtZW50O20oZS5zcmNFdmVudC50YXJnZXQsaCkmJihoPWUuc3JjRXZlbnQudGFyZ2V0KSxlLnRhcmdldD1ofWZ1bmN0aW9uIFAodCxlKXt2YXIgcj1lLmNlbnRlcixuPXQub2Zmc2V0RGVsdGF8fHt9LG89dC5wcmV2RGVsdGF8fHt9LGk9dC5wcmV2SW5wdXR8fHt9O2UuZXZlbnRUeXBlIT09Q3QmJmkuZXZlbnRUeXBlIT09T3R8fChvPXQucHJldkRlbHRhPXt4OmkuZGVsdGFYfHwwLHk6aS5kZWx0YVl8fDB9LG49dC5vZmZzZXREZWx0YT17eDpyLngseTpyLnl9KSxlLmRlbHRhWD1vLngrKHIueC1uLngpLGUuZGVsdGFZPW8ueSsoci55LW4ueSl9ZnVuY3Rpb24gRSh0LGUpe3ZhciByLG4sbyxzLGE9dC5sYXN0SW50ZXJ2YWx8fGUsbD1lLnRpbWVTdGFtcC1hLnRpbWVTdGFtcDtpZihlLmV2ZW50VHlwZSE9cXQmJihsPkF0fHxhLnZlbG9jaXR5PT09aSkpe3ZhciB1PWUuZGVsdGFYLWEuZGVsdGFYLGg9ZS5kZWx0YVktYS5kZWx0YVksYz1OKGwsdSxoKTtuPWMueCxvPWMueSxyPXl0KGMueCk+eXQoYy55KT9jLng6Yy55LHM9Tyh1LGgpLHQubGFzdEludGVydmFsPWV9ZWxzZSByPWEudmVsb2NpdHksbj1hLnZlbG9jaXR5WCxvPWEudmVsb2NpdHlZLHM9YS5kaXJlY3Rpb247ZS52ZWxvY2l0eT1yLGUudmVsb2NpdHlYPW4sZS52ZWxvY2l0eVk9byxlLmRpcmVjdGlvbj1zfWZ1bmN0aW9uIEEodCl7Zm9yKHZhciBlPVtdLHI9MDtyPHQucG9pbnRlcnMubGVuZ3RoOyllW3JdPXtjbGllbnRYOmd0KHQucG9pbnRlcnNbcl0uY2xpZW50WCksY2xpZW50WTpndCh0LnBvaW50ZXJzW3JdLmNsaWVudFkpfSxyKys7cmV0dXJue3RpbWVTdGFtcDp2dCgpLHBvaW50ZXJzOmUsY2VudGVyOkMoZSksZGVsdGFYOnQuZGVsdGFYLGRlbHRhWTp0LmRlbHRhWX19ZnVuY3Rpb24gQyh0KXt2YXIgZT10Lmxlbmd0aDtpZigxPT09ZSlyZXR1cm57eDpndCh0WzBdLmNsaWVudFgpLHk6Z3QodFswXS5jbGllbnRZKX07Zm9yKHZhciByPTAsbj0wLG89MDtvPGU7KXIrPXRbb10uY2xpZW50WCxuKz10W29dLmNsaWVudFksbysrO3JldHVybnt4Omd0KHIvZSkseTpndChuL2UpfX1mdW5jdGlvbiBOKHQsZSxyKXtyZXR1cm57eDplL3R8fDAseTpyL3R8fDB9fWZ1bmN0aW9uIE8odCxlKXtyZXR1cm4gdD09PWU/RHQ6eXQodCk+PXl0KGUpP3Q8MD9JdDpSdDplPDA/RnQ6QnR9ZnVuY3Rpb24gcSh0LGUscil7cnx8KHI9VXQpO3ZhciBuPWVbclswXV0tdFtyWzBdXSxvPWVbclsxXV0tdFtyWzFdXTtyZXR1cm4gTWF0aC5zcXJ0KG4qbitvKm8pfWZ1bmN0aW9uIEQodCxlLHIpe3J8fChyPVV0KTt2YXIgbj1lW3JbMF1dLXRbclswXV0sbz1lW3JbMV1dLXRbclsxXV07cmV0dXJuIDE4MCpNYXRoLmF0YW4yKG8sbikvTWF0aC5QSX1mdW5jdGlvbiBJKHQsZSl7cmV0dXJuIEQoZVsxXSxlWzBdLFl0KStEKHRbMV0sdFswXSxZdCl9ZnVuY3Rpb24gUih0LGUpe3JldHVybiBxKGVbMF0sZVsxXSxZdCkvcSh0WzBdLHRbMV0sWXQpfWZ1bmN0aW9uIEYoKXt0aGlzLmV2RWw9WHQsdGhpcy5ldldpbj0kdCx0aGlzLnByZXNzZWQ9ITEsai5hcHBseSh0aGlzLGFyZ3VtZW50cyl9ZnVuY3Rpb24gQigpe3RoaXMuZXZFbD1RdCx0aGlzLmV2V2luPUt0LGouYXBwbHkodGhpcyxhcmd1bWVudHMpLHRoaXMuc3RvcmU9dGhpcy5tYW5hZ2VyLnNlc3Npb24ucG9pbnRlckV2ZW50cz1bXX1mdW5jdGlvbiBMKCl7dGhpcy5ldlRhcmdldD10ZSx0aGlzLmV2V2luPWVlLHRoaXMuc3RhcnRlZD0hMSxqLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1mdW5jdGlvbiBHKHQsZSl7dmFyIHI9Yih0LnRvdWNoZXMpLG49Yih0LmNoYW5nZWRUb3VjaGVzKTtyZXR1cm4gZSYoT3R8cXQpJiYocj14KHIuY29uY2F0KG4pLCJpZGVudGlmaWVyIiwhMCkpLFtyLG5dfWZ1bmN0aW9uIFYoKXt0aGlzLmV2VGFyZ2V0PW5lLHRoaXMudGFyZ2V0SWRzPXt9LGouYXBwbHkodGhpcyxhcmd1bWVudHMpfWZ1bmN0aW9uIFUodCxlKXt2YXIgcj1iKHQudG91Y2hlcyksbj10aGlzLnRhcmdldElkcztpZihlJihDdHxOdCkmJjE9PT1yLmxlbmd0aClyZXR1cm4gbltyWzBdLmlkZW50aWZpZXJdPSEwLFtyLHJdO3ZhciBvLGkscz1iKHQuY2hhbmdlZFRvdWNoZXMpLGE9W10sbD10aGlzLnRhcmdldDtpZihpPXIuZmlsdGVyKGZ1bmN0aW9uKHQpe3JldHVybiBtKHQudGFyZ2V0LGwpfSksZT09PUN0KWZvcihvPTA7bzxpLmxlbmd0aDspbltpW29dLmlkZW50aWZpZXJdPSEwLG8rKztmb3Iobz0wO288cy5sZW5ndGg7KW5bc1tvXS5pZGVudGlmaWVyXSYmYS5wdXNoKHNbb10pLGUmKE90fHF0KSYmZGVsZXRlIG5bc1tvXS5pZGVudGlmaWVyXSxvKys7cmV0dXJuIGEubGVuZ3RoP1t4KGkuY29uY2F0KGEpLCJpZGVudGlmaWVyIiwhMCksYV06dm9pZCAwfWZ1bmN0aW9uIFkoKXtqLmFwcGx5KHRoaXMsYXJndW1lbnRzKTt2YXIgdD1jKHRoaXMuaGFuZGxlcix0aGlzKTt0aGlzLnRvdWNoPW5ldyBWKHRoaXMubWFuYWdlcix0KSx0aGlzLm1vdXNlPW5ldyBGKHRoaXMubWFuYWdlcix0KSx0aGlzLnByaW1hcnlUb3VjaD1udWxsLHRoaXMubGFzdFRvdWNoZXM9W119ZnVuY3Rpb24gSCh0LGUpe3QmQ3Q/KHRoaXMucHJpbWFyeVRvdWNoPWUuY2hhbmdlZFBvaW50ZXJzWzBdLmlkZW50aWZpZXIsWC5jYWxsKHRoaXMsZSkpOnQmKE90fHF0KSYmWC5jYWxsKHRoaXMsZSl9ZnVuY3Rpb24gWCh0KXt2YXIgZT10LmNoYW5nZWRQb2ludGVyc1swXTtpZihlLmlkZW50aWZpZXI9PT10aGlzLnByaW1hcnlUb3VjaCl7dmFyIHI9e3g6ZS5jbGllbnRYLHk6ZS5jbGllbnRZfTt0aGlzLmxhc3RUb3VjaGVzLnB1c2gocik7dmFyIG49dGhpcy5sYXN0VG91Y2hlcyxvPWZ1bmN0aW9uKCl7dmFyIHQ9bi5pbmRleE9mKHIpO3Q+LTEmJm4uc3BsaWNlKHQsMSl9O3NldFRpbWVvdXQobyxvZSl9fWZ1bmN0aW9uICQodCl7Zm9yKHZhciBlPXQuc3JjRXZlbnQuY2xpZW50WCxyPXQuc3JjRXZlbnQuY2xpZW50WSxuPTA7bjx0aGlzLmxhc3RUb3VjaGVzLmxlbmd0aDtuKyspe3ZhciBvPXRoaXMubGFzdFRvdWNoZXNbbl0saT1NYXRoLmFicyhlLW8ueCkscz1NYXRoLmFicyhyLW8ueSk7aWYoaTw9aWUmJnM8PWllKXJldHVybiEwfXJldHVybiExfWZ1bmN0aW9uIFcodCxlKXt0aGlzLm1hbmFnZXI9dCx0aGlzLnNldChlKX1mdW5jdGlvbiBKKHQpe2lmKGcodCxjZSkpcmV0dXJuIGNlO3ZhciBlPWcodCxwZSkscj1nKHQsX2UpO3JldHVybiBlJiZyP2NlOmV8fHI/ZT9wZTpfZTpnKHQsaGUpP2hlOnVlfWZ1bmN0aW9uIFEoKXtpZighYWUpcmV0dXJuITE7dmFyIHQ9e30scj1lLkNTUyYmZS5DU1Muc3VwcG9ydHM7cmV0dXJuWyJhdXRvIiwibWFuaXB1bGF0aW9uIiwicGFuLXkiLCJwYW4teCIsInBhbi14IHBhbi15Iiwibm9uZSJdLmZvckVhY2goZnVuY3Rpb24obil7dFtuXT0hcnx8ZS5DU1Muc3VwcG9ydHMoInRvdWNoLWFjdGlvbiIsbil9KSx0fWZ1bmN0aW9uIEsodCl7dGhpcy5vcHRpb25zPV90KHt9LHRoaXMuZGVmYXVsdHMsdHx8e30pLHRoaXMuaWQ9TSgpLHRoaXMubWFuYWdlcj1udWxsLHRoaXMub3B0aW9ucy5lbmFibGU9Xyh0aGlzLm9wdGlvbnMuZW5hYmxlLCEwKSx0aGlzLnN0YXRlPWZlLHRoaXMuc2ltdWx0YW5lb3VzPXt9LHRoaXMucmVxdWlyZUZhaWw9W119ZnVuY3Rpb24gWih0KXtyZXR1cm4gdCZiZT8iY2FuY2VsIjp0JnllPyJlbmQiOnQmZ2U/Im1vdmUiOnQmbWU/InN0YXJ0IjoiIn1mdW5jdGlvbiB0dCh0KXtyZXR1cm4gdD09QnQ/ImRvd24iOnQ9PUZ0PyJ1cCI6dD09SXQ/ImxlZnQiOnQ9PVJ0PyJyaWdodCI6IiJ9ZnVuY3Rpb24gZXQodCxlKXt2YXIgcj1lLm1hbmFnZXI7cmV0dXJuIHI/ci5nZXQodCk6dH1mdW5jdGlvbiBydCgpe0suYXBwbHkodGhpcyxhcmd1bWVudHMpfWZ1bmN0aW9uIG50KCl7cnQuYXBwbHkodGhpcyxhcmd1bWVudHMpLHRoaXMucFg9bnVsbCx0aGlzLnBZPW51bGx9ZnVuY3Rpb24gb3QoKXtydC5hcHBseSh0aGlzLGFyZ3VtZW50cyl9ZnVuY3Rpb24gaXQoKXtLLmFwcGx5KHRoaXMsYXJndW1lbnRzKSx0aGlzLl90aW1lcj1udWxsLHRoaXMuX2lucHV0PW51bGx9ZnVuY3Rpb24gc3QoKXtydC5hcHBseSh0aGlzLGFyZ3VtZW50cyl9ZnVuY3Rpb24gYXQoKXtydC5hcHBseSh0aGlzLGFyZ3VtZW50cyl9ZnVuY3Rpb24gbHQoKXtLLmFwcGx5KHRoaXMsYXJndW1lbnRzKSx0aGlzLnBUaW1lPSExLHRoaXMucENlbnRlcj0hMSx0aGlzLl90aW1lcj1udWxsLHRoaXMuX2lucHV0PW51bGwsdGhpcy5jb3VudD0wfWZ1bmN0aW9uIHV0KHQsZSl7cmV0dXJuIGU9ZXx8e30sZS5yZWNvZ25pemVycz1fKGUucmVjb2duaXplcnMsdXQuZGVmYXVsdHMucHJlc2V0KSxuZXcgaHQodCxlKX1mdW5jdGlvbiBodCh0LGUpe3RoaXMub3B0aW9ucz1fdCh7fSx1dC5kZWZhdWx0cyxlfHx7fSksdGhpcy5vcHRpb25zLmlucHV0VGFyZ2V0PXRoaXMub3B0aW9ucy5pbnB1dFRhcmdldHx8dCx0aGlzLmhhbmRsZXJzPXt9LHRoaXMuc2Vzc2lvbj17fSx0aGlzLnJlY29nbml6ZXJzPVtdLHRoaXMub2xkQ3NzUHJvcHM9e30sdGhpcy5lbGVtZW50PXQsdGhpcy5pbnB1dD1UKHRoaXMpLHRoaXMudG91Y2hBY3Rpb249bmV3IFcodGhpcyx0aGlzLm9wdGlvbnMudG91Y2hBY3Rpb24pLGN0KHRoaXMsITApLGwodGhpcy5vcHRpb25zLnJlY29nbml6ZXJzLGZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuYWRkKG5ldyB0WzBdKHRbMV0pKTt0WzJdJiZlLnJlY29nbml6ZVdpdGgodFsyXSksdFszXSYmZS5yZXF1aXJlRmFpbHVyZSh0WzNdKX0sdGhpcyl9ZnVuY3Rpb24gY3QodCxlKXt2YXIgcj10LmVsZW1lbnQ7aWYoci5zdHlsZSl7dmFyIG47bCh0Lm9wdGlvbnMuY3NzUHJvcHMsZnVuY3Rpb24obyxpKXtuPXcoci5zdHlsZSxpKSxlPyh0Lm9sZENzc1Byb3BzW25dPXIuc3R5bGVbbl0sci5zdHlsZVtuXT1vKTpyLnN0eWxlW25dPXQub2xkQ3NzUHJvcHNbbl18fCIifSksZXx8KHQub2xkQ3NzUHJvcHM9e30pfX1mdW5jdGlvbiBwdCh0LGUpe3ZhciByPW4uY3JlYXRlRXZlbnQoIkV2ZW50Iik7ci5pbml0RXZlbnQodCwhMCwhMCksci5nZXN0dXJlPWUsZS50YXJnZXQuZGlzcGF0Y2hFdmVudChyKX12YXIgX3QsZHQ9WyIiLCJ3ZWJraXQiLCJNb3oiLCJNUyIsIm1zIiwibyJdLGZ0PW4uY3JlYXRlRWxlbWVudCgiZGl2IiksbXQ9ImZ1bmN0aW9uIixndD1NYXRoLnJvdW5kLHl0PU1hdGguYWJzLHZ0PURhdGUubm93O190PSJmdW5jdGlvbiIhPXR5cGVvZiBPYmplY3QuYXNzaWduP2Z1bmN0aW9uKHQpe2lmKHQ9PT1pfHxudWxsPT09dCl0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgY29udmVydCB1bmRlZmluZWQgb3IgbnVsbCB0byBvYmplY3QiKTtmb3IodmFyIGU9T2JqZWN0KHQpLHI9MTtyPGFyZ3VtZW50cy5sZW5ndGg7cisrKXt2YXIgbj1hcmd1bWVudHNbcl07aWYobiE9PWkmJm51bGwhPT1uKWZvcih2YXIgbyBpbiBuKW4uaGFzT3duUHJvcGVydHkobykmJihlW29dPW5bb10pfXJldHVybiBlfTpPYmplY3QuYXNzaWduO3ZhciBidD11KGZ1bmN0aW9uKHQsZSxyKXtmb3IodmFyIG49T2JqZWN0LmtleXMoZSksbz0wO288bi5sZW5ndGg7KSghcnx8ciYmdFtuW29dXT09PWkpJiYodFtuW29dXT1lW25bb11dKSxvKys7cmV0dXJuIHR9LCJleHRlbmQiLCJVc2UgYGFzc2lnbmAuIikseHQ9dShmdW5jdGlvbih0LGUpe3JldHVybiBidCh0LGUsITApfSwibWVyZ2UiLCJVc2UgYGFzc2lnbmAuIiksd3Q9MSxNdD0vbW9iaWxlfHRhYmxldHxpcChhZHxob25lfG9kKXxhbmRyb2lkL2ksa3Q9Im9udG91Y2hzdGFydCJpbiBlLGp0PXcoZSwiUG9pbnRlckV2ZW50IikhPT1pLFR0PWt0JiZNdC50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpLFN0PSJ0b3VjaCIsenQ9InBlbiIsUHQ9Im1vdXNlIixFdD0ia2luZWN0IixBdD0yNSxDdD0xLE50PTIsT3Q9NCxxdD04LER0PTEsSXQ9MixSdD00LEZ0PTgsQnQ9MTYsTHQ9SXR8UnQsR3Q9RnR8QnQsVnQ9THR8R3QsVXQ9WyJ4IiwieSJdLFl0PVsiY2xpZW50WCIsImNsaWVudFkiXTtqLnByb3RvdHlwZT17aGFuZGxlcjpmdW5jdGlvbigpe30saW5pdDpmdW5jdGlvbigpe3RoaXMuZXZFbCYmZCh0aGlzLmVsZW1lbnQsdGhpcy5ldkVsLHRoaXMuZG9tSGFuZGxlciksdGhpcy5ldlRhcmdldCYmZCh0aGlzLnRhcmdldCx0aGlzLmV2VGFyZ2V0LHRoaXMuZG9tSGFuZGxlciksdGhpcy5ldldpbiYmZChrKHRoaXMuZWxlbWVudCksdGhpcy5ldldpbix0aGlzLmRvbUhhbmRsZXIpfSxkZXN0cm95OmZ1bmN0aW9uKCl7dGhpcy5ldkVsJiZmKHRoaXMuZWxlbWVudCx0aGlzLmV2RWwsdGhpcy5kb21IYW5kbGVyKSx0aGlzLmV2VGFyZ2V0JiZmKHRoaXMudGFyZ2V0LHRoaXMuZXZUYXJnZXQsdGhpcy5kb21IYW5kbGVyKSx0aGlzLmV2V2luJiZmKGsodGhpcy5lbGVtZW50KSx0aGlzLmV2V2luLHRoaXMuZG9tSGFuZGxlcil9fTt2YXIgSHQ9e21vdXNlZG93bjpDdCxtb3VzZW1vdmU6TnQsbW91c2V1cDpPdH0sWHQ9Im1vdXNlZG93biIsJHQ9Im1vdXNlbW92ZSBtb3VzZXVwIjtoKEYsaix7aGFuZGxlcjpmdW5jdGlvbih0KXt2YXIgZT1IdFt0LnR5cGVdO2UmQ3QmJjA9PT10LmJ1dHRvbiYmKHRoaXMucHJlc3NlZD0hMCksZSZOdCYmMSE9PXQud2hpY2gmJihlPU90KSx0aGlzLnByZXNzZWQmJihlJk90JiYodGhpcy5wcmVzc2VkPSExKSx0aGlzLmNhbGxiYWNrKHRoaXMubWFuYWdlcixlLHtwb2ludGVyczpbdF0sY2hhbmdlZFBvaW50ZXJzOlt0XSxwb2ludGVyVHlwZTpQdCxzcmNFdmVudDp0fSkpfX0pO3ZhciBXdD17cG9pbnRlcmRvd246Q3QscG9pbnRlcm1vdmU6TnQscG9pbnRlcnVwOk90LHBvaW50ZXJjYW5jZWw6cXQscG9pbnRlcm91dDpxdH0sSnQ9ezI6U3QsMzp6dCw0OlB0LDU6RXR9LFF0PSJwb2ludGVyZG93biIsS3Q9InBvaW50ZXJtb3ZlIHBvaW50ZXJ1cCBwb2ludGVyY2FuY2VsIjtlLk1TUG9pbnRlckV2ZW50JiYhZS5Qb2ludGVyRXZlbnQmJihRdD0iTVNQb2ludGVyRG93biIsS3Q9Ik1TUG9pbnRlck1vdmUgTVNQb2ludGVyVXAgTVNQb2ludGVyQ2FuY2VsIiksaChCLGose2hhbmRsZXI6ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5zdG9yZSxyPSExLG49dC50eXBlLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgibXMiLCIiKSxvPVd0W25dLGk9SnRbdC5wb2ludGVyVHlwZV18fHQucG9pbnRlclR5cGUscz1pPT1TdCxhPXYoZSx0LnBvaW50ZXJJZCwicG9pbnRlcklkIik7byZDdCYmKDA9PT10LmJ1dHRvbnx8cyk/YTwwJiYoZS5wdXNoKHQpLGE9ZS5sZW5ndGgtMSk6byYoT3R8cXQpJiYocj0hMCksYTwwfHwoZVthXT10LHRoaXMuY2FsbGJhY2sodGhpcy5tYW5hZ2VyLG8se3BvaW50ZXJzOmUsY2hhbmdlZFBvaW50ZXJzOlt0XSxwb2ludGVyVHlwZTppLHNyY0V2ZW50OnR9KSxyJiZlLnNwbGljZShhLDEpKX19KTt2YXIgWnQ9e3RvdWNoc3RhcnQ6Q3QsdG91Y2htb3ZlOk50LHRvdWNoZW5kOk90LHRvdWNoY2FuY2VsOnF0fSx0ZT0idG91Y2hzdGFydCIsZWU9InRvdWNoc3RhcnQgdG91Y2htb3ZlIHRvdWNoZW5kIHRvdWNoY2FuY2VsIjtoKEwsaix7aGFuZGxlcjpmdW5jdGlvbih0KXt2YXIgZT1adFt0LnR5cGVdO2lmKGU9PT1DdCYmKHRoaXMuc3RhcnRlZD0hMCksdGhpcy5zdGFydGVkKXt2YXIgcj1HLmNhbGwodGhpcyx0LGUpO2UmKE90fHF0KSYmclswXS5sZW5ndGgtclsxXS5sZW5ndGg9PT0wJiYodGhpcy5zdGFydGVkPSExKSx0aGlzLmNhbGxiYWNrKHRoaXMubWFuYWdlcixlLHtwb2ludGVyczpyWzBdLGNoYW5nZWRQb2ludGVyczpyWzFdLHBvaW50ZXJUeXBlOlN0LHNyY0V2ZW50OnR9KX19fSk7dmFyIHJlPXt0b3VjaHN0YXJ0OkN0LHRvdWNobW92ZTpOdCx0b3VjaGVuZDpPdCx0b3VjaGNhbmNlbDpxdH0sbmU9InRvdWNoc3RhcnQgdG91Y2htb3ZlIHRvdWNoZW5kIHRvdWNoY2FuY2VsIjtoKFYsaix7aGFuZGxlcjpmdW5jdGlvbih0KXt2YXIgZT1yZVt0LnR5cGVdLHI9VS5jYWxsKHRoaXMsdCxlKTtyJiZ0aGlzLmNhbGxiYWNrKHRoaXMubWFuYWdlcixlLHtwb2ludGVyczpyWzBdLGNoYW5nZWRQb2ludGVyczpyWzFdLHBvaW50ZXJUeXBlOlN0LHNyY0V2ZW50OnR9KX19KTt2YXIgb2U9MjUwMCxpZT0yNTtoKFksaix7aGFuZGxlcjpmdW5jdGlvbih0LGUscil7dmFyIG49ci5wb2ludGVyVHlwZT09U3Qsbz1yLnBvaW50ZXJUeXBlPT1QdDtpZighKG8mJnIuc291cmNlQ2FwYWJpbGl0aWVzJiZyLnNvdXJjZUNhcGFiaWxpdGllcy5maXJlc1RvdWNoRXZlbnRzKSl7aWYobilILmNhbGwodGhpcyxlLHIpO2Vsc2UgaWYobyYmJC5jYWxsKHRoaXMscikpcmV0dXJuO3RoaXMuY2FsbGJhY2sodCxlLHIpfX0sZGVzdHJveTpmdW5jdGlvbigpe3RoaXMudG91Y2guZGVzdHJveSgpLHRoaXMubW91c2UuZGVzdHJveSgpfX0pO3ZhciBzZT13KGZ0LnN0eWxlLCJ0b3VjaEFjdGlvbiIpLGFlPXNlIT09aSxsZT0iY29tcHV0ZSIsdWU9ImF1dG8iLGhlPSJtYW5pcHVsYXRpb24iLGNlPSJub25lIixwZT0icGFuLXgiLF9lPSJwYW4teSIsZGU9USgpO1cucHJvdG90eXBlPXtzZXQ6ZnVuY3Rpb24odCl7dD09bGUmJih0PXRoaXMuY29tcHV0ZSgpKSxhZSYmdGhpcy5tYW5hZ2VyLmVsZW1lbnQuc3R5bGUmJmRlW3RdJiYodGhpcy5tYW5hZ2VyLmVsZW1lbnQuc3R5bGVbc2VdPXQpLHRoaXMuYWN0aW9ucz10LnRvTG93ZXJDYXNlKCkudHJpbSgpfSx1cGRhdGU6ZnVuY3Rpb24oKXt0aGlzLnNldCh0aGlzLm1hbmFnZXIub3B0aW9ucy50b3VjaEFjdGlvbil9LGNvbXB1dGU6ZnVuY3Rpb24oKXt2YXIgdD1bXTtyZXR1cm4gbCh0aGlzLm1hbmFnZXIucmVjb2duaXplcnMsZnVuY3Rpb24oZSl7cChlLm9wdGlvbnMuZW5hYmxlLFtlXSkmJih0PXQuY29uY2F0KGUuZ2V0VG91Y2hBY3Rpb24oKSkpfSksSih0LmpvaW4oIiAiKSl9LHByZXZlbnREZWZhdWx0czpmdW5jdGlvbih0KXt2YXIgZT10LnNyY0V2ZW50LHI9dC5vZmZzZXREaXJlY3Rpb247aWYodGhpcy5tYW5hZ2VyLnNlc3Npb24ucHJldmVudGVkKXJldHVybiB2b2lkIGUucHJldmVudERlZmF1bHQoKTt2YXIgbj10aGlzLmFjdGlvbnMsbz1nKG4sY2UpJiYhZGVbY2VdLGk9ZyhuLF9lKSYmIWRlW19lXSxzPWcobixwZSkmJiFkZVtwZV07aWYobyl7dmFyIGE9MT09PXQucG9pbnRlcnMubGVuZ3RoLGw9dC5kaXN0YW5jZTwyLHU9dC5kZWx0YVRpbWU8MjUwO2lmKGEmJmwmJnUpcmV0dXJufXJldHVybiBzJiZpP3ZvaWQgMDpvfHxpJiZyJkx0fHxzJiZyJkd0P3RoaXMucHJldmVudFNyYyhlKTp2b2lkIDB9LHByZXZlbnRTcmM6ZnVuY3Rpb24odCl7dGhpcy5tYW5hZ2VyLnNlc3Npb24ucHJldmVudGVkPSEwLHQucHJldmVudERlZmF1bHQoKX19O3ZhciBmZT0xLG1lPTIsZ2U9NCx5ZT04LHZlPXllLGJlPTE2LHhlPTMyO0sucHJvdG90eXBlPXtkZWZhdWx0czp7fSxzZXQ6ZnVuY3Rpb24odCl7cmV0dXJuIF90KHRoaXMub3B0aW9ucyx0KSx0aGlzLm1hbmFnZXImJnRoaXMubWFuYWdlci50b3VjaEFjdGlvbi51cGRhdGUoKSx0aGlzfSxyZWNvZ25pemVXaXRoOmZ1bmN0aW9uKHQpe2lmKGEodCwicmVjb2duaXplV2l0aCIsdGhpcykpcmV0dXJuIHRoaXM7dmFyIGU9dGhpcy5zaW11bHRhbmVvdXM7cmV0dXJuIHQ9ZXQodCx0aGlzKSxlW3QuaWRdfHwoZVt0LmlkXT10LHQucmVjb2duaXplV2l0aCh0aGlzKSksdGhpc30sZHJvcFJlY29nbml6ZVdpdGg6ZnVuY3Rpb24odCl7cmV0dXJuIGEodCwiZHJvcFJlY29nbml6ZVdpdGgiLHRoaXMpP3RoaXM6KHQ9ZXQodCx0aGlzKSxkZWxldGUgdGhpcy5zaW11bHRhbmVvdXNbdC5pZF0sdGhpcyl9LHJlcXVpcmVGYWlsdXJlOmZ1bmN0aW9uKHQpe2lmKGEodCwicmVxdWlyZUZhaWx1cmUiLHRoaXMpKXJldHVybiB0aGlzO3ZhciBlPXRoaXMucmVxdWlyZUZhaWw7cmV0dXJuIHQ9ZXQodCx0aGlzKSx2KGUsdCk9PT0tMSYmKGUucHVzaCh0KSx0LnJlcXVpcmVGYWlsdXJlKHRoaXMpKSx0aGlzfSxkcm9wUmVxdWlyZUZhaWx1cmU6ZnVuY3Rpb24odCl7aWYoYSh0LCJkcm9wUmVxdWlyZUZhaWx1cmUiLHRoaXMpKXJldHVybiB0aGlzO3Q9ZXQodCx0aGlzKTt2YXIgZT12KHRoaXMucmVxdWlyZUZhaWwsdCk7cmV0dXJuIGU+LTEmJnRoaXMucmVxdWlyZUZhaWwuc3BsaWNlKGUsMSksdGhpc30saGFzUmVxdWlyZUZhaWx1cmVzOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucmVxdWlyZUZhaWwubGVuZ3RoPjB9LGNhblJlY29nbml6ZVdpdGg6ZnVuY3Rpb24odCl7cmV0dXJuISF0aGlzLnNpbXVsdGFuZW91c1t0LmlkXX0sZW1pdDpmdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUpe3IubWFuYWdlci5lbWl0KGUsdCl9dmFyIHI9dGhpcyxuPXRoaXMuc3RhdGU7bjx5ZSYmZShyLm9wdGlvbnMuZXZlbnQrWihuKSksZShyLm9wdGlvbnMuZXZlbnQpLHQuYWRkaXRpb25hbEV2ZW50JiZlKHQuYWRkaXRpb25hbEV2ZW50KSxuPj15ZSYmZShyLm9wdGlvbnMuZXZlbnQrWihuKSl9LHRyeUVtaXQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuY2FuRW1pdCgpP3RoaXMuZW1pdCh0KTp2b2lkKHRoaXMuc3RhdGU9eGUpfSxjYW5FbWl0OmZ1bmN0aW9uKCl7Zm9yKHZhciB0PTA7dDx0aGlzLnJlcXVpcmVGYWlsLmxlbmd0aDspe2lmKCEodGhpcy5yZXF1aXJlRmFpbFt0XS5zdGF0ZSYoeGV8ZmUpKSlyZXR1cm4hMTt0Kyt9cmV0dXJuITB9LHJlY29nbml6ZTpmdW5jdGlvbih0KXt2YXIgZT1fdCh7fSx0KTtyZXR1cm4gcCh0aGlzLm9wdGlvbnMuZW5hYmxlLFt0aGlzLGVdKT8odGhpcy5zdGF0ZSYodmV8YmV8eGUpJiYodGhpcy5zdGF0ZT1mZSksdGhpcy5zdGF0ZT10aGlzLnByb2Nlc3MoZSksdm9pZCh0aGlzLnN0YXRlJihtZXxnZXx5ZXxiZSkmJnRoaXMudHJ5RW1pdChlKSkpOih0aGlzLnJlc2V0KCksdm9pZCh0aGlzLnN0YXRlPXhlKSl9LHByb2Nlc3M6ZnVuY3Rpb24odCl7fSxnZXRUb3VjaEFjdGlvbjpmdW5jdGlvbigpe30scmVzZXQ6ZnVuY3Rpb24oKXt9fSxoKHJ0LEsse2RlZmF1bHRzOntwb2ludGVyczoxfSxhdHRyVGVzdDpmdW5jdGlvbih0KXt2YXIgZT10aGlzLm9wdGlvbnMucG9pbnRlcnM7cmV0dXJuIDA9PT1lfHx0LnBvaW50ZXJzLmxlbmd0aD09PWV9LHByb2Nlc3M6ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5zdGF0ZSxyPXQuZXZlbnRUeXBlLG49ZSYobWV8Z2UpLG89dGhpcy5hdHRyVGVzdCh0KTtyZXR1cm4gbiYmKHImcXR8fCFvKT9lfGJlOm58fG8/ciZPdD9lfHllOmUmbWU/ZXxnZTptZTp4ZX19KSxoKG50LHJ0LHtkZWZhdWx0czp7ZXZlbnQ6InBhbiIsdGhyZXNob2xkOjEwLHBvaW50ZXJzOjEsZGlyZWN0aW9uOlZ0fSxnZXRUb3VjaEFjdGlvbjpmdW5jdGlvbigpe3ZhciB0PXRoaXMub3B0aW9ucy5kaXJlY3Rpb24sZT1bXTtyZXR1cm4gdCZMdCYmZS5wdXNoKF9lKSx0Jkd0JiZlLnB1c2gocGUpLGV9LGRpcmVjdGlvblRlc3Q6ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5vcHRpb25zLHI9ITAsbj10LmRpc3RhbmNlLG89dC5kaXJlY3Rpb24saT10LmRlbHRhWCxzPXQuZGVsdGFZO3JldHVybiBvJmUuZGlyZWN0aW9ufHwoZS5kaXJlY3Rpb24mTHQ/KG89MD09PWk/RHQ6aTwwP0l0OlJ0LHI9aSE9dGhpcy5wWCxuPU1hdGguYWJzKHQuZGVsdGFYKSk6KG89MD09PXM/RHQ6czwwP0Z0OkJ0LHI9cyE9dGhpcy5wWSxuPU1hdGguYWJzKHQuZGVsdGFZKSkpLHQuZGlyZWN0aW9uPW8sciYmbj5lLnRocmVzaG9sZCYmbyZlLmRpcmVjdGlvbn0sYXR0clRlc3Q6ZnVuY3Rpb24odCl7cmV0dXJuIHJ0LnByb3RvdHlwZS5hdHRyVGVzdC5jYWxsKHRoaXMsdCkmJih0aGlzLnN0YXRlJm1lfHwhKHRoaXMuc3RhdGUmbWUpJiZ0aGlzLmRpcmVjdGlvblRlc3QodCkpfSxlbWl0OmZ1bmN0aW9uKHQpe3RoaXMucFg9dC5kZWx0YVgsdGhpcy5wWT10LmRlbHRhWTt2YXIgZT10dCh0LmRpcmVjdGlvbik7ZSYmKHQuYWRkaXRpb25hbEV2ZW50PXRoaXMub3B0aW9ucy5ldmVudCtlKSx0aGlzLl9zdXBlci5lbWl0LmNhbGwodGhpcyx0KX19KSxoKG90LHJ0LHtkZWZhdWx0czp7ZXZlbnQ6InBpbmNoIix0aHJlc2hvbGQ6MCxwb2ludGVyczoyfSxnZXRUb3VjaEFjdGlvbjpmdW5jdGlvbigpe3JldHVybltjZV19LGF0dHJUZXN0OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9zdXBlci5hdHRyVGVzdC5jYWxsKHRoaXMsdCkmJihNYXRoLmFicyh0LnNjYWxlLTEpPnRoaXMub3B0aW9ucy50aHJlc2hvbGR8fHRoaXMuc3RhdGUmbWUpfSxlbWl0OmZ1bmN0aW9uKHQpe2lmKDEhPT10LnNjYWxlKXt2YXIgZT10LnNjYWxlPDE/ImluIjoib3V0Ijt0LmFkZGl0aW9uYWxFdmVudD10aGlzLm9wdGlvbnMuZXZlbnQrZX10aGlzLl9zdXBlci5lbWl0LmNhbGwodGhpcyx0KX19KSxoKGl0LEsse2RlZmF1bHRzOntldmVudDoicHJlc3MiLHBvaW50ZXJzOjEsdGltZToyNTEsdGhyZXNob2xkOjl9LGdldFRvdWNoQWN0aW9uOmZ1bmN0aW9uKCl7cmV0dXJuW3VlXX0scHJvY2VzczpmdW5jdGlvbih0KXt2YXIgZT10aGlzLm9wdGlvbnMscj10LnBvaW50ZXJzLmxlbmd0aD09PWUucG9pbnRlcnMsbj10LmRpc3RhbmNlPGUudGhyZXNob2xkLG89dC5kZWx0YVRpbWU+ZS50aW1lO2lmKHRoaXMuX2lucHV0PXQsIW58fCFyfHx0LmV2ZW50VHlwZSYoT3R8cXQpJiYhbyl0aGlzLnJlc2V0KCk7ZWxzZSBpZih0LmV2ZW50VHlwZSZDdCl0aGlzLnJlc2V0KCksdGhpcy5fdGltZXI9cyhmdW5jdGlvbigpe3RoaXMuc3RhdGU9dmUsdGhpcy50cnlFbWl0KCl9LGUudGltZSx0aGlzKTtlbHNlIGlmKHQuZXZlbnRUeXBlJk90KXJldHVybiB2ZTtyZXR1cm4geGV9LHJlc2V0OmZ1bmN0aW9uKCl7Y2xlYXJUaW1lb3V0KHRoaXMuX3RpbWVyKX0sZW1pdDpmdW5jdGlvbih0KXt0aGlzLnN0YXRlPT09dmUmJih0JiZ0LmV2ZW50VHlwZSZPdD90aGlzLm1hbmFnZXIuZW1pdCh0aGlzLm9wdGlvbnMuZXZlbnQrInVwIix0KToodGhpcy5faW5wdXQudGltZVN0YW1wPXZ0KCksdGhpcy5tYW5hZ2VyLmVtaXQodGhpcy5vcHRpb25zLmV2ZW50LHRoaXMuX2lucHV0KSkpfX0pLGgoc3QscnQse2RlZmF1bHRzOntldmVudDoicm90YXRlIix0aHJlc2hvbGQ6MCxwb2ludGVyczoyfSxnZXRUb3VjaEFjdGlvbjpmdW5jdGlvbigpe3JldHVybltjZV19LGF0dHJUZXN0OmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLl9zdXBlci5hdHRyVGVzdC5jYWxsKHRoaXMsdCkmJihNYXRoLmFicyh0LnJvdGF0aW9uKT50aGlzLm9wdGlvbnMudGhyZXNob2xkfHx0aGlzLnN0YXRlJm1lKX19KSxoKGF0LHJ0LHtkZWZhdWx0czp7ZXZlbnQ6InN3aXBlIix0aHJlc2hvbGQ6MTAsdmVsb2NpdHk6LjMsZGlyZWN0aW9uOkx0fEd0LHBvaW50ZXJzOjF9LGdldFRvdWNoQWN0aW9uOmZ1bmN0aW9uKCl7cmV0dXJuIG50LnByb3RvdHlwZS5nZXRUb3VjaEFjdGlvbi5jYWxsKHRoaXMpfSxhdHRyVGVzdDpmdW5jdGlvbih0KXt2YXIgZSxyPXRoaXMub3B0aW9ucy5kaXJlY3Rpb247cmV0dXJuIHImKEx0fEd0KT9lPXQub3ZlcmFsbFZlbG9jaXR5OnImTHQ/ZT10Lm92ZXJhbGxWZWxvY2l0eVg6ciZHdCYmKGU9dC5vdmVyYWxsVmVsb2NpdHlZKSx0aGlzLl9zdXBlci5hdHRyVGVzdC5jYWxsKHRoaXMsdCkmJnImdC5vZmZzZXREaXJlY3Rpb24mJnQuZGlzdGFuY2U+dGhpcy5vcHRpb25zLnRocmVzaG9sZCYmdC5tYXhQb2ludGVycz09dGhpcy5vcHRpb25zLnBvaW50ZXJzJiZ5dChlKT50aGlzLm9wdGlvbnMudmVsb2NpdHkmJnQuZXZlbnRUeXBlJk90fSxlbWl0OmZ1bmN0aW9uKHQpe3ZhciBlPXR0KHQub2Zmc2V0RGlyZWN0aW9uKTtlJiZ0aGlzLm1hbmFnZXIuZW1pdCh0aGlzLm9wdGlvbnMuZXZlbnQrZSx0KSx0aGlzLm1hbmFnZXIuZW1pdCh0aGlzLm9wdGlvbnMuZXZlbnQsdCl9fSksaChsdCxLLHtkZWZhdWx0czp7ZXZlbnQ6InRhcCIscG9pbnRlcnM6MSx0YXBzOjEsaW50ZXJ2YWw6MzAwLHRpbWU6MjUwLHRocmVzaG9sZDo5LHBvc1RocmVzaG9sZDoxMH0sZ2V0VG91Y2hBY3Rpb246ZnVuY3Rpb24oKXtyZXR1cm5baGVdfSxwcm9jZXNzOmZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMub3B0aW9ucyxyPXQucG9pbnRlcnMubGVuZ3RoPT09ZS5wb2ludGVycyxuPXQuZGlzdGFuY2U8ZS50aHJlc2hvbGQsbz10LmRlbHRhVGltZTxlLnRpbWU7aWYodGhpcy5yZXNldCgpLHQuZXZlbnRUeXBlJkN0JiYwPT09dGhpcy5jb3VudClyZXR1cm4gdGhpcy5mYWlsVGltZW91dCgpO2lmKG4mJm8mJnIpe2lmKHQuZXZlbnRUeXBlIT1PdClyZXR1cm4gdGhpcy5mYWlsVGltZW91dCgpO3ZhciBpPSF0aGlzLnBUaW1lfHx0LnRpbWVTdGFtcC10aGlzLnBUaW1lPGUuaW50ZXJ2YWwsYT0hdGhpcy5wQ2VudGVyfHxxKHRoaXMucENlbnRlcix0LmNlbnRlcik8ZS5wb3NUaHJlc2hvbGQ7dGhpcy5wVGltZT10LnRpbWVTdGFtcCx0aGlzLnBDZW50ZXI9dC5jZW50ZXIsYSYmaT90aGlzLmNvdW50Kz0xOnRoaXMuY291bnQ9MSx0aGlzLl9pbnB1dD10O3ZhciBsPXRoaXMuY291bnQlZS50YXBzO2lmKDA9PT1sKXJldHVybiB0aGlzLmhhc1JlcXVpcmVGYWlsdXJlcygpPyh0aGlzLl90aW1lcj1zKGZ1bmN0aW9uKCl7dGhpcy5zdGF0ZT12ZSx0aGlzLnRyeUVtaXQoKX0sZS5pbnRlcnZhbCx0aGlzKSxtZSk6dmV9cmV0dXJuIHhlfSxmYWlsVGltZW91dDpmdW5jdGlvbigpe3JldHVybiB0aGlzLl90aW1lcj1zKGZ1bmN0aW9uKCl7dGhpcy5zdGF0ZT14ZX0sdGhpcy5vcHRpb25zLmludGVydmFsLHRoaXMpLHhlfSxyZXNldDpmdW5jdGlvbigpe2NsZWFyVGltZW91dCh0aGlzLl90aW1lcil9LGVtaXQ6ZnVuY3Rpb24oKXt0aGlzLnN0YXRlPT12ZSYmKHRoaXMuX2lucHV0LnRhcENvdW50PXRoaXMuY291bnQsdGhpcy5tYW5hZ2VyLmVtaXQodGhpcy5vcHRpb25zLmV2ZW50LHRoaXMuX2lucHV0KSl9fSksdXQuVkVSU0lPTj0iMi4wLjciLHV0LmRlZmF1bHRzPXtkb21FdmVudHM6ITEsdG91Y2hBY3Rpb246bGUsZW5hYmxlOiEwLGlucHV0VGFyZ2V0Om51bGwsaW5wdXRDbGFzczpudWxsLHByZXNldDpbW3N0LHtlbmFibGU6ITF9XSxbb3Qse2VuYWJsZTohMX0sWyJyb3RhdGUiXV0sW2F0LHtkaXJlY3Rpb246THR9XSxbbnQse2RpcmVjdGlvbjpMdH0sWyJzd2lwZSJdXSxbbHRdLFtsdCx7ZXZlbnQ6ImRvdWJsZXRhcCIsdGFwczoyfSxbInRhcCJdXSxbaXRdXSxjc3NQcm9wczp7dXNlclNlbGVjdDoibm9uZSIsdG91Y2hTZWxlY3Q6Im5vbmUiLHRvdWNoQ2FsbG91dDoibm9uZSIsY29udGVudFpvb21pbmc6Im5vbmUiLHVzZXJEcmFnOiJub25lIix0YXBIaWdobGlnaHRDb2xvcjoicmdiYSgwLDAsMCwwKSJ9fTt2YXIgd2U9MSxNZT0yO2h0LnByb3RvdHlwZT17c2V0OmZ1bmN0aW9uKHQpe3JldHVybiBfdCh0aGlzLm9wdGlvbnMsdCksdC50b3VjaEFjdGlvbiYmdGhpcy50b3VjaEFjdGlvbi51cGRhdGUoKSx0LmlucHV0VGFyZ2V0JiYodGhpcy5pbnB1dC5kZXN0cm95KCksdGhpcy5pbnB1dC50YXJnZXQ9dC5pbnB1dFRhcmdldCx0aGlzLmlucHV0LmluaXQoKSksdGhpc30sc3RvcDpmdW5jdGlvbih0KXt0aGlzLnNlc3Npb24uc3RvcHBlZD10P01lOndlfSxyZWNvZ25pemU6ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5zZXNzaW9uO2lmKCFlLnN0b3BwZWQpe3RoaXMudG91Y2hBY3Rpb24ucHJldmVudERlZmF1bHRzKHQpO3ZhciByLG49dGhpcy5yZWNvZ25pemVycyxvPWUuY3VyUmVjb2duaXplcjsoIW98fG8mJm8uc3RhdGUmdmUpJiYobz1lLmN1clJlY29nbml6ZXI9bnVsbCk7Zm9yKHZhciBpPTA7aTxuLmxlbmd0aDspcj1uW2ldLGUuc3RvcHBlZD09PU1lfHxvJiZyIT1vJiYhci5jYW5SZWNvZ25pemVXaXRoKG8pP3IucmVzZXQoKTpyLnJlY29nbml6ZSh0KSwhbyYmci5zdGF0ZSYobWV8Z2V8eWUpJiYobz1lLmN1clJlY29nbml6ZXI9ciksaSsrfX0sZ2V0OmZ1bmN0aW9uKHQpe2lmKHQgaW5zdGFuY2VvZiBLKXJldHVybiB0O2Zvcih2YXIgZT10aGlzLnJlY29nbml6ZXJzLHI9MDtyPGUubGVuZ3RoO3IrKylpZihlW3JdLm9wdGlvbnMuZXZlbnQ9PXQpcmV0dXJuIGVbcl07cmV0dXJuIG51bGx9LGFkZDpmdW5jdGlvbih0KXtpZihhKHQsImFkZCIsdGhpcykpcmV0dXJuIHRoaXM7dmFyIGU9dGhpcy5nZXQodC5vcHRpb25zLmV2ZW50KTtyZXR1cm4gZSYmdGhpcy5yZW1vdmUoZSksdGhpcy5yZWNvZ25pemVycy5wdXNoKHQpLHQubWFuYWdlcj10aGlzLHRoaXMudG91Y2hBY3Rpb24udXBkYXRlKCksdH0scmVtb3ZlOmZ1bmN0aW9uKHQpe2lmKGEodCwicmVtb3ZlIix0aGlzKSlyZXR1cm4gdGhpcztpZih0PXRoaXMuZ2V0KHQpKXt2YXIgZT10aGlzLnJlY29nbml6ZXJzLHI9dihlLHQpO3IhPT0tMSYmKGUuc3BsaWNlKHIsMSksdGhpcy50b3VjaEFjdGlvbi51cGRhdGUoKSl9cmV0dXJuIHRoaXN9LG9uOmZ1bmN0aW9uKHQsZSl7aWYodCE9PWkmJmUhPT1pKXt2YXIgcj10aGlzLmhhbmRsZXJzO3JldHVybiBsKHkodCksZnVuY3Rpb24odCl7clt0XT1yW3RdfHxbXSxyW3RdLnB1c2goZSl9KSx0aGlzfX0sb2ZmOmZ1bmN0aW9uKHQsZSl7aWYodCE9PWkpe3ZhciByPXRoaXMuaGFuZGxlcnM7cmV0dXJuIGwoeSh0KSxmdW5jdGlvbih0KXtlP3JbdF0mJnJbdF0uc3BsaWNlKHYoclt0XSxlKSwxKTpkZWxldGUgclt0XX0pLHRoaXN9fSxlbWl0OmZ1bmN0aW9uKHQsZSl7dGhpcy5vcHRpb25zLmRvbUV2ZW50cyYmcHQodCxlKTt2YXIgcj10aGlzLmhhbmRsZXJzW3RdJiZ0aGlzLmhhbmRsZXJzW3RdLnNsaWNlKCk7aWYociYmci5sZW5ndGgpe2UudHlwZT10LGUucHJldmVudERlZmF1bHQ9ZnVuY3Rpb24oKXtlLnNyY0V2ZW50LnByZXZlbnREZWZhdWx0KCl9O2Zvcih2YXIgbj0wO248ci5sZW5ndGg7KXJbbl0oZSksbisrfX0sZGVzdHJveTpmdW5jdGlvbigpe3RoaXMuZWxlbWVudCYmY3QodGhpcywhMSksdGhpcy5oYW5kbGVycz17fSx0aGlzLnNlc3Npb249e30sdGhpcy5pbnB1dC5kZXN0cm95KCksdGhpcy5lbGVtZW50PW51bGx9fSxfdCh1dCx7SU5QVVRfU1RBUlQ6Q3QsSU5QVVRfTU9WRTpOdCxJTlBVVF9FTkQ6T3QsSU5QVVRfQ0FOQ0VMOnF0LFNUQVRFX1BPU1NJQkxFOmZlLFNUQVRFX0JFR0FOOm1lLFNUQVRFX0NIQU5HRUQ6Z2UsU1RBVEVfRU5ERUQ6eWUsU1RBVEVfUkVDT0dOSVpFRDp2ZSxTVEFURV9DQU5DRUxMRUQ6YmUsU1RBVEVfRkFJTEVEOnhlLERJUkVDVElPTl9OT05FOkR0LERJUkVDVElPTl9MRUZUOkl0LERJUkVDVElPTl9SSUdIVDpSdCxESVJFQ1RJT05fVVA6RnQsRElSRUNUSU9OX0RPV046QnQsRElSRUNUSU9OX0hPUklaT05UQUw6THQsRElSRUNUSU9OX1ZFUlRJQ0FMOkd0LERJUkVDVElPTl9BTEw6VnQsTWFuYWdlcjpodCxJbnB1dDpqLFRvdWNoQWN0aW9uOlcsVG91Y2hJbnB1dDpWLE1vdXNlSW5wdXQ6RixQb2ludGVyRXZlbnRJbnB1dDpCLFRvdWNoTW91c2VJbnB1dDpZLFNpbmdsZVRvdWNoSW5wdXQ6TCxSZWNvZ25pemVyOkssQXR0clJlY29nbml6ZXI6cnQsVGFwOmx0LFBhbjpudCxTd2lwZTphdCxQaW5jaDpvdCxSb3RhdGU6c3QsUHJlc3M6aXQsb246ZCxvZmY6ZixlYWNoOmwsbWVyZ2U6eHQsZXh0ZW5kOmJ0LGFzc2lnbjpfdCxpbmhlcml0OmgsYmluZEZuOmMscHJlZml4ZWQ6d30pO3ZhciBrZT0idW5kZWZpbmVkIiE9dHlwZW9mIGU/ZToidW5kZWZpbmVkIiE9dHlwZW9mIHNlbGY/c2VsZjp7fTtrZS5IYW1tZXI9dXQsImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQuYW1kP3QoZnVuY3Rpb24oKXtyZXR1cm4gdXR9KToidW5kZWZpbmVkIiE9dHlwZW9mIHImJnIuZXhwb3J0cz9yLmV4cG9ydHM9dXQ6ZVtvXT11dH0od2luZG93LGRvY3VtZW50LCJIYW1tZXIiKX0se31dLCJqcXVlcnktbW91c2V3aGVlbCI6W2Z1bmN0aW9uKGUscixuKXsvKiEKICogalF1ZXJ5IE1vdXNld2hlZWwgMy4xLjEzCiAqCiAqIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzCiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZQogKiBodHRwOi8vanF1ZXJ5Lm9yZy9saWNlbnNlCiAqLwohZnVuY3Rpb24oZSl7ImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQuYW1kP3QoWyJqcXVlcnkiXSxlKToib2JqZWN0Ij09dHlwZW9mIG4/ci5leHBvcnRzPWU6ZShqUXVlcnkpfShmdW5jdGlvbih0KXtmdW5jdGlvbiBlKGUpe3ZhciBzPWV8fHdpbmRvdy5ldmVudCxhPWwuY2FsbChhcmd1bWVudHMsMSksdT0wLGM9MCxwPTAsXz0wLGQ9MCxmPTA7aWYoZT10LmV2ZW50LmZpeChzKSxlLnR5cGU9Im1vdXNld2hlZWwiLCJkZXRhaWwiaW4gcyYmKHA9cy5kZXRhaWwqLTEpLCJ3aGVlbERlbHRhImluIHMmJihwPXMud2hlZWxEZWx0YSksIndoZWVsRGVsdGFZImluIHMmJihwPXMud2hlZWxEZWx0YVkpLCJ3aGVlbERlbHRhWCJpbiBzJiYoYz1zLndoZWVsRGVsdGFYKi0xKSwiYXhpcyJpbiBzJiZzLmF4aXM9PT1zLkhPUklaT05UQUxfQVhJUyYmKGM9cCotMSxwPTApLHU9MD09PXA/YzpwLCJkZWx0YVkiaW4gcyYmKHA9cy5kZWx0YVkqLTEsdT1wKSwiZGVsdGFYImluIHMmJihjPXMuZGVsdGFYLDA9PT1wJiYodT1jKi0xKSksMCE9PXB8fDAhPT1jKXtpZigxPT09cy5kZWx0YU1vZGUpe3ZhciBtPXQuZGF0YSh0aGlzLCJtb3VzZXdoZWVsLWxpbmUtaGVpZ2h0Iik7dSo9bSxwKj1tLGMqPW19ZWxzZSBpZigyPT09cy5kZWx0YU1vZGUpe3ZhciBnPXQuZGF0YSh0aGlzLCJtb3VzZXdoZWVsLXBhZ2UtaGVpZ2h0Iik7dSo9ZyxwKj1nLGMqPWd9aWYoXz1NYXRoLm1heChNYXRoLmFicyhwKSxNYXRoLmFicyhjKSksKCFpfHxfPGkpJiYoaT1fLG4ocyxfKSYmKGkvPTQwKSksbihzLF8pJiYodS89NDAsYy89NDAscC89NDApLHU9TWF0aFt1Pj0xPyJmbG9vciI6ImNlaWwiXSh1L2kpLGM9TWF0aFtjPj0xPyJmbG9vciI6ImNlaWwiXShjL2kpLHA9TWF0aFtwPj0xPyJmbG9vciI6ImNlaWwiXShwL2kpLGguc2V0dGluZ3Mubm9ybWFsaXplT2Zmc2V0JiZ0aGlzLmdldEJvdW5kaW5nQ2xpZW50UmVjdCl7dmFyIHk9dGhpcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtkPWUuY2xpZW50WC15LmxlZnQsZj1lLmNsaWVudFkteS50b3B9cmV0dXJuIGUuZGVsdGFYPWMsZS5kZWx0YVk9cCxlLmRlbHRhRmFjdG9yPWksZS5vZmZzZXRYPWQsZS5vZmZzZXRZPWYsZS5kZWx0YU1vZGU9MCxhLnVuc2hpZnQoZSx1LGMscCksbyYmY2xlYXJUaW1lb3V0KG8pLG89c2V0VGltZW91dChyLDIwMCksKHQuZXZlbnQuZGlzcGF0Y2h8fHQuZXZlbnQuaGFuZGxlKS5hcHBseSh0aGlzLGEpfX1mdW5jdGlvbiByKCl7aT1udWxsfWZ1bmN0aW9uIG4odCxlKXtyZXR1cm4gaC5zZXR0aW5ncy5hZGp1c3RPbGREZWx0YXMmJiJtb3VzZXdoZWVsIj09PXQudHlwZSYmZSUxMjA9PT0wfXZhciBvLGkscz1bIndoZWVsIiwibW91c2V3aGVlbCIsIkRPTU1vdXNlU2Nyb2xsIiwiTW96TW91c2VQaXhlbFNjcm9sbCJdLGE9Im9ud2hlZWwiaW4gZG9jdW1lbnR8fGRvY3VtZW50LmRvY3VtZW50TW9kZT49OT9bIndoZWVsIl06WyJtb3VzZXdoZWVsIiwiRG9tTW91c2VTY3JvbGwiLCJNb3pNb3VzZVBpeGVsU2Nyb2xsIl0sbD1BcnJheS5wcm90b3R5cGUuc2xpY2U7aWYodC5ldmVudC5maXhIb29rcylmb3IodmFyIHU9cy5sZW5ndGg7dTspdC5ldmVudC5maXhIb29rc1tzWy0tdV1dPXQuZXZlbnQubW91c2VIb29rczt2YXIgaD10LmV2ZW50LnNwZWNpYWwubW91c2V3aGVlbD17dmVyc2lvbjoiMy4xLjEyIixzZXR1cDpmdW5jdGlvbigpe2lmKHRoaXMuYWRkRXZlbnRMaXN0ZW5lcilmb3IodmFyIHI9YS5sZW5ndGg7cjspdGhpcy5hZGRFdmVudExpc3RlbmVyKGFbLS1yXSxlLCExKTtlbHNlIHRoaXMub25tb3VzZXdoZWVsPWU7dC5kYXRhKHRoaXMsIm1vdXNld2hlZWwtbGluZS1oZWlnaHQiLGguZ2V0TGluZUhlaWdodCh0aGlzKSksdC5kYXRhKHRoaXMsIm1vdXNld2hlZWwtcGFnZS1oZWlnaHQiLGguZ2V0UGFnZUhlaWdodCh0aGlzKSl9LHRlYXJkb3duOmZ1bmN0aW9uKCl7aWYodGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKWZvcih2YXIgcj1hLmxlbmd0aDtyOyl0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoYVstLXJdLGUsITEpO2Vsc2UgdGhpcy5vbm1vdXNld2hlZWw9bnVsbDt0LnJlbW92ZURhdGEodGhpcywibW91c2V3aGVlbC1saW5lLWhlaWdodCIpLHQucmVtb3ZlRGF0YSh0aGlzLCJtb3VzZXdoZWVsLXBhZ2UtaGVpZ2h0Iil9LGdldExpbmVIZWlnaHQ6ZnVuY3Rpb24oZSl7dmFyIHI9dChlKSxuPXJbIm9mZnNldFBhcmVudCJpbiB0LmZuPyJvZmZzZXRQYXJlbnQiOiJwYXJlbnQiXSgpO3JldHVybiBuLmxlbmd0aHx8KG49dCgiYm9keSIpKSxwYXJzZUludChuLmNzcygiZm9udFNpemUiKSwxMCl8fHBhcnNlSW50KHIuY3NzKCJmb250U2l6ZSIpLDEwKXx8MTZ9LGdldFBhZ2VIZWlnaHQ6ZnVuY3Rpb24oZSl7cmV0dXJuIHQoZSkuaGVpZ2h0KCl9LHNldHRpbmdzOnthZGp1c3RPbGREZWx0YXM6ITAsbm9ybWFsaXplT2Zmc2V0OiEwfX07dC5mbi5leHRlbmQoe21vdXNld2hlZWw6ZnVuY3Rpb24odCl7cmV0dXJuIHQ/dGhpcy5iaW5kKCJtb3VzZXdoZWVsIix0KTp0aGlzLnRyaWdnZXIoIm1vdXNld2hlZWwiKX0sdW5tb3VzZXdoZWVsOmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnVuYmluZCgibW91c2V3aGVlbCIsdCl9fSl9KX0se31dLGpxdWVyeTpbZnVuY3Rpb24oZSxyLG4pey8qIQogKiBqUXVlcnkgSmF2YVNjcmlwdCBMaWJyYXJ5IHYyLjIuNAogKiBodHRwOi8vanF1ZXJ5LmNvbS8KICoKICogSW5jbHVkZXMgU2l6emxlLmpzCiAqIGh0dHA6Ly9zaXp6bGVqcy5jb20vCiAqCiAqIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzCiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZQogKiBodHRwOi8vanF1ZXJ5Lm9yZy9saWNlbnNlCiAqCiAqIERhdGU6IDIwMTYtMDUtMjBUMTc6MjNaCiAqLwohZnVuY3Rpb24odCxlKXsib2JqZWN0Ij09dHlwZW9mIHImJiJvYmplY3QiPT10eXBlb2Ygci5leHBvcnRzP3IuZXhwb3J0cz10LmRvY3VtZW50P2UodCwhMCk6ZnVuY3Rpb24odCl7aWYoIXQuZG9jdW1lbnQpdGhyb3cgbmV3IEVycm9yKCJqUXVlcnkgcmVxdWlyZXMgYSB3aW5kb3cgd2l0aCBhIGRvY3VtZW50Iik7cmV0dXJuIGUodCl9OmUodCl9KCJ1bmRlZmluZWQiIT10eXBlb2Ygd2luZG93P3dpbmRvdzp0aGlzLGZ1bmN0aW9uKGUscil7ZnVuY3Rpb24gbih0KXt2YXIgZT0hIXQmJiJsZW5ndGgiaW4gdCYmdC5sZW5ndGgscj1zdC50eXBlKHQpO3JldHVybiJmdW5jdGlvbiIhPT1yJiYhc3QuaXNXaW5kb3codCkmJigiYXJyYXkiPT09cnx8MD09PWV8fCJudW1iZXIiPT10eXBlb2YgZSYmZT4wJiZlLTEgaW4gdCl9ZnVuY3Rpb24gbyh0LGUscil7aWYoc3QuaXNGdW5jdGlvbihlKSlyZXR1cm4gc3QuZ3JlcCh0LGZ1bmN0aW9uKHQsbil7cmV0dXJuISFlLmNhbGwodCxuLHQpIT09cn0pO2lmKGUubm9kZVR5cGUpcmV0dXJuIHN0LmdyZXAodCxmdW5jdGlvbih0KXtyZXR1cm4gdD09PWUhPT1yfSk7aWYoInN0cmluZyI9PXR5cGVvZiBlKXtpZihtdC50ZXN0KGUpKXJldHVybiBzdC5maWx0ZXIoZSx0LHIpO2U9c3QuZmlsdGVyKGUsdCl9cmV0dXJuIHN0LmdyZXAodCxmdW5jdGlvbih0KXtyZXR1cm4gdHQuY2FsbChlLHQpPi0xIT09cn0pfWZ1bmN0aW9uIGkodCxlKXtmb3IoOyh0PXRbZV0pJiYxIT09dC5ub2RlVHlwZTspO3JldHVybiB0fWZ1bmN0aW9uIHModCl7dmFyIGU9e307cmV0dXJuIHN0LmVhY2godC5tYXRjaCh3dCl8fFtdLGZ1bmN0aW9uKHQscil7ZVtyXT0hMH0pLGV9ZnVuY3Rpb24gYSgpe0oucmVtb3ZlRXZlbnRMaXN0ZW5lcigiRE9NQ29udGVudExvYWRlZCIsYSksZS5yZW1vdmVFdmVudExpc3RlbmVyKCJsb2FkIixhKSxzdC5yZWFkeSgpfWZ1bmN0aW9uIGwoKXt0aGlzLmV4cGFuZG89c3QuZXhwYW5kbytsLnVpZCsrfWZ1bmN0aW9uIHUodCxlLHIpe3ZhciBuO2lmKHZvaWQgMD09PXImJjE9PT10Lm5vZGVUeXBlKWlmKG49ImRhdGEtIitlLnJlcGxhY2UoUHQsIi0kJiIpLnRvTG93ZXJDYXNlKCkscj10LmdldEF0dHJpYnV0ZShuKSwic3RyaW5nIj09dHlwZW9mIHIpe3RyeXtyPSJ0cnVlIj09PXJ8fCJmYWxzZSIhPT1yJiYoIm51bGwiPT09cj9udWxsOityKyIiPT09cj8rcjp6dC50ZXN0KHIpP3N0LnBhcnNlSlNPTihyKTpyKX1jYXRjaChvKXt9U3Quc2V0KHQsZSxyKX1lbHNlIHI9dm9pZCAwO3JldHVybiByfWZ1bmN0aW9uIGgodCxlLHIsbil7dmFyIG8saT0xLHM9MjAsYT1uP2Z1bmN0aW9uKCl7cmV0dXJuIG4uY3VyKCl9OmZ1bmN0aW9uKCl7cmV0dXJuIHN0LmNzcyh0LGUsIiIpfSxsPWEoKSx1PXImJnJbM118fChzdC5jc3NOdW1iZXJbZV0/IiI6InB4IiksaD0oc3QuY3NzTnVtYmVyW2VdfHwicHgiIT09dSYmK2wpJiZBdC5leGVjKHN0LmNzcyh0LGUpKTtpZihoJiZoWzNdIT09dSl7dT11fHxoWzNdLHI9cnx8W10saD0rbHx8MTtkbyBpPWl8fCIuNSIsaC89aSxzdC5zdHlsZSh0LGUsaCt1KTt3aGlsZShpIT09KGk9YSgpL2wpJiYxIT09aSYmLS1zKX1yZXR1cm4gciYmKGg9K2h8fCtsfHwwLG89clsxXT9oKyhyWzFdKzEpKnJbMl06K3JbMl0sbiYmKG4udW5pdD11LG4uc3RhcnQ9aCxuLmVuZD1vKSksb31mdW5jdGlvbiBjKHQsZSl7dmFyIHI9InVuZGVmaW5lZCIhPXR5cGVvZiB0LmdldEVsZW1lbnRzQnlUYWdOYW1lP3QuZ2V0RWxlbWVudHNCeVRhZ05hbWUoZXx8IioiKToidW5kZWZpbmVkIiE9dHlwZW9mIHQucXVlcnlTZWxlY3RvckFsbD90LnF1ZXJ5U2VsZWN0b3JBbGwoZXx8IioiKTpbXTtyZXR1cm4gdm9pZCAwPT09ZXx8ZSYmc3Qubm9kZU5hbWUodCxlKT9zdC5tZXJnZShbdF0scik6cn1mdW5jdGlvbiBwKHQsZSl7Zm9yKHZhciByPTAsbj10Lmxlbmd0aDtyPG47cisrKVR0LnNldCh0W3JdLCJnbG9iYWxFdmFsIiwhZXx8VHQuZ2V0KGVbcl0sImdsb2JhbEV2YWwiKSl9ZnVuY3Rpb24gXyh0LGUscixuLG8pe2Zvcih2YXIgaSxzLGEsbCx1LGgsXz1lLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKSxkPVtdLGY9MCxtPXQubGVuZ3RoO2Y8bTtmKyspaWYoaT10W2ZdLGl8fDA9PT1pKWlmKCJvYmplY3QiPT09c3QudHlwZShpKSlzdC5tZXJnZShkLGkubm9kZVR5cGU/W2ldOmkpO2Vsc2UgaWYoUnQudGVzdChpKSl7Zm9yKHM9c3x8Xy5hcHBlbmRDaGlsZChlLmNyZWF0ZUVsZW1lbnQoImRpdiIpKSxhPShxdC5leGVjKGkpfHxbIiIsIiJdKVsxXS50b0xvd2VyQ2FzZSgpLGw9SXRbYV18fEl0Ll9kZWZhdWx0LHMuaW5uZXJIVE1MPWxbMV0rc3QuaHRtbFByZWZpbHRlcihpKStsWzJdLGg9bFswXTtoLS07KXM9cy5sYXN0Q2hpbGQ7c3QubWVyZ2UoZCxzLmNoaWxkTm9kZXMpLHM9Xy5maXJzdENoaWxkLHMudGV4dENvbnRlbnQ9IiJ9ZWxzZSBkLnB1c2goZS5jcmVhdGVUZXh0Tm9kZShpKSk7Zm9yKF8udGV4dENvbnRlbnQ9IiIsZj0wO2k9ZFtmKytdOylpZihuJiZzdC5pbkFycmF5KGksbik+LTEpbyYmby5wdXNoKGkpO2Vsc2UgaWYodT1zdC5jb250YWlucyhpLm93bmVyRG9jdW1lbnQsaSkscz1jKF8uYXBwZW5kQ2hpbGQoaSksInNjcmlwdCIpLHUmJnAocykscilmb3IoaD0wO2k9c1toKytdOylEdC50ZXN0KGkudHlwZXx8IiIpJiZyLnB1c2goaSk7cmV0dXJuIF99ZnVuY3Rpb24gZCgpe3JldHVybiEwfWZ1bmN0aW9uIGYoKXtyZXR1cm4hMX1mdW5jdGlvbiBtKCl7dHJ5e3JldHVybiBKLmFjdGl2ZUVsZW1lbnR9Y2F0Y2godCl7fX1mdW5jdGlvbiBnKHQsZSxyLG4sbyxpKXt2YXIgcyxhO2lmKCJvYmplY3QiPT10eXBlb2YgZSl7InN0cmluZyIhPXR5cGVvZiByJiYobj1ufHxyLHI9dm9pZCAwKTtmb3IoYSBpbiBlKWcodCxhLHIsbixlW2FdLGkpO3JldHVybiB0fWlmKG51bGw9PW4mJm51bGw9PW8/KG89cixuPXI9dm9pZCAwKTpudWxsPT1vJiYoInN0cmluZyI9PXR5cGVvZiByPyhvPW4sbj12b2lkIDApOihvPW4sbj1yLHI9dm9pZCAwKSksbz09PSExKW89ZjtlbHNlIGlmKCFvKXJldHVybiB0O3JldHVybiAxPT09aSYmKHM9byxvPWZ1bmN0aW9uKHQpe3JldHVybiBzdCgpLm9mZih0KSxzLmFwcGx5KHRoaXMsYXJndW1lbnRzKX0sby5ndWlkPXMuZ3VpZHx8KHMuZ3VpZD1zdC5ndWlkKyspKSx0LmVhY2goZnVuY3Rpb24oKXtzdC5ldmVudC5hZGQodGhpcyxlLG8sbixyKX0pfWZ1bmN0aW9uIHkodCxlKXtyZXR1cm4gc3Qubm9kZU5hbWUodCwidGFibGUiKSYmc3Qubm9kZU5hbWUoMTEhPT1lLm5vZGVUeXBlP2U6ZS5maXJzdENoaWxkLCJ0ciIpP3QuZ2V0RWxlbWVudHNCeVRhZ05hbWUoInRib2R5IilbMF18fHQuYXBwZW5kQ2hpbGQodC5vd25lckRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInRib2R5IikpOnR9ZnVuY3Rpb24gdih0KXtyZXR1cm4gdC50eXBlPShudWxsIT09dC5nZXRBdHRyaWJ1dGUoInR5cGUiKSkrIi8iK3QudHlwZSx0fWZ1bmN0aW9uIGIodCl7dmFyIGU9WXQuZXhlYyh0LnR5cGUpO3JldHVybiBlP3QudHlwZT1lWzFdOnQucmVtb3ZlQXR0cmlidXRlKCJ0eXBlIiksdH1mdW5jdGlvbiB4KHQsZSl7dmFyIHIsbixvLGkscyxhLGwsdTtpZigxPT09ZS5ub2RlVHlwZSl7aWYoVHQuaGFzRGF0YSh0KSYmKGk9VHQuYWNjZXNzKHQpLHM9VHQuc2V0KGUsaSksdT1pLmV2ZW50cykpe2RlbGV0ZSBzLmhhbmRsZSxzLmV2ZW50cz17fTtmb3IobyBpbiB1KWZvcihyPTAsbj11W29dLmxlbmd0aDtyPG47cisrKXN0LmV2ZW50LmFkZChlLG8sdVtvXVtyXSl9U3QuaGFzRGF0YSh0KSYmKGE9U3QuYWNjZXNzKHQpLGw9c3QuZXh0ZW5kKHt9LGEpLFN0LnNldChlLGwpKX19ZnVuY3Rpb24gdyh0LGUpe3ZhciByPWUubm9kZU5hbWUudG9Mb3dlckNhc2UoKTsiaW5wdXQiPT09ciYmT3QudGVzdCh0LnR5cGUpP2UuY2hlY2tlZD10LmNoZWNrZWQ6ImlucHV0IiE9PXImJiJ0ZXh0YXJlYSIhPT1yfHwoZS5kZWZhdWx0VmFsdWU9dC5kZWZhdWx0VmFsdWUpfWZ1bmN0aW9uIE0odCxlLHIsbil7ZT1LLmFwcGx5KFtdLGUpO3ZhciBvLGkscyxhLGwsdSxoPTAscD10Lmxlbmd0aCxkPXAtMSxmPWVbMF0sbT1zdC5pc0Z1bmN0aW9uKGYpO2lmKG18fHA+MSYmInN0cmluZyI9PXR5cGVvZiBmJiYhb3QuY2hlY2tDbG9uZSYmVXQudGVzdChmKSlyZXR1cm4gdC5lYWNoKGZ1bmN0aW9uKG8pe3ZhciBpPXQuZXEobyk7bSYmKGVbMF09Zi5jYWxsKHRoaXMsbyxpLmh0bWwoKSkpLE0oaSxlLHIsbil9KTtpZihwJiYobz1fKGUsdFswXS5vd25lckRvY3VtZW50LCExLHQsbiksaT1vLmZpcnN0Q2hpbGQsMT09PW8uY2hpbGROb2Rlcy5sZW5ndGgmJihvPWkpLGl8fG4pKXtmb3Iocz1zdC5tYXAoYyhvLCJzY3JpcHQiKSx2KSxhPXMubGVuZ3RoO2g8cDtoKyspbD1vLGghPT1kJiYobD1zdC5jbG9uZShsLCEwLCEwKSxhJiZzdC5tZXJnZShzLGMobCwic2NyaXB0IikpKSxyLmNhbGwodFtoXSxsLGgpO2lmKGEpZm9yKHU9c1tzLmxlbmd0aC0xXS5vd25lckRvY3VtZW50LHN0Lm1hcChzLGIpLGg9MDtoPGE7aCsrKWw9c1toXSxEdC50ZXN0KGwudHlwZXx8IiIpJiYhVHQuYWNjZXNzKGwsImdsb2JhbEV2YWwiKSYmc3QuY29udGFpbnModSxsKSYmKGwuc3JjP3N0Ll9ldmFsVXJsJiZzdC5fZXZhbFVybChsLnNyYyk6c3QuZ2xvYmFsRXZhbChsLnRleHRDb250ZW50LnJlcGxhY2UoSHQsIiIpKSl9cmV0dXJuIHR9ZnVuY3Rpb24gayh0LGUscil7Zm9yKHZhciBuLG89ZT9zdC5maWx0ZXIoZSx0KTp0LGk9MDtudWxsIT0obj1vW2ldKTtpKyspcnx8MSE9PW4ubm9kZVR5cGV8fHN0LmNsZWFuRGF0YShjKG4pKSxuLnBhcmVudE5vZGUmJihyJiZzdC5jb250YWlucyhuLm93bmVyRG9jdW1lbnQsbikmJnAoYyhuLCJzY3JpcHQiKSksbi5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG4pKTtyZXR1cm4gdH1mdW5jdGlvbiBqKHQsZSl7dmFyIHI9c3QoZS5jcmVhdGVFbGVtZW50KHQpKS5hcHBlbmRUbyhlLmJvZHkpLG49c3QuY3NzKHJbMF0sImRpc3BsYXkiKTtyZXR1cm4gci5kZXRhY2goKSxufWZ1bmN0aW9uIFQodCl7dmFyIGU9SixyPSR0W3RdO3JldHVybiByfHwocj1qKHQsZSksIm5vbmUiIT09ciYmcnx8KFh0PShYdHx8c3QoIjxpZnJhbWUgZnJhbWVib3JkZXI9JzAnIHdpZHRoPScwJyBoZWlnaHQ9JzAnLz4iKSkuYXBwZW5kVG8oZS5kb2N1bWVudEVsZW1lbnQpLGU9WHRbMF0uY29udGVudERvY3VtZW50LGUud3JpdGUoKSxlLmNsb3NlKCkscj1qKHQsZSksWHQuZGV0YWNoKCkpLCR0W3RdPXIpLHJ9ZnVuY3Rpb24gUyh0LGUscil7dmFyIG4sbyxpLHMsYT10LnN0eWxlO3JldHVybiByPXJ8fFF0KHQpLHM9cj9yLmdldFByb3BlcnR5VmFsdWUoZSl8fHJbZV06dm9pZCAwLCIiIT09cyYmdm9pZCAwIT09c3x8c3QuY29udGFpbnModC5vd25lckRvY3VtZW50LHQpfHwocz1zdC5zdHlsZSh0LGUpKSxyJiYhb3QucGl4ZWxNYXJnaW5SaWdodCgpJiZKdC50ZXN0KHMpJiZXdC50ZXN0KGUpJiYobj1hLndpZHRoLG89YS5taW5XaWR0aCxpPWEubWF4V2lkdGgsYS5taW5XaWR0aD1hLm1heFdpZHRoPWEud2lkdGg9cyxzPXIud2lkdGgsYS53aWR0aD1uLGEubWluV2lkdGg9byxhLm1heFdpZHRoPWkpLHZvaWQgMCE9PXM/cysiIjpzfWZ1bmN0aW9uIHoodCxlKXtyZXR1cm57Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHQoKT92b2lkIGRlbGV0ZSB0aGlzLmdldDoodGhpcy5nZXQ9ZSkuYXBwbHkodGhpcyxhcmd1bWVudHMpfX19ZnVuY3Rpb24gUCh0KXtpZih0IGluIG9lKXJldHVybiB0O2Zvcih2YXIgZT10WzBdLnRvVXBwZXJDYXNlKCkrdC5zbGljZSgxKSxyPW5lLmxlbmd0aDtyLS07KWlmKHQ9bmVbcl0rZSx0IGluIG9lKXJldHVybiB0fWZ1bmN0aW9uIEUodCxlLHIpe3ZhciBuPUF0LmV4ZWMoZSk7cmV0dXJuIG4/TWF0aC5tYXgoMCxuWzJdLShyfHwwKSkrKG5bM118fCJweCIpOmV9ZnVuY3Rpb24gQSh0LGUscixuLG8pe2Zvcih2YXIgaT1yPT09KG4/ImJvcmRlciI6ImNvbnRlbnQiKT80OiJ3aWR0aCI9PT1lPzE6MCxzPTA7aTw0O2krPTIpIm1hcmdpbiI9PT1yJiYocys9c3QuY3NzKHQscitDdFtpXSwhMCxvKSksbj8oImNvbnRlbnQiPT09ciYmKHMtPXN0LmNzcyh0LCJwYWRkaW5nIitDdFtpXSwhMCxvKSksIm1hcmdpbiIhPT1yJiYocy09c3QuY3NzKHQsImJvcmRlciIrQ3RbaV0rIldpZHRoIiwhMCxvKSkpOihzKz1zdC5jc3ModCwicGFkZGluZyIrQ3RbaV0sITAsbyksInBhZGRpbmciIT09ciYmKHMrPXN0LmNzcyh0LCJib3JkZXIiK0N0W2ldKyJXaWR0aCIsITAsbykpKTtyZXR1cm4gc31mdW5jdGlvbiBDKHQsZSxyKXt2YXIgbj0hMCxvPSJ3aWR0aCI9PT1lP3Qub2Zmc2V0V2lkdGg6dC5vZmZzZXRIZWlnaHQsaT1RdCh0KSxzPSJib3JkZXItYm94Ij09PXN0LmNzcyh0LCJib3hTaXppbmciLCExLGkpO2lmKG88PTB8fG51bGw9PW8pe2lmKG89Uyh0LGUsaSksKG88MHx8bnVsbD09bykmJihvPXQuc3R5bGVbZV0pLEp0LnRlc3QobykpcmV0dXJuIG87bj1zJiYob3QuYm94U2l6aW5nUmVsaWFibGUoKXx8bz09PXQuc3R5bGVbZV0pLG89cGFyc2VGbG9hdChvKXx8MH1yZXR1cm4gbytBKHQsZSxyfHwocz8iYm9yZGVyIjoiY29udGVudCIpLG4saSkrInB4In1mdW5jdGlvbiBOKHQsZSl7Zm9yKHZhciByLG4sbyxpPVtdLHM9MCxhPXQubGVuZ3RoO3M8YTtzKyspbj10W3NdLG4uc3R5bGUmJihpW3NdPVR0LmdldChuLCJvbGRkaXNwbGF5Iikscj1uLnN0eWxlLmRpc3BsYXksZT8oaVtzXXx8Im5vbmUiIT09cnx8KG4uc3R5bGUuZGlzcGxheT0iIiksIiI9PT1uLnN0eWxlLmRpc3BsYXkmJk50KG4pJiYoaVtzXT1UdC5hY2Nlc3Mobiwib2xkZGlzcGxheSIsVChuLm5vZGVOYW1lKSkpKToobz1OdChuKSwibm9uZSI9PT1yJiZvfHxUdC5zZXQobiwib2xkZGlzcGxheSIsbz9yOnN0LmNzcyhuLCJkaXNwbGF5IikpKSk7Zm9yKHM9MDtzPGE7cysrKW49dFtzXSxuLnN0eWxlJiYoZSYmIm5vbmUiIT09bi5zdHlsZS5kaXNwbGF5JiYiIiE9PW4uc3R5bGUuZGlzcGxheXx8KG4uc3R5bGUuZGlzcGxheT1lP2lbc118fCIiOiJub25lIikpO3JldHVybiB0fWZ1bmN0aW9uIE8odCxlLHIsbixvKXtyZXR1cm4gbmV3IE8ucHJvdG90eXBlLmluaXQodCxlLHIsbixvKX1mdW5jdGlvbiBxKCl7cmV0dXJuIGUuc2V0VGltZW91dChmdW5jdGlvbigpe2llPXZvaWQgMH0pLGllPXN0Lm5vdygpfWZ1bmN0aW9uIEQodCxlKXt2YXIgcixuPTAsbz17aGVpZ2h0OnR9O2ZvcihlPWU/MTowO248NDtuKz0yLWUpcj1DdFtuXSxvWyJtYXJnaW4iK3JdPW9bInBhZGRpbmciK3JdPXQ7cmV0dXJuIGUmJihvLm9wYWNpdHk9by53aWR0aD10KSxvfWZ1bmN0aW9uIEkodCxlLHIpe2Zvcih2YXIgbixvPShCLnR3ZWVuZXJzW2VdfHxbXSkuY29uY2F0KEIudHdlZW5lcnNbIioiXSksaT0wLHM9by5sZW5ndGg7aTxzO2krKylpZihuPW9baV0uY2FsbChyLGUsdCkpcmV0dXJuIG59ZnVuY3Rpb24gUih0LGUscil7dmFyIG4sbyxpLHMsYSxsLHUsaCxjPXRoaXMscD17fSxfPXQuc3R5bGUsZD10Lm5vZGVUeXBlJiZOdCh0KSxmPVR0LmdldCh0LCJmeHNob3ciKTtyLnF1ZXVlfHwoYT1zdC5fcXVldWVIb29rcyh0LCJmeCIpLG51bGw9PWEudW5xdWV1ZWQmJihhLnVucXVldWVkPTAsbD1hLmVtcHR5LmZpcmUsYS5lbXB0eS5maXJlPWZ1bmN0aW9uKCl7YS51bnF1ZXVlZHx8bCgpfSksYS51bnF1ZXVlZCsrLGMuYWx3YXlzKGZ1bmN0aW9uKCl7Yy5hbHdheXMoZnVuY3Rpb24oKXthLnVucXVldWVkLS0sc3QucXVldWUodCwiZngiKS5sZW5ndGh8fGEuZW1wdHkuZmlyZSgpfSl9KSksMT09PXQubm9kZVR5cGUmJigiaGVpZ2h0ImluIGV8fCJ3aWR0aCJpbiBlKSYmKHIub3ZlcmZsb3c9W18ub3ZlcmZsb3csXy5vdmVyZmxvd1gsXy5vdmVyZmxvd1ldLHU9c3QuY3NzKHQsImRpc3BsYXkiKSxoPSJub25lIj09PXU/VHQuZ2V0KHQsIm9sZGRpc3BsYXkiKXx8VCh0Lm5vZGVOYW1lKTp1LCJpbmxpbmUiPT09aCYmIm5vbmUiPT09c3QuY3NzKHQsImZsb2F0IikmJihfLmRpc3BsYXk9ImlubGluZS1ibG9jayIpKSxyLm92ZXJmbG93JiYoXy5vdmVyZmxvdz0iaGlkZGVuIixjLmFsd2F5cyhmdW5jdGlvbigpe18ub3ZlcmZsb3c9ci5vdmVyZmxvd1swXSxfLm92ZXJmbG93WD1yLm92ZXJmbG93WzFdLF8ub3ZlcmZsb3dZPXIub3ZlcmZsb3dbMl19KSk7Zm9yKG4gaW4gZSlpZihvPWVbbl0sYWUuZXhlYyhvKSl7aWYoZGVsZXRlIGVbbl0saT1pfHwidG9nZ2xlIj09PW8sbz09PShkPyJoaWRlIjoic2hvdyIpKXtpZigic2hvdyIhPT1vfHwhZnx8dm9pZCAwPT09ZltuXSljb250aW51ZTtkPSEwfXBbbl09ZiYmZltuXXx8c3Quc3R5bGUodCxuKX1lbHNlIHU9dm9pZCAwO2lmKHN0LmlzRW1wdHlPYmplY3QocCkpImlubGluZSI9PT0oIm5vbmUiPT09dT9UKHQubm9kZU5hbWUpOnUpJiYoXy5kaXNwbGF5PXUpO2Vsc2V7Zj8iaGlkZGVuImluIGYmJihkPWYuaGlkZGVuKTpmPVR0LmFjY2Vzcyh0LCJmeHNob3ciLHt9KSxpJiYoZi5oaWRkZW49IWQpLGQ/c3QodCkuc2hvdygpOmMuZG9uZShmdW5jdGlvbigpe3N0KHQpLmhpZGUoKX0pLGMuZG9uZShmdW5jdGlvbigpe3ZhciBlO1R0LnJlbW92ZSh0LCJmeHNob3ciKTtmb3IoZSBpbiBwKXN0LnN0eWxlKHQsZSxwW2VdKX0pO2ZvcihuIGluIHApcz1JKGQ/ZltuXTowLG4sYyksbiBpbiBmfHwoZltuXT1zLnN0YXJ0LGQmJihzLmVuZD1zLnN0YXJ0LHMuc3RhcnQ9IndpZHRoIj09PW58fCJoZWlnaHQiPT09bj8xOjApKX19ZnVuY3Rpb24gRih0LGUpe3ZhciByLG4sbyxpLHM7Zm9yKHIgaW4gdClpZihuPXN0LmNhbWVsQ2FzZShyKSxvPWVbbl0saT10W3JdLHN0LmlzQXJyYXkoaSkmJihvPWlbMV0saT10W3JdPWlbMF0pLHIhPT1uJiYodFtuXT1pLGRlbGV0ZSB0W3JdKSxzPXN0LmNzc0hvb2tzW25dLHMmJiJleHBhbmQiaW4gcyl7aT1zLmV4cGFuZChpKSxkZWxldGUgdFtuXTtmb3IociBpbiBpKXIgaW4gdHx8KHRbcl09aVtyXSxlW3JdPW8pfWVsc2UgZVtuXT1vfWZ1bmN0aW9uIEIodCxlLHIpe3ZhciBuLG8saT0wLHM9Qi5wcmVmaWx0ZXJzLmxlbmd0aCxhPXN0LkRlZmVycmVkKCkuYWx3YXlzKGZ1bmN0aW9uKCl7ZGVsZXRlIGwuZWxlbX0pLGw9ZnVuY3Rpb24oKXtpZihvKXJldHVybiExO2Zvcih2YXIgZT1pZXx8cSgpLHI9TWF0aC5tYXgoMCx1LnN0YXJ0VGltZSt1LmR1cmF0aW9uLWUpLG49ci91LmR1cmF0aW9ufHwwLGk9MS1uLHM9MCxsPXUudHdlZW5zLmxlbmd0aDtzPGw7cysrKXUudHdlZW5zW3NdLnJ1bihpKTtyZXR1cm4gYS5ub3RpZnlXaXRoKHQsW3UsaSxyXSksaTwxJiZsP3I6KGEucmVzb2x2ZVdpdGgodCxbdV0pLCExKX0sdT1hLnByb21pc2Uoe2VsZW06dCxwcm9wczpzdC5leHRlbmQoe30sZSksb3B0czpzdC5leHRlbmQoITAse3NwZWNpYWxFYXNpbmc6e30sZWFzaW5nOnN0LmVhc2luZy5fZGVmYXVsdH0sciksb3JpZ2luYWxQcm9wZXJ0aWVzOmUsb3JpZ2luYWxPcHRpb25zOnIsc3RhcnRUaW1lOmllfHxxKCksZHVyYXRpb246ci5kdXJhdGlvbix0d2VlbnM6W10sY3JlYXRlVHdlZW46ZnVuY3Rpb24oZSxyKXt2YXIgbj1zdC5Ud2Vlbih0LHUub3B0cyxlLHIsdS5vcHRzLnNwZWNpYWxFYXNpbmdbZV18fHUub3B0cy5lYXNpbmcpO3JldHVybiB1LnR3ZWVucy5wdXNoKG4pLG59LHN0b3A6ZnVuY3Rpb24oZSl7dmFyIHI9MCxuPWU/dS50d2VlbnMubGVuZ3RoOjA7aWYobylyZXR1cm4gdGhpcztmb3Iobz0hMDtyPG47cisrKXUudHdlZW5zW3JdLnJ1bigxKTtyZXR1cm4gZT8oYS5ub3RpZnlXaXRoKHQsW3UsMSwwXSksYS5yZXNvbHZlV2l0aCh0LFt1LGVdKSk6YS5yZWplY3RXaXRoKHQsW3UsZV0pLHRoaXN9fSksaD11LnByb3BzO2ZvcihGKGgsdS5vcHRzLnNwZWNpYWxFYXNpbmcpO2k8cztpKyspaWYobj1CLnByZWZpbHRlcnNbaV0uY2FsbCh1LHQsaCx1Lm9wdHMpKXJldHVybiBzdC5pc0Z1bmN0aW9uKG4uc3RvcCkmJihzdC5fcXVldWVIb29rcyh1LmVsZW0sdS5vcHRzLnF1ZXVlKS5zdG9wPXN0LnByb3h5KG4uc3RvcCxuKSksbjtyZXR1cm4gc3QubWFwKGgsSSx1KSxzdC5pc0Z1bmN0aW9uKHUub3B0cy5zdGFydCkmJnUub3B0cy5zdGFydC5jYWxsKHQsdSksc3QuZngudGltZXIoc3QuZXh0ZW5kKGwse2VsZW06dCxhbmltOnUscXVldWU6dS5vcHRzLnF1ZXVlfSkpLHUucHJvZ3Jlc3ModS5vcHRzLnByb2dyZXNzKS5kb25lKHUub3B0cy5kb25lLHUub3B0cy5jb21wbGV0ZSkuZmFpbCh1Lm9wdHMuZmFpbCkuYWx3YXlzKHUub3B0cy5hbHdheXMpfWZ1bmN0aW9uIEwodCl7cmV0dXJuIHQuZ2V0QXR0cmlidXRlJiZ0LmdldEF0dHJpYnV0ZSgiY2xhc3MiKXx8IiJ9ZnVuY3Rpb24gRyh0KXtyZXR1cm4gZnVuY3Rpb24oZSxyKXsic3RyaW5nIiE9dHlwZW9mIGUmJihyPWUsZT0iKiIpO3ZhciBuLG89MCxpPWUudG9Mb3dlckNhc2UoKS5tYXRjaCh3dCl8fFtdO2lmKHN0LmlzRnVuY3Rpb24ocikpZm9yKDtuPWlbbysrXTspIisiPT09blswXT8obj1uLnNsaWNlKDEpfHwiKiIsKHRbbl09dFtuXXx8W10pLnVuc2hpZnQocikpOih0W25dPXRbbl18fFtdKS5wdXNoKHIpfX1mdW5jdGlvbiBWKHQsZSxyLG4pe2Z1bmN0aW9uIG8oYSl7dmFyIGw7cmV0dXJuIGlbYV09ITAsc3QuZWFjaCh0W2FdfHxbXSxmdW5jdGlvbih0LGEpe3ZhciB1PWEoZSxyLG4pO3JldHVybiJzdHJpbmciIT10eXBlb2YgdXx8c3x8aVt1XT9zPyEobD11KTp2b2lkIDA6KGUuZGF0YVR5cGVzLnVuc2hpZnQodSksbyh1KSwhMSl9KSxsfXZhciBpPXt9LHM9dD09PVNlO3JldHVybiBvKGUuZGF0YVR5cGVzWzBdKXx8IWlbIioiXSYmbygiKiIpfWZ1bmN0aW9uIFUodCxlKXt2YXIgcixuLG89c3QuYWpheFNldHRpbmdzLmZsYXRPcHRpb25zfHx7fTtmb3IociBpbiBlKXZvaWQgMCE9PWVbcl0mJigob1tyXT90Om58fChuPXt9KSlbcl09ZVtyXSk7cmV0dXJuIG4mJnN0LmV4dGVuZCghMCx0LG4pLHR9ZnVuY3Rpb24gWSh0LGUscil7Zm9yKHZhciBuLG8saSxzLGE9dC5jb250ZW50cyxsPXQuZGF0YVR5cGVzOyIqIj09PWxbMF07KWwuc2hpZnQoKSx2b2lkIDA9PT1uJiYobj10Lm1pbWVUeXBlfHxlLmdldFJlc3BvbnNlSGVhZGVyKCJDb250ZW50LVR5cGUiKSk7aWYobilmb3IobyBpbiBhKWlmKGFbb10mJmFbb10udGVzdChuKSl7bC51bnNoaWZ0KG8pO2JyZWFrfWlmKGxbMF1pbiByKWk9bFswXTtlbHNle2ZvcihvIGluIHIpe2lmKCFsWzBdfHx0LmNvbnZlcnRlcnNbbysiICIrbFswXV0pe2k9bzticmVha31zfHwocz1vKX1pPWl8fHN9aWYoaSlyZXR1cm4gaSE9PWxbMF0mJmwudW5zaGlmdChpKSxyW2ldfWZ1bmN0aW9uIEgodCxlLHIsbil7dmFyIG8saSxzLGEsbCx1PXt9LGg9dC5kYXRhVHlwZXMuc2xpY2UoKTtpZihoWzFdKWZvcihzIGluIHQuY29udmVydGVycyl1W3MudG9Mb3dlckNhc2UoKV09dC5jb252ZXJ0ZXJzW3NdO2ZvcihpPWguc2hpZnQoKTtpOylpZih0LnJlc3BvbnNlRmllbGRzW2ldJiYoclt0LnJlc3BvbnNlRmllbGRzW2ldXT1lKSwhbCYmbiYmdC5kYXRhRmlsdGVyJiYoZT10LmRhdGFGaWx0ZXIoZSx0LmRhdGFUeXBlKSksbD1pLGk9aC5zaGlmdCgpKWlmKCIqIj09PWkpaT1sO2Vsc2UgaWYoIioiIT09bCYmbCE9PWkpe2lmKHM9dVtsKyIgIitpXXx8dVsiKiAiK2ldLCFzKWZvcihvIGluIHUpaWYoYT1vLnNwbGl0KCIgIiksYVsxXT09PWkmJihzPXVbbCsiICIrYVswXV18fHVbIiogIithWzBdXSkpe3M9PT0hMD9zPXVbb106dVtvXSE9PSEwJiYoaT1hWzBdLGgudW5zaGlmdChhWzFdKSk7YnJlYWt9aWYocyE9PSEwKWlmKHMmJnRbInRocm93cyJdKWU9cyhlKTtlbHNlIHRyeXtlPXMoZSl9Y2F0Y2goYyl7cmV0dXJue3N0YXRlOiJwYXJzZXJlcnJvciIsZXJyb3I6cz9jOiJObyBjb252ZXJzaW9uIGZyb20gIitsKyIgdG8gIitpfX19cmV0dXJue3N0YXRlOiJzdWNjZXNzIixkYXRhOmV9fWZ1bmN0aW9uIFgodCxlLHIsbil7dmFyIG87aWYoc3QuaXNBcnJheShlKSlzdC5lYWNoKGUsZnVuY3Rpb24oZSxvKXtyfHxBZS50ZXN0KHQpP24odCxvKTpYKHQrIlsiKygib2JqZWN0Ij09dHlwZW9mIG8mJm51bGwhPW8/ZToiIikrIl0iLG8scixuKX0pO2Vsc2UgaWYocnx8Im9iamVjdCIhPT1zdC50eXBlKGUpKW4odCxlKTtlbHNlIGZvcihvIGluIGUpWCh0KyJbIitvKyJdIixlW29dLHIsbil9ZnVuY3Rpb24gJCh0KXtyZXR1cm4gc3QuaXNXaW5kb3codCk/dDo5PT09dC5ub2RlVHlwZSYmdC5kZWZhdWx0Vmlld312YXIgVz1bXSxKPWUuZG9jdW1lbnQsUT1XLnNsaWNlLEs9Vy5jb25jYXQsWj1XLnB1c2gsdHQ9Vy5pbmRleE9mLGV0PXt9LHJ0PWV0LnRvU3RyaW5nLG50PWV0Lmhhc093blByb3BlcnR5LG90PXt9LGl0PSIyLjIuNCIsc3Q9ZnVuY3Rpb24odCxlKXtyZXR1cm4gbmV3IHN0LmZuLmluaXQodCxlKX0sYXQ9L15bXHNcdUZFRkZceEEwXSt8W1xzXHVGRUZGXHhBMF0rJC9nLGx0PS9eLW1zLS8sdXQ9Ly0oW1xkYS16XSkvZ2ksaHQ9ZnVuY3Rpb24odCxlKXtyZXR1cm4gZS50b1VwcGVyQ2FzZSgpfTtzdC5mbj1zdC5wcm90b3R5cGU9e2pxdWVyeTppdCxjb25zdHJ1Y3RvcjpzdCxzZWxlY3RvcjoiIixsZW5ndGg6MCx0b0FycmF5OmZ1bmN0aW9uKCl7cmV0dXJuIFEuY2FsbCh0aGlzKX0sZ2V0OmZ1bmN0aW9uKHQpe3JldHVybiBudWxsIT10P3Q8MD90aGlzW3QrdGhpcy5sZW5ndGhdOnRoaXNbdF06US5jYWxsKHRoaXMpfSxwdXNoU3RhY2s6ZnVuY3Rpb24odCl7dmFyIGU9c3QubWVyZ2UodGhpcy5jb25zdHJ1Y3RvcigpLHQpO3JldHVybiBlLnByZXZPYmplY3Q9dGhpcyxlLmNvbnRleHQ9dGhpcy5jb250ZXh0LGV9LGVhY2g6ZnVuY3Rpb24odCl7cmV0dXJuIHN0LmVhY2godGhpcyx0KX0sbWFwOmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnB1c2hTdGFjayhzdC5tYXAodGhpcyxmdW5jdGlvbihlLHIpe3JldHVybiB0LmNhbGwoZSxyLGUpfSkpfSxzbGljZTpmdW5jdGlvbigpe3JldHVybiB0aGlzLnB1c2hTdGFjayhRLmFwcGx5KHRoaXMsYXJndW1lbnRzKSl9LGZpcnN0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZXEoMCl9LGxhc3Q6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5lcSgtMSl9LGVxOmZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMubGVuZ3RoLHI9K3QrKHQ8MD9lOjApO3JldHVybiB0aGlzLnB1c2hTdGFjayhyPj0wJiZyPGU/W3RoaXNbcl1dOltdKX0sZW5kOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucHJldk9iamVjdHx8dGhpcy5jb25zdHJ1Y3RvcigpfSxwdXNoOlosc29ydDpXLnNvcnQsc3BsaWNlOlcuc3BsaWNlfSxzdC5leHRlbmQ9c3QuZm4uZXh0ZW5kPWZ1bmN0aW9uKCl7dmFyIHQsZSxyLG4sbyxpLHM9YXJndW1lbnRzWzBdfHx7fSxhPTEsbD1hcmd1bWVudHMubGVuZ3RoLHU9ITE7Zm9yKCJib29sZWFuIj09dHlwZW9mIHMmJih1PXMscz1hcmd1bWVudHNbYV18fHt9LGErKyksIm9iamVjdCI9PXR5cGVvZiBzfHxzdC5pc0Z1bmN0aW9uKHMpfHwocz17fSksYT09PWwmJihzPXRoaXMsYS0tKTthPGw7YSsrKWlmKG51bGwhPSh0PWFyZ3VtZW50c1thXSkpZm9yKGUgaW4gdClyPXNbZV0sbj10W2VdLHMhPT1uJiYodSYmbiYmKHN0LmlzUGxhaW5PYmplY3Qobil8fChvPXN0LmlzQXJyYXkobikpKT8obz8obz0hMSxpPXImJnN0LmlzQXJyYXkocik/cjpbXSk6aT1yJiZzdC5pc1BsYWluT2JqZWN0KHIpP3I6e30sc1tlXT1zdC5leHRlbmQodSxpLG4pKTp2b2lkIDAhPT1uJiYoc1tlXT1uKSk7cmV0dXJuIHN9LHN0LmV4dGVuZCh7ZXhwYW5kbzoialF1ZXJ5IisoaXQrTWF0aC5yYW5kb20oKSkucmVwbGFjZSgvXEQvZywiIiksaXNSZWFkeTohMCxlcnJvcjpmdW5jdGlvbih0KXt0aHJvdyBuZXcgRXJyb3IodCl9LG5vb3A6ZnVuY3Rpb24oKXt9LGlzRnVuY3Rpb246ZnVuY3Rpb24odCl7cmV0dXJuImZ1bmN0aW9uIj09PXN0LnR5cGUodCl9LGlzQXJyYXk6QXJyYXkuaXNBcnJheSxpc1dpbmRvdzpmdW5jdGlvbih0KXtyZXR1cm4gbnVsbCE9dCYmdD09PXQud2luZG93fSxpc051bWVyaWM6ZnVuY3Rpb24odCl7dmFyIGU9dCYmdC50b1N0cmluZygpO3JldHVybiFzdC5pc0FycmF5KHQpJiZlLXBhcnNlRmxvYXQoZSkrMT49MH0saXNQbGFpbk9iamVjdDpmdW5jdGlvbih0KXt2YXIgZTtpZigib2JqZWN0IiE9PXN0LnR5cGUodCl8fHQubm9kZVR5cGV8fHN0LmlzV2luZG93KHQpKXJldHVybiExO2lmKHQuY29uc3RydWN0b3ImJiFudC5jYWxsKHQsImNvbnN0cnVjdG9yIikmJiFudC5jYWxsKHQuY29uc3RydWN0b3IucHJvdG90eXBlfHx7fSwiaXNQcm90b3R5cGVPZiIpKXJldHVybiExO2ZvcihlIGluIHQpO3JldHVybiB2b2lkIDA9PT1lfHxudC5jYWxsKHQsZSl9LGlzRW1wdHlPYmplY3Q6ZnVuY3Rpb24odCl7dmFyIGU7Zm9yKGUgaW4gdClyZXR1cm4hMTtyZXR1cm4hMH0sdHlwZTpmdW5jdGlvbih0KXtyZXR1cm4gbnVsbD09dD90KyIiOiJvYmplY3QiPT10eXBlb2YgdHx8ImZ1bmN0aW9uIj09dHlwZW9mIHQ/ZXRbcnQuY2FsbCh0KV18fCJvYmplY3QiOnR5cGVvZiB0fSxnbG9iYWxFdmFsOmZ1bmN0aW9uKHQpe3ZhciBlLHI9ZXZhbDt0PXN0LnRyaW0odCksdCYmKDE9PT10LmluZGV4T2YoInVzZSBzdHJpY3QiKT8oZT1KLmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpLGUudGV4dD10LEouaGVhZC5hcHBlbmRDaGlsZChlKS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGUpKTpyKHQpKX0sY2FtZWxDYXNlOmZ1bmN0aW9uKHQpe3JldHVybiB0LnJlcGxhY2UobHQsIm1zLSIpLnJlcGxhY2UodXQsaHQpfSxub2RlTmFtZTpmdW5jdGlvbih0LGUpe3JldHVybiB0Lm5vZGVOYW1lJiZ0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk9PT1lLnRvTG93ZXJDYXNlKCl9LGVhY2g6ZnVuY3Rpb24odCxlKXt2YXIgcixvPTA7aWYobih0KSlmb3Iocj10Lmxlbmd0aDtvPHImJmUuY2FsbCh0W29dLG8sdFtvXSkhPT0hMTtvKyspO2Vsc2UgZm9yKG8gaW4gdClpZihlLmNhbGwodFtvXSxvLHRbb10pPT09ITEpYnJlYWs7cmV0dXJuIHR9LHRyaW06ZnVuY3Rpb24odCl7cmV0dXJuIG51bGw9PXQ/IiI6KHQrIiIpLnJlcGxhY2UoYXQsIiIpfSxtYWtlQXJyYXk6ZnVuY3Rpb24odCxlKXt2YXIgcj1lfHxbXTtyZXR1cm4gbnVsbCE9dCYmKG4oT2JqZWN0KHQpKT9zdC5tZXJnZShyLCJzdHJpbmciPT10eXBlb2YgdD9bdF06dCk6Wi5jYWxsKHIsdCkpLHJ9LGluQXJyYXk6ZnVuY3Rpb24odCxlLHIpe3JldHVybiBudWxsPT1lPy0xOnR0LmNhbGwoZSx0LHIpfSxtZXJnZTpmdW5jdGlvbih0LGUpe2Zvcih2YXIgcj0rZS5sZW5ndGgsbj0wLG89dC5sZW5ndGg7bjxyO24rKyl0W28rK109ZVtuXTtyZXR1cm4gdC5sZW5ndGg9byx0fSxncmVwOmZ1bmN0aW9uKHQsZSxyKXtmb3IodmFyIG4sbz1bXSxpPTAscz10Lmxlbmd0aCxhPSFyO2k8cztpKyspbj0hZSh0W2ldLGkpLG4hPT1hJiZvLnB1c2godFtpXSk7cmV0dXJuIG99LG1hcDpmdW5jdGlvbih0LGUscil7dmFyIG8saSxzPTAsYT1bXTtpZihuKHQpKWZvcihvPXQubGVuZ3RoO3M8bztzKyspaT1lKHRbc10scyxyKSxudWxsIT1pJiZhLnB1c2goaSk7ZWxzZSBmb3IocyBpbiB0KWk9ZSh0W3NdLHMsciksbnVsbCE9aSYmYS5wdXNoKGkpO3JldHVybiBLLmFwcGx5KFtdLGEpfSxndWlkOjEscHJveHk6ZnVuY3Rpb24odCxlKXt2YXIgcixuLG87aWYoInN0cmluZyI9PXR5cGVvZiBlJiYocj10W2VdLGU9dCx0PXIpLHN0LmlzRnVuY3Rpb24odCkpcmV0dXJuIG49US5jYWxsKGFyZ3VtZW50cywyKSxvPWZ1bmN0aW9uKCl7cmV0dXJuIHQuYXBwbHkoZXx8dGhpcyxuLmNvbmNhdChRLmNhbGwoYXJndW1lbnRzKSkpfSxvLmd1aWQ9dC5ndWlkPXQuZ3VpZHx8c3QuZ3VpZCsrLG99LG5vdzpEYXRlLm5vdyxzdXBwb3J0Om90fSksImZ1bmN0aW9uIj09dHlwZW9mIFN5bWJvbCYmKHN0LmZuW1N5bWJvbC5pdGVyYXRvcl09V1tTeW1ib2wuaXRlcmF0b3JdKSxzdC5lYWNoKCJCb29sZWFuIE51bWJlciBTdHJpbmcgRnVuY3Rpb24gQXJyYXkgRGF0ZSBSZWdFeHAgT2JqZWN0IEVycm9yIFN5bWJvbCIuc3BsaXQoIiAiKSxmdW5jdGlvbih0LGUpe2V0WyJbb2JqZWN0ICIrZSsiXSJdPWUudG9Mb3dlckNhc2UoKX0pO3ZhciBjdD0vKiEKICogU2l6emxlIENTUyBTZWxlY3RvciBFbmdpbmUgdjIuMi4xCiAqIGh0dHA6Ly9zaXp6bGVqcy5jb20vCiAqCiAqIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzCiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZQogKiBodHRwOi8vanF1ZXJ5Lm9yZy9saWNlbnNlCiAqCiAqIERhdGU6IDIwMTUtMTAtMTcKICovCmZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUodCxlLHIsbil7dmFyIG8saSxzLGEsbCx1LGMsXyxkPWUmJmUub3duZXJEb2N1bWVudCxmPWU/ZS5ub2RlVHlwZTo5O2lmKHI9cnx8W10sInN0cmluZyIhPXR5cGVvZiB0fHwhdHx8MSE9PWYmJjkhPT1mJiYxMSE9PWYpcmV0dXJuIHI7aWYoIW4mJigoZT9lLm93bmVyRG9jdW1lbnR8fGU6QikhPT1DJiZBKGUpLGU9ZXx8QyxPKSl7aWYoMTEhPT1mJiYodT1ndC5leGVjKHQpKSlpZihvPXVbMV0pe2lmKDk9PT1mKXtpZighKHM9ZS5nZXRFbGVtZW50QnlJZChvKSkpcmV0dXJuIHI7aWYocy5pZD09PW8pcmV0dXJuIHIucHVzaChzKSxyfWVsc2UgaWYoZCYmKHM9ZC5nZXRFbGVtZW50QnlJZChvKSkmJlIoZSxzKSYmcy5pZD09PW8pcmV0dXJuIHIucHVzaChzKSxyfWVsc2V7aWYodVsyXSlyZXR1cm4gSy5hcHBseShyLGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUodCkpLHI7aWYoKG89dVszXSkmJnguZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSYmZS5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKXJldHVybiBLLmFwcGx5KHIsZS5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKG8pKSxyfWlmKHgucXNhJiYhWVt0KyIgIl0mJighcXx8IXEudGVzdCh0KSkpe2lmKDEhPT1mKWQ9ZSxfPXQ7ZWxzZSBpZigib2JqZWN0IiE9PWUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSl7Zm9yKChhPWUuZ2V0QXR0cmlidXRlKCJpZCIpKT9hPWEucmVwbGFjZSh2dCwiXFwkJiIpOmUuc2V0QXR0cmlidXRlKCJpZCIsYT1GKSxjPWoodCksaT1jLmxlbmd0aCxsPXB0LnRlc3QoYSk/IiMiK2E6IltpZD0nIithKyInXSI7aS0tOyljW2ldPWwrIiAiK3AoY1tpXSk7Xz1jLmpvaW4oIiwiKSxkPXl0LnRlc3QodCkmJmgoZS5wYXJlbnROb2RlKXx8ZX1pZihfKXRyeXtyZXR1cm4gSy5hcHBseShyLGQucXVlcnlTZWxlY3RvckFsbChfKSkscn1jYXRjaChtKXt9ZmluYWxseXthPT09RiYmZS5yZW1vdmVBdHRyaWJ1dGUoImlkIil9fX1yZXR1cm4gUyh0LnJlcGxhY2UoYXQsIiQxIiksZSxyLG4pfWZ1bmN0aW9uIHIoKXtmdW5jdGlvbiB0KHIsbil7cmV0dXJuIGUucHVzaChyKyIgIik+dy5jYWNoZUxlbmd0aCYmZGVsZXRlIHRbZS5zaGlmdCgpXSx0W3IrIiAiXT1ufXZhciBlPVtdO3JldHVybiB0fWZ1bmN0aW9uIG4odCl7cmV0dXJuIHRbRl09ITAsdH1mdW5jdGlvbiBvKHQpe3ZhciBlPUMuY3JlYXRlRWxlbWVudCgiZGl2Iik7dHJ5e3JldHVybiEhdChlKX1jYXRjaChyKXtyZXR1cm4hMX1maW5hbGx5e2UucGFyZW50Tm9kZSYmZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGUpLGU9bnVsbH19ZnVuY3Rpb24gaSh0LGUpe2Zvcih2YXIgcj10LnNwbGl0KCJ8Iiksbj1yLmxlbmd0aDtuLS07KXcuYXR0ckhhbmRsZVtyW25dXT1lfWZ1bmN0aW9uIHModCxlKXt2YXIgcj1lJiZ0LG49ciYmMT09PXQubm9kZVR5cGUmJjE9PT1lLm5vZGVUeXBlJiYofmUuc291cmNlSW5kZXh8fFgpLSh+dC5zb3VyY2VJbmRleHx8WCk7aWYobilyZXR1cm4gbjtpZihyKWZvcig7cj1yLm5leHRTaWJsaW5nOylpZihyPT09ZSlyZXR1cm4tMTtyZXR1cm4gdD8xOi0xfWZ1bmN0aW9uIGEodCl7cmV0dXJuIGZ1bmN0aW9uKGUpe3ZhciByPWUubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtyZXR1cm4iaW5wdXQiPT09ciYmZS50eXBlPT09dH19ZnVuY3Rpb24gbCh0KXtyZXR1cm4gZnVuY3Rpb24oZSl7dmFyIHI9ZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO3JldHVybigiaW5wdXQiPT09cnx8ImJ1dHRvbiI9PT1yKSYmZS50eXBlPT09dH19ZnVuY3Rpb24gdSh0KXtyZXR1cm4gbihmdW5jdGlvbihlKXtyZXR1cm4gZT0rZSxuKGZ1bmN0aW9uKHIsbil7Zm9yKHZhciBvLGk9dChbXSxyLmxlbmd0aCxlKSxzPWkubGVuZ3RoO3MtLTspcltvPWlbc11dJiYocltvXT0hKG5bb109cltvXSkpfSl9KX1mdW5jdGlvbiBoKHQpe3JldHVybiB0JiYidW5kZWZpbmVkIiE9dHlwZW9mIHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUmJnR9ZnVuY3Rpb24gYygpe31mdW5jdGlvbiBwKHQpe2Zvcih2YXIgZT0wLHI9dC5sZW5ndGgsbj0iIjtlPHI7ZSsrKW4rPXRbZV0udmFsdWU7cmV0dXJuIG59ZnVuY3Rpb24gXyh0LGUscil7dmFyIG49ZS5kaXIsbz1yJiYicGFyZW50Tm9kZSI9PT1uLGk9RysrO3JldHVybiBlLmZpcnN0P2Z1bmN0aW9uKGUscixpKXtmb3IoO2U9ZVtuXTspaWYoMT09PWUubm9kZVR5cGV8fG8pcmV0dXJuIHQoZSxyLGkpfTpmdW5jdGlvbihlLHIscyl7dmFyIGEsbCx1LGg9W0wsaV07aWYocyl7Zm9yKDtlPWVbbl07KWlmKCgxPT09ZS5ub2RlVHlwZXx8bykmJnQoZSxyLHMpKXJldHVybiEwfWVsc2UgZm9yKDtlPWVbbl07KWlmKDE9PT1lLm5vZGVUeXBlfHxvKXtpZih1PWVbRl18fChlW0ZdPXt9KSxsPXVbZS51bmlxdWVJRF18fCh1W2UudW5pcXVlSURdPXt9KSwoYT1sW25dKSYmYVswXT09PUwmJmFbMV09PT1pKXJldHVybiBoWzJdPWFbMl07aWYobFtuXT1oLGhbMl09dChlLHIscykpcmV0dXJuITB9fX1mdW5jdGlvbiBkKHQpe3JldHVybiB0Lmxlbmd0aD4xP2Z1bmN0aW9uKGUscixuKXtmb3IodmFyIG89dC5sZW5ndGg7by0tOylpZighdFtvXShlLHIsbikpcmV0dXJuITE7cmV0dXJuITB9OnRbMF19ZnVuY3Rpb24gZih0LHIsbil7Zm9yKHZhciBvPTAsaT1yLmxlbmd0aDtvPGk7bysrKWUodCxyW29dLG4pO3JldHVybiBufWZ1bmN0aW9uIG0odCxlLHIsbixvKXtmb3IodmFyIGkscz1bXSxhPTAsbD10Lmxlbmd0aCx1PW51bGwhPWU7YTxsO2ErKykoaT10W2FdKSYmKHImJiFyKGksbixvKXx8KHMucHVzaChpKSx1JiZlLnB1c2goYSkpKTtyZXR1cm4gc31mdW5jdGlvbiBnKHQsZSxyLG8saSxzKXtyZXR1cm4gbyYmIW9bRl0mJihvPWcobykpLGkmJiFpW0ZdJiYoaT1nKGkscykpLG4oZnVuY3Rpb24obixzLGEsbCl7dmFyIHUsaCxjLHA9W10sXz1bXSxkPXMubGVuZ3RoLGc9bnx8ZihlfHwiKiIsYS5ub2RlVHlwZT9bYV06YSxbXSkseT0hdHx8IW4mJmU/ZzptKGcscCx0LGEsbCksdj1yP2l8fChuP3Q6ZHx8byk/W106czp5O2lmKHImJnIoeSx2LGEsbCksbylmb3IodT1tKHYsXyksbyh1LFtdLGEsbCksaD11Lmxlbmd0aDtoLS07KShjPXVbaF0pJiYodltfW2hdXT0hKHlbX1toXV09YykpO2lmKG4pe2lmKGl8fHQpe2lmKGkpe2Zvcih1PVtdLGg9di5sZW5ndGg7aC0tOykoYz12W2hdKSYmdS5wdXNoKHlbaF09Yyk7aShudWxsLHY9W10sdSxsKX1mb3IoaD12Lmxlbmd0aDtoLS07KShjPXZbaF0pJiYodT1pP3R0KG4sYyk6cFtoXSk+LTEmJihuW3VdPSEoc1t1XT1jKSl9fWVsc2Ugdj1tKHY9PT1zP3Yuc3BsaWNlKGQsdi5sZW5ndGgpOnYpLGk/aShudWxsLHMsdixsKTpLLmFwcGx5KHMsdil9KX1mdW5jdGlvbiB5KHQpe2Zvcih2YXIgZSxyLG4sbz10Lmxlbmd0aCxpPXcucmVsYXRpdmVbdFswXS50eXBlXSxzPWl8fHcucmVsYXRpdmVbIiAiXSxhPWk/MTowLGw9XyhmdW5jdGlvbih0KXtyZXR1cm4gdD09PWV9LHMsITApLHU9XyhmdW5jdGlvbih0KXtyZXR1cm4gdHQoZSx0KT4tMX0scywhMCksaD1bZnVuY3Rpb24odCxyLG4pe3ZhciBvPSFpJiYobnx8ciE9PXopfHwoKGU9cikubm9kZVR5cGU/bCh0LHIsbik6dSh0LHIsbikpO3JldHVybiBlPW51bGwsb31dO2E8bzthKyspaWYocj13LnJlbGF0aXZlW3RbYV0udHlwZV0paD1bXyhkKGgpLHIpXTtlbHNle2lmKHI9dy5maWx0ZXJbdFthXS50eXBlXS5hcHBseShudWxsLHRbYV0ubWF0Y2hlcykscltGXSl7Zm9yKG49KythO248byYmIXcucmVsYXRpdmVbdFtuXS50eXBlXTtuKyspO3JldHVybiBnKGE+MSYmZChoKSxhPjEmJnAodC5zbGljZSgwLGEtMSkuY29uY2F0KHt2YWx1ZToiICI9PT10W2EtMl0udHlwZT8iKiI6IiJ9KSkucmVwbGFjZShhdCwiJDEiKSxyLGE8biYmeSh0LnNsaWNlKGEsbikpLG48byYmeSh0PXQuc2xpY2UobikpLG48byYmcCh0KSl9aC5wdXNoKHIpfXJldHVybiBkKGgpfWZ1bmN0aW9uIHYodCxyKXt2YXIgbz1yLmxlbmd0aD4wLGk9dC5sZW5ndGg+MCxzPWZ1bmN0aW9uKG4scyxhLGwsdSl7dmFyIGgsYyxwLF89MCxkPSIwIixmPW4mJltdLGc9W10seT16LHY9bnx8aSYmdy5maW5kLlRBRygiKiIsdSksYj1MKz1udWxsPT15PzE6TWF0aC5yYW5kb20oKXx8LjEseD12Lmxlbmd0aDtmb3IodSYmKHo9cz09PUN8fHN8fHUpO2QhPT14JiZudWxsIT0oaD12W2RdKTtkKyspe2lmKGkmJmgpe2ZvcihjPTAsc3x8aC5vd25lckRvY3VtZW50PT09Q3x8KEEoaCksYT0hTyk7cD10W2MrK107KWlmKHAoaCxzfHxDLGEpKXtsLnB1c2goaCk7YnJlYWt9dSYmKEw9Yil9byYmKChoPSFwJiZoKSYmXy0tLG4mJmYucHVzaChoKSl9aWYoXys9ZCxvJiZkIT09Xyl7Zm9yKGM9MDtwPXJbYysrXTspcChmLGcscyxhKTtpZihuKXtpZihfPjApZm9yKDtkLS07KWZbZF18fGdbZF18fChnW2RdPUouY2FsbChsKSk7Zz1tKGcpfUsuYXBwbHkobCxnKSx1JiYhbiYmZy5sZW5ndGg+MCYmXytyLmxlbmd0aD4xJiZlLnVuaXF1ZVNvcnQobCl9cmV0dXJuIHUmJihMPWIsej15KSxmfTtyZXR1cm4gbz9uKHMpOnN9dmFyIGIseCx3LE0sayxqLFQsUyx6LFAsRSxBLEMsTixPLHEsRCxJLFIsRj0ic2l6emxlIisxKm5ldyBEYXRlLEI9dC5kb2N1bWVudCxMPTAsRz0wLFY9cigpLFU9cigpLFk9cigpLEg9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdD09PWUmJihFPSEwKSwwfSxYPTE8PDMxLCQ9e30uaGFzT3duUHJvcGVydHksVz1bXSxKPVcucG9wLFE9Vy5wdXNoLEs9Vy5wdXNoLFo9Vy5zbGljZSx0dD1mdW5jdGlvbih0LGUpe2Zvcih2YXIgcj0wLG49dC5sZW5ndGg7cjxuO3IrKylpZih0W3JdPT09ZSlyZXR1cm4gcjtyZXR1cm4tMX0sZXQ9ImNoZWNrZWR8c2VsZWN0ZWR8YXN5bmN8YXV0b2ZvY3VzfGF1dG9wbGF5fGNvbnRyb2xzfGRlZmVyfGRpc2FibGVkfGhpZGRlbnxpc21hcHxsb29wfG11bHRpcGxlfG9wZW58cmVhZG9ubHl8cmVxdWlyZWR8c2NvcGVkIixydD0iW1xceDIwXFx0XFxyXFxuXFxmXSIsbnQ9Iig/OlxcXFwufFtcXHctXXxbXlxceDAwLVxceGEwXSkrIixvdD0iXFxbIitydCsiKigiK250KyIpKD86IitydCsiKihbKl4kfCF+XT89KSIrcnQrIiooPzonKCg/OlxcXFwufFteXFxcXCddKSopJ3xcIigoPzpcXFxcLnxbXlxcXFxcIl0pKilcInwoIitudCsiKSl8KSIrcnQrIipcXF0iLGl0PSI6KCIrbnQrIikoPzpcXCgoKCcoKD86XFxcXC58W15cXFxcJ10pKiknfFwiKCg/OlxcXFwufFteXFxcXFwiXSkqKVwiKXwoKD86XFxcXC58W15cXFxcKClbXFxdXXwiK290KyIpKil8LiopXFwpfCkiLHN0PW5ldyBSZWdFeHAocnQrIisiLCJnIiksYXQ9bmV3IFJlZ0V4cCgiXiIrcnQrIit8KCg/Ol58W15cXFxcXSkoPzpcXFxcLikqKSIrcnQrIiskIiwiZyIpLGx0PW5ldyBSZWdFeHAoIl4iK3J0KyIqLCIrcnQrIioiKSx1dD1uZXcgUmVnRXhwKCJeIitydCsiKihbPit+XXwiK3J0KyIpIitydCsiKiIpLGh0PW5ldyBSZWdFeHAoIj0iK3J0KyIqKFteXFxdJ1wiXSo/KSIrcnQrIipcXF0iLCJnIiksY3Q9bmV3IFJlZ0V4cChpdCkscHQ9bmV3IFJlZ0V4cCgiXiIrbnQrIiQiKSxfdD17SUQ6bmV3IFJlZ0V4cCgiXiMoIitudCsiKSIpLENMQVNTOm5ldyBSZWdFeHAoIl5cXC4oIitudCsiKSIpLFRBRzpuZXcgUmVnRXhwKCJeKCIrbnQrInxbKl0pIiksQVRUUjpuZXcgUmVnRXhwKCJeIitvdCksUFNFVURPOm5ldyBSZWdFeHAoIl4iK2l0KSxDSElMRDpuZXcgUmVnRXhwKCJeOihvbmx5fGZpcnN0fGxhc3R8bnRofG50aC1sYXN0KS0oY2hpbGR8b2YtdHlwZSkoPzpcXCgiK3J0KyIqKGV2ZW58b2RkfCgoWystXXwpKFxcZCopbnwpIitydCsiKig/OihbKy1dfCkiK3J0KyIqKFxcZCspfCkpIitydCsiKlxcKXwpIiwiaSIpLGJvb2w6bmV3IFJlZ0V4cCgiXig/OiIrZXQrIikkIiwiaSIpLG5lZWRzQ29udGV4dDpuZXcgUmVnRXhwKCJeIitydCsiKls+K35dfDooZXZlbnxvZGR8ZXF8Z3R8bHR8bnRofGZpcnN0fGxhc3QpKD86XFwoIitydCsiKigoPzotXFxkKT9cXGQqKSIrcnQrIipcXCl8KSg/PVteLV18JCkiLCJpIil9LGR0PS9eKD86aW5wdXR8c2VsZWN0fHRleHRhcmVhfGJ1dHRvbikkL2ksZnQ9L15oXGQkL2ksbXQ9L15bXntdK1x7XHMqXFtuYXRpdmUgXHcvLGd0PS9eKD86IyhbXHctXSspfChcdyspfFwuKFtcdy1dKykpJC8seXQ9L1srfl0vLHZ0PS8nfFxcL2csYnQ9bmV3IFJlZ0V4cCgiXFxcXChbXFxkYS1mXXsxLDZ9IitydCsiP3woIitydCsiKXwuKSIsImlnIikseHQ9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPSIweCIrZS02NTUzNjtyZXR1cm4gbiE9PW58fHI/ZTpuPDA/U3RyaW5nLmZyb21DaGFyQ29kZShuKzY1NTM2KTpTdHJpbmcuZnJvbUNoYXJDb2RlKG4+PjEwfDU1Mjk2LDEwMjMmbnw1NjMyMCl9LHd0PWZ1bmN0aW9uKCl7QSgpfTt0cnl7Sy5hcHBseShXPVouY2FsbChCLmNoaWxkTm9kZXMpLEIuY2hpbGROb2RlcyksV1tCLmNoaWxkTm9kZXMubGVuZ3RoXS5ub2RlVHlwZX1jYXRjaChNdCl7Sz17YXBwbHk6Vy5sZW5ndGg/ZnVuY3Rpb24odCxlKXtRLmFwcGx5KHQsWi5jYWxsKGUpKX06ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9dC5sZW5ndGgsbj0wO3RbcisrXT1lW24rK107KTt0Lmxlbmd0aD1yLTF9fX14PWUuc3VwcG9ydD17fSxrPWUuaXNYTUw9ZnVuY3Rpb24odCl7dmFyIGU9dCYmKHQub3duZXJEb2N1bWVudHx8dCkuZG9jdW1lbnRFbGVtZW50O3JldHVybiEhZSYmIkhUTUwiIT09ZS5ub2RlTmFtZX0sQT1lLnNldERvY3VtZW50PWZ1bmN0aW9uKHQpe3ZhciBlLHIsbj10P3Qub3duZXJEb2N1bWVudHx8dDpCO3JldHVybiBuIT09QyYmOT09PW4ubm9kZVR5cGUmJm4uZG9jdW1lbnRFbGVtZW50PyhDPW4sTj1DLmRvY3VtZW50RWxlbWVudCxPPSFrKEMpLChyPUMuZGVmYXVsdFZpZXcpJiZyLnRvcCE9PXImJihyLmFkZEV2ZW50TGlzdGVuZXI/ci5hZGRFdmVudExpc3RlbmVyKCJ1bmxvYWQiLHd0LCExKTpyLmF0dGFjaEV2ZW50JiZyLmF0dGFjaEV2ZW50KCJvbnVubG9hZCIsd3QpKSx4LmF0dHJpYnV0ZXM9byhmdW5jdGlvbih0KXtyZXR1cm4gdC5jbGFzc05hbWU9ImkiLCF0LmdldEF0dHJpYnV0ZSgiY2xhc3NOYW1lIil9KSx4LmdldEVsZW1lbnRzQnlUYWdOYW1lPW8oZnVuY3Rpb24odCl7cmV0dXJuIHQuYXBwZW5kQ2hpbGQoQy5jcmVhdGVDb21tZW50KCIiKSksIXQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIioiKS5sZW5ndGh9KSx4LmdldEVsZW1lbnRzQnlDbGFzc05hbWU9bXQudGVzdChDLmdldEVsZW1lbnRzQnlDbGFzc05hbWUpLHguZ2V0QnlJZD1vKGZ1bmN0aW9uKHQpe3JldHVybiBOLmFwcGVuZENoaWxkKHQpLmlkPUYsIUMuZ2V0RWxlbWVudHNCeU5hbWV8fCFDLmdldEVsZW1lbnRzQnlOYW1lKEYpLmxlbmd0aH0pLHguZ2V0QnlJZD8ody5maW5kLklEPWZ1bmN0aW9uKHQsZSl7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiBlLmdldEVsZW1lbnRCeUlkJiZPKXt2YXIgcj1lLmdldEVsZW1lbnRCeUlkKHQpO3JldHVybiByP1tyXTpbXX19LHcuZmlsdGVyLklEPWZ1bmN0aW9uKHQpe3ZhciBlPXQucmVwbGFjZShidCx4dCk7cmV0dXJuIGZ1bmN0aW9uKHQpe3JldHVybiB0LmdldEF0dHJpYnV0ZSgiaWQiKT09PWV9fSk6KGRlbGV0ZSB3LmZpbmQuSUQsdy5maWx0ZXIuSUQ9ZnVuY3Rpb24odCl7dmFyIGU9dC5yZXBsYWNlKGJ0LHh0KTtyZXR1cm4gZnVuY3Rpb24odCl7dmFyIHI9InVuZGVmaW5lZCIhPXR5cGVvZiB0LmdldEF0dHJpYnV0ZU5vZGUmJnQuZ2V0QXR0cmlidXRlTm9kZSgiaWQiKTtyZXR1cm4gciYmci52YWx1ZT09PWV9fSksdy5maW5kLlRBRz14LmdldEVsZW1lbnRzQnlUYWdOYW1lP2Z1bmN0aW9uKHQsZSl7cmV0dXJuInVuZGVmaW5lZCIhPXR5cGVvZiBlLmdldEVsZW1lbnRzQnlUYWdOYW1lP2UuZ2V0RWxlbWVudHNCeVRhZ05hbWUodCk6eC5xc2E/ZS5xdWVyeVNlbGVjdG9yQWxsKHQpOnZvaWQgMH06ZnVuY3Rpb24odCxlKXt2YXIgcixuPVtdLG89MCxpPWUuZ2V0RWxlbWVudHNCeVRhZ05hbWUodCk7aWYoIioiPT09dCl7Zm9yKDtyPWlbbysrXTspMT09PXIubm9kZVR5cGUmJm4ucHVzaChyKTtyZXR1cm4gbn1yZXR1cm4gaX0sdy5maW5kLkNMQVNTPXguZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSYmZnVuY3Rpb24odCxlKXtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGUuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSYmTylyZXR1cm4gZS5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKHQpfSxEPVtdLHE9W10sKHgucXNhPW10LnRlc3QoQy5xdWVyeVNlbGVjdG9yQWxsKSkmJihvKGZ1bmN0aW9uKHQpe04uYXBwZW5kQ2hpbGQodCkuaW5uZXJIVE1MPSI8YSBpZD0nIitGKyInPjwvYT48c2VsZWN0IGlkPSciK0YrIi1cclxcJyBtc2FsbG93Y2FwdHVyZT0nJz48b3B0aW9uIHNlbGVjdGVkPScnPjwvb3B0aW9uPjwvc2VsZWN0PiIsdC5xdWVyeVNlbGVjdG9yQWxsKCJbbXNhbGxvd2NhcHR1cmVePScnXSIpLmxlbmd0aCYmcS5wdXNoKCJbKl4kXT0iK3J0KyIqKD86Jyd8XCJcIikiKSx0LnF1ZXJ5U2VsZWN0b3JBbGwoIltzZWxlY3RlZF0iKS5sZW5ndGh8fHEucHVzaCgiXFxbIitydCsiKig/OnZhbHVlfCIrZXQrIikiKSx0LnF1ZXJ5U2VsZWN0b3JBbGwoIltpZH49IitGKyItXSIpLmxlbmd0aHx8cS5wdXNoKCJ+PSIpLHQucXVlcnlTZWxlY3RvckFsbCgiOmNoZWNrZWQiKS5sZW5ndGh8fHEucHVzaCgiOmNoZWNrZWQiKSx0LnF1ZXJ5U2VsZWN0b3JBbGwoImEjIitGKyIrKiIpLmxlbmd0aHx8cS5wdXNoKCIuIy4rWyt+XSIpfSksbyhmdW5jdGlvbih0KXt2YXIgZT1DLmNyZWF0ZUVsZW1lbnQoImlucHV0Iik7ZS5zZXRBdHRyaWJ1dGUoInR5cGUiLCJoaWRkZW4iKSx0LmFwcGVuZENoaWxkKGUpLnNldEF0dHJpYnV0ZSgibmFtZSIsIkQiKSx0LnF1ZXJ5U2VsZWN0b3JBbGwoIltuYW1lPWRdIikubGVuZ3RoJiZxLnB1c2goIm5hbWUiK3J0KyIqWypeJHwhfl0/PSIpLHQucXVlcnlTZWxlY3RvckFsbCgiOmVuYWJsZWQiKS5sZW5ndGh8fHEucHVzaCgiOmVuYWJsZWQiLCI6ZGlzYWJsZWQiKSx0LnF1ZXJ5U2VsZWN0b3JBbGwoIiosOngiKSxxLnB1c2goIiwuKjoiKX0pKSwoeC5tYXRjaGVzU2VsZWN0b3I9bXQudGVzdChJPU4ubWF0Y2hlc3x8Ti53ZWJraXRNYXRjaGVzU2VsZWN0b3J8fE4ubW96TWF0Y2hlc1NlbGVjdG9yfHxOLm9NYXRjaGVzU2VsZWN0b3J8fE4ubXNNYXRjaGVzU2VsZWN0b3IpKSYmbyhmdW5jdGlvbih0KXt4LmRpc2Nvbm5lY3RlZE1hdGNoPUkuY2FsbCh0LCJkaXYiKSxJLmNhbGwodCwiW3MhPScnXTp4IiksRC5wdXNoKCIhPSIsaXQpfSkscT1xLmxlbmd0aCYmbmV3IFJlZ0V4cChxLmpvaW4oInwiKSksRD1ELmxlbmd0aCYmbmV3IFJlZ0V4cChELmpvaW4oInwiKSksZT1tdC50ZXN0KE4uY29tcGFyZURvY3VtZW50UG9zaXRpb24pLFI9ZXx8bXQudGVzdChOLmNvbnRhaW5zKT9mdW5jdGlvbih0LGUpe3ZhciByPTk9PT10Lm5vZGVUeXBlP3QuZG9jdW1lbnRFbGVtZW50OnQsbj1lJiZlLnBhcmVudE5vZGU7cmV0dXJuIHQ9PT1ufHwhKCFufHwxIT09bi5ub2RlVHlwZXx8IShyLmNvbnRhaW5zP3IuY29udGFpbnMobik6dC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiYmMTYmdC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihuKSkpfTpmdW5jdGlvbih0LGUpe2lmKGUpZm9yKDtlPWUucGFyZW50Tm9kZTspaWYoZT09PXQpcmV0dXJuITA7cmV0dXJuITF9LEg9ZT9mdW5jdGlvbih0LGUpe2lmKHQ9PT1lKXJldHVybiBFPSEwLDA7dmFyIHI9IXQuY29tcGFyZURvY3VtZW50UG9zaXRpb24tIWUuY29tcGFyZURvY3VtZW50UG9zaXRpb247cmV0dXJuIHI/cjoocj0odC5vd25lckRvY3VtZW50fHx0KT09PShlLm93bmVyRG9jdW1lbnR8fGUpP3QuY29tcGFyZURvY3VtZW50UG9zaXRpb24oZSk6MSwxJnJ8fCF4LnNvcnREZXRhY2hlZCYmZS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbih0KT09PXI/dD09PUN8fHQub3duZXJEb2N1bWVudD09PUImJlIoQix0KT8tMTplPT09Q3x8ZS5vd25lckRvY3VtZW50PT09QiYmUihCLGUpPzE6UD90dChQLHQpLXR0KFAsZSk6MDo0JnI/LTE6MSl9OmZ1bmN0aW9uKHQsZSl7aWYodD09PWUpcmV0dXJuIEU9ITAsMDt2YXIgcixuPTAsbz10LnBhcmVudE5vZGUsaT1lLnBhcmVudE5vZGUsYT1bdF0sbD1bZV07aWYoIW98fCFpKXJldHVybiB0PT09Qz8tMTplPT09Qz8xOm8/LTE6aT8xOlA/dHQoUCx0KS10dChQLGUpOjA7aWYobz09PWkpcmV0dXJuIHModCxlKTtmb3Iocj10O3I9ci5wYXJlbnROb2RlOylhLnVuc2hpZnQocik7Zm9yKHI9ZTtyPXIucGFyZW50Tm9kZTspbC51bnNoaWZ0KHIpO2Zvcig7YVtuXT09PWxbbl07KW4rKztyZXR1cm4gbj9zKGFbbl0sbFtuXSk6YVtuXT09PUI/LTE6bFtuXT09PUI/MTowfSxDKTpDfSxlLm1hdGNoZXM9ZnVuY3Rpb24odCxyKXtyZXR1cm4gZSh0LG51bGwsbnVsbCxyKX0sZS5tYXRjaGVzU2VsZWN0b3I9ZnVuY3Rpb24odCxyKXtpZigodC5vd25lckRvY3VtZW50fHx0KSE9PUMmJkEodCkscj1yLnJlcGxhY2UoaHQsIj0nJDEnXSIpLHgubWF0Y2hlc1NlbGVjdG9yJiZPJiYhWVtyKyIgIl0mJighRHx8IUQudGVzdChyKSkmJighcXx8IXEudGVzdChyKSkpdHJ5e3ZhciBuPUkuY2FsbCh0LHIpO2lmKG58fHguZGlzY29ubmVjdGVkTWF0Y2h8fHQuZG9jdW1lbnQmJjExIT09dC5kb2N1bWVudC5ub2RlVHlwZSlyZXR1cm4gbn1jYXRjaChvKXt9cmV0dXJuIGUocixDLG51bGwsW3RdKS5sZW5ndGg+MH0sZS5jb250YWlucz1mdW5jdGlvbih0LGUpe3JldHVybih0Lm93bmVyRG9jdW1lbnR8fHQpIT09QyYmQSh0KSxSKHQsZSl9LGUuYXR0cj1mdW5jdGlvbih0LGUpeyh0Lm93bmVyRG9jdW1lbnR8fHQpIT09QyYmQSh0KTt2YXIgcj13LmF0dHJIYW5kbGVbZS50b0xvd2VyQ2FzZSgpXSxuPXImJiQuY2FsbCh3LmF0dHJIYW5kbGUsZS50b0xvd2VyQ2FzZSgpKT9yKHQsZSwhTyk6dm9pZCAwO3JldHVybiB2b2lkIDAhPT1uP246eC5hdHRyaWJ1dGVzfHwhTz90LmdldEF0dHJpYnV0ZShlKToobj10LmdldEF0dHJpYnV0ZU5vZGUoZSkpJiZuLnNwZWNpZmllZD9uLnZhbHVlOm51bGx9LGUuZXJyb3I9ZnVuY3Rpb24odCl7dGhyb3cgbmV3IEVycm9yKCJTeW50YXggZXJyb3IsIHVucmVjb2duaXplZCBleHByZXNzaW9uOiAiK3QpfSxlLnVuaXF1ZVNvcnQ9ZnVuY3Rpb24odCl7dmFyIGUscj1bXSxuPTAsbz0wO2lmKEU9IXguZGV0ZWN0RHVwbGljYXRlcyxQPSF4LnNvcnRTdGFibGUmJnQuc2xpY2UoMCksdC5zb3J0KEgpLEUpe2Zvcig7ZT10W28rK107KWU9PT10W29dJiYobj1yLnB1c2gobykpO2Zvcig7bi0tOyl0LnNwbGljZShyW25dLDEpfXJldHVybiBQPW51bGwsdH0sTT1lLmdldFRleHQ9ZnVuY3Rpb24odCl7dmFyIGUscj0iIixuPTAsbz10Lm5vZGVUeXBlO2lmKG8pe2lmKDE9PT1vfHw5PT09b3x8MTE9PT1vKXtpZigic3RyaW5nIj09dHlwZW9mIHQudGV4dENvbnRlbnQpcmV0dXJuIHQudGV4dENvbnRlbnQ7Zm9yKHQ9dC5maXJzdENoaWxkO3Q7dD10Lm5leHRTaWJsaW5nKXIrPU0odCl9ZWxzZSBpZigzPT09b3x8ND09PW8pcmV0dXJuIHQubm9kZVZhbHVlfWVsc2UgZm9yKDtlPXRbbisrXTspcis9TShlKTtyZXR1cm4gcn0sdz1lLnNlbGVjdG9ycz17Y2FjaGVMZW5ndGg6NTAsY3JlYXRlUHNldWRvOm4sbWF0Y2g6X3QsYXR0ckhhbmRsZTp7fSxmaW5kOnt9LHJlbGF0aXZlOnsiPiI6e2RpcjoicGFyZW50Tm9kZSIsZmlyc3Q6ITB9LCIgIjp7ZGlyOiJwYXJlbnROb2RlIn0sIisiOntkaXI6InByZXZpb3VzU2libGluZyIsZmlyc3Q6ITB9LCJ+Ijp7ZGlyOiJwcmV2aW91c1NpYmxpbmcifX0scHJlRmlsdGVyOntBVFRSOmZ1bmN0aW9uKHQpe3JldHVybiB0WzFdPXRbMV0ucmVwbGFjZShidCx4dCksdFszXT0odFszXXx8dFs0XXx8dFs1XXx8IiIpLnJlcGxhY2UoYnQseHQpLCJ+PSI9PT10WzJdJiYodFszXT0iICIrdFszXSsiICIpLHQuc2xpY2UoMCw0KX0sQ0hJTEQ6ZnVuY3Rpb24odCl7cmV0dXJuIHRbMV09dFsxXS50b0xvd2VyQ2FzZSgpLCJudGgiPT09dFsxXS5zbGljZSgwLDMpPyh0WzNdfHxlLmVycm9yKHRbMF0pLHRbNF09Kyh0WzRdP3RbNV0rKHRbNl18fDEpOjIqKCJldmVuIj09PXRbM118fCJvZGQiPT09dFszXSkpLHRbNV09Kyh0WzddK3RbOF18fCJvZGQiPT09dFszXSkpOnRbM10mJmUuZXJyb3IodFswXSksdH0sUFNFVURPOmZ1bmN0aW9uKHQpe3ZhciBlLHI9IXRbNl0mJnRbMl07cmV0dXJuIF90LkNISUxELnRlc3QodFswXSk/bnVsbDoodFszXT90WzJdPXRbNF18fHRbNV18fCIiOnImJmN0LnRlc3QocikmJihlPWoociwhMCkpJiYoZT1yLmluZGV4T2YoIikiLHIubGVuZ3RoLWUpLXIubGVuZ3RoKSYmKHRbMF09dFswXS5zbGljZSgwLGUpLHRbMl09ci5zbGljZSgwLGUpKSx0LnNsaWNlKDAsMykpfX0sZmlsdGVyOntUQUc6ZnVuY3Rpb24odCl7dmFyIGU9dC5yZXBsYWNlKGJ0LHh0KS50b0xvd2VyQ2FzZSgpO3JldHVybiIqIj09PXQ/ZnVuY3Rpb24oKXtyZXR1cm4hMH06ZnVuY3Rpb24odCl7cmV0dXJuIHQubm9kZU5hbWUmJnQubm9kZU5hbWUudG9Mb3dlckNhc2UoKT09PWV9fSxDTEFTUzpmdW5jdGlvbih0KXt2YXIgZT1WW3QrIiAiXTtyZXR1cm4gZXx8KGU9bmV3IFJlZ0V4cCgiKF58IitydCsiKSIrdCsiKCIrcnQrInwkKSIpKSYmVih0LGZ1bmN0aW9uKHQpe3JldHVybiBlLnRlc3QoInN0cmluZyI9PXR5cGVvZiB0LmNsYXNzTmFtZSYmdC5jbGFzc05hbWV8fCJ1bmRlZmluZWQiIT10eXBlb2YgdC5nZXRBdHRyaWJ1dGUmJnQuZ2V0QXR0cmlidXRlKCJjbGFzcyIpfHwiIil9KX0sQVRUUjpmdW5jdGlvbih0LHIsbil7cmV0dXJuIGZ1bmN0aW9uKG8pe3ZhciBpPWUuYXR0cihvLHQpO3JldHVybiBudWxsPT1pPyIhPSI9PT1yOiFyfHwoaSs9IiIsIj0iPT09cj9pPT09bjoiIT0iPT09cj9pIT09bjoiXj0iPT09cj9uJiYwPT09aS5pbmRleE9mKG4pOiIqPSI9PT1yP24mJmkuaW5kZXhPZihuKT4tMToiJD0iPT09cj9uJiZpLnNsaWNlKC1uLmxlbmd0aCk9PT1uOiJ+PSI9PT1yPygiICIraS5yZXBsYWNlKHN0LCIgIikrIiAiKS5pbmRleE9mKG4pPi0xOiJ8PSI9PT1yJiYoaT09PW58fGkuc2xpY2UoMCxuLmxlbmd0aCsxKT09PW4rIi0iKSl9fSxDSElMRDpmdW5jdGlvbih0LGUscixuLG8pe3ZhciBpPSJudGgiIT09dC5zbGljZSgwLDMpLHM9Imxhc3QiIT09dC5zbGljZSgtNCksYT0ib2YtdHlwZSI9PT1lO3JldHVybiAxPT09biYmMD09PW8/ZnVuY3Rpb24odCl7cmV0dXJuISF0LnBhcmVudE5vZGV9OmZ1bmN0aW9uKGUscixsKXt2YXIgdSxoLGMscCxfLGQsZj1pIT09cz8ibmV4dFNpYmxpbmciOiJwcmV2aW91c1NpYmxpbmciLG09ZS5wYXJlbnROb2RlLGc9YSYmZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpLHk9IWwmJiFhLHY9ITE7aWYobSl7aWYoaSl7Zm9yKDtmOyl7Zm9yKHA9ZTtwPXBbZl07KWlmKGE/cC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpPT09ZzoxPT09cC5ub2RlVHlwZSlyZXR1cm4hMTtkPWY9Im9ubHkiPT09dCYmIWQmJiJuZXh0U2libGluZyJ9cmV0dXJuITB9aWYoZD1bcz9tLmZpcnN0Q2hpbGQ6bS5sYXN0Q2hpbGRdLHMmJnkpe2ZvcihwPW0sYz1wW0ZdfHwocFtGXT17fSksaD1jW3AudW5pcXVlSURdfHwoY1twLnVuaXF1ZUlEXT17fSksdT1oW3RdfHxbXSxfPXVbMF09PT1MJiZ1WzFdLHY9XyYmdVsyXSxwPV8mJm0uY2hpbGROb2Rlc1tfXTtwPSsrXyYmcCYmcFtmXXx8KHY9Xz0wKXx8ZC5wb3AoKTspaWYoMT09PXAubm9kZVR5cGUmJisrdiYmcD09PWUpe2hbdF09W0wsXyx2XTticmVha319ZWxzZSBpZih5JiYocD1lLGM9cFtGXXx8KHBbRl09e30pLGg9Y1twLnVuaXF1ZUlEXXx8KGNbcC51bmlxdWVJRF09e30pLHU9aFt0XXx8W10sXz11WzBdPT09TCYmdVsxXSx2PV8pLHY9PT0hMSlmb3IoOyhwPSsrXyYmcCYmcFtmXXx8KHY9Xz0wKXx8ZC5wb3AoKSkmJigoYT9wLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkhPT1nOjEhPT1wLm5vZGVUeXBlKXx8ISsrdnx8KHkmJihjPXBbRl18fChwW0ZdPXt9KSxoPWNbcC51bmlxdWVJRF18fChjW3AudW5pcXVlSURdPXt9KSxoW3RdPVtMLHZdKSxwIT09ZSkpOyk7cmV0dXJuIHYtPW8sdj09PW58fHYlbj09PTAmJnYvbj49MH19fSxQU0VVRE86ZnVuY3Rpb24odCxyKXt2YXIgbyxpPXcucHNldWRvc1t0XXx8dy5zZXRGaWx0ZXJzW3QudG9Mb3dlckNhc2UoKV18fGUuZXJyb3IoInVuc3VwcG9ydGVkIHBzZXVkbzogIit0KTtyZXR1cm4gaVtGXT9pKHIpOmkubGVuZ3RoPjE/KG89W3QsdCwiIixyXSx3LnNldEZpbHRlcnMuaGFzT3duUHJvcGVydHkodC50b0xvd2VyQ2FzZSgpKT9uKGZ1bmN0aW9uKHQsZSl7Zm9yKHZhciBuLG89aSh0LHIpLHM9by5sZW5ndGg7cy0tOyluPXR0KHQsb1tzXSksdFtuXT0hKGVbbl09b1tzXSl9KTpmdW5jdGlvbih0KXtyZXR1cm4gaSh0LDAsbyl9KTppfX0scHNldWRvczp7bm90Om4oZnVuY3Rpb24odCl7dmFyIGU9W10scj1bXSxvPVQodC5yZXBsYWNlKGF0LCIkMSIpKTtyZXR1cm4gb1tGXT9uKGZ1bmN0aW9uKHQsZSxyLG4pe2Zvcih2YXIgaSxzPW8odCxudWxsLG4sW10pLGE9dC5sZW5ndGg7YS0tOykoaT1zW2FdKSYmKHRbYV09IShlW2FdPWkpKX0pOmZ1bmN0aW9uKHQsbixpKXtyZXR1cm4gZVswXT10LG8oZSxudWxsLGksciksZVswXT1udWxsLCFyLnBvcCgpfX0pLGhhczpuKGZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbihyKXtyZXR1cm4gZSh0LHIpLmxlbmd0aD4wfX0pLGNvbnRhaW5zOm4oZnVuY3Rpb24odCl7cmV0dXJuIHQ9dC5yZXBsYWNlKGJ0LHh0KSxmdW5jdGlvbihlKXtyZXR1cm4oZS50ZXh0Q29udGVudHx8ZS5pbm5lclRleHR8fE0oZSkpLmluZGV4T2YodCk+LTF9fSksbGFuZzpuKGZ1bmN0aW9uKHQpe3JldHVybiBwdC50ZXN0KHR8fCIiKXx8ZS5lcnJvcigidW5zdXBwb3J0ZWQgbGFuZzogIit0KSx0PXQucmVwbGFjZShidCx4dCkudG9Mb3dlckNhc2UoKSxmdW5jdGlvbihlKXt2YXIgcjtkbyBpZihyPU8/ZS5sYW5nOmUuZ2V0QXR0cmlidXRlKCJ4bWw6bGFuZyIpfHxlLmdldEF0dHJpYnV0ZSgibGFuZyIpKXJldHVybiByPXIudG9Mb3dlckNhc2UoKSxyPT09dHx8MD09PXIuaW5kZXhPZih0KyItIik7d2hpbGUoKGU9ZS5wYXJlbnROb2RlKSYmMT09PWUubm9kZVR5cGUpO3JldHVybiExfX0pLHRhcmdldDpmdW5jdGlvbihlKXt2YXIgcj10LmxvY2F0aW9uJiZ0LmxvY2F0aW9uLmhhc2g7cmV0dXJuIHImJnIuc2xpY2UoMSk9PT1lLmlkfSxyb290OmZ1bmN0aW9uKHQpe3JldHVybiB0PT09Tn0sZm9jdXM6ZnVuY3Rpb24odCl7cmV0dXJuIHQ9PT1DLmFjdGl2ZUVsZW1lbnQmJighQy5oYXNGb2N1c3x8Qy5oYXNGb2N1cygpKSYmISEodC50eXBlfHx0LmhyZWZ8fH50LnRhYkluZGV4KX0sZW5hYmxlZDpmdW5jdGlvbih0KXtyZXR1cm4gdC5kaXNhYmxlZD09PSExfSxkaXNhYmxlZDpmdW5jdGlvbih0KXtyZXR1cm4gdC5kaXNhYmxlZD09PSEwfSxjaGVja2VkOmZ1bmN0aW9uKHQpe3ZhciBlPXQubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtyZXR1cm4iaW5wdXQiPT09ZSYmISF0LmNoZWNrZWR8fCJvcHRpb24iPT09ZSYmISF0LnNlbGVjdGVkfSxzZWxlY3RlZDpmdW5jdGlvbih0KXtyZXR1cm4gdC5wYXJlbnROb2RlJiZ0LnBhcmVudE5vZGUuc2VsZWN0ZWRJbmRleCx0LnNlbGVjdGVkPT09ITB9LGVtcHR5OmZ1bmN0aW9uKHQpe2Zvcih0PXQuZmlyc3RDaGlsZDt0O3Q9dC5uZXh0U2libGluZylpZih0Lm5vZGVUeXBlPDYpcmV0dXJuITE7cmV0dXJuITB9LHBhcmVudDpmdW5jdGlvbih0KXtyZXR1cm4hdy5wc2V1ZG9zLmVtcHR5KHQpfSxoZWFkZXI6ZnVuY3Rpb24odCl7cmV0dXJuIGZ0LnRlc3QodC5ub2RlTmFtZSl9LGlucHV0OmZ1bmN0aW9uKHQpe3JldHVybiBkdC50ZXN0KHQubm9kZU5hbWUpfSxidXR0b246ZnVuY3Rpb24odCl7dmFyIGU9dC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO3JldHVybiJpbnB1dCI9PT1lJiYiYnV0dG9uIj09PXQudHlwZXx8ImJ1dHRvbiI9PT1lfSx0ZXh0OmZ1bmN0aW9uKHQpe3ZhciBlO3JldHVybiJpbnB1dCI9PT10Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkmJiJ0ZXh0Ij09PXQudHlwZSYmKG51bGw9PShlPXQuZ2V0QXR0cmlidXRlKCJ0eXBlIikpfHwidGV4dCI9PT1lLnRvTG93ZXJDYXNlKCkpfSxmaXJzdDp1KGZ1bmN0aW9uKCl7cmV0dXJuWzBdfSksbGFzdDp1KGZ1bmN0aW9uKHQsZSl7cmV0dXJuW2UtMV19KSxlcTp1KGZ1bmN0aW9uKHQsZSxyKXtyZXR1cm5bcjwwP3IrZTpyXX0pLGV2ZW46dShmdW5jdGlvbih0LGUpe2Zvcih2YXIgcj0wO3I8ZTtyKz0yKXQucHVzaChyKTtyZXR1cm4gdH0pLG9kZDp1KGZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPTE7cjxlO3IrPTIpdC5wdXNoKHIpO3JldHVybiB0fSksbHQ6dShmdW5jdGlvbih0LGUscil7Zm9yKHZhciBuPXI8MD9yK2U6cjstLW4+PTA7KXQucHVzaChuKTtyZXR1cm4gdH0pLGd0OnUoZnVuY3Rpb24odCxlLHIpe2Zvcih2YXIgbj1yPDA/citlOnI7KytuPGU7KXQucHVzaChuKTtyZXR1cm4gdH0pfX0sdy5wc2V1ZG9zLm50aD13LnBzZXVkb3MuZXE7Zm9yKGIgaW57cmFkaW86ITAsY2hlY2tib3g6ITAsZmlsZTohMCxwYXNzd29yZDohMCxpbWFnZTohMH0pdy5wc2V1ZG9zW2JdPWEoYik7Zm9yKGIgaW57c3VibWl0OiEwLHJlc2V0OiEwfSl3LnBzZXVkb3NbYl09bChiKTtyZXR1cm4gYy5wcm90b3R5cGU9dy5maWx0ZXJzPXcucHNldWRvcyx3LnNldEZpbHRlcnM9bmV3IGMsaj1lLnRva2VuaXplPWZ1bmN0aW9uKHQscil7dmFyIG4sbyxpLHMsYSxsLHUsaD1VW3QrIiAiXTtpZihoKXJldHVybiByPzA6aC5zbGljZSgwKTtmb3IoYT10LGw9W10sdT13LnByZUZpbHRlcjthOyl7biYmIShvPWx0LmV4ZWMoYSkpfHwobyYmKGE9YS5zbGljZShvWzBdLmxlbmd0aCl8fGEpLGwucHVzaChpPVtdKSksbj0hMSwobz11dC5leGVjKGEpKSYmKG49by5zaGlmdCgpLGkucHVzaCh7dmFsdWU6bix0eXBlOm9bMF0ucmVwbGFjZShhdCwiICIpfSksYT1hLnNsaWNlKG4ubGVuZ3RoKSk7Zm9yKHMgaW4gdy5maWx0ZXIpIShvPV90W3NdLmV4ZWMoYSkpfHx1W3NdJiYhKG89dVtzXShvKSl8fChuPW8uc2hpZnQoKSxpLnB1c2goe3ZhbHVlOm4sdHlwZTpzLG1hdGNoZXM6b30pLGE9YS5zbGljZShuLmxlbmd0aCkpO2lmKCFuKWJyZWFrfXJldHVybiByP2EubGVuZ3RoOmE/ZS5lcnJvcih0KTpVKHQsbCkuc2xpY2UoMCl9LFQ9ZS5jb21waWxlPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbj1bXSxvPVtdLGk9WVt0KyIgIl07aWYoIWkpe2ZvcihlfHwoZT1qKHQpKSxyPWUubGVuZ3RoO3ItLTspaT15KGVbcl0pLGlbRl0/bi5wdXNoKGkpOm8ucHVzaChpKTtpPVkodCx2KG8sbikpLGkuc2VsZWN0b3I9dH1yZXR1cm4gaX0sUz1lLnNlbGVjdD1mdW5jdGlvbih0LGUscixuKXt2YXIgbyxpLHMsYSxsLHU9ImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQsYz0hbiYmaih0PXUuc2VsZWN0b3J8fHQpO2lmKHI9cnx8W10sMT09PWMubGVuZ3RoKXtpZihpPWNbMF09Y1swXS5zbGljZSgwKSxpLmxlbmd0aD4yJiYiSUQiPT09KHM9aVswXSkudHlwZSYmeC5nZXRCeUlkJiY5PT09ZS5ub2RlVHlwZSYmTyYmdy5yZWxhdGl2ZVtpWzFdLnR5cGVdKXtpZihlPSh3LmZpbmQuSUQocy5tYXRjaGVzWzBdLnJlcGxhY2UoYnQseHQpLGUpfHxbXSlbMF0sIWUpcmV0dXJuIHI7dSYmKGU9ZS5wYXJlbnROb2RlKSx0PXQuc2xpY2UoaS5zaGlmdCgpLnZhbHVlLmxlbmd0aCl9Zm9yKG89X3QubmVlZHNDb250ZXh0LnRlc3QodCk/MDppLmxlbmd0aDtvLS0mJihzPWlbb10sIXcucmVsYXRpdmVbYT1zLnR5cGVdKTspaWYoKGw9dy5maW5kW2FdKSYmKG49bChzLm1hdGNoZXNbMF0ucmVwbGFjZShidCx4dCkseXQudGVzdChpWzBdLnR5cGUpJiZoKGUucGFyZW50Tm9kZSl8fGUpKSl7aWYoaS5zcGxpY2UobywxKSx0PW4ubGVuZ3RoJiZwKGkpLCF0KXJldHVybiBLLmFwcGx5KHIsbikscjticmVha319cmV0dXJuKHV8fFQodCxjKSkobixlLCFPLHIsIWV8fHl0LnRlc3QodCkmJmgoZS5wYXJlbnROb2RlKXx8ZSkscn0seC5zb3J0U3RhYmxlPUYuc3BsaXQoIiIpLnNvcnQoSCkuam9pbigiIik9PT1GLHguZGV0ZWN0RHVwbGljYXRlcz0hIUUsQSgpLHguc29ydERldGFjaGVkPW8oZnVuY3Rpb24odCl7cmV0dXJuIDEmdC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihDLmNyZWF0ZUVsZW1lbnQoImRpdiIpKX0pLG8oZnVuY3Rpb24odCl7cmV0dXJuIHQuaW5uZXJIVE1MPSI8YSBocmVmPScjJz48L2E+IiwiIyI9PT10LmZpcnN0Q2hpbGQuZ2V0QXR0cmlidXRlKCJocmVmIil9KXx8aSgidHlwZXxocmVmfGhlaWdodHx3aWR0aCIsZnVuY3Rpb24odCxlLHIpe2lmKCFyKXJldHVybiB0LmdldEF0dHJpYnV0ZShlLCJ0eXBlIj09PWUudG9Mb3dlckNhc2UoKT8xOjIpfSkseC5hdHRyaWJ1dGVzJiZvKGZ1bmN0aW9uKHQpe3JldHVybiB0LmlubmVySFRNTD0iPGlucHV0Lz4iLHQuZmlyc3RDaGlsZC5zZXRBdHRyaWJ1dGUoInZhbHVlIiwiIiksIiI9PT10LmZpcnN0Q2hpbGQuZ2V0QXR0cmlidXRlKCJ2YWx1ZSIpfSl8fGkoInZhbHVlIixmdW5jdGlvbih0LGUscil7aWYoIXImJiJpbnB1dCI9PT10Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkpcmV0dXJuIHQuZGVmYXVsdFZhbHVlfSksbyhmdW5jdGlvbih0KXtyZXR1cm4gbnVsbD09dC5nZXRBdHRyaWJ1dGUoImRpc2FibGVkIil9KXx8aShldCxmdW5jdGlvbih0LGUscil7dmFyIG47aWYoIXIpcmV0dXJuIHRbZV09PT0hMD9lLnRvTG93ZXJDYXNlKCk6KG49dC5nZXRBdHRyaWJ1dGVOb2RlKGUpKSYmbi5zcGVjaWZpZWQ/bi52YWx1ZTpudWxsfSksZX0oZSk7c3QuZmluZD1jdCxzdC5leHByPWN0LnNlbGVjdG9ycyxzdC5leHByWyI6Il09c3QuZXhwci5wc2V1ZG9zLHN0LnVuaXF1ZVNvcnQ9c3QudW5pcXVlPWN0LnVuaXF1ZVNvcnQsc3QudGV4dD1jdC5nZXRUZXh0LHN0LmlzWE1MRG9jPWN0LmlzWE1MLHN0LmNvbnRhaW5zPWN0LmNvbnRhaW5zO3ZhciBwdD1mdW5jdGlvbih0LGUscil7Zm9yKHZhciBuPVtdLG89dm9pZCAwIT09cjsodD10W2VdKSYmOSE9PXQubm9kZVR5cGU7KWlmKDE9PT10Lm5vZGVUeXBlKXtpZihvJiZzdCh0KS5pcyhyKSlicmVhaztuLnB1c2godCl9cmV0dXJuIG59LF90PWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPVtdO3Q7dD10Lm5leHRTaWJsaW5nKTE9PT10Lm5vZGVUeXBlJiZ0IT09ZSYmci5wdXNoKHQpO3JldHVybiByfSxkdD1zdC5leHByLm1hdGNoLm5lZWRzQ29udGV4dCxmdD0vXjwoW1x3LV0rKVxzKlwvPz4oPzo8XC9cMT58KSQvLG10PS9eLlteOiNcW1wuLF0qJC87c3QuZmlsdGVyPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj1lWzBdO3JldHVybiByJiYodD0iOm5vdCgiK3QrIikiKSwxPT09ZS5sZW5ndGgmJjE9PT1uLm5vZGVUeXBlP3N0LmZpbmQubWF0Y2hlc1NlbGVjdG9yKG4sdCk/W25dOltdOnN0LmZpbmQubWF0Y2hlcyh0LHN0LmdyZXAoZSxmdW5jdGlvbih0KXtyZXR1cm4gMT09PXQubm9kZVR5cGV9KSl9LHN0LmZuLmV4dGVuZCh7ZmluZDpmdW5jdGlvbih0KXt2YXIgZSxyPXRoaXMubGVuZ3RoLG49W10sbz10aGlzO2lmKCJzdHJpbmciIT10eXBlb2YgdClyZXR1cm4gdGhpcy5wdXNoU3RhY2soc3QodCkuZmlsdGVyKGZ1bmN0aW9uKCl7Zm9yKGU9MDtlPHI7ZSsrKWlmKHN0LmNvbnRhaW5zKG9bZV0sdGhpcykpcmV0dXJuITB9KSk7Zm9yKGU9MDtlPHI7ZSsrKXN0LmZpbmQodCxvW2VdLG4pO3JldHVybiBuPXRoaXMucHVzaFN0YWNrKHI+MT9zdC51bmlxdWUobik6biksbi5zZWxlY3Rvcj10aGlzLnNlbGVjdG9yP3RoaXMuc2VsZWN0b3IrIiAiK3Q6dCxufSxmaWx0ZXI6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMucHVzaFN0YWNrKG8odGhpcyx0fHxbXSwhMSkpfSxub3Q6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMucHVzaFN0YWNrKG8odGhpcyx0fHxbXSwhMCkpfSxpczpmdW5jdGlvbih0KXtyZXR1cm4hIW8odGhpcywic3RyaW5nIj09dHlwZW9mIHQmJmR0LnRlc3QodCk/c3QodCk6dHx8W10sITEpLmxlbmd0aH19KTt2YXIgZ3QseXQ9L14oPzpccyooPFtcd1xXXSs+KVtePl0qfCMoW1x3LV0qKSkkLyx2dD1zdC5mbi5pbml0PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvO2lmKCF0KXJldHVybiB0aGlzO2lmKHI9cnx8Z3QsInN0cmluZyI9PXR5cGVvZiB0KXtpZihuPSI8Ij09PXRbMF0mJiI+Ij09PXRbdC5sZW5ndGgtMV0mJnQubGVuZ3RoPj0zP1tudWxsLHQsbnVsbF06eXQuZXhlYyh0KSwhbnx8IW5bMV0mJmUpcmV0dXJuIWV8fGUuanF1ZXJ5PyhlfHxyKS5maW5kKHQpOnRoaXMuY29uc3RydWN0b3IoZSkuZmluZCh0KTtpZihuWzFdKXtpZihlPWUgaW5zdGFuY2VvZiBzdD9lWzBdOmUsc3QubWVyZ2UodGhpcyxzdC5wYXJzZUhUTUwoblsxXSxlJiZlLm5vZGVUeXBlP2Uub3duZXJEb2N1bWVudHx8ZTpKLCEwKSksZnQudGVzdChuWzFdKSYmc3QuaXNQbGFpbk9iamVjdChlKSlmb3IobiBpbiBlKXN0LmlzRnVuY3Rpb24odGhpc1tuXSk/dGhpc1tuXShlW25dKTp0aGlzLmF0dHIobixlW25dKTtyZXR1cm4gdGhpc31yZXR1cm4gbz1KLmdldEVsZW1lbnRCeUlkKG5bMl0pLG8mJm8ucGFyZW50Tm9kZSYmKHRoaXMubGVuZ3RoPTEsdGhpc1swXT1vKSx0aGlzLmNvbnRleHQ9Six0aGlzLnNlbGVjdG9yPXQsdGhpc31yZXR1cm4gdC5ub2RlVHlwZT8odGhpcy5jb250ZXh0PXRoaXNbMF09dCx0aGlzLmxlbmd0aD0xLHRoaXMpOnN0LmlzRnVuY3Rpb24odCk/dm9pZCAwIT09ci5yZWFkeT9yLnJlYWR5KHQpOnQoc3QpOih2b2lkIDAhPT10LnNlbGVjdG9yJiYodGhpcy5zZWxlY3Rvcj10LnNlbGVjdG9yLHRoaXMuY29udGV4dD10LmNvbnRleHQpLHN0Lm1ha2VBcnJheSh0LHRoaXMpKX07dnQucHJvdG90eXBlPXN0LmZuLGd0PXN0KEopO3ZhciBidD0vXig/OnBhcmVudHN8cHJldig/OlVudGlsfEFsbCkpLyx4dD17Y2hpbGRyZW46ITAsY29udGVudHM6ITAsbmV4dDohMCxwcmV2OiEwfTtzdC5mbi5leHRlbmQoe2hhczpmdW5jdGlvbih0KXt2YXIgZT1zdCh0LHRoaXMpLHI9ZS5sZW5ndGg7cmV0dXJuIHRoaXMuZmlsdGVyKGZ1bmN0aW9uKCl7Zm9yKHZhciB0PTA7dDxyO3QrKylpZihzdC5jb250YWlucyh0aGlzLGVbdF0pKXJldHVybiEwfSl9LGNsb3Nlc3Q6ZnVuY3Rpb24odCxlKXtmb3IodmFyIHIsbj0wLG89dGhpcy5sZW5ndGgsaT1bXSxzPWR0LnRlc3QodCl8fCJzdHJpbmciIT10eXBlb2YgdD9zdCh0LGV8fHRoaXMuY29udGV4dCk6MDtuPG87bisrKWZvcihyPXRoaXNbbl07ciYmciE9PWU7cj1yLnBhcmVudE5vZGUpaWYoci5ub2RlVHlwZTwxMSYmKHM/cy5pbmRleChyKT4tMToxPT09ci5ub2RlVHlwZSYmc3QuZmluZC5tYXRjaGVzU2VsZWN0b3Iocix0KSkpe2kucHVzaChyKTticmVha31yZXR1cm4gdGhpcy5wdXNoU3RhY2soaS5sZW5ndGg+MT9zdC51bmlxdWVTb3J0KGkpOmkpfSxpbmRleDpmdW5jdGlvbih0KXtyZXR1cm4gdD8ic3RyaW5nIj09dHlwZW9mIHQ/dHQuY2FsbChzdCh0KSx0aGlzWzBdKTp0dC5jYWxsKHRoaXMsdC5qcXVlcnk/dFswXTp0KTp0aGlzWzBdJiZ0aGlzWzBdLnBhcmVudE5vZGU/dGhpcy5maXJzdCgpLnByZXZBbGwoKS5sZW5ndGg6LTF9LGFkZDpmdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLnB1c2hTdGFjayhzdC51bmlxdWVTb3J0KHN0Lm1lcmdlKHRoaXMuZ2V0KCksc3QodCxlKSkpKX0sYWRkQmFjazpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5hZGQobnVsbD09dD90aGlzLnByZXZPYmplY3Q6dGhpcy5wcmV2T2JqZWN0LmZpbHRlcih0KSl9fSksc3QuZWFjaCh7cGFyZW50OmZ1bmN0aW9uKHQpe3ZhciBlPXQucGFyZW50Tm9kZTtyZXR1cm4gZSYmMTEhPT1lLm5vZGVUeXBlP2U6bnVsbH0scGFyZW50czpmdW5jdGlvbih0KXtyZXR1cm4gcHQodCwicGFyZW50Tm9kZSIpfSxwYXJlbnRzVW50aWw6ZnVuY3Rpb24odCxlLHIpe3JldHVybiBwdCh0LCJwYXJlbnROb2RlIixyKX0sbmV4dDpmdW5jdGlvbih0KXtyZXR1cm4gaSh0LCJuZXh0U2libGluZyIpfSxwcmV2OmZ1bmN0aW9uKHQpe3JldHVybiBpKHQsInByZXZpb3VzU2libGluZyIpfSxuZXh0QWxsOmZ1bmN0aW9uKHQpe3JldHVybiBwdCh0LCJuZXh0U2libGluZyIpfSxwcmV2QWxsOmZ1bmN0aW9uKHQpe3JldHVybiBwdCh0LCJwcmV2aW91c1NpYmxpbmciKX0sbmV4dFVudGlsOmZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gcHQodCwibmV4dFNpYmxpbmciLHIpfSxwcmV2VW50aWw6ZnVuY3Rpb24odCxlLHIpe3JldHVybiBwdCh0LCJwcmV2aW91c1NpYmxpbmciLHIpfSxzaWJsaW5nczpmdW5jdGlvbih0KXtyZXR1cm4gX3QoKHQucGFyZW50Tm9kZXx8e30pLmZpcnN0Q2hpbGQsdCl9LGNoaWxkcmVuOmZ1bmN0aW9uKHQpe3JldHVybiBfdCh0LmZpcnN0Q2hpbGQpfSxjb250ZW50czpmdW5jdGlvbih0KXtyZXR1cm4gdC5jb250ZW50RG9jdW1lbnR8fHN0Lm1lcmdlKFtdLHQuY2hpbGROb2Rlcyl9fSxmdW5jdGlvbih0LGUpe3N0LmZuW3RdPWZ1bmN0aW9uKHIsbil7dmFyIG89c3QubWFwKHRoaXMsZSxyKTtyZXR1cm4iVW50aWwiIT09dC5zbGljZSgtNSkmJihuPXIpLG4mJiJzdHJpbmciPT10eXBlb2YgbiYmKG89c3QuZmlsdGVyKG4sbykpLHRoaXMubGVuZ3RoPjEmJih4dFt0XXx8c3QudW5pcXVlU29ydChvKSxidC50ZXN0KHQpJiZvLnJldmVyc2UoKSksdGhpcy5wdXNoU3RhY2sobyl9fSk7dmFyIHd0PS9cUysvZztzdC5DYWxsYmFja3M9ZnVuY3Rpb24odCl7dD0ic3RyaW5nIj09dHlwZW9mIHQ/cyh0KTpzdC5leHRlbmQoe30sdCk7dmFyIGUscixuLG8saT1bXSxhPVtdLGw9LTEsdT1mdW5jdGlvbigpe2ZvcihvPXQub25jZSxuPWU9ITA7YS5sZW5ndGg7bD0tMSlmb3Iocj1hLnNoaWZ0KCk7KytsPGkubGVuZ3RoOylpW2xdLmFwcGx5KHJbMF0sclsxXSk9PT0hMSYmdC5zdG9wT25GYWxzZSYmKGw9aS5sZW5ndGgscj0hMSk7dC5tZW1vcnl8fChyPSExKSxlPSExLG8mJihpPXI/W106IiIpfSxoPXthZGQ6ZnVuY3Rpb24oKXtyZXR1cm4gaSYmKHImJiFlJiYobD1pLmxlbmd0aC0xLGEucHVzaChyKSksZnVuY3Rpb24gbihlKXtzdC5lYWNoKGUsZnVuY3Rpb24oZSxyKXtzdC5pc0Z1bmN0aW9uKHIpP3QudW5pcXVlJiZoLmhhcyhyKXx8aS5wdXNoKHIpOnImJnIubGVuZ3RoJiYic3RyaW5nIiE9PXN0LnR5cGUocikmJm4ocil9KX0oYXJndW1lbnRzKSxyJiYhZSYmdSgpKSx0aGlzfSxyZW1vdmU6ZnVuY3Rpb24oKXtyZXR1cm4gc3QuZWFjaChhcmd1bWVudHMsZnVuY3Rpb24odCxlKXtmb3IodmFyIHI7KHI9c3QuaW5BcnJheShlLGkscikpPi0xOylpLnNwbGljZShyLDEpLHI8PWwmJmwtLX0pLHRoaXN9LGhhczpmdW5jdGlvbih0KXtyZXR1cm4gdD9zdC5pbkFycmF5KHQsaSk+LTE6aS5sZW5ndGg+MH0sZW1wdHk6ZnVuY3Rpb24oKXtyZXR1cm4gaSYmKGk9W10pLHRoaXN9LGRpc2FibGU6ZnVuY3Rpb24oKXtyZXR1cm4gbz1hPVtdLGk9cj0iIix0aGlzfSxkaXNhYmxlZDpmdW5jdGlvbigpe3JldHVybiFpfSxsb2NrOmZ1bmN0aW9uKCl7cmV0dXJuIG89YT1bXSxyfHwoaT1yPSIiKSx0aGlzfSxsb2NrZWQ6ZnVuY3Rpb24oKXtyZXR1cm4hIW99LGZpcmVXaXRoOmZ1bmN0aW9uKHQscil7cmV0dXJuIG98fChyPXJ8fFtdLHI9W3Qsci5zbGljZT9yLnNsaWNlKCk6cl0sYS5wdXNoKHIpLGV8fHUoKSksdGhpc30sZmlyZTpmdW5jdGlvbigpe3JldHVybiBoLmZpcmVXaXRoKHRoaXMsYXJndW1lbnRzKSx0aGlzfSxmaXJlZDpmdW5jdGlvbigpe3JldHVybiEhbn19O3JldHVybiBofSxzdC5leHRlbmQoe0RlZmVycmVkOmZ1bmN0aW9uKHQpe3ZhciBlPVtbInJlc29sdmUiLCJkb25lIixzdC5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IiksInJlc29sdmVkIl0sWyJyZWplY3QiLCJmYWlsIixzdC5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IiksInJlamVjdGVkIl0sWyJub3RpZnkiLCJwcm9ncmVzcyIsc3QuQ2FsbGJhY2tzKCJtZW1vcnkiKV1dLHI9InBlbmRpbmciLG49e3N0YXRlOmZ1bmN0aW9uKCl7cmV0dXJuIHJ9LGFsd2F5czpmdW5jdGlvbigpe3JldHVybiBvLmRvbmUoYXJndW1lbnRzKS5mYWlsKGFyZ3VtZW50cyksdGhpc30sdGhlbjpmdW5jdGlvbigpe3ZhciB0PWFyZ3VtZW50cztyZXR1cm4gc3QuRGVmZXJyZWQoZnVuY3Rpb24ocil7c3QuZWFjaChlLGZ1bmN0aW9uKGUsaSl7dmFyIHM9c3QuaXNGdW5jdGlvbih0W2VdKSYmdFtlXTtvW2lbMV1dKGZ1bmN0aW9uKCl7dmFyIHQ9cyYmcy5hcHBseSh0aGlzLGFyZ3VtZW50cyk7dCYmc3QuaXNGdW5jdGlvbih0LnByb21pc2UpP3QucHJvbWlzZSgpLnByb2dyZXNzKHIubm90aWZ5KS5kb25lKHIucmVzb2x2ZSkuZmFpbChyLnJlamVjdCk6cltpWzBdKyJXaXRoIl0odGhpcz09PW4/ci5wcm9taXNlKCk6dGhpcyxzP1t0XTphcmd1bWVudHMpfSl9KSx0PW51bGx9KS5wcm9taXNlKCl9LHByb21pc2U6ZnVuY3Rpb24odCl7cmV0dXJuIG51bGwhPXQ/c3QuZXh0ZW5kKHQsbik6bn19LG89e307cmV0dXJuIG4ucGlwZT1uLnRoZW4sc3QuZWFjaChlLGZ1bmN0aW9uKHQsaSl7dmFyIHM9aVsyXSxhPWlbM107bltpWzFdXT1zLmFkZCxhJiZzLmFkZChmdW5jdGlvbigpe3I9YX0sZVsxXnRdWzJdLmRpc2FibGUsZVsyXVsyXS5sb2NrKSxvW2lbMF1dPWZ1bmN0aW9uKCl7cmV0dXJuIG9baVswXSsiV2l0aCJdKHRoaXM9PT1vP246dGhpcyxhcmd1bWVudHMpLHRoaXN9LG9baVswXSsiV2l0aCJdPXMuZmlyZVdpdGh9KSxuLnByb21pc2UobyksdCYmdC5jYWxsKG8sbyksb30sd2hlbjpmdW5jdGlvbih0KXt2YXIgZSxyLG4sbz0wLGk9US5jYWxsKGFyZ3VtZW50cykscz1pLmxlbmd0aCxhPTEhPT1zfHx0JiZzdC5pc0Z1bmN0aW9uKHQucHJvbWlzZSk/czowLGw9MT09PWE/dDpzdC5EZWZlcnJlZCgpLHU9ZnVuY3Rpb24odCxyLG4pe3JldHVybiBmdW5jdGlvbihvKXtyW3RdPXRoaXMsblt0XT1hcmd1bWVudHMubGVuZ3RoPjE/US5jYWxsKGFyZ3VtZW50cyk6byxuPT09ZT9sLm5vdGlmeVdpdGgocixuKTotLWF8fGwucmVzb2x2ZVdpdGgocixuKX19O2lmKHM+MSlmb3IoZT1uZXcgQXJyYXkocykscj1uZXcgQXJyYXkocyksbj1uZXcgQXJyYXkocyk7bzxzO28rKylpW29dJiZzdC5pc0Z1bmN0aW9uKGlbb10ucHJvbWlzZSk/aVtvXS5wcm9taXNlKCkucHJvZ3Jlc3ModShvLHIsZSkpLmRvbmUodShvLG4saSkpLmZhaWwobC5yZWplY3QpOi0tYTtyZXR1cm4gYXx8bC5yZXNvbHZlV2l0aChuLGkpLGwucHJvbWlzZSgpfX0pO3ZhciBNdDtzdC5mbi5yZWFkeT1mdW5jdGlvbih0KXtyZXR1cm4gc3QucmVhZHkucHJvbWlzZSgpLmRvbmUodCksdGhpc30sc3QuZXh0ZW5kKHtpc1JlYWR5OiExLHJlYWR5V2FpdDoxLGhvbGRSZWFkeTpmdW5jdGlvbih0KXt0P3N0LnJlYWR5V2FpdCsrOnN0LnJlYWR5KCEwKX0scmVhZHk6ZnVuY3Rpb24odCl7KHQ9PT0hMD8tLXN0LnJlYWR5V2FpdDpzdC5pc1JlYWR5KXx8KHN0LmlzUmVhZHk9ITAsdCE9PSEwJiYtLXN0LnJlYWR5V2FpdD4wfHwoTXQucmVzb2x2ZVdpdGgoSixbc3RdKSxzdC5mbi50cmlnZ2VySGFuZGxlciYmKHN0KEopLnRyaWdnZXJIYW5kbGVyKCJyZWFkeSIpLHN0KEopLm9mZigicmVhZHkiKSkpKX19KSxzdC5yZWFkeS5wcm9taXNlPWZ1bmN0aW9uKHQpe3JldHVybiBNdHx8KE10PXN0LkRlZmVycmVkKCksImNvbXBsZXRlIj09PUoucmVhZHlTdGF0ZXx8ImxvYWRpbmciIT09Si5yZWFkeVN0YXRlJiYhSi5kb2N1bWVudEVsZW1lbnQuZG9TY3JvbGw/ZS5zZXRUaW1lb3V0KHN0LnJlYWR5KTooSi5hZGRFdmVudExpc3RlbmVyKCJET01Db250ZW50TG9hZGVkIixhKSxlLmFkZEV2ZW50TGlzdGVuZXIoImxvYWQiLGEpKSksTXQucHJvbWlzZSh0KX0sc3QucmVhZHkucHJvbWlzZSgpO3ZhciBrdD1mdW5jdGlvbih0LGUscixuLG8saSxzKXt2YXIgYT0wLGw9dC5sZW5ndGgsdT1udWxsPT1yO2lmKCJvYmplY3QiPT09c3QudHlwZShyKSl7bz0hMDtmb3IoYSBpbiByKWt0KHQsZSxhLHJbYV0sITAsaSxzKX1lbHNlIGlmKHZvaWQgMCE9PW4mJihvPSEwLHN0LmlzRnVuY3Rpb24obil8fChzPSEwKSx1JiYocz8oZS5jYWxsKHQsbiksZT1udWxsKToodT1lLGU9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB1LmNhbGwoc3QodCkscil9KSksZSkpZm9yKDthPGw7YSsrKWUodFthXSxyLHM/bjpuLmNhbGwodFthXSxhLGUodFthXSxyKSkpO3JldHVybiBvP3Q6dT9lLmNhbGwodCk6bD9lKHRbMF0scik6aX0sanQ9ZnVuY3Rpb24odCl7cmV0dXJuIDE9PT10Lm5vZGVUeXBlfHw5PT09dC5ub2RlVHlwZXx8ISt0Lm5vZGVUeXBlfTtsLnVpZD0xLGwucHJvdG90eXBlPXtyZWdpc3RlcjpmdW5jdGlvbih0LGUpe3ZhciByPWV8fHt9O3JldHVybiB0Lm5vZGVUeXBlP3RbdGhpcy5leHBhbmRvXT1yOk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LHRoaXMuZXhwYW5kbyx7dmFsdWU6cix3cml0YWJsZTohMCxjb25maWd1cmFibGU6ITB9KSx0W3RoaXMuZXhwYW5kb119LGNhY2hlOmZ1bmN0aW9uKHQpe2lmKCFqdCh0KSlyZXR1cm57fTt2YXIgZT10W3RoaXMuZXhwYW5kb107cmV0dXJuIGV8fChlPXt9LGp0KHQpJiYodC5ub2RlVHlwZT90W3RoaXMuZXhwYW5kb109ZTpPYmplY3QuZGVmaW5lUHJvcGVydHkodCx0aGlzLmV4cGFuZG8se3ZhbHVlOmUsY29uZmlndXJhYmxlOiEwfSkpKSxlfSxzZXQ6ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG89dGhpcy5jYWNoZSh0KTtpZigic3RyaW5nIj09dHlwZW9mIGUpb1tlXT1yO2Vsc2UgZm9yKG4gaW4gZSlvW25dPWVbbl07cmV0dXJuIG99LGdldDpmdW5jdGlvbih0LGUpe3JldHVybiB2b2lkIDA9PT1lP3RoaXMuY2FjaGUodCk6dFt0aGlzLmV4cGFuZG9dJiZ0W3RoaXMuZXhwYW5kb11bZV19LGFjY2VzczpmdW5jdGlvbih0LGUscil7dmFyIG47cmV0dXJuIHZvaWQgMD09PWV8fGUmJiJzdHJpbmciPT10eXBlb2YgZSYmdm9pZCAwPT09cj8obj10aGlzLmdldCh0LGUpLHZvaWQgMCE9PW4/bjp0aGlzLmdldCh0LHN0LmNhbWVsQ2FzZShlKSkpOih0aGlzLnNldCh0LGUsciksdm9pZCAwIT09cj9yOmUpfSxyZW1vdmU6ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saT10W3RoaXMuZXhwYW5kb107aWYodm9pZCAwIT09aSl7aWYodm9pZCAwPT09ZSl0aGlzLnJlZ2lzdGVyKHQpO2Vsc2V7c3QuaXNBcnJheShlKT9uPWUuY29uY2F0KGUubWFwKHN0LmNhbWVsQ2FzZSkpOihvPXN0LmNhbWVsQ2FzZShlKSxlIGluIGk/bj1bZSxvXToobj1vLG49biBpbiBpP1tuXTpuLm1hdGNoKHd0KXx8W10pKSxyPW4ubGVuZ3RoO2Zvcig7ci0tOylkZWxldGUgaVtuW3JdXX0odm9pZCAwPT09ZXx8c3QuaXNFbXB0eU9iamVjdChpKSkmJih0Lm5vZGVUeXBlP3RbdGhpcy5leHBhbmRvXT12b2lkIDA6ZGVsZXRlIHRbdGhpcy5leHBhbmRvXSl9fSxoYXNEYXRhOmZ1bmN0aW9uKHQpe3ZhciBlPXRbdGhpcy5leHBhbmRvXTtyZXR1cm4gdm9pZCAwIT09ZSYmIXN0LmlzRW1wdHlPYmplY3QoZSl9fTt2YXIgVHQ9bmV3IGwsU3Q9bmV3IGwsenQ9L14oPzpce1tcd1xXXSpcfXxcW1tcd1xXXSpcXSkkLyxQdD0vW0EtWl0vZztzdC5leHRlbmQoe2hhc0RhdGE6ZnVuY3Rpb24odCl7cmV0dXJuIFN0Lmhhc0RhdGEodCl8fFR0Lmhhc0RhdGEodCl9LGRhdGE6ZnVuY3Rpb24odCxlLHIpe3JldHVybiBTdC5hY2Nlc3ModCxlLHIpfSxyZW1vdmVEYXRhOmZ1bmN0aW9uKHQsZSl7U3QucmVtb3ZlKHQsZSl9LF9kYXRhOmZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gVHQuYWNjZXNzKHQsZSxyKX0sX3JlbW92ZURhdGE6ZnVuY3Rpb24odCxlKXtUdC5yZW1vdmUodCxlKX19KSxzdC5mbi5leHRlbmQoe2RhdGE6ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saT10aGlzWzBdLHM9aSYmaS5hdHRyaWJ1dGVzO2lmKHZvaWQgMD09PXQpe2lmKHRoaXMubGVuZ3RoJiYobz1TdC5nZXQoaSksMT09PWkubm9kZVR5cGUmJiFUdC5nZXQoaSwiaGFzRGF0YUF0dHJzIikpKXtmb3Iocj1zLmxlbmd0aDtyLS07KXNbcl0mJihuPXNbcl0ubmFtZSwwPT09bi5pbmRleE9mKCJkYXRhLSIpJiYobj1zdC5jYW1lbENhc2Uobi5zbGljZSg1KSksdShpLG4sb1tuXSkpKTtUdC5zZXQoaSwiaGFzRGF0YUF0dHJzIiwhMCl9cmV0dXJuIG99cmV0dXJuIm9iamVjdCI9PXR5cGVvZiB0P3RoaXMuZWFjaChmdW5jdGlvbigpe1N0LnNldCh0aGlzLHQpfSk6a3QodGhpcyxmdW5jdGlvbihlKXt2YXIgcixuO2lmKGkmJnZvaWQgMD09PWUpe2lmKHI9U3QuZ2V0KGksdCl8fFN0LmdldChpLHQucmVwbGFjZShQdCwiLSQmIikudG9Mb3dlckNhc2UoKSksdm9pZCAwIT09cilyZXR1cm4gcjtpZihuPXN0LmNhbWVsQ2FzZSh0KSxyPVN0LmdldChpLG4pLHZvaWQgMCE9PXIpcmV0dXJuIHI7aWYocj11KGksbix2b2lkIDApLHZvaWQgMCE9PXIpcmV0dXJuIHJ9ZWxzZSBuPXN0LmNhbWVsQ2FzZSh0KSx0aGlzLmVhY2goZnVuY3Rpb24oKXt2YXIgcj1TdC5nZXQodGhpcyxuKTtTdC5zZXQodGhpcyxuLGUpLHQuaW5kZXhPZigiLSIpPi0xJiZ2b2lkIDAhPT1yJiZTdC5zZXQodGhpcyx0LGUpfSl9LG51bGwsZSxhcmd1bWVudHMubGVuZ3RoPjEsbnVsbCwhMCl9LHJlbW92ZURhdGE6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpe1N0LnJlbW92ZSh0aGlzLHQpfSl9fSksc3QuZXh0ZW5kKHtxdWV1ZTpmdW5jdGlvbih0LGUscil7dmFyIG47aWYodClyZXR1cm4gZT0oZXx8ImZ4IikrInF1ZXVlIixuPVR0LmdldCh0LGUpLHImJighbnx8c3QuaXNBcnJheShyKT9uPVR0LmFjY2Vzcyh0LGUsc3QubWFrZUFycmF5KHIpKTpuLnB1c2gocikpLG58fFtdfSxkZXF1ZXVlOmZ1bmN0aW9uKHQsZSl7ZT1lfHwiZngiO3ZhciByPXN0LnF1ZXVlKHQsZSksbj1yLmxlbmd0aCxvPXIuc2hpZnQoKSxpPXN0Ll9xdWV1ZUhvb2tzKHQsZSkscz1mdW5jdGlvbigpe3N0LmRlcXVldWUodCxlKX07ImlucHJvZ3Jlc3MiPT09byYmKG89ci5zaGlmdCgpLG4tLSksbyYmKCJmeCI9PT1lJiZyLnVuc2hpZnQoImlucHJvZ3Jlc3MiKSxkZWxldGUgaS5zdG9wLG8uY2FsbCh0LHMsaSkpLCFuJiZpJiZpLmVtcHR5LmZpcmUoKX0sX3F1ZXVlSG9va3M6ZnVuY3Rpb24odCxlKXt2YXIgcj1lKyJxdWV1ZUhvb2tzIjtyZXR1cm4gVHQuZ2V0KHQscil8fFR0LmFjY2Vzcyh0LHIse2VtcHR5OnN0LkNhbGxiYWNrcygib25jZSBtZW1vcnkiKS5hZGQoZnVuY3Rpb24oKXtUdC5yZW1vdmUodCxbZSsicXVldWUiLHJdKX0pfSl9fSksc3QuZm4uZXh0ZW5kKHtxdWV1ZTpmdW5jdGlvbih0LGUpe3ZhciByPTI7cmV0dXJuInN0cmluZyIhPXR5cGVvZiB0JiYoZT10LHQ9ImZ4IixyLS0pLGFyZ3VtZW50cy5sZW5ndGg8cj9zdC5xdWV1ZSh0aGlzWzBdLHQpOnZvaWQgMD09PWU/dGhpczp0aGlzLmVhY2goZnVuY3Rpb24oKXt2YXIgcj1zdC5xdWV1ZSh0aGlzLHQsZSk7c3QuX3F1ZXVlSG9va3ModGhpcyx0KSwiZngiPT09dCYmImlucHJvZ3Jlc3MiIT09clswXSYmc3QuZGVxdWV1ZSh0aGlzLHQpfSl9LGRlcXVldWU6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpe3N0LmRlcXVldWUodGhpcyx0KX0pfSxjbGVhclF1ZXVlOmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLnF1ZXVlKHR8fCJmeCIsW10pfSxwcm9taXNlOmZ1bmN0aW9uKHQsZSl7dmFyIHIsbj0xLG89c3QuRGVmZXJyZWQoKSxpPXRoaXMscz10aGlzLmxlbmd0aCxhPWZ1bmN0aW9uKCl7LS1ufHxvLnJlc29sdmVXaXRoKGksW2ldKX07Zm9yKCJzdHJpbmciIT10eXBlb2YgdCYmKGU9dCx0PXZvaWQgMCksdD10fHwiZngiO3MtLTspcj1UdC5nZXQoaVtzXSx0KyJxdWV1ZUhvb2tzIiksciYmci5lbXB0eSYmKG4rKyxyLmVtcHR5LmFkZChhKSk7cmV0dXJuIGEoKSxvLnByb21pc2UoZSl9fSk7dmFyIEV0PS9bKy1dPyg/OlxkKlwufClcZCsoPzpbZUVdWystXT9cZCt8KS8uc291cmNlLEF0PW5ldyBSZWdFeHAoIl4oPzooWystXSk9fCkoIitFdCsiKShbYS16JV0qKSQiLCJpIiksQ3Q9WyJUb3AiLCJSaWdodCIsIkJvdHRvbSIsIkxlZnQiXSxOdD1mdW5jdGlvbih0LGUpe3JldHVybiB0PWV8fHQsIm5vbmUiPT09c3QuY3NzKHQsImRpc3BsYXkiKXx8IXN0LmNvbnRhaW5zKHQub3duZXJEb2N1bWVudCx0KX0sT3Q9L14oPzpjaGVja2JveHxyYWRpbykkL2kscXQ9LzwoW1x3Oi1dKykvLER0PS9eJHxcLyg/OmphdmF8ZWNtYSlzY3JpcHQvaSxJdD17b3B0aW9uOlsxLCI8c2VsZWN0IG11bHRpcGxlPSdtdWx0aXBsZSc+IiwiPC9zZWxlY3Q+Il0sdGhlYWQ6WzEsIjx0YWJsZT4iLCI8L3RhYmxlPiJdLGNvbDpbMiwiPHRhYmxlPjxjb2xncm91cD4iLCI8L2NvbGdyb3VwPjwvdGFibGU+Il0sdHI6WzIsIjx0YWJsZT48dGJvZHk+IiwiPC90Ym9keT48L3RhYmxlPiJdLHRkOlszLCI8dGFibGU+PHRib2R5Pjx0cj4iLCI8L3RyPjwvdGJvZHk+PC90YWJsZT4iXSxfZGVmYXVsdDpbMCwiIiwiIl19O0l0Lm9wdGdyb3VwPUl0Lm9wdGlvbixJdC50Ym9keT1JdC50Zm9vdD1JdC5jb2xncm91cD1JdC5jYXB0aW9uPUl0LnRoZWFkLEl0LnRoPUl0LnRkO3ZhciBSdD0vPHwmIz9cdys7LzshZnVuY3Rpb24oKXt2YXIgdD1KLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKSxlPXQuYXBwZW5kQ2hpbGQoSi5jcmVhdGVFbGVtZW50KCJkaXYiKSkscj1KLmNyZWF0ZUVsZW1lbnQoImlucHV0Iik7ci5zZXRBdHRyaWJ1dGUoInR5cGUiLCJyYWRpbyIpLHIuc2V0QXR0cmlidXRlKCJjaGVja2VkIiwiY2hlY2tlZCIpLHIuc2V0QXR0cmlidXRlKCJuYW1lIiwidCIpLGUuYXBwZW5kQ2hpbGQociksb3QuY2hlY2tDbG9uZT1lLmNsb25lTm9kZSghMCkuY2xvbmVOb2RlKCEwKS5sYXN0Q2hpbGQuY2hlY2tlZCxlLmlubmVySFRNTD0iPHRleHRhcmVhPng8L3RleHRhcmVhPiIsb3Qubm9DbG9uZUNoZWNrZWQ9ISFlLmNsb25lTm9kZSghMCkubGFzdENoaWxkLmRlZmF1bHRWYWx1ZX0oKTt2YXIgRnQ9L15rZXkvLEJ0PS9eKD86bW91c2V8cG9pbnRlcnxjb250ZXh0bWVudXxkcmFnfGRyb3ApfGNsaWNrLyxMdD0vXihbXi5dKikoPzpcLiguKyl8KS87c3QuZXZlbnQ9e2dsb2JhbDp7fSxhZGQ6ZnVuY3Rpb24odCxlLHIsbixvKXt2YXIgaSxzLGEsbCx1LGgsYyxwLF8sZCxmLG09VHQuZ2V0KHQpO2lmKG0pZm9yKHIuaGFuZGxlciYmKGk9cixyPWkuaGFuZGxlcixvPWkuc2VsZWN0b3IpLHIuZ3VpZHx8KHIuZ3VpZD1zdC5ndWlkKyspLChsPW0uZXZlbnRzKXx8KGw9bS5ldmVudHM9e30pLChzPW0uaGFuZGxlKXx8KHM9bS5oYW5kbGU9ZnVuY3Rpb24oZSl7cmV0dXJuInVuZGVmaW5lZCIhPXR5cGVvZiBzdCYmc3QuZXZlbnQudHJpZ2dlcmVkIT09ZS50eXBlP3N0LmV2ZW50LmRpc3BhdGNoLmFwcGx5KHQsYXJndW1lbnRzKTp2b2lkIDB9KSxlPShlfHwiIikubWF0Y2god3QpfHxbIiJdLHU9ZS5sZW5ndGg7dS0tOylhPUx0LmV4ZWMoZVt1XSl8fFtdLF89Zj1hWzFdLGQ9KGFbMl18fCIiKS5zcGxpdCgiLiIpLnNvcnQoKSxfJiYoYz1zdC5ldmVudC5zcGVjaWFsW19dfHx7fSxfPShvP2MuZGVsZWdhdGVUeXBlOmMuYmluZFR5cGUpfHxfLGM9c3QuZXZlbnQuc3BlY2lhbFtfXXx8e30saD1zdC5leHRlbmQoe3R5cGU6XyxvcmlnVHlwZTpmLGRhdGE6bixoYW5kbGVyOnIsZ3VpZDpyLmd1aWQsc2VsZWN0b3I6byxuZWVkc0NvbnRleHQ6byYmc3QuZXhwci5tYXRjaC5uZWVkc0NvbnRleHQudGVzdChvKSxuYW1lc3BhY2U6ZC5qb2luKCIuIil9LGkpLChwPWxbX10pfHwocD1sW19dPVtdLHAuZGVsZWdhdGVDb3VudD0wLGMuc2V0dXAmJmMuc2V0dXAuY2FsbCh0LG4sZCxzKSE9PSExfHx0LmFkZEV2ZW50TGlzdGVuZXImJnQuYWRkRXZlbnRMaXN0ZW5lcihfLHMpKSxjLmFkZCYmKGMuYWRkLmNhbGwodCxoKSxoLmhhbmRsZXIuZ3VpZHx8KGguaGFuZGxlci5ndWlkPXIuZ3VpZCkpLG8/cC5zcGxpY2UocC5kZWxlZ2F0ZUNvdW50KyssMCxoKTpwLnB1c2goaCksc3QuZXZlbnQuZ2xvYmFsW19dPSEwKX0scmVtb3ZlOmZ1bmN0aW9uKHQsZSxyLG4sbyl7dmFyIGkscyxhLGwsdSxoLGMscCxfLGQsZixtPVR0Lmhhc0RhdGEodCkmJlR0LmdldCh0KTtpZihtJiYobD1tLmV2ZW50cykpe2ZvcihlPShlfHwiIikubWF0Y2god3QpfHxbIiJdLHU9ZS5sZW5ndGg7dS0tOylpZihhPUx0LmV4ZWMoZVt1XSl8fFtdLF89Zj1hWzFdLGQ9KGFbMl18fCIiKS5zcGxpdCgiLiIpLnNvcnQoKSxfKXtmb3IoYz1zdC5ldmVudC5zcGVjaWFsW19dfHx7fSxfPShuP2MuZGVsZWdhdGVUeXBlOmMuYmluZFR5cGUpfHxfLHA9bFtfXXx8W10sYT1hWzJdJiZuZXcgUmVnRXhwKCIoXnxcXC4pIitkLmpvaW4oIlxcLig/Oi4qXFwufCkiKSsiKFxcLnwkKSIpLHM9aT1wLmxlbmd0aDtpLS07KWg9cFtpXSwhbyYmZiE9PWgub3JpZ1R5cGV8fHImJnIuZ3VpZCE9PWguZ3VpZHx8YSYmIWEudGVzdChoLm5hbWVzcGFjZSl8fG4mJm4hPT1oLnNlbGVjdG9yJiYoIioqIiE9PW58fCFoLnNlbGVjdG9yKXx8KHAuc3BsaWNlKGksMSksCmguc2VsZWN0b3ImJnAuZGVsZWdhdGVDb3VudC0tLGMucmVtb3ZlJiZjLnJlbW92ZS5jYWxsKHQsaCkpO3MmJiFwLmxlbmd0aCYmKGMudGVhcmRvd24mJmMudGVhcmRvd24uY2FsbCh0LGQsbS5oYW5kbGUpIT09ITF8fHN0LnJlbW92ZUV2ZW50KHQsXyxtLmhhbmRsZSksZGVsZXRlIGxbX10pfWVsc2UgZm9yKF8gaW4gbClzdC5ldmVudC5yZW1vdmUodCxfK2VbdV0scixuLCEwKTtzdC5pc0VtcHR5T2JqZWN0KGwpJiZUdC5yZW1vdmUodCwiaGFuZGxlIGV2ZW50cyIpfX0sZGlzcGF0Y2g6ZnVuY3Rpb24odCl7dD1zdC5ldmVudC5maXgodCk7dmFyIGUscixuLG8saSxzPVtdLGE9US5jYWxsKGFyZ3VtZW50cyksbD0oVHQuZ2V0KHRoaXMsImV2ZW50cyIpfHx7fSlbdC50eXBlXXx8W10sdT1zdC5ldmVudC5zcGVjaWFsW3QudHlwZV18fHt9O2lmKGFbMF09dCx0LmRlbGVnYXRlVGFyZ2V0PXRoaXMsIXUucHJlRGlzcGF0Y2h8fHUucHJlRGlzcGF0Y2guY2FsbCh0aGlzLHQpIT09ITEpe2ZvcihzPXN0LmV2ZW50LmhhbmRsZXJzLmNhbGwodGhpcyx0LGwpLGU9MDsobz1zW2UrK10pJiYhdC5pc1Byb3BhZ2F0aW9uU3RvcHBlZCgpOylmb3IodC5jdXJyZW50VGFyZ2V0PW8uZWxlbSxyPTA7KGk9by5oYW5kbGVyc1tyKytdKSYmIXQuaXNJbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQoKTspdC5ybmFtZXNwYWNlJiYhdC5ybmFtZXNwYWNlLnRlc3QoaS5uYW1lc3BhY2UpfHwodC5oYW5kbGVPYmo9aSx0LmRhdGE9aS5kYXRhLG49KChzdC5ldmVudC5zcGVjaWFsW2kub3JpZ1R5cGVdfHx7fSkuaGFuZGxlfHxpLmhhbmRsZXIpLmFwcGx5KG8uZWxlbSxhKSx2b2lkIDAhPT1uJiYodC5yZXN1bHQ9bik9PT0hMSYmKHQucHJldmVudERlZmF1bHQoKSx0LnN0b3BQcm9wYWdhdGlvbigpKSk7cmV0dXJuIHUucG9zdERpc3BhdGNoJiZ1LnBvc3REaXNwYXRjaC5jYWxsKHRoaXMsdCksdC5yZXN1bHR9fSxoYW5kbGVyczpmdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpLHM9W10sYT1lLmRlbGVnYXRlQ291bnQsbD10LnRhcmdldDtpZihhJiZsLm5vZGVUeXBlJiYoImNsaWNrIiE9PXQudHlwZXx8aXNOYU4odC5idXR0b24pfHx0LmJ1dHRvbjwxKSlmb3IoO2whPT10aGlzO2w9bC5wYXJlbnROb2RlfHx0aGlzKWlmKDE9PT1sLm5vZGVUeXBlJiYobC5kaXNhYmxlZCE9PSEwfHwiY2xpY2siIT09dC50eXBlKSl7Zm9yKG49W10scj0wO3I8YTtyKyspaT1lW3JdLG89aS5zZWxlY3RvcisiICIsdm9pZCAwPT09bltvXSYmKG5bb109aS5uZWVkc0NvbnRleHQ/c3Qobyx0aGlzKS5pbmRleChsKT4tMTpzdC5maW5kKG8sdGhpcyxudWxsLFtsXSkubGVuZ3RoKSxuW29dJiZuLnB1c2goaSk7bi5sZW5ndGgmJnMucHVzaCh7ZWxlbTpsLGhhbmRsZXJzOm59KX1yZXR1cm4gYTxlLmxlbmd0aCYmcy5wdXNoKHtlbGVtOnRoaXMsaGFuZGxlcnM6ZS5zbGljZShhKX0pLHN9LHByb3BzOiJhbHRLZXkgYnViYmxlcyBjYW5jZWxhYmxlIGN0cmxLZXkgY3VycmVudFRhcmdldCBkZXRhaWwgZXZlbnRQaGFzZSBtZXRhS2V5IHJlbGF0ZWRUYXJnZXQgc2hpZnRLZXkgdGFyZ2V0IHRpbWVTdGFtcCB2aWV3IHdoaWNoIi5zcGxpdCgiICIpLGZpeEhvb2tzOnt9LGtleUhvb2tzOntwcm9wczoiY2hhciBjaGFyQ29kZSBrZXkga2V5Q29kZSIuc3BsaXQoIiAiKSxmaWx0ZXI6ZnVuY3Rpb24odCxlKXtyZXR1cm4gbnVsbD09dC53aGljaCYmKHQud2hpY2g9bnVsbCE9ZS5jaGFyQ29kZT9lLmNoYXJDb2RlOmUua2V5Q29kZSksdH19LG1vdXNlSG9va3M6e3Byb3BzOiJidXR0b24gYnV0dG9ucyBjbGllbnRYIGNsaWVudFkgb2Zmc2V0WCBvZmZzZXRZIHBhZ2VYIHBhZ2VZIHNjcmVlblggc2NyZWVuWSB0b0VsZW1lbnQiLnNwbGl0KCIgIiksZmlsdGVyOmZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLGk9ZS5idXR0b247cmV0dXJuIG51bGw9PXQucGFnZVgmJm51bGwhPWUuY2xpZW50WCYmKHI9dC50YXJnZXQub3duZXJEb2N1bWVudHx8SixuPXIuZG9jdW1lbnRFbGVtZW50LG89ci5ib2R5LHQucGFnZVg9ZS5jbGllbnRYKyhuJiZuLnNjcm9sbExlZnR8fG8mJm8uc2Nyb2xsTGVmdHx8MCktKG4mJm4uY2xpZW50TGVmdHx8byYmby5jbGllbnRMZWZ0fHwwKSx0LnBhZ2VZPWUuY2xpZW50WSsobiYmbi5zY3JvbGxUb3B8fG8mJm8uc2Nyb2xsVG9wfHwwKS0obiYmbi5jbGllbnRUb3B8fG8mJm8uY2xpZW50VG9wfHwwKSksdC53aGljaHx8dm9pZCAwPT09aXx8KHQud2hpY2g9MSZpPzE6MiZpPzM6NCZpPzI6MCksdH19LGZpeDpmdW5jdGlvbih0KXtpZih0W3N0LmV4cGFuZG9dKXJldHVybiB0O3ZhciBlLHIsbixvPXQudHlwZSxpPXQscz10aGlzLmZpeEhvb2tzW29dO2ZvcihzfHwodGhpcy5maXhIb29rc1tvXT1zPUJ0LnRlc3Qobyk/dGhpcy5tb3VzZUhvb2tzOkZ0LnRlc3Qobyk/dGhpcy5rZXlIb29rczp7fSksbj1zLnByb3BzP3RoaXMucHJvcHMuY29uY2F0KHMucHJvcHMpOnRoaXMucHJvcHMsdD1uZXcgc3QuRXZlbnQoaSksZT1uLmxlbmd0aDtlLS07KXI9bltlXSx0W3JdPWlbcl07cmV0dXJuIHQudGFyZ2V0fHwodC50YXJnZXQ9SiksMz09PXQudGFyZ2V0Lm5vZGVUeXBlJiYodC50YXJnZXQ9dC50YXJnZXQucGFyZW50Tm9kZSkscy5maWx0ZXI/cy5maWx0ZXIodCxpKTp0fSxzcGVjaWFsOntsb2FkOntub0J1YmJsZTohMH0sZm9jdXM6e3RyaWdnZXI6ZnVuY3Rpb24oKXtpZih0aGlzIT09bSgpJiZ0aGlzLmZvY3VzKXJldHVybiB0aGlzLmZvY3VzKCksITF9LGRlbGVnYXRlVHlwZToiZm9jdXNpbiJ9LGJsdXI6e3RyaWdnZXI6ZnVuY3Rpb24oKXtpZih0aGlzPT09bSgpJiZ0aGlzLmJsdXIpcmV0dXJuIHRoaXMuYmx1cigpLCExfSxkZWxlZ2F0ZVR5cGU6ImZvY3Vzb3V0In0sY2xpY2s6e3RyaWdnZXI6ZnVuY3Rpb24oKXtpZigiY2hlY2tib3giPT09dGhpcy50eXBlJiZ0aGlzLmNsaWNrJiZzdC5ub2RlTmFtZSh0aGlzLCJpbnB1dCIpKXJldHVybiB0aGlzLmNsaWNrKCksITF9LF9kZWZhdWx0OmZ1bmN0aW9uKHQpe3JldHVybiBzdC5ub2RlTmFtZSh0LnRhcmdldCwiYSIpfX0sYmVmb3JldW5sb2FkOntwb3N0RGlzcGF0Y2g6ZnVuY3Rpb24odCl7dm9pZCAwIT09dC5yZXN1bHQmJnQub3JpZ2luYWxFdmVudCYmKHQub3JpZ2luYWxFdmVudC5yZXR1cm5WYWx1ZT10LnJlc3VsdCl9fX19LHN0LnJlbW92ZUV2ZW50PWZ1bmN0aW9uKHQsZSxyKXt0LnJlbW92ZUV2ZW50TGlzdGVuZXImJnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihlLHIpfSxzdC5FdmVudD1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzIGluc3RhbmNlb2Ygc3QuRXZlbnQ/KHQmJnQudHlwZT8odGhpcy5vcmlnaW5hbEV2ZW50PXQsdGhpcy50eXBlPXQudHlwZSx0aGlzLmlzRGVmYXVsdFByZXZlbnRlZD10LmRlZmF1bHRQcmV2ZW50ZWR8fHZvaWQgMD09PXQuZGVmYXVsdFByZXZlbnRlZCYmdC5yZXR1cm5WYWx1ZT09PSExP2Q6Zik6dGhpcy50eXBlPXQsZSYmc3QuZXh0ZW5kKHRoaXMsZSksdGhpcy50aW1lU3RhbXA9dCYmdC50aW1lU3RhbXB8fHN0Lm5vdygpLHZvaWQodGhpc1tzdC5leHBhbmRvXT0hMCkpOm5ldyBzdC5FdmVudCh0LGUpfSxzdC5FdmVudC5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOnN0LkV2ZW50LGlzRGVmYXVsdFByZXZlbnRlZDpmLGlzUHJvcGFnYXRpb25TdG9wcGVkOmYsaXNJbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQ6Zixpc1NpbXVsYXRlZDohMSxwcmV2ZW50RGVmYXVsdDpmdW5jdGlvbigpe3ZhciB0PXRoaXMub3JpZ2luYWxFdmVudDt0aGlzLmlzRGVmYXVsdFByZXZlbnRlZD1kLHQmJiF0aGlzLmlzU2ltdWxhdGVkJiZ0LnByZXZlbnREZWZhdWx0KCl9LHN0b3BQcm9wYWdhdGlvbjpmdW5jdGlvbigpe3ZhciB0PXRoaXMub3JpZ2luYWxFdmVudDt0aGlzLmlzUHJvcGFnYXRpb25TdG9wcGVkPWQsdCYmIXRoaXMuaXNTaW11bGF0ZWQmJnQuc3RvcFByb3BhZ2F0aW9uKCl9LHN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbjpmdW5jdGlvbigpe3ZhciB0PXRoaXMub3JpZ2luYWxFdmVudDt0aGlzLmlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkPWQsdCYmIXRoaXMuaXNTaW11bGF0ZWQmJnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCksdGhpcy5zdG9wUHJvcGFnYXRpb24oKX19LHN0LmVhY2goe21vdXNlZW50ZXI6Im1vdXNlb3ZlciIsbW91c2VsZWF2ZToibW91c2VvdXQiLHBvaW50ZXJlbnRlcjoicG9pbnRlcm92ZXIiLHBvaW50ZXJsZWF2ZToicG9pbnRlcm91dCJ9LGZ1bmN0aW9uKHQsZSl7c3QuZXZlbnQuc3BlY2lhbFt0XT17ZGVsZWdhdGVUeXBlOmUsYmluZFR5cGU6ZSxoYW5kbGU6ZnVuY3Rpb24odCl7dmFyIHIsbj10aGlzLG89dC5yZWxhdGVkVGFyZ2V0LGk9dC5oYW5kbGVPYmo7cmV0dXJuIG8mJihvPT09bnx8c3QuY29udGFpbnMobixvKSl8fCh0LnR5cGU9aS5vcmlnVHlwZSxyPWkuaGFuZGxlci5hcHBseSh0aGlzLGFyZ3VtZW50cyksdC50eXBlPWUpLHJ9fX0pLHN0LmZuLmV4dGVuZCh7b246ZnVuY3Rpb24odCxlLHIsbil7cmV0dXJuIGcodGhpcyx0LGUscixuKX0sb25lOmZ1bmN0aW9uKHQsZSxyLG4pe3JldHVybiBnKHRoaXMsdCxlLHIsbiwxKX0sb2ZmOmZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvO2lmKHQmJnQucHJldmVudERlZmF1bHQmJnQuaGFuZGxlT2JqKXJldHVybiBuPXQuaGFuZGxlT2JqLHN0KHQuZGVsZWdhdGVUYXJnZXQpLm9mZihuLm5hbWVzcGFjZT9uLm9yaWdUeXBlKyIuIituLm5hbWVzcGFjZTpuLm9yaWdUeXBlLG4uc2VsZWN0b3Isbi5oYW5kbGVyKSx0aGlzO2lmKCJvYmplY3QiPT10eXBlb2YgdCl7Zm9yKG8gaW4gdCl0aGlzLm9mZihvLGUsdFtvXSk7cmV0dXJuIHRoaXN9cmV0dXJuIGUhPT0hMSYmImZ1bmN0aW9uIiE9dHlwZW9mIGV8fChyPWUsZT12b2lkIDApLHI9PT0hMSYmKHI9ZiksdGhpcy5lYWNoKGZ1bmN0aW9uKCl7c3QuZXZlbnQucmVtb3ZlKHRoaXMsdCxyLGUpfSl9fSk7dmFyIEd0PS88KD8hYXJlYXxicnxjb2x8ZW1iZWR8aHJ8aW1nfGlucHV0fGxpbmt8bWV0YXxwYXJhbSkoKFtcdzotXSspW14+XSopXC8+L2dpLFZ0PS88c2NyaXB0fDxzdHlsZXw8bGluay9pLFV0PS9jaGVja2VkXHMqKD86W149XXw9XHMqLmNoZWNrZWQuKS9pLFl0PS9edHJ1ZVwvKC4qKS8sSHQ9L15ccyo8ISg/OlxbQ0RBVEFcW3wtLSl8KD86XF1cXXwtLSk+XHMqJC9nO3N0LmV4dGVuZCh7aHRtbFByZWZpbHRlcjpmdW5jdGlvbih0KXtyZXR1cm4gdC5yZXBsYWNlKEd0LCI8JDE+PC8kMj4iKX0sY2xvbmU6ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxzLGE9dC5jbG9uZU5vZGUoITApLGw9c3QuY29udGFpbnModC5vd25lckRvY3VtZW50LHQpO2lmKCEob3Qubm9DbG9uZUNoZWNrZWR8fDEhPT10Lm5vZGVUeXBlJiYxMSE9PXQubm9kZVR5cGV8fHN0LmlzWE1MRG9jKHQpKSlmb3Iocz1jKGEpLGk9Yyh0KSxuPTAsbz1pLmxlbmd0aDtuPG87bisrKXcoaVtuXSxzW25dKTtpZihlKWlmKHIpZm9yKGk9aXx8Yyh0KSxzPXN8fGMoYSksbj0wLG89aS5sZW5ndGg7bjxvO24rKyl4KGlbbl0sc1tuXSk7ZWxzZSB4KHQsYSk7cmV0dXJuIHM9YyhhLCJzY3JpcHQiKSxzLmxlbmd0aD4wJiZwKHMsIWwmJmModCwic2NyaXB0IikpLGF9LGNsZWFuRGF0YTpmdW5jdGlvbih0KXtmb3IodmFyIGUscixuLG89c3QuZXZlbnQuc3BlY2lhbCxpPTA7dm9pZCAwIT09KHI9dFtpXSk7aSsrKWlmKGp0KHIpKXtpZihlPXJbVHQuZXhwYW5kb10pe2lmKGUuZXZlbnRzKWZvcihuIGluIGUuZXZlbnRzKW9bbl0/c3QuZXZlbnQucmVtb3ZlKHIsbik6c3QucmVtb3ZlRXZlbnQocixuLGUuaGFuZGxlKTtyW1R0LmV4cGFuZG9dPXZvaWQgMH1yW1N0LmV4cGFuZG9dJiYocltTdC5leHBhbmRvXT12b2lkIDApfX19KSxzdC5mbi5leHRlbmQoe2RvbU1hbmlwOk0sZGV0YWNoOmZ1bmN0aW9uKHQpe3JldHVybiBrKHRoaXMsdCwhMCl9LHJlbW92ZTpmdW5jdGlvbih0KXtyZXR1cm4gayh0aGlzLHQpfSx0ZXh0OmZ1bmN0aW9uKHQpe3JldHVybiBrdCh0aGlzLGZ1bmN0aW9uKHQpe3JldHVybiB2b2lkIDA9PT10P3N0LnRleHQodGhpcyk6dGhpcy5lbXB0eSgpLmVhY2goZnVuY3Rpb24oKXsxIT09dGhpcy5ub2RlVHlwZSYmMTEhPT10aGlzLm5vZGVUeXBlJiY5IT09dGhpcy5ub2RlVHlwZXx8KHRoaXMudGV4dENvbnRlbnQ9dCl9KX0sbnVsbCx0LGFyZ3VtZW50cy5sZW5ndGgpfSxhcHBlbmQ6ZnVuY3Rpb24oKXtyZXR1cm4gTSh0aGlzLGFyZ3VtZW50cyxmdW5jdGlvbih0KXtpZigxPT09dGhpcy5ub2RlVHlwZXx8MTE9PT10aGlzLm5vZGVUeXBlfHw5PT09dGhpcy5ub2RlVHlwZSl7dmFyIGU9eSh0aGlzLHQpO2UuYXBwZW5kQ2hpbGQodCl9fSl9LHByZXBlbmQ6ZnVuY3Rpb24oKXtyZXR1cm4gTSh0aGlzLGFyZ3VtZW50cyxmdW5jdGlvbih0KXtpZigxPT09dGhpcy5ub2RlVHlwZXx8MTE9PT10aGlzLm5vZGVUeXBlfHw5PT09dGhpcy5ub2RlVHlwZSl7dmFyIGU9eSh0aGlzLHQpO2UuaW5zZXJ0QmVmb3JlKHQsZS5maXJzdENoaWxkKX19KX0sYmVmb3JlOmZ1bmN0aW9uKCl7cmV0dXJuIE0odGhpcyxhcmd1bWVudHMsZnVuY3Rpb24odCl7dGhpcy5wYXJlbnROb2RlJiZ0aGlzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHQsdGhpcyl9KX0sYWZ0ZXI6ZnVuY3Rpb24oKXtyZXR1cm4gTSh0aGlzLGFyZ3VtZW50cyxmdW5jdGlvbih0KXt0aGlzLnBhcmVudE5vZGUmJnRoaXMucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodCx0aGlzLm5leHRTaWJsaW5nKX0pfSxlbXB0eTpmdW5jdGlvbigpe2Zvcih2YXIgdCxlPTA7bnVsbCE9KHQ9dGhpc1tlXSk7ZSsrKTE9PT10Lm5vZGVUeXBlJiYoc3QuY2xlYW5EYXRhKGModCwhMSkpLHQudGV4dENvbnRlbnQ9IiIpO3JldHVybiB0aGlzfSxjbG9uZTpmdW5jdGlvbih0LGUpe3JldHVybiB0PW51bGwhPXQmJnQsZT1udWxsPT1lP3Q6ZSx0aGlzLm1hcChmdW5jdGlvbigpe3JldHVybiBzdC5jbG9uZSh0aGlzLHQsZSl9KX0saHRtbDpmdW5jdGlvbih0KXtyZXR1cm4ga3QodGhpcyxmdW5jdGlvbih0KXt2YXIgZT10aGlzWzBdfHx7fSxyPTAsbj10aGlzLmxlbmd0aDtpZih2b2lkIDA9PT10JiYxPT09ZS5ub2RlVHlwZSlyZXR1cm4gZS5pbm5lckhUTUw7aWYoInN0cmluZyI9PXR5cGVvZiB0JiYhVnQudGVzdCh0KSYmIUl0WyhxdC5leGVjKHQpfHxbIiIsIiJdKVsxXS50b0xvd2VyQ2FzZSgpXSl7dD1zdC5odG1sUHJlZmlsdGVyKHQpO3RyeXtmb3IoO3I8bjtyKyspZT10aGlzW3JdfHx7fSwxPT09ZS5ub2RlVHlwZSYmKHN0LmNsZWFuRGF0YShjKGUsITEpKSxlLmlubmVySFRNTD10KTtlPTB9Y2F0Y2gobyl7fX1lJiZ0aGlzLmVtcHR5KCkuYXBwZW5kKHQpfSxudWxsLHQsYXJndW1lbnRzLmxlbmd0aCl9LHJlcGxhY2VXaXRoOmZ1bmN0aW9uKCl7dmFyIHQ9W107cmV0dXJuIE0odGhpcyxhcmd1bWVudHMsZnVuY3Rpb24oZSl7dmFyIHI9dGhpcy5wYXJlbnROb2RlO3N0LmluQXJyYXkodGhpcyx0KTwwJiYoc3QuY2xlYW5EYXRhKGModGhpcykpLHImJnIucmVwbGFjZUNoaWxkKGUsdGhpcykpfSx0KX19KSxzdC5lYWNoKHthcHBlbmRUbzoiYXBwZW5kIixwcmVwZW5kVG86InByZXBlbmQiLGluc2VydEJlZm9yZToiYmVmb3JlIixpbnNlcnRBZnRlcjoiYWZ0ZXIiLHJlcGxhY2VBbGw6InJlcGxhY2VXaXRoIn0sZnVuY3Rpb24odCxlKXtzdC5mblt0XT1mdW5jdGlvbih0KXtmb3IodmFyIHIsbj1bXSxvPXN0KHQpLGk9by5sZW5ndGgtMSxzPTA7czw9aTtzKyspcj1zPT09aT90aGlzOnRoaXMuY2xvbmUoITApLHN0KG9bc10pW2VdKHIpLFouYXBwbHkobixyLmdldCgpKTtyZXR1cm4gdGhpcy5wdXNoU3RhY2sobil9fSk7dmFyIFh0LCR0PXtIVE1MOiJibG9jayIsQk9EWToiYmxvY2sifSxXdD0vXm1hcmdpbi8sSnQ9bmV3IFJlZ0V4cCgiXigiK0V0KyIpKD8hcHgpW2EteiVdKyQiLCJpIiksUXQ9ZnVuY3Rpb24odCl7dmFyIHI9dC5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3O3JldHVybiByJiZyLm9wZW5lcnx8KHI9ZSksci5nZXRDb21wdXRlZFN0eWxlKHQpfSxLdD1mdW5jdGlvbih0LGUscixuKXt2YXIgbyxpLHM9e307Zm9yKGkgaW4gZSlzW2ldPXQuc3R5bGVbaV0sdC5zdHlsZVtpXT1lW2ldO289ci5hcHBseSh0LG58fFtdKTtmb3IoaSBpbiBlKXQuc3R5bGVbaV09c1tpXTtyZXR1cm4gb30sWnQ9Si5kb2N1bWVudEVsZW1lbnQ7IWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCgpe2Euc3R5bGUuY3NzVGV4dD0iLXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94O3Bvc2l0aW9uOnJlbGF0aXZlO2Rpc3BsYXk6YmxvY2s7bWFyZ2luOmF1dG87Ym9yZGVyOjFweDtwYWRkaW5nOjFweDt0b3A6MSU7d2lkdGg6NTAlIixhLmlubmVySFRNTD0iIixadC5hcHBlbmRDaGlsZChzKTt2YXIgdD1lLmdldENvbXB1dGVkU3R5bGUoYSk7cj0iMSUiIT09dC50b3AsaT0iMnB4Ij09PXQubWFyZ2luTGVmdCxuPSI0cHgiPT09dC53aWR0aCxhLnN0eWxlLm1hcmdpblJpZ2h0PSI1MCUiLG89IjRweCI9PT10Lm1hcmdpblJpZ2h0LFp0LnJlbW92ZUNoaWxkKHMpfXZhciByLG4sbyxpLHM9Si5jcmVhdGVFbGVtZW50KCJkaXYiKSxhPUouY3JlYXRlRWxlbWVudCgiZGl2Iik7YS5zdHlsZSYmKGEuc3R5bGUuYmFja2dyb3VuZENsaXA9ImNvbnRlbnQtYm94IixhLmNsb25lTm9kZSghMCkuc3R5bGUuYmFja2dyb3VuZENsaXA9IiIsb3QuY2xlYXJDbG9uZVN0eWxlPSJjb250ZW50LWJveCI9PT1hLnN0eWxlLmJhY2tncm91bmRDbGlwLHMuc3R5bGUuY3NzVGV4dD0iYm9yZGVyOjA7d2lkdGg6OHB4O2hlaWdodDowO3RvcDowO2xlZnQ6LTk5OTlweDtwYWRkaW5nOjA7bWFyZ2luLXRvcDoxcHg7cG9zaXRpb246YWJzb2x1dGUiLHMuYXBwZW5kQ2hpbGQoYSksc3QuZXh0ZW5kKG90LHtwaXhlbFBvc2l0aW9uOmZ1bmN0aW9uKCl7cmV0dXJuIHQoKSxyfSxib3hTaXppbmdSZWxpYWJsZTpmdW5jdGlvbigpe3JldHVybiBudWxsPT1uJiZ0KCksbn0scGl4ZWxNYXJnaW5SaWdodDpmdW5jdGlvbigpe3JldHVybiBudWxsPT1uJiZ0KCksb30scmVsaWFibGVNYXJnaW5MZWZ0OmZ1bmN0aW9uKCl7cmV0dXJuIG51bGw9PW4mJnQoKSxpfSxyZWxpYWJsZU1hcmdpblJpZ2h0OmZ1bmN0aW9uKCl7dmFyIHQscj1hLmFwcGVuZENoaWxkKEouY3JlYXRlRWxlbWVudCgiZGl2IikpO3JldHVybiByLnN0eWxlLmNzc1RleHQ9YS5zdHlsZS5jc3NUZXh0PSItd2Via2l0LWJveC1zaXppbmc6Y29udGVudC1ib3g7Ym94LXNpemluZzpjb250ZW50LWJveDtkaXNwbGF5OmJsb2NrO21hcmdpbjowO2JvcmRlcjowO3BhZGRpbmc6MCIsci5zdHlsZS5tYXJnaW5SaWdodD1yLnN0eWxlLndpZHRoPSIwIixhLnN0eWxlLndpZHRoPSIxcHgiLFp0LmFwcGVuZENoaWxkKHMpLHQ9IXBhcnNlRmxvYXQoZS5nZXRDb21wdXRlZFN0eWxlKHIpLm1hcmdpblJpZ2h0KSxadC5yZW1vdmVDaGlsZChzKSxhLnJlbW92ZUNoaWxkKHIpLHR9fSkpfSgpO3ZhciB0ZT0vXihub25lfHRhYmxlKD8hLWNbZWFdKS4rKS8sZWU9e3Bvc2l0aW9uOiJhYnNvbHV0ZSIsdmlzaWJpbGl0eToiaGlkZGVuIixkaXNwbGF5OiJibG9jayJ9LHJlPXtsZXR0ZXJTcGFjaW5nOiIwIixmb250V2VpZ2h0OiI0MDAifSxuZT1bIldlYmtpdCIsIk8iLCJNb3oiLCJtcyJdLG9lPUouY3JlYXRlRWxlbWVudCgiZGl2Iikuc3R5bGU7c3QuZXh0ZW5kKHtjc3NIb29rczp7b3BhY2l0eTp7Z2V0OmZ1bmN0aW9uKHQsZSl7aWYoZSl7dmFyIHI9Uyh0LCJvcGFjaXR5Iik7cmV0dXJuIiI9PT1yPyIxIjpyfX19fSxjc3NOdW1iZXI6e2FuaW1hdGlvbkl0ZXJhdGlvbkNvdW50OiEwLGNvbHVtbkNvdW50OiEwLGZpbGxPcGFjaXR5OiEwLGZsZXhHcm93OiEwLGZsZXhTaHJpbms6ITAsZm9udFdlaWdodDohMCxsaW5lSGVpZ2h0OiEwLG9wYWNpdHk6ITAsb3JkZXI6ITAsb3JwaGFuczohMCx3aWRvd3M6ITAsekluZGV4OiEwLHpvb206ITB9LGNzc1Byb3BzOnsiZmxvYXQiOiJjc3NGbG9hdCJ9LHN0eWxlOmZ1bmN0aW9uKHQsZSxyLG4pe2lmKHQmJjMhPT10Lm5vZGVUeXBlJiY4IT09dC5ub2RlVHlwZSYmdC5zdHlsZSl7dmFyIG8saSxzLGE9c3QuY2FtZWxDYXNlKGUpLGw9dC5zdHlsZTtyZXR1cm4gZT1zdC5jc3NQcm9wc1thXXx8KHN0LmNzc1Byb3BzW2FdPVAoYSl8fGEpLHM9c3QuY3NzSG9va3NbZV18fHN0LmNzc0hvb2tzW2FdLHZvaWQgMD09PXI/cyYmImdldCJpbiBzJiZ2b2lkIDAhPT0obz1zLmdldCh0LCExLG4pKT9vOmxbZV06KGk9dHlwZW9mIHIsInN0cmluZyI9PT1pJiYobz1BdC5leGVjKHIpKSYmb1sxXSYmKHI9aCh0LGUsbyksaT0ibnVtYmVyIiksbnVsbCE9ciYmcj09PXImJigibnVtYmVyIj09PWkmJihyKz1vJiZvWzNdfHwoc3QuY3NzTnVtYmVyW2FdPyIiOiJweCIpKSxvdC5jbGVhckNsb25lU3R5bGV8fCIiIT09cnx8MCE9PWUuaW5kZXhPZigiYmFja2dyb3VuZCIpfHwobFtlXT0iaW5oZXJpdCIpLHMmJiJzZXQiaW4gcyYmdm9pZCAwPT09KHI9cy5zZXQodCxyLG4pKXx8KGxbZV09cikpLHZvaWQgMCl9fSxjc3M6ZnVuY3Rpb24odCxlLHIsbil7dmFyIG8saSxzLGE9c3QuY2FtZWxDYXNlKGUpO3JldHVybiBlPXN0LmNzc1Byb3BzW2FdfHwoc3QuY3NzUHJvcHNbYV09UChhKXx8YSkscz1zdC5jc3NIb29rc1tlXXx8c3QuY3NzSG9va3NbYV0scyYmImdldCJpbiBzJiYobz1zLmdldCh0LCEwLHIpKSx2b2lkIDA9PT1vJiYobz1TKHQsZSxuKSksIm5vcm1hbCI9PT1vJiZlIGluIHJlJiYobz1yZVtlXSksIiI9PT1yfHxyPyhpPXBhcnNlRmxvYXQobykscj09PSEwfHxpc0Zpbml0ZShpKT9pfHwwOm8pOm99fSksc3QuZWFjaChbImhlaWdodCIsIndpZHRoIl0sZnVuY3Rpb24odCxlKXtzdC5jc3NIb29rc1tlXT17Z2V0OmZ1bmN0aW9uKHQscixuKXtpZihyKXJldHVybiB0ZS50ZXN0KHN0LmNzcyh0LCJkaXNwbGF5IikpJiYwPT09dC5vZmZzZXRXaWR0aD9LdCh0LGVlLGZ1bmN0aW9uKCl7cmV0dXJuIEModCxlLG4pfSk6Qyh0LGUsbil9LHNldDpmdW5jdGlvbih0LHIsbil7dmFyIG8saT1uJiZRdCh0KSxzPW4mJkEodCxlLG4sImJvcmRlci1ib3giPT09c3QuY3NzKHQsImJveFNpemluZyIsITEsaSksaSk7cmV0dXJuIHMmJihvPUF0LmV4ZWMocikpJiYicHgiIT09KG9bM118fCJweCIpJiYodC5zdHlsZVtlXT1yLHI9c3QuY3NzKHQsZSkpLEUodCxyLHMpfX19KSxzdC5jc3NIb29rcy5tYXJnaW5MZWZ0PXoob3QucmVsaWFibGVNYXJnaW5MZWZ0LGZ1bmN0aW9uKHQsZSl7aWYoZSlyZXR1cm4ocGFyc2VGbG9hdChTKHQsIm1hcmdpbkxlZnQiKSl8fHQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdC1LdCh0LHttYXJnaW5MZWZ0OjB9LGZ1bmN0aW9uKCl7cmV0dXJuIHQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdH0pKSsicHgifSksc3QuY3NzSG9va3MubWFyZ2luUmlnaHQ9eihvdC5yZWxpYWJsZU1hcmdpblJpZ2h0LGZ1bmN0aW9uKHQsZSl7aWYoZSlyZXR1cm4gS3QodCx7ZGlzcGxheToiaW5saW5lLWJsb2NrIn0sUyxbdCwibWFyZ2luUmlnaHQiXSl9KSxzdC5lYWNoKHttYXJnaW46IiIscGFkZGluZzoiIixib3JkZXI6IldpZHRoIn0sZnVuY3Rpb24odCxlKXtzdC5jc3NIb29rc1t0K2VdPXtleHBhbmQ6ZnVuY3Rpb24ocil7Zm9yKHZhciBuPTAsbz17fSxpPSJzdHJpbmciPT10eXBlb2Ygcj9yLnNwbGl0KCIgIik6W3JdO248NDtuKyspb1t0K0N0W25dK2VdPWlbbl18fGlbbi0yXXx8aVswXTtyZXR1cm4gb319LFd0LnRlc3QodCl8fChzdC5jc3NIb29rc1t0K2VdLnNldD1FKX0pLHN0LmZuLmV4dGVuZCh7Y3NzOmZ1bmN0aW9uKHQsZSl7cmV0dXJuIGt0KHRoaXMsZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saT17fSxzPTA7aWYoc3QuaXNBcnJheShlKSl7Zm9yKG49UXQodCksbz1lLmxlbmd0aDtzPG87cysrKWlbZVtzXV09c3QuY3NzKHQsZVtzXSwhMSxuKTtyZXR1cm4gaX1yZXR1cm4gdm9pZCAwIT09cj9zdC5zdHlsZSh0LGUscik6c3QuY3NzKHQsZSl9LHQsZSxhcmd1bWVudHMubGVuZ3RoPjEpfSxzaG93OmZ1bmN0aW9uKCl7cmV0dXJuIE4odGhpcywhMCl9LGhpZGU6ZnVuY3Rpb24oKXtyZXR1cm4gTih0aGlzKX0sdG9nZ2xlOmZ1bmN0aW9uKHQpe3JldHVybiJib29sZWFuIj09dHlwZW9mIHQ/dD90aGlzLnNob3coKTp0aGlzLmhpZGUoKTp0aGlzLmVhY2goZnVuY3Rpb24oKXtOdCh0aGlzKT9zdCh0aGlzKS5zaG93KCk6c3QodGhpcykuaGlkZSgpfSl9fSksc3QuVHdlZW49TyxPLnByb3RvdHlwZT17Y29uc3RydWN0b3I6Tyxpbml0OmZ1bmN0aW9uKHQsZSxyLG4sbyxpKXt0aGlzLmVsZW09dCx0aGlzLnByb3A9cix0aGlzLmVhc2luZz1vfHxzdC5lYXNpbmcuX2RlZmF1bHQsdGhpcy5vcHRpb25zPWUsdGhpcy5zdGFydD10aGlzLm5vdz10aGlzLmN1cigpLHRoaXMuZW5kPW4sdGhpcy51bml0PWl8fChzdC5jc3NOdW1iZXJbcl0/IiI6InB4Iil9LGN1cjpmdW5jdGlvbigpe3ZhciB0PU8ucHJvcEhvb2tzW3RoaXMucHJvcF07cmV0dXJuIHQmJnQuZ2V0P3QuZ2V0KHRoaXMpOk8ucHJvcEhvb2tzLl9kZWZhdWx0LmdldCh0aGlzKX0scnVuOmZ1bmN0aW9uKHQpe3ZhciBlLHI9Ty5wcm9wSG9va3NbdGhpcy5wcm9wXTtyZXR1cm4gdGhpcy5vcHRpb25zLmR1cmF0aW9uP3RoaXMucG9zPWU9c3QuZWFzaW5nW3RoaXMuZWFzaW5nXSh0LHRoaXMub3B0aW9ucy5kdXJhdGlvbip0LDAsMSx0aGlzLm9wdGlvbnMuZHVyYXRpb24pOnRoaXMucG9zPWU9dCx0aGlzLm5vdz0odGhpcy5lbmQtdGhpcy5zdGFydCkqZSt0aGlzLnN0YXJ0LHRoaXMub3B0aW9ucy5zdGVwJiZ0aGlzLm9wdGlvbnMuc3RlcC5jYWxsKHRoaXMuZWxlbSx0aGlzLm5vdyx0aGlzKSxyJiZyLnNldD9yLnNldCh0aGlzKTpPLnByb3BIb29rcy5fZGVmYXVsdC5zZXQodGhpcyksdGhpc319LE8ucHJvdG90eXBlLmluaXQucHJvdG90eXBlPU8ucHJvdG90eXBlLE8ucHJvcEhvb2tzPXtfZGVmYXVsdDp7Z2V0OmZ1bmN0aW9uKHQpe3ZhciBlO3JldHVybiAxIT09dC5lbGVtLm5vZGVUeXBlfHxudWxsIT10LmVsZW1bdC5wcm9wXSYmbnVsbD09dC5lbGVtLnN0eWxlW3QucHJvcF0/dC5lbGVtW3QucHJvcF06KGU9c3QuY3NzKHQuZWxlbSx0LnByb3AsIiIpLGUmJiJhdXRvIiE9PWU/ZTowKX0sc2V0OmZ1bmN0aW9uKHQpe3N0LmZ4LnN0ZXBbdC5wcm9wXT9zdC5meC5zdGVwW3QucHJvcF0odCk6MSE9PXQuZWxlbS5ub2RlVHlwZXx8bnVsbD09dC5lbGVtLnN0eWxlW3N0LmNzc1Byb3BzW3QucHJvcF1dJiYhc3QuY3NzSG9va3NbdC5wcm9wXT90LmVsZW1bdC5wcm9wXT10Lm5vdzpzdC5zdHlsZSh0LmVsZW0sdC5wcm9wLHQubm93K3QudW5pdCl9fX0sTy5wcm9wSG9va3Muc2Nyb2xsVG9wPU8ucHJvcEhvb2tzLnNjcm9sbExlZnQ9e3NldDpmdW5jdGlvbih0KXt0LmVsZW0ubm9kZVR5cGUmJnQuZWxlbS5wYXJlbnROb2RlJiYodC5lbGVtW3QucHJvcF09dC5ub3cpfX0sc3QuZWFzaW5nPXtsaW5lYXI6ZnVuY3Rpb24odCl7cmV0dXJuIHR9LHN3aW5nOmZ1bmN0aW9uKHQpe3JldHVybi41LU1hdGguY29zKHQqTWF0aC5QSSkvMn0sX2RlZmF1bHQ6InN3aW5nIn0sc3QuZng9Ty5wcm90b3R5cGUuaW5pdCxzdC5meC5zdGVwPXt9O3ZhciBpZSxzZSxhZT0vXig/OnRvZ2dsZXxzaG93fGhpZGUpJC8sbGU9L3F1ZXVlSG9va3MkLztzdC5BbmltYXRpb249c3QuZXh0ZW5kKEIse3R3ZWVuZXJzOnsiKiI6W2Z1bmN0aW9uKHQsZSl7dmFyIHI9dGhpcy5jcmVhdGVUd2Vlbih0LGUpO3JldHVybiBoKHIuZWxlbSx0LEF0LmV4ZWMoZSkscikscn1dfSx0d2VlbmVyOmZ1bmN0aW9uKHQsZSl7c3QuaXNGdW5jdGlvbih0KT8oZT10LHQ9WyIqIl0pOnQ9dC5tYXRjaCh3dCk7Zm9yKHZhciByLG49MCxvPXQubGVuZ3RoO248bztuKyspcj10W25dLEIudHdlZW5lcnNbcl09Qi50d2VlbmVyc1tyXXx8W10sQi50d2VlbmVyc1tyXS51bnNoaWZ0KGUpfSxwcmVmaWx0ZXJzOltSXSxwcmVmaWx0ZXI6ZnVuY3Rpb24odCxlKXtlP0IucHJlZmlsdGVycy51bnNoaWZ0KHQpOkIucHJlZmlsdGVycy5wdXNoKHQpfX0pLHN0LnNwZWVkPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj10JiYib2JqZWN0Ij09dHlwZW9mIHQ/c3QuZXh0ZW5kKHt9LHQpOntjb21wbGV0ZTpyfHwhciYmZXx8c3QuaXNGdW5jdGlvbih0KSYmdCxkdXJhdGlvbjp0LGVhc2luZzpyJiZlfHxlJiYhc3QuaXNGdW5jdGlvbihlKSYmZX07cmV0dXJuIG4uZHVyYXRpb249c3QuZngub2ZmPzA6Im51bWJlciI9PXR5cGVvZiBuLmR1cmF0aW9uP24uZHVyYXRpb246bi5kdXJhdGlvbiBpbiBzdC5meC5zcGVlZHM/c3QuZnguc3BlZWRzW24uZHVyYXRpb25dOnN0LmZ4LnNwZWVkcy5fZGVmYXVsdCxudWxsIT1uLnF1ZXVlJiZuLnF1ZXVlIT09ITB8fChuLnF1ZXVlPSJmeCIpLG4ub2xkPW4uY29tcGxldGUsbi5jb21wbGV0ZT1mdW5jdGlvbigpe3N0LmlzRnVuY3Rpb24obi5vbGQpJiZuLm9sZC5jYWxsKHRoaXMpLG4ucXVldWUmJnN0LmRlcXVldWUodGhpcyxuLnF1ZXVlKX0sbn0sc3QuZm4uZXh0ZW5kKHtmYWRlVG86ZnVuY3Rpb24odCxlLHIsbil7cmV0dXJuIHRoaXMuZmlsdGVyKE50KS5jc3MoIm9wYWNpdHkiLDApLnNob3coKS5lbmQoKS5hbmltYXRlKHtvcGFjaXR5OmV9LHQscixuKX0sYW5pbWF0ZTpmdW5jdGlvbih0LGUscixuKXt2YXIgbz1zdC5pc0VtcHR5T2JqZWN0KHQpLGk9c3Quc3BlZWQoZSxyLG4pLHM9ZnVuY3Rpb24oKXt2YXIgZT1CKHRoaXMsc3QuZXh0ZW5kKHt9LHQpLGkpOyhvfHxUdC5nZXQodGhpcywiZmluaXNoIikpJiZlLnN0b3AoITApfTtyZXR1cm4gcy5maW5pc2g9cyxvfHxpLnF1ZXVlPT09ITE/dGhpcy5lYWNoKHMpOnRoaXMucXVldWUoaS5xdWV1ZSxzKX0sc3RvcDpmdW5jdGlvbih0LGUscil7dmFyIG49ZnVuY3Rpb24odCl7dmFyIGU9dC5zdG9wO2RlbGV0ZSB0LnN0b3AsZShyKX07cmV0dXJuInN0cmluZyIhPXR5cGVvZiB0JiYocj1lLGU9dCx0PXZvaWQgMCksZSYmdCE9PSExJiZ0aGlzLnF1ZXVlKHR8fCJmeCIsW10pLHRoaXMuZWFjaChmdW5jdGlvbigpe3ZhciBlPSEwLG89bnVsbCE9dCYmdCsicXVldWVIb29rcyIsaT1zdC50aW1lcnMscz1UdC5nZXQodGhpcyk7aWYobylzW29dJiZzW29dLnN0b3AmJm4oc1tvXSk7ZWxzZSBmb3IobyBpbiBzKXNbb10mJnNbb10uc3RvcCYmbGUudGVzdChvKSYmbihzW29dKTtmb3Iobz1pLmxlbmd0aDtvLS07KWlbb10uZWxlbSE9PXRoaXN8fG51bGwhPXQmJmlbb10ucXVldWUhPT10fHwoaVtvXS5hbmltLnN0b3AociksZT0hMSxpLnNwbGljZShvLDEpKTshZSYmcnx8c3QuZGVxdWV1ZSh0aGlzLHQpfSl9LGZpbmlzaDpmdW5jdGlvbih0KXtyZXR1cm4gdCE9PSExJiYodD10fHwiZngiKSx0aGlzLmVhY2goZnVuY3Rpb24oKXt2YXIgZSxyPVR0LmdldCh0aGlzKSxuPXJbdCsicXVldWUiXSxvPXJbdCsicXVldWVIb29rcyJdLGk9c3QudGltZXJzLHM9bj9uLmxlbmd0aDowO2ZvcihyLmZpbmlzaD0hMCxzdC5xdWV1ZSh0aGlzLHQsW10pLG8mJm8uc3RvcCYmby5zdG9wLmNhbGwodGhpcywhMCksZT1pLmxlbmd0aDtlLS07KWlbZV0uZWxlbT09PXRoaXMmJmlbZV0ucXVldWU9PT10JiYoaVtlXS5hbmltLnN0b3AoITApLGkuc3BsaWNlKGUsMSkpO2ZvcihlPTA7ZTxzO2UrKyluW2VdJiZuW2VdLmZpbmlzaCYmbltlXS5maW5pc2guY2FsbCh0aGlzKTtkZWxldGUgci5maW5pc2h9KX19KSxzdC5lYWNoKFsidG9nZ2xlIiwic2hvdyIsImhpZGUiXSxmdW5jdGlvbih0LGUpe3ZhciByPXN0LmZuW2VdO3N0LmZuW2VdPWZ1bmN0aW9uKHQsbixvKXtyZXR1cm4gbnVsbD09dHx8ImJvb2xlYW4iPT10eXBlb2YgdD9yLmFwcGx5KHRoaXMsYXJndW1lbnRzKTp0aGlzLmFuaW1hdGUoRChlLCEwKSx0LG4sbyl9fSksc3QuZWFjaCh7c2xpZGVEb3duOkQoInNob3ciKSxzbGlkZVVwOkQoImhpZGUiKSxzbGlkZVRvZ2dsZTpEKCJ0b2dnbGUiKSxmYWRlSW46e29wYWNpdHk6InNob3cifSxmYWRlT3V0OntvcGFjaXR5OiJoaWRlIn0sZmFkZVRvZ2dsZTp7b3BhY2l0eToidG9nZ2xlIn19LGZ1bmN0aW9uKHQsZSl7c3QuZm5bdF09ZnVuY3Rpb24odCxyLG4pe3JldHVybiB0aGlzLmFuaW1hdGUoZSx0LHIsbil9fSksc3QudGltZXJzPVtdLHN0LmZ4LnRpY2s9ZnVuY3Rpb24oKXt2YXIgdCxlPTAscj1zdC50aW1lcnM7Zm9yKGllPXN0Lm5vdygpO2U8ci5sZW5ndGg7ZSsrKXQ9cltlXSx0KCl8fHJbZV0hPT10fHxyLnNwbGljZShlLS0sMSk7ci5sZW5ndGh8fHN0LmZ4LnN0b3AoKSxpZT12b2lkIDB9LHN0LmZ4LnRpbWVyPWZ1bmN0aW9uKHQpe3N0LnRpbWVycy5wdXNoKHQpLHQoKT9zdC5meC5zdGFydCgpOnN0LnRpbWVycy5wb3AoKX0sc3QuZnguaW50ZXJ2YWw9MTMsc3QuZnguc3RhcnQ9ZnVuY3Rpb24oKXtzZXx8KHNlPWUuc2V0SW50ZXJ2YWwoc3QuZngudGljayxzdC5meC5pbnRlcnZhbCkpfSxzdC5meC5zdG9wPWZ1bmN0aW9uKCl7ZS5jbGVhckludGVydmFsKHNlKSxzZT1udWxsfSxzdC5meC5zcGVlZHM9e3Nsb3c6NjAwLGZhc3Q6MjAwLF9kZWZhdWx0OjQwMH0sc3QuZm4uZGVsYXk9ZnVuY3Rpb24odCxyKXtyZXR1cm4gdD1zdC5meD9zdC5meC5zcGVlZHNbdF18fHQ6dCxyPXJ8fCJmeCIsdGhpcy5xdWV1ZShyLGZ1bmN0aW9uKHIsbil7dmFyIG89ZS5zZXRUaW1lb3V0KHIsdCk7bi5zdG9wPWZ1bmN0aW9uKCl7ZS5jbGVhclRpbWVvdXQobyl9fSl9LGZ1bmN0aW9uKCl7dmFyIHQ9Si5jcmVhdGVFbGVtZW50KCJpbnB1dCIpLGU9Si5jcmVhdGVFbGVtZW50KCJzZWxlY3QiKSxyPWUuYXBwZW5kQ2hpbGQoSi5jcmVhdGVFbGVtZW50KCJvcHRpb24iKSk7dC50eXBlPSJjaGVja2JveCIsb3QuY2hlY2tPbj0iIiE9PXQudmFsdWUsb3Qub3B0U2VsZWN0ZWQ9ci5zZWxlY3RlZCxlLmRpc2FibGVkPSEwLG90Lm9wdERpc2FibGVkPSFyLmRpc2FibGVkLHQ9Si5jcmVhdGVFbGVtZW50KCJpbnB1dCIpLHQudmFsdWU9InQiLHQudHlwZT0icmFkaW8iLG90LnJhZGlvVmFsdWU9InQiPT09dC52YWx1ZX0oKTt2YXIgdWUsaGU9c3QuZXhwci5hdHRySGFuZGxlO3N0LmZuLmV4dGVuZCh7YXR0cjpmdW5jdGlvbih0LGUpe3JldHVybiBrdCh0aGlzLHN0LmF0dHIsdCxlLGFyZ3VtZW50cy5sZW5ndGg+MSl9LHJlbW92ZUF0dHI6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpe3N0LnJlbW92ZUF0dHIodGhpcyx0KX0pfX0pLHN0LmV4dGVuZCh7YXR0cjpmdW5jdGlvbih0LGUscil7dmFyIG4sbyxpPXQubm9kZVR5cGU7aWYoMyE9PWkmJjghPT1pJiYyIT09aSlyZXR1cm4idW5kZWZpbmVkIj09dHlwZW9mIHQuZ2V0QXR0cmlidXRlP3N0LnByb3AodCxlLHIpOigxPT09aSYmc3QuaXNYTUxEb2ModCl8fChlPWUudG9Mb3dlckNhc2UoKSxvPXN0LmF0dHJIb29rc1tlXXx8KHN0LmV4cHIubWF0Y2guYm9vbC50ZXN0KGUpP3VlOnZvaWQgMCkpLHZvaWQgMCE9PXI/bnVsbD09PXI/dm9pZCBzdC5yZW1vdmVBdHRyKHQsZSk6byYmInNldCJpbiBvJiZ2b2lkIDAhPT0obj1vLnNldCh0LHIsZSkpP246KHQuc2V0QXR0cmlidXRlKGUscisiIikscik6byYmImdldCJpbiBvJiZudWxsIT09KG49by5nZXQodCxlKSk/bjoobj1zdC5maW5kLmF0dHIodCxlKSxudWxsPT1uP3ZvaWQgMDpuKSl9LGF0dHJIb29rczp7dHlwZTp7c2V0OmZ1bmN0aW9uKHQsZSl7aWYoIW90LnJhZGlvVmFsdWUmJiJyYWRpbyI9PT1lJiZzdC5ub2RlTmFtZSh0LCJpbnB1dCIpKXt2YXIgcj10LnZhbHVlO3JldHVybiB0LnNldEF0dHJpYnV0ZSgidHlwZSIsZSksciYmKHQudmFsdWU9ciksZX19fX0scmVtb3ZlQXR0cjpmdW5jdGlvbih0LGUpe3ZhciByLG4sbz0wLGk9ZSYmZS5tYXRjaCh3dCk7aWYoaSYmMT09PXQubm9kZVR5cGUpZm9yKDtyPWlbbysrXTspbj1zdC5wcm9wRml4W3JdfHxyLHN0LmV4cHIubWF0Y2guYm9vbC50ZXN0KHIpJiYodFtuXT0hMSksdC5yZW1vdmVBdHRyaWJ1dGUocil9fSksdWU9e3NldDpmdW5jdGlvbih0LGUscil7cmV0dXJuIGU9PT0hMT9zdC5yZW1vdmVBdHRyKHQscik6dC5zZXRBdHRyaWJ1dGUocixyKSxyfX0sc3QuZWFjaChzdC5leHByLm1hdGNoLmJvb2wuc291cmNlLm1hdGNoKC9cdysvZyksZnVuY3Rpb24odCxlKXt2YXIgcj1oZVtlXXx8c3QuZmluZC5hdHRyO2hlW2VdPWZ1bmN0aW9uKHQsZSxuKXt2YXIgbyxpO3JldHVybiBufHwoaT1oZVtlXSxoZVtlXT1vLG89bnVsbCE9cih0LGUsbik/ZS50b0xvd2VyQ2FzZSgpOm51bGwsaGVbZV09aSksb319KTt2YXIgY2U9L14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8YnV0dG9uKSQvaSxwZT0vXig/OmF8YXJlYSkkL2k7c3QuZm4uZXh0ZW5kKHtwcm9wOmZ1bmN0aW9uKHQsZSl7cmV0dXJuIGt0KHRoaXMsc3QucHJvcCx0LGUsYXJndW1lbnRzLmxlbmd0aD4xKX0scmVtb3ZlUHJvcDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCl7ZGVsZXRlIHRoaXNbc3QucHJvcEZpeFt0XXx8dF19KX19KSxzdC5leHRlbmQoe3Byb3A6ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saT10Lm5vZGVUeXBlO2lmKDMhPT1pJiY4IT09aSYmMiE9PWkpcmV0dXJuIDE9PT1pJiZzdC5pc1hNTERvYyh0KXx8KGU9c3QucHJvcEZpeFtlXXx8ZSxvPXN0LnByb3BIb29rc1tlXSksdm9pZCAwIT09cj9vJiYic2V0ImluIG8mJnZvaWQgMCE9PShuPW8uc2V0KHQscixlKSk/bjp0W2VdPXI6byYmImdldCJpbiBvJiZudWxsIT09KG49by5nZXQodCxlKSk/bjp0W2VdfSxwcm9wSG9va3M6e3RhYkluZGV4OntnZXQ6ZnVuY3Rpb24odCl7dmFyIGU9c3QuZmluZC5hdHRyKHQsInRhYmluZGV4Iik7cmV0dXJuIGU/cGFyc2VJbnQoZSwxMCk6Y2UudGVzdCh0Lm5vZGVOYW1lKXx8cGUudGVzdCh0Lm5vZGVOYW1lKSYmdC5ocmVmPzA6LTF9fX0scHJvcEZpeDp7ImZvciI6Imh0bWxGb3IiLCJjbGFzcyI6ImNsYXNzTmFtZSJ9fSksb3Qub3B0U2VsZWN0ZWR8fChzdC5wcm9wSG9va3Muc2VsZWN0ZWQ9e2dldDpmdW5jdGlvbih0KXt2YXIgZT10LnBhcmVudE5vZGU7cmV0dXJuIGUmJmUucGFyZW50Tm9kZSYmZS5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXgsbnVsbH0sc2V0OmZ1bmN0aW9uKHQpe3ZhciBlPXQucGFyZW50Tm9kZTtlJiYoZS5zZWxlY3RlZEluZGV4LGUucGFyZW50Tm9kZSYmZS5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXgpfX0pLHN0LmVhY2goWyJ0YWJJbmRleCIsInJlYWRPbmx5IiwibWF4TGVuZ3RoIiwiY2VsbFNwYWNpbmciLCJjZWxsUGFkZGluZyIsInJvd1NwYW4iLCJjb2xTcGFuIiwidXNlTWFwIiwiZnJhbWVCb3JkZXIiLCJjb250ZW50RWRpdGFibGUiXSxmdW5jdGlvbigpe3N0LnByb3BGaXhbdGhpcy50b0xvd2VyQ2FzZSgpXT10aGlzfSk7dmFyIF9lPS9bXHRcclxuXGZdL2c7c3QuZm4uZXh0ZW5kKHthZGRDbGFzczpmdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYSxsPTA7aWYoc3QuaXNGdW5jdGlvbih0KSlyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKGUpe3N0KHRoaXMpLmFkZENsYXNzKHQuY2FsbCh0aGlzLGUsTCh0aGlzKSkpfSk7aWYoInN0cmluZyI9PXR5cGVvZiB0JiZ0KWZvcihlPXQubWF0Y2god3QpfHxbXTtyPXRoaXNbbCsrXTspaWYobz1MKHIpLG49MT09PXIubm9kZVR5cGUmJigiICIrbysiICIpLnJlcGxhY2UoX2UsIiAiKSl7Zm9yKHM9MDtpPWVbcysrXTspbi5pbmRleE9mKCIgIitpKyIgIik8MCYmKG4rPWkrIiAiKTthPXN0LnRyaW0obiksbyE9PWEmJnIuc2V0QXR0cmlidXRlKCJjbGFzcyIsYSl9cmV0dXJuIHRoaXN9LHJlbW92ZUNsYXNzOmZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGw9MDtpZihzdC5pc0Z1bmN0aW9uKHQpKXJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oZSl7c3QodGhpcykucmVtb3ZlQ2xhc3ModC5jYWxsKHRoaXMsZSxMKHRoaXMpKSl9KTtpZighYXJndW1lbnRzLmxlbmd0aClyZXR1cm4gdGhpcy5hdHRyKCJjbGFzcyIsIiIpO2lmKCJzdHJpbmciPT10eXBlb2YgdCYmdClmb3IoZT10Lm1hdGNoKHd0KXx8W107cj10aGlzW2wrK107KWlmKG89TChyKSxuPTE9PT1yLm5vZGVUeXBlJiYoIiAiK28rIiAiKS5yZXBsYWNlKF9lLCIgIikpe2ZvcihzPTA7aT1lW3MrK107KWZvcig7bi5pbmRleE9mKCIgIitpKyIgIik+LTE7KW49bi5yZXBsYWNlKCIgIitpKyIgIiwiICIpO2E9c3QudHJpbShuKSxvIT09YSYmci5zZXRBdHRyaWJ1dGUoImNsYXNzIixhKX1yZXR1cm4gdGhpc30sdG9nZ2xlQ2xhc3M6ZnVuY3Rpb24odCxlKXt2YXIgcj10eXBlb2YgdDtyZXR1cm4iYm9vbGVhbiI9PXR5cGVvZiBlJiYic3RyaW5nIj09PXI/ZT90aGlzLmFkZENsYXNzKHQpOnRoaXMucmVtb3ZlQ2xhc3ModCk6c3QuaXNGdW5jdGlvbih0KT90aGlzLmVhY2goZnVuY3Rpb24ocil7c3QodGhpcykudG9nZ2xlQ2xhc3ModC5jYWxsKHRoaXMscixMKHRoaXMpLGUpLGUpfSk6dGhpcy5lYWNoKGZ1bmN0aW9uKCl7dmFyIGUsbixvLGk7aWYoInN0cmluZyI9PT1yKWZvcihuPTAsbz1zdCh0aGlzKSxpPXQubWF0Y2god3QpfHxbXTtlPWlbbisrXTspby5oYXNDbGFzcyhlKT9vLnJlbW92ZUNsYXNzKGUpOm8uYWRkQ2xhc3MoZSk7ZWxzZSB2b2lkIDAhPT10JiYiYm9vbGVhbiIhPT1yfHwoZT1MKHRoaXMpLGUmJlR0LnNldCh0aGlzLCJfX2NsYXNzTmFtZV9fIixlKSx0aGlzLnNldEF0dHJpYnV0ZSYmdGhpcy5zZXRBdHRyaWJ1dGUoImNsYXNzIixlfHx0PT09ITE/IiI6VHQuZ2V0KHRoaXMsIl9fY2xhc3NOYW1lX18iKXx8IiIpKX0pfSxoYXNDbGFzczpmdW5jdGlvbih0KXt2YXIgZSxyLG49MDtmb3IoZT0iICIrdCsiICI7cj10aGlzW24rK107KWlmKDE9PT1yLm5vZGVUeXBlJiYoIiAiK0wocikrIiAiKS5yZXBsYWNlKF9lLCIgIikuaW5kZXhPZihlKT4tMSlyZXR1cm4hMDtyZXR1cm4hMX19KTt2YXIgZGU9L1xyL2csZmU9L1tceDIwXHRcclxuXGZdKy9nO3N0LmZuLmV4dGVuZCh7dmFsOmZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvPXRoaXNbMF07e2lmKGFyZ3VtZW50cy5sZW5ndGgpcmV0dXJuIG49c3QuaXNGdW5jdGlvbih0KSx0aGlzLmVhY2goZnVuY3Rpb24ocil7dmFyIG87MT09PXRoaXMubm9kZVR5cGUmJihvPW4/dC5jYWxsKHRoaXMscixzdCh0aGlzKS52YWwoKSk6dCxudWxsPT1vP289IiI6Im51bWJlciI9PXR5cGVvZiBvP28rPSIiOnN0LmlzQXJyYXkobykmJihvPXN0Lm1hcChvLGZ1bmN0aW9uKHQpe3JldHVybiBudWxsPT10PyIiOnQrIiJ9KSksZT1zdC52YWxIb29rc1t0aGlzLnR5cGVdfHxzdC52YWxIb29rc1t0aGlzLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCldLGUmJiJzZXQiaW4gZSYmdm9pZCAwIT09ZS5zZXQodGhpcyxvLCJ2YWx1ZSIpfHwodGhpcy52YWx1ZT1vKSl9KTtpZihvKXJldHVybiBlPXN0LnZhbEhvb2tzW28udHlwZV18fHN0LnZhbEhvb2tzW28ubm9kZU5hbWUudG9Mb3dlckNhc2UoKV0sZSYmImdldCJpbiBlJiZ2b2lkIDAhPT0ocj1lLmdldChvLCJ2YWx1ZSIpKT9yOihyPW8udmFsdWUsInN0cmluZyI9PXR5cGVvZiByP3IucmVwbGFjZShkZSwiIik6bnVsbD09cj8iIjpyKX19fSksc3QuZXh0ZW5kKHt2YWxIb29rczp7b3B0aW9uOntnZXQ6ZnVuY3Rpb24odCl7dmFyIGU9c3QuZmluZC5hdHRyKHQsInZhbHVlIik7cmV0dXJuIG51bGwhPWU/ZTpzdC50cmltKHN0LnRleHQodCkpLnJlcGxhY2UoZmUsIiAiKX19LHNlbGVjdDp7Z2V0OmZ1bmN0aW9uKHQpe2Zvcih2YXIgZSxyLG49dC5vcHRpb25zLG89dC5zZWxlY3RlZEluZGV4LGk9InNlbGVjdC1vbmUiPT09dC50eXBlfHxvPDAscz1pP251bGw6W10sYT1pP28rMTpuLmxlbmd0aCxsPW88MD9hOmk/bzowO2w8YTtsKyspaWYocj1uW2xdLChyLnNlbGVjdGVkfHxsPT09bykmJihvdC5vcHREaXNhYmxlZD8hci5kaXNhYmxlZDpudWxsPT09ci5nZXRBdHRyaWJ1dGUoImRpc2FibGVkIikpJiYoIXIucGFyZW50Tm9kZS5kaXNhYmxlZHx8IXN0Lm5vZGVOYW1lKHIucGFyZW50Tm9kZSwib3B0Z3JvdXAiKSkpe2lmKGU9c3QocikudmFsKCksaSlyZXR1cm4gZTtzLnB1c2goZSl9cmV0dXJuIHN9LHNldDpmdW5jdGlvbih0LGUpe2Zvcih2YXIgcixuLG89dC5vcHRpb25zLGk9c3QubWFrZUFycmF5KGUpLHM9by5sZW5ndGg7cy0tOyluPW9bc10sKG4uc2VsZWN0ZWQ9c3QuaW5BcnJheShzdC52YWxIb29rcy5vcHRpb24uZ2V0KG4pLGkpPi0xKSYmKHI9ITApO3JldHVybiByfHwodC5zZWxlY3RlZEluZGV4PS0xKSxpfX19fSksc3QuZWFjaChbInJhZGlvIiwiY2hlY2tib3giXSxmdW5jdGlvbigpe3N0LnZhbEhvb2tzW3RoaXNdPXtzZXQ6ZnVuY3Rpb24odCxlKXtpZihzdC5pc0FycmF5KGUpKXJldHVybiB0LmNoZWNrZWQ9c3QuaW5BcnJheShzdCh0KS52YWwoKSxlKT4tMX19LG90LmNoZWNrT258fChzdC52YWxIb29rc1t0aGlzXS5nZXQ9ZnVuY3Rpb24odCl7cmV0dXJuIG51bGw9PT10LmdldEF0dHJpYnV0ZSgidmFsdWUiKT8ib24iOnQudmFsdWV9KX0pO3ZhciBtZT0vXig/OmZvY3VzaW5mb2N1c3xmb2N1c291dGJsdXIpJC87c3QuZXh0ZW5kKHN0LmV2ZW50LHt0cmlnZ2VyOmZ1bmN0aW9uKHQscixuLG8pe3ZhciBpLHMsYSxsLHUsaCxjLHA9W258fEpdLF89bnQuY2FsbCh0LCJ0eXBlIik/dC50eXBlOnQsZD1udC5jYWxsKHQsIm5hbWVzcGFjZSIpP3QubmFtZXNwYWNlLnNwbGl0KCIuIik6W107aWYocz1hPW49bnx8SiwzIT09bi5ub2RlVHlwZSYmOCE9PW4ubm9kZVR5cGUmJiFtZS50ZXN0KF8rc3QuZXZlbnQudHJpZ2dlcmVkKSYmKF8uaW5kZXhPZigiLiIpPi0xJiYoZD1fLnNwbGl0KCIuIiksXz1kLnNoaWZ0KCksZC5zb3J0KCkpLHU9Xy5pbmRleE9mKCI6Iik8MCYmIm9uIitfLHQ9dFtzdC5leHBhbmRvXT90Om5ldyBzdC5FdmVudChfLCJvYmplY3QiPT10eXBlb2YgdCYmdCksdC5pc1RyaWdnZXI9bz8yOjMsdC5uYW1lc3BhY2U9ZC5qb2luKCIuIiksdC5ybmFtZXNwYWNlPXQubmFtZXNwYWNlP25ldyBSZWdFeHAoIihefFxcLikiK2Quam9pbigiXFwuKD86LipcXC58KSIpKyIoXFwufCQpIik6bnVsbCx0LnJlc3VsdD12b2lkIDAsdC50YXJnZXR8fCh0LnRhcmdldD1uKSxyPW51bGw9PXI/W3RdOnN0Lm1ha2VBcnJheShyLFt0XSksYz1zdC5ldmVudC5zcGVjaWFsW19dfHx7fSxvfHwhYy50cmlnZ2VyfHxjLnRyaWdnZXIuYXBwbHkobixyKSE9PSExKSl7aWYoIW8mJiFjLm5vQnViYmxlJiYhc3QuaXNXaW5kb3cobikpe2ZvcihsPWMuZGVsZWdhdGVUeXBlfHxfLG1lLnRlc3QobCtfKXx8KHM9cy5wYXJlbnROb2RlKTtzO3M9cy5wYXJlbnROb2RlKXAucHVzaChzKSxhPXM7YT09PShuLm93bmVyRG9jdW1lbnR8fEopJiZwLnB1c2goYS5kZWZhdWx0Vmlld3x8YS5wYXJlbnRXaW5kb3d8fGUpfWZvcihpPTA7KHM9cFtpKytdKSYmIXQuaXNQcm9wYWdhdGlvblN0b3BwZWQoKTspdC50eXBlPWk+MT9sOmMuYmluZFR5cGV8fF8saD0oVHQuZ2V0KHMsImV2ZW50cyIpfHx7fSlbdC50eXBlXSYmVHQuZ2V0KHMsImhhbmRsZSIpLGgmJmguYXBwbHkocyxyKSxoPXUmJnNbdV0saCYmaC5hcHBseSYmanQocykmJih0LnJlc3VsdD1oLmFwcGx5KHMsciksdC5yZXN1bHQ9PT0hMSYmdC5wcmV2ZW50RGVmYXVsdCgpKTtyZXR1cm4gdC50eXBlPV8sb3x8dC5pc0RlZmF1bHRQcmV2ZW50ZWQoKXx8Yy5fZGVmYXVsdCYmYy5fZGVmYXVsdC5hcHBseShwLnBvcCgpLHIpIT09ITF8fCFqdChuKXx8dSYmc3QuaXNGdW5jdGlvbihuW19dKSYmIXN0LmlzV2luZG93KG4pJiYoYT1uW3VdLGEmJihuW3VdPW51bGwpLHN0LmV2ZW50LnRyaWdnZXJlZD1fLG5bX10oKSxzdC5ldmVudC50cmlnZ2VyZWQ9dm9pZCAwLGEmJihuW3VdPWEpKSx0LnJlc3VsdH19LHNpbXVsYXRlOmZ1bmN0aW9uKHQsZSxyKXt2YXIgbj1zdC5leHRlbmQobmV3IHN0LkV2ZW50LHIse3R5cGU6dCxpc1NpbXVsYXRlZDohMH0pO3N0LmV2ZW50LnRyaWdnZXIobixudWxsLGUpfX0pLHN0LmZuLmV4dGVuZCh7dHJpZ2dlcjpmdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXtzdC5ldmVudC50cmlnZ2VyKHQsZSx0aGlzKX0pfSx0cmlnZ2VySGFuZGxlcjpmdW5jdGlvbih0LGUpe3ZhciByPXRoaXNbMF07aWYocilyZXR1cm4gc3QuZXZlbnQudHJpZ2dlcih0LGUsciwhMCl9fSksc3QuZWFjaCgiYmx1ciBmb2N1cyBmb2N1c2luIGZvY3Vzb3V0IGxvYWQgcmVzaXplIHNjcm9sbCB1bmxvYWQgY2xpY2sgZGJsY2xpY2sgbW91c2Vkb3duIG1vdXNldXAgbW91c2Vtb3ZlIG1vdXNlb3ZlciBtb3VzZW91dCBtb3VzZWVudGVyIG1vdXNlbGVhdmUgY2hhbmdlIHNlbGVjdCBzdWJtaXQga2V5ZG93biBrZXlwcmVzcyBrZXl1cCBlcnJvciBjb250ZXh0bWVudSIuc3BsaXQoIiAiKSxmdW5jdGlvbih0LGUpe3N0LmZuW2VdPWZ1bmN0aW9uKHQscil7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGg+MD90aGlzLm9uKGUsbnVsbCx0LHIpOnRoaXMudHJpZ2dlcihlKX19KSxzdC5mbi5leHRlbmQoe2hvdmVyOmZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMubW91c2VlbnRlcih0KS5tb3VzZWxlYXZlKGV8fHQpfX0pLG90LmZvY3VzaW49Im9uZm9jdXNpbiJpbiBlLG90LmZvY3VzaW58fHN0LmVhY2goe2ZvY3VzOiJmb2N1c2luIixibHVyOiJmb2N1c291dCJ9LGZ1bmN0aW9uKHQsZSl7dmFyIHI9ZnVuY3Rpb24odCl7c3QuZXZlbnQuc2ltdWxhdGUoZSx0LnRhcmdldCxzdC5ldmVudC5maXgodCkpfTtzdC5ldmVudC5zcGVjaWFsW2VdPXtzZXR1cDpmdW5jdGlvbigpe3ZhciBuPXRoaXMub3duZXJEb2N1bWVudHx8dGhpcyxvPVR0LmFjY2VzcyhuLGUpO298fG4uYWRkRXZlbnRMaXN0ZW5lcih0LHIsITApLFR0LmFjY2VzcyhuLGUsKG98fDApKzEpfSx0ZWFyZG93bjpmdW5jdGlvbigpe3ZhciBuPXRoaXMub3duZXJEb2N1bWVudHx8dGhpcyxvPVR0LmFjY2VzcyhuLGUpLTE7bz9UdC5hY2Nlc3MobixlLG8pOihuLnJlbW92ZUV2ZW50TGlzdGVuZXIodCxyLCEwKSxUdC5yZW1vdmUobixlKSl9fX0pO3ZhciBnZT1lLmxvY2F0aW9uLHllPXN0Lm5vdygpLHZlPS9cPy87c3QucGFyc2VKU09OPWZ1bmN0aW9uKHQpe3JldHVybiBKU09OLnBhcnNlKHQrIiIpfSxzdC5wYXJzZVhNTD1mdW5jdGlvbih0KXt2YXIgcjtpZighdHx8InN0cmluZyIhPXR5cGVvZiB0KXJldHVybiBudWxsO3RyeXtyPShuZXcgZS5ET01QYXJzZXIpLnBhcnNlRnJvbVN0cmluZyh0LCJ0ZXh0L3htbCIpfWNhdGNoKG4pe3I9dm9pZCAwfXJldHVybiByJiYhci5nZXRFbGVtZW50c0J5VGFnTmFtZSgicGFyc2VyZXJyb3IiKS5sZW5ndGh8fHN0LmVycm9yKCJJbnZhbGlkIFhNTDogIit0KSxyfTt2YXIgYmU9LyMuKiQvLHhlPS8oWz8mXSlfPVteJl0qLyx3ZT0vXiguKj8pOlsgXHRdKihbXlxyXG5dKikkL2dtLE1lPS9eKD86YWJvdXR8YXBwfGFwcC1zdG9yYWdlfC4rLWV4dGVuc2lvbnxmaWxlfHJlc3x3aWRnZXQpOiQvLGtlPS9eKD86R0VUfEhFQUQpJC8samU9L15cL1wvLyxUZT17fSxTZT17fSx6ZT0iKi8iLmNvbmNhdCgiKiIpLFBlPUouY3JlYXRlRWxlbWVudCgiYSIpO1BlLmhyZWY9Z2UuaHJlZixzdC5leHRlbmQoe2FjdGl2ZTowLGxhc3RNb2RpZmllZDp7fSxldGFnOnt9LGFqYXhTZXR0aW5nczp7dXJsOmdlLmhyZWYsdHlwZToiR0VUIixpc0xvY2FsOk1lLnRlc3QoZ2UucHJvdG9jb2wpLGdsb2JhbDohMCxwcm9jZXNzRGF0YTohMCxhc3luYzohMCxjb250ZW50VHlwZToiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkOyBjaGFyc2V0PVVURi04IixhY2NlcHRzOnsiKiI6emUsdGV4dDoidGV4dC9wbGFpbiIsaHRtbDoidGV4dC9odG1sIix4bWw6ImFwcGxpY2F0aW9uL3htbCwgdGV4dC94bWwiLGpzb246ImFwcGxpY2F0aW9uL2pzb24sIHRleHQvamF2YXNjcmlwdCJ9LGNvbnRlbnRzOnt4bWw6L1xieG1sXGIvLGh0bWw6L1xiaHRtbC8sanNvbjovXGJqc29uXGIvfSxyZXNwb25zZUZpZWxkczp7eG1sOiJyZXNwb25zZVhNTCIsdGV4dDoicmVzcG9uc2VUZXh0Iixqc29uOiJyZXNwb25zZUpTT04ifSxjb252ZXJ0ZXJzOnsiKiB0ZXh0IjpTdHJpbmcsInRleHQgaHRtbCI6ITAsInRleHQganNvbiI6c3QucGFyc2VKU09OLCJ0ZXh0IHhtbCI6c3QucGFyc2VYTUx9LGZsYXRPcHRpb25zOnt1cmw6ITAsY29udGV4dDohMH19LGFqYXhTZXR1cDpmdW5jdGlvbih0LGUpe3JldHVybiBlP1UoVSh0LHN0LmFqYXhTZXR0aW5ncyksZSk6VShzdC5hamF4U2V0dGluZ3MsdCl9LGFqYXhQcmVmaWx0ZXI6RyhUZSksYWpheFRyYW5zcG9ydDpHKFNlKSxhamF4OmZ1bmN0aW9uKHQscil7ZnVuY3Rpb24gbih0LHIsbixhKXt2YXIgdSxjLHksdix4LE09cjsyIT09YiYmKGI9MixsJiZlLmNsZWFyVGltZW91dChsKSxvPXZvaWQgMCxzPWF8fCIiLHcucmVhZHlTdGF0ZT10PjA/NDowLHU9dD49MjAwJiZ0PDMwMHx8MzA0PT09dCxuJiYodj1ZKHAsdyxuKSksdj1IKHAsdix3LHUpLHU/KHAuaWZNb2RpZmllZCYmKHg9dy5nZXRSZXNwb25zZUhlYWRlcigiTGFzdC1Nb2RpZmllZCIpLHgmJihzdC5sYXN0TW9kaWZpZWRbaV09eCkseD13LmdldFJlc3BvbnNlSGVhZGVyKCJldGFnIikseCYmKHN0LmV0YWdbaV09eCkpLDIwND09PXR8fCJIRUFEIj09PXAudHlwZT9NPSJub2NvbnRlbnQiOjMwND09PXQ/TT0ibm90bW9kaWZpZWQiOihNPXYuc3RhdGUsYz12LmRhdGEseT12LmVycm9yLHU9IXkpKTooeT1NLCF0JiZNfHwoTT0iZXJyb3IiLHQ8MCYmKHQ9MCkpKSx3LnN0YXR1cz10LHcuc3RhdHVzVGV4dD0ocnx8TSkrIiIsdT9mLnJlc29sdmVXaXRoKF8sW2MsTSx3XSk6Zi5yZWplY3RXaXRoKF8sW3csTSx5XSksdy5zdGF0dXNDb2RlKGcpLGc9dm9pZCAwLGgmJmQudHJpZ2dlcih1PyJhamF4U3VjY2VzcyI6ImFqYXhFcnJvciIsW3cscCx1P2M6eV0pLG0uZmlyZVdpdGgoXyxbdyxNXSksaCYmKGQudHJpZ2dlcigiYWpheENvbXBsZXRlIixbdyxwXSksLS1zdC5hY3RpdmV8fHN0LmV2ZW50LnRyaWdnZXIoImFqYXhTdG9wIikpKX0ib2JqZWN0Ij09dHlwZW9mIHQmJihyPXQsdD12b2lkIDApLHI9cnx8e307dmFyIG8saSxzLGEsbCx1LGgsYyxwPXN0LmFqYXhTZXR1cCh7fSxyKSxfPXAuY29udGV4dHx8cCxkPXAuY29udGV4dCYmKF8ubm9kZVR5cGV8fF8uanF1ZXJ5KT9zdChfKTpzdC5ldmVudCxmPXN0LkRlZmVycmVkKCksbT1zdC5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IiksZz1wLnN0YXR1c0NvZGV8fHt9LHk9e30sdj17fSxiPTAseD0iY2FuY2VsZWQiLHc9e3JlYWR5U3RhdGU6MCxnZXRSZXNwb25zZUhlYWRlcjpmdW5jdGlvbih0KXt2YXIgZTtpZigyPT09Yil7aWYoIWEpZm9yKGE9e307ZT13ZS5leGVjKHMpOylhW2VbMV0udG9Mb3dlckNhc2UoKV09ZVsyXTtlPWFbdC50b0xvd2VyQ2FzZSgpXX1yZXR1cm4gbnVsbD09ZT9udWxsOmV9LGdldEFsbFJlc3BvbnNlSGVhZGVyczpmdW5jdGlvbigpe3JldHVybiAyPT09Yj9zOm51bGx9LHNldFJlcXVlc3RIZWFkZXI6ZnVuY3Rpb24odCxlKXt2YXIgcj10LnRvTG93ZXJDYXNlKCk7cmV0dXJuIGJ8fCh0PXZbcl09dltyXXx8dCx5W3RdPWUpLHRoaXN9LG92ZXJyaWRlTWltZVR5cGU6ZnVuY3Rpb24odCl7cmV0dXJuIGJ8fChwLm1pbWVUeXBlPXQpLHRoaXN9LHN0YXR1c0NvZGU6ZnVuY3Rpb24odCl7dmFyIGU7aWYodClpZihiPDIpZm9yKGUgaW4gdClnW2VdPVtnW2VdLHRbZV1dO2Vsc2Ugdy5hbHdheXModFt3LnN0YXR1c10pO3JldHVybiB0aGlzfSxhYm9ydDpmdW5jdGlvbih0KXt2YXIgZT10fHx4O3JldHVybiBvJiZvLmFib3J0KGUpLG4oMCxlKSx0aGlzfX07aWYoZi5wcm9taXNlKHcpLmNvbXBsZXRlPW0uYWRkLHcuc3VjY2Vzcz13LmRvbmUsdy5lcnJvcj13LmZhaWwscC51cmw9KCh0fHxwLnVybHx8Z2UuaHJlZikrIiIpLnJlcGxhY2UoYmUsIiIpLnJlcGxhY2UoamUsZ2UucHJvdG9jb2wrIi8vIikscC50eXBlPXIubWV0aG9kfHxyLnR5cGV8fHAubWV0aG9kfHxwLnR5cGUscC5kYXRhVHlwZXM9c3QudHJpbShwLmRhdGFUeXBlfHwiKiIpLnRvTG93ZXJDYXNlKCkubWF0Y2god3QpfHxbIiJdLG51bGw9PXAuY3Jvc3NEb21haW4pe3U9Si5jcmVhdGVFbGVtZW50KCJhIik7dHJ5e3UuaHJlZj1wLnVybCx1LmhyZWY9dS5ocmVmLHAuY3Jvc3NEb21haW49UGUucHJvdG9jb2wrIi8vIitQZS5ob3N0IT11LnByb3RvY29sKyIvLyIrdS5ob3N0fWNhdGNoKE0pe3AuY3Jvc3NEb21haW49ITB9fWlmKHAuZGF0YSYmcC5wcm9jZXNzRGF0YSYmInN0cmluZyIhPXR5cGVvZiBwLmRhdGEmJihwLmRhdGE9c3QucGFyYW0ocC5kYXRhLHAudHJhZGl0aW9uYWwpKSxWKFRlLHAscix3KSwyPT09YilyZXR1cm4gdztoPXN0LmV2ZW50JiZwLmdsb2JhbCxoJiYwPT09c3QuYWN0aXZlKysmJnN0LmV2ZW50LnRyaWdnZXIoImFqYXhTdGFydCIpLHAudHlwZT1wLnR5cGUudG9VcHBlckNhc2UoKSxwLmhhc0NvbnRlbnQ9IWtlLnRlc3QocC50eXBlKSxpPXAudXJsLHAuaGFzQ29udGVudHx8KHAuZGF0YSYmKGk9cC51cmwrPSh2ZS50ZXN0KGkpPyImIjoiPyIpK3AuZGF0YSxkZWxldGUgcC5kYXRhKSxwLmNhY2hlPT09ITEmJihwLnVybD14ZS50ZXN0KGkpP2kucmVwbGFjZSh4ZSwiJDFfPSIreWUrKyk6aSsodmUudGVzdChpKT8iJiI6Ij8iKSsiXz0iK3llKyspKSxwLmlmTW9kaWZpZWQmJihzdC5sYXN0TW9kaWZpZWRbaV0mJncuc2V0UmVxdWVzdEhlYWRlcigiSWYtTW9kaWZpZWQtU2luY2UiLHN0Lmxhc3RNb2RpZmllZFtpXSksc3QuZXRhZ1tpXSYmdy5zZXRSZXF1ZXN0SGVhZGVyKCJJZi1Ob25lLU1hdGNoIixzdC5ldGFnW2ldKSksKHAuZGF0YSYmcC5oYXNDb250ZW50JiZwLmNvbnRlbnRUeXBlIT09ITF8fHIuY29udGVudFR5cGUpJiZ3LnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtVHlwZSIscC5jb250ZW50VHlwZSksdy5zZXRSZXF1ZXN0SGVhZGVyKCJBY2NlcHQiLHAuZGF0YVR5cGVzWzBdJiZwLmFjY2VwdHNbcC5kYXRhVHlwZXNbMF1dP3AuYWNjZXB0c1twLmRhdGFUeXBlc1swXV0rKCIqIiE9PXAuZGF0YVR5cGVzWzBdPyIsICIremUrIjsgcT0wLjAxIjoiIik6cC5hY2NlcHRzWyIqIl0pO2ZvcihjIGluIHAuaGVhZGVycyl3LnNldFJlcXVlc3RIZWFkZXIoYyxwLmhlYWRlcnNbY10pO2lmKHAuYmVmb3JlU2VuZCYmKHAuYmVmb3JlU2VuZC5jYWxsKF8sdyxwKT09PSExfHwyPT09YikpcmV0dXJuIHcuYWJvcnQoKTt4PSJhYm9ydCI7Zm9yKGMgaW57c3VjY2VzczoxLGVycm9yOjEsY29tcGxldGU6MX0pd1tjXShwW2NdKTtpZihvPVYoU2UscCxyLHcpKXtpZih3LnJlYWR5U3RhdGU9MSxoJiZkLnRyaWdnZXIoImFqYXhTZW5kIixbdyxwXSksMj09PWIpcmV0dXJuIHc7cC5hc3luYyYmcC50aW1lb3V0PjAmJihsPWUuc2V0VGltZW91dChmdW5jdGlvbigpe3cuYWJvcnQoInRpbWVvdXQiKX0scC50aW1lb3V0KSk7dHJ5e2I9MSxvLnNlbmQoeSxuKX1jYXRjaChNKXtpZighKGI8MikpdGhyb3cgTTtuKC0xLE0pfX1lbHNlIG4oLTEsIk5vIFRyYW5zcG9ydCIpO3JldHVybiB3fSxnZXRKU09OOmZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gc3QuZ2V0KHQsZSxyLCJqc29uIil9LGdldFNjcmlwdDpmdW5jdGlvbih0LGUpe3JldHVybiBzdC5nZXQodCx2b2lkIDAsZSwic2NyaXB0Iil9fSksc3QuZWFjaChbImdldCIsInBvc3QiXSxmdW5jdGlvbih0LGUpe3N0W2VdPWZ1bmN0aW9uKHQscixuLG8pe3JldHVybiBzdC5pc0Z1bmN0aW9uKHIpJiYobz1vfHxuLG49cixyPXZvaWQgMCksc3QuYWpheChzdC5leHRlbmQoe3VybDp0LHR5cGU6ZSxkYXRhVHlwZTpvLGRhdGE6cixzdWNjZXNzOm59LHN0LmlzUGxhaW5PYmplY3QodCkmJnQpKX19KSxzdC5fZXZhbFVybD1mdW5jdGlvbih0KXtyZXR1cm4gc3QuYWpheCh7dXJsOnQsdHlwZToiR0VUIixkYXRhVHlwZToic2NyaXB0Iixhc3luYzohMSxnbG9iYWw6ITEsInRocm93cyI6ITB9KX0sc3QuZm4uZXh0ZW5kKHt3cmFwQWxsOmZ1bmN0aW9uKHQpe3ZhciBlO3JldHVybiBzdC5pc0Z1bmN0aW9uKHQpP3RoaXMuZWFjaChmdW5jdGlvbihlKXtzdCh0aGlzKS53cmFwQWxsKHQuY2FsbCh0aGlzLGUpKX0pOih0aGlzWzBdJiYoZT1zdCh0LHRoaXNbMF0ub3duZXJEb2N1bWVudCkuZXEoMCkuY2xvbmUoITApLHRoaXNbMF0ucGFyZW50Tm9kZSYmZS5pbnNlcnRCZWZvcmUodGhpc1swXSksZS5tYXAoZnVuY3Rpb24oKXtmb3IodmFyIHQ9dGhpczt0LmZpcnN0RWxlbWVudENoaWxkOyl0PXQuZmlyc3RFbGVtZW50Q2hpbGQ7cmV0dXJuIHR9KS5hcHBlbmQodGhpcykpLHRoaXMpfSx3cmFwSW5uZXI6ZnVuY3Rpb24odCl7cmV0dXJuIHN0LmlzRnVuY3Rpb24odCk/dGhpcy5lYWNoKGZ1bmN0aW9uKGUpe3N0KHRoaXMpLndyYXBJbm5lcih0LmNhbGwodGhpcyxlKSl9KTp0aGlzLmVhY2goZnVuY3Rpb24oKXt2YXIgZT1zdCh0aGlzKSxyPWUuY29udGVudHMoKTtyLmxlbmd0aD9yLndyYXBBbGwodCk6ZS5hcHBlbmQodCl9KX0sd3JhcDpmdW5jdGlvbih0KXt2YXIgZT1zdC5pc0Z1bmN0aW9uKHQpO3JldHVybiB0aGlzLmVhY2goZnVuY3Rpb24ocil7c3QodGhpcykud3JhcEFsbChlP3QuY2FsbCh0aGlzLHIpOnQpfSl9LHVud3JhcDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnBhcmVudCgpLmVhY2goZnVuY3Rpb24oKXtzdC5ub2RlTmFtZSh0aGlzLCJib2R5Iil8fHN0KHRoaXMpLnJlcGxhY2VXaXRoKHRoaXMuY2hpbGROb2Rlcyl9KS5lbmQoKX19KSxzdC5leHByLmZpbHRlcnMuaGlkZGVuPWZ1bmN0aW9uKHQpe3JldHVybiFzdC5leHByLmZpbHRlcnMudmlzaWJsZSh0KX0sc3QuZXhwci5maWx0ZXJzLnZpc2libGU9ZnVuY3Rpb24odCl7cmV0dXJuIHQub2Zmc2V0V2lkdGg+MHx8dC5vZmZzZXRIZWlnaHQ+MHx8dC5nZXRDbGllbnRSZWN0cygpLmxlbmd0aD4wfTt2YXIgRWU9LyUyMC9nLEFlPS9cW1xdJC8sQ2U9L1xyP1xuL2csTmU9L14oPzpzdWJtaXR8YnV0dG9ufGltYWdlfHJlc2V0fGZpbGUpJC9pLE9lPS9eKD86aW5wdXR8c2VsZWN0fHRleHRhcmVhfGtleWdlbikvaTtzdC5wYXJhbT1mdW5jdGlvbih0LGUpe3ZhciByLG49W10sbz1mdW5jdGlvbih0LGUpe2U9c3QuaXNGdW5jdGlvbihlKT9lKCk6bnVsbD09ZT8iIjplLG5bbi5sZW5ndGhdPWVuY29kZVVSSUNvbXBvbmVudCh0KSsiPSIrZW5jb2RlVVJJQ29tcG9uZW50KGUpfTtpZih2b2lkIDA9PT1lJiYoZT1zdC5hamF4U2V0dGluZ3MmJnN0LmFqYXhTZXR0aW5ncy50cmFkaXRpb25hbCksc3QuaXNBcnJheSh0KXx8dC5qcXVlcnkmJiFzdC5pc1BsYWluT2JqZWN0KHQpKXN0LmVhY2godCxmdW5jdGlvbigpe28odGhpcy5uYW1lLHRoaXMudmFsdWUpfSk7ZWxzZSBmb3IociBpbiB0KVgocix0W3JdLGUsbyk7cmV0dXJuIG4uam9pbigiJiIpLnJlcGxhY2UoRWUsIisiKX0sc3QuZm4uZXh0ZW5kKHtzZXJpYWxpemU6ZnVuY3Rpb24oKXtyZXR1cm4gc3QucGFyYW0odGhpcy5zZXJpYWxpemVBcnJheSgpKX0sc2VyaWFsaXplQXJyYXk6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tYXAoZnVuY3Rpb24oKXt2YXIgdD1zdC5wcm9wKHRoaXMsImVsZW1lbnRzIik7cmV0dXJuIHQ/c3QubWFrZUFycmF5KHQpOnRoaXN9KS5maWx0ZXIoZnVuY3Rpb24oKXt2YXIgdD10aGlzLnR5cGU7cmV0dXJuIHRoaXMubmFtZSYmIXN0KHRoaXMpLmlzKCI6ZGlzYWJsZWQiKSYmT2UudGVzdCh0aGlzLm5vZGVOYW1lKSYmIU5lLnRlc3QodCkmJih0aGlzLmNoZWNrZWR8fCFPdC50ZXN0KHQpKX0pLm1hcChmdW5jdGlvbih0LGUpe3ZhciByPXN0KHRoaXMpLnZhbCgpO3JldHVybiBudWxsPT1yP251bGw6c3QuaXNBcnJheShyKT9zdC5tYXAocixmdW5jdGlvbih0KXtyZXR1cm57bmFtZTplLm5hbWUsdmFsdWU6dC5yZXBsYWNlKENlLCJcclxuIil9fSk6e25hbWU6ZS5uYW1lLHZhbHVlOnIucmVwbGFjZShDZSwiXHJcbiIpfX0pLmdldCgpfX0pLHN0LmFqYXhTZXR0aW5ncy54aHI9ZnVuY3Rpb24oKXt0cnl7cmV0dXJuIG5ldyBlLlhNTEh0dHBSZXF1ZXN0fWNhdGNoKHQpe319O3ZhciBxZT17MDoyMDAsMTIyMzoyMDR9LERlPXN0LmFqYXhTZXR0aW5ncy54aHIoKTtvdC5jb3JzPSEhRGUmJiJ3aXRoQ3JlZGVudGlhbHMiaW4gRGUsb3QuYWpheD1EZT0hIURlLHN0LmFqYXhUcmFuc3BvcnQoZnVuY3Rpb24odCl7dmFyIHIsbjtpZihvdC5jb3JzfHxEZSYmIXQuY3Jvc3NEb21haW4pcmV0dXJue3NlbmQ6ZnVuY3Rpb24obyxpKXt2YXIgcyxhPXQueGhyKCk7aWYoYS5vcGVuKHQudHlwZSx0LnVybCx0LmFzeW5jLHQudXNlcm5hbWUsdC5wYXNzd29yZCksdC54aHJGaWVsZHMpZm9yKHMgaW4gdC54aHJGaWVsZHMpYVtzXT10LnhockZpZWxkc1tzXTt0Lm1pbWVUeXBlJiZhLm92ZXJyaWRlTWltZVR5cGUmJmEub3ZlcnJpZGVNaW1lVHlwZSh0Lm1pbWVUeXBlKSx0LmNyb3NzRG9tYWlufHxvWyJYLVJlcXVlc3RlZC1XaXRoIl18fChvWyJYLVJlcXVlc3RlZC1XaXRoIl09IlhNTEh0dHBSZXF1ZXN0Iik7CmZvcihzIGluIG8pYS5zZXRSZXF1ZXN0SGVhZGVyKHMsb1tzXSk7cj1mdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oKXtyJiYocj1uPWEub25sb2FkPWEub25lcnJvcj1hLm9uYWJvcnQ9YS5vbnJlYWR5c3RhdGVjaGFuZ2U9bnVsbCwiYWJvcnQiPT09dD9hLmFib3J0KCk6ImVycm9yIj09PXQ/Im51bWJlciIhPXR5cGVvZiBhLnN0YXR1cz9pKDAsImVycm9yIik6aShhLnN0YXR1cyxhLnN0YXR1c1RleHQpOmkocWVbYS5zdGF0dXNdfHxhLnN0YXR1cyxhLnN0YXR1c1RleHQsInRleHQiIT09KGEucmVzcG9uc2VUeXBlfHwidGV4dCIpfHwic3RyaW5nIiE9dHlwZW9mIGEucmVzcG9uc2VUZXh0P3tiaW5hcnk6YS5yZXNwb25zZX06e3RleHQ6YS5yZXNwb25zZVRleHR9LGEuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkpKX19LGEub25sb2FkPXIoKSxuPWEub25lcnJvcj1yKCJlcnJvciIpLHZvaWQgMCE9PWEub25hYm9ydD9hLm9uYWJvcnQ9bjphLm9ucmVhZHlzdGF0ZWNoYW5nZT1mdW5jdGlvbigpezQ9PT1hLnJlYWR5U3RhdGUmJmUuc2V0VGltZW91dChmdW5jdGlvbigpe3ImJm4oKX0pfSxyPXIoImFib3J0Iik7dHJ5e2Euc2VuZCh0Lmhhc0NvbnRlbnQmJnQuZGF0YXx8bnVsbCl9Y2F0Y2gobCl7aWYocil0aHJvdyBsfX0sYWJvcnQ6ZnVuY3Rpb24oKXtyJiZyKCl9fX0pLHN0LmFqYXhTZXR1cCh7YWNjZXB0czp7c2NyaXB0OiJ0ZXh0L2phdmFzY3JpcHQsIGFwcGxpY2F0aW9uL2phdmFzY3JpcHQsIGFwcGxpY2F0aW9uL2VjbWFzY3JpcHQsIGFwcGxpY2F0aW9uL3gtZWNtYXNjcmlwdCJ9LGNvbnRlbnRzOntzY3JpcHQ6L1xiKD86amF2YXxlY21hKXNjcmlwdFxiL30sY29udmVydGVyczp7InRleHQgc2NyaXB0IjpmdW5jdGlvbih0KXtyZXR1cm4gc3QuZ2xvYmFsRXZhbCh0KSx0fX19KSxzdC5hamF4UHJlZmlsdGVyKCJzY3JpcHQiLGZ1bmN0aW9uKHQpe3ZvaWQgMD09PXQuY2FjaGUmJih0LmNhY2hlPSExKSx0LmNyb3NzRG9tYWluJiYodC50eXBlPSJHRVQiKX0pLHN0LmFqYXhUcmFuc3BvcnQoInNjcmlwdCIsZnVuY3Rpb24odCl7aWYodC5jcm9zc0RvbWFpbil7dmFyIGUscjtyZXR1cm57c2VuZDpmdW5jdGlvbihuLG8pe2U9c3QoIjxzY3JpcHQ+IikucHJvcCh7Y2hhcnNldDp0LnNjcmlwdENoYXJzZXQsc3JjOnQudXJsfSkub24oImxvYWQgZXJyb3IiLHI9ZnVuY3Rpb24odCl7ZS5yZW1vdmUoKSxyPW51bGwsdCYmbygiZXJyb3IiPT09dC50eXBlPzQwNDoyMDAsdC50eXBlKX0pLEouaGVhZC5hcHBlbmRDaGlsZChlWzBdKX0sYWJvcnQ6ZnVuY3Rpb24oKXtyJiZyKCl9fX19KTt2YXIgSWU9W10sUmU9Lyg9KVw/KD89JnwkKXxcP1w/LztzdC5hamF4U2V0dXAoe2pzb25wOiJjYWxsYmFjayIsanNvbnBDYWxsYmFjazpmdW5jdGlvbigpe3ZhciB0PUllLnBvcCgpfHxzdC5leHBhbmRvKyJfIit5ZSsrO3JldHVybiB0aGlzW3RdPSEwLHR9fSksc3QuYWpheFByZWZpbHRlcigianNvbiBqc29ucCIsZnVuY3Rpb24odCxyLG4pe3ZhciBvLGkscyxhPXQuanNvbnAhPT0hMSYmKFJlLnRlc3QodC51cmwpPyJ1cmwiOiJzdHJpbmciPT10eXBlb2YgdC5kYXRhJiYwPT09KHQuY29udGVudFR5cGV8fCIiKS5pbmRleE9mKCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiKSYmUmUudGVzdCh0LmRhdGEpJiYiZGF0YSIpO2lmKGF8fCJqc29ucCI9PT10LmRhdGFUeXBlc1swXSlyZXR1cm4gbz10Lmpzb25wQ2FsbGJhY2s9c3QuaXNGdW5jdGlvbih0Lmpzb25wQ2FsbGJhY2spP3QuanNvbnBDYWxsYmFjaygpOnQuanNvbnBDYWxsYmFjayxhP3RbYV09dFthXS5yZXBsYWNlKFJlLCIkMSIrbyk6dC5qc29ucCE9PSExJiYodC51cmwrPSh2ZS50ZXN0KHQudXJsKT8iJiI6Ij8iKSt0Lmpzb25wKyI9IitvKSx0LmNvbnZlcnRlcnNbInNjcmlwdCBqc29uIl09ZnVuY3Rpb24oKXtyZXR1cm4gc3x8c3QuZXJyb3IobysiIHdhcyBub3QgY2FsbGVkIiksc1swXX0sdC5kYXRhVHlwZXNbMF09Impzb24iLGk9ZVtvXSxlW29dPWZ1bmN0aW9uKCl7cz1hcmd1bWVudHN9LG4uYWx3YXlzKGZ1bmN0aW9uKCl7dm9pZCAwPT09aT9zdChlKS5yZW1vdmVQcm9wKG8pOmVbb109aSx0W29dJiYodC5qc29ucENhbGxiYWNrPXIuanNvbnBDYWxsYmFjayxJZS5wdXNoKG8pKSxzJiZzdC5pc0Z1bmN0aW9uKGkpJiZpKHNbMF0pLHM9aT12b2lkIDB9KSwic2NyaXB0In0pLHN0LnBhcnNlSFRNTD1mdW5jdGlvbih0LGUscil7aWYoIXR8fCJzdHJpbmciIT10eXBlb2YgdClyZXR1cm4gbnVsbDsiYm9vbGVhbiI9PXR5cGVvZiBlJiYocj1lLGU9ITEpLGU9ZXx8Sjt2YXIgbj1mdC5leGVjKHQpLG89IXImJltdO3JldHVybiBuP1tlLmNyZWF0ZUVsZW1lbnQoblsxXSldOihuPV8oW3RdLGUsbyksbyYmby5sZW5ndGgmJnN0KG8pLnJlbW92ZSgpLHN0Lm1lcmdlKFtdLG4uY2hpbGROb2RlcykpfTt2YXIgRmU9c3QuZm4ubG9hZDtzdC5mbi5sb2FkPWZ1bmN0aW9uKHQsZSxyKXtpZigic3RyaW5nIiE9dHlwZW9mIHQmJkZlKXJldHVybiBGZS5hcHBseSh0aGlzLGFyZ3VtZW50cyk7dmFyIG4sbyxpLHM9dGhpcyxhPXQuaW5kZXhPZigiICIpO3JldHVybiBhPi0xJiYobj1zdC50cmltKHQuc2xpY2UoYSkpLHQ9dC5zbGljZSgwLGEpKSxzdC5pc0Z1bmN0aW9uKGUpPyhyPWUsZT12b2lkIDApOmUmJiJvYmplY3QiPT10eXBlb2YgZSYmKG89IlBPU1QiKSxzLmxlbmd0aD4wJiZzdC5hamF4KHt1cmw6dCx0eXBlOm98fCJHRVQiLGRhdGFUeXBlOiJodG1sIixkYXRhOmV9KS5kb25lKGZ1bmN0aW9uKHQpe2k9YXJndW1lbnRzLHMuaHRtbChuP3N0KCI8ZGl2PiIpLmFwcGVuZChzdC5wYXJzZUhUTUwodCkpLmZpbmQobik6dCl9KS5hbHdheXMociYmZnVuY3Rpb24odCxlKXtzLmVhY2goZnVuY3Rpb24oKXtyLmFwcGx5KHRoaXMsaXx8W3QucmVzcG9uc2VUZXh0LGUsdF0pfSl9KSx0aGlzfSxzdC5lYWNoKFsiYWpheFN0YXJ0IiwiYWpheFN0b3AiLCJhamF4Q29tcGxldGUiLCJhamF4RXJyb3IiLCJhamF4U3VjY2VzcyIsImFqYXhTZW5kIl0sZnVuY3Rpb24odCxlKXtzdC5mbltlXT1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5vbihlLHQpfX0pLHN0LmV4cHIuZmlsdGVycy5hbmltYXRlZD1mdW5jdGlvbih0KXtyZXR1cm4gc3QuZ3JlcChzdC50aW1lcnMsZnVuY3Rpb24oZSl7cmV0dXJuIHQ9PT1lLmVsZW19KS5sZW5ndGh9LHN0Lm9mZnNldD17c2V0T2Zmc2V0OmZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoPXN0LmNzcyh0LCJwb3NpdGlvbiIpLGM9c3QodCkscD17fTsic3RhdGljIj09PWgmJih0LnN0eWxlLnBvc2l0aW9uPSJyZWxhdGl2ZSIpLGE9Yy5vZmZzZXQoKSxpPXN0LmNzcyh0LCJ0b3AiKSxsPXN0LmNzcyh0LCJsZWZ0IiksdT0oImFic29sdXRlIj09PWh8fCJmaXhlZCI9PT1oKSYmKGkrbCkuaW5kZXhPZigiYXV0byIpPi0xLHU/KG49Yy5wb3NpdGlvbigpLHM9bi50b3Asbz1uLmxlZnQpOihzPXBhcnNlRmxvYXQoaSl8fDAsbz1wYXJzZUZsb2F0KGwpfHwwKSxzdC5pc0Z1bmN0aW9uKGUpJiYoZT1lLmNhbGwodCxyLHN0LmV4dGVuZCh7fSxhKSkpLG51bGwhPWUudG9wJiYocC50b3A9ZS50b3AtYS50b3ArcyksbnVsbCE9ZS5sZWZ0JiYocC5sZWZ0PWUubGVmdC1hLmxlZnQrbyksInVzaW5nImluIGU/ZS51c2luZy5jYWxsKHQscCk6Yy5jc3MocCl9fSxzdC5mbi5leHRlbmQoe29mZnNldDpmdW5jdGlvbih0KXtpZihhcmd1bWVudHMubGVuZ3RoKXJldHVybiB2b2lkIDA9PT10P3RoaXM6dGhpcy5lYWNoKGZ1bmN0aW9uKGUpe3N0Lm9mZnNldC5zZXRPZmZzZXQodGhpcyx0LGUpfSk7dmFyIGUscixuPXRoaXNbMF0sbz17dG9wOjAsbGVmdDowfSxpPW4mJm4ub3duZXJEb2N1bWVudDtpZihpKXJldHVybiBlPWkuZG9jdW1lbnRFbGVtZW50LHN0LmNvbnRhaW5zKGUsbik/KG89bi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxyPSQoaSkse3RvcDpvLnRvcCtyLnBhZ2VZT2Zmc2V0LWUuY2xpZW50VG9wLGxlZnQ6by5sZWZ0K3IucGFnZVhPZmZzZXQtZS5jbGllbnRMZWZ0fSk6b30scG9zaXRpb246ZnVuY3Rpb24oKXtpZih0aGlzWzBdKXt2YXIgdCxlLHI9dGhpc1swXSxuPXt0b3A6MCxsZWZ0OjB9O3JldHVybiJmaXhlZCI9PT1zdC5jc3MociwicG9zaXRpb24iKT9lPXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk6KHQ9dGhpcy5vZmZzZXRQYXJlbnQoKSxlPXRoaXMub2Zmc2V0KCksc3Qubm9kZU5hbWUodFswXSwiaHRtbCIpfHwobj10Lm9mZnNldCgpKSxuLnRvcCs9c3QuY3NzKHRbMF0sImJvcmRlclRvcFdpZHRoIiwhMCksbi5sZWZ0Kz1zdC5jc3ModFswXSwiYm9yZGVyTGVmdFdpZHRoIiwhMCkpLHt0b3A6ZS50b3Atbi50b3Atc3QuY3NzKHIsIm1hcmdpblRvcCIsITApLGxlZnQ6ZS5sZWZ0LW4ubGVmdC1zdC5jc3MociwibWFyZ2luTGVmdCIsITApfX19LG9mZnNldFBhcmVudDpmdW5jdGlvbigpe3JldHVybiB0aGlzLm1hcChmdW5jdGlvbigpe2Zvcih2YXIgdD10aGlzLm9mZnNldFBhcmVudDt0JiYic3RhdGljIj09PXN0LmNzcyh0LCJwb3NpdGlvbiIpOyl0PXQub2Zmc2V0UGFyZW50O3JldHVybiB0fHxadH0pfX0pLHN0LmVhY2goe3Njcm9sbExlZnQ6InBhZ2VYT2Zmc2V0IixzY3JvbGxUb3A6InBhZ2VZT2Zmc2V0In0sZnVuY3Rpb24odCxlKXt2YXIgcj0icGFnZVlPZmZzZXQiPT09ZTtzdC5mblt0XT1mdW5jdGlvbihuKXtyZXR1cm4ga3QodGhpcyxmdW5jdGlvbih0LG4sbyl7dmFyIGk9JCh0KTtyZXR1cm4gdm9pZCAwPT09bz9pP2lbZV06dFtuXTp2b2lkKGk/aS5zY3JvbGxUbyhyP2kucGFnZVhPZmZzZXQ6byxyP286aS5wYWdlWU9mZnNldCk6dFtuXT1vKX0sdCxuLGFyZ3VtZW50cy5sZW5ndGgpfX0pLHN0LmVhY2goWyJ0b3AiLCJsZWZ0Il0sZnVuY3Rpb24odCxlKXtzdC5jc3NIb29rc1tlXT16KG90LnBpeGVsUG9zaXRpb24sZnVuY3Rpb24odCxyKXtpZihyKXJldHVybiByPVModCxlKSxKdC50ZXN0KHIpP3N0KHQpLnBvc2l0aW9uKClbZV0rInB4IjpyfSl9KSxzdC5lYWNoKHtIZWlnaHQ6ImhlaWdodCIsV2lkdGg6IndpZHRoIn0sZnVuY3Rpb24odCxlKXtzdC5lYWNoKHtwYWRkaW5nOiJpbm5lciIrdCxjb250ZW50OmUsIiI6Im91dGVyIit0fSxmdW5jdGlvbihyLG4pe3N0LmZuW25dPWZ1bmN0aW9uKG4sbyl7dmFyIGk9YXJndW1lbnRzLmxlbmd0aCYmKHJ8fCJib29sZWFuIiE9dHlwZW9mIG4pLHM9cnx8KG49PT0hMHx8bz09PSEwPyJtYXJnaW4iOiJib3JkZXIiKTtyZXR1cm4ga3QodGhpcyxmdW5jdGlvbihlLHIsbil7dmFyIG87cmV0dXJuIHN0LmlzV2luZG93KGUpP2UuZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50WyJjbGllbnQiK3RdOjk9PT1lLm5vZGVUeXBlPyhvPWUuZG9jdW1lbnRFbGVtZW50LE1hdGgubWF4KGUuYm9keVsic2Nyb2xsIit0XSxvWyJzY3JvbGwiK3RdLGUuYm9keVsib2Zmc2V0Iit0XSxvWyJvZmZzZXQiK3RdLG9bImNsaWVudCIrdF0pKTp2b2lkIDA9PT1uP3N0LmNzcyhlLHIscyk6c3Quc3R5bGUoZSxyLG4scyl9LGUsaT9uOnZvaWQgMCxpLG51bGwpfX0pfSksc3QuZm4uZXh0ZW5kKHtiaW5kOmZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gdGhpcy5vbih0LG51bGwsZSxyKX0sdW5iaW5kOmZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMub2ZmKHQsbnVsbCxlKX0sZGVsZWdhdGU6ZnVuY3Rpb24odCxlLHIsbil7cmV0dXJuIHRoaXMub24oZSx0LHIsbil9LHVuZGVsZWdhdGU6ZnVuY3Rpb24odCxlLHIpe3JldHVybiAxPT09YXJndW1lbnRzLmxlbmd0aD90aGlzLm9mZih0LCIqKiIpOnRoaXMub2ZmKGUsdHx8IioqIixyKX0sc2l6ZTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmxlbmd0aH19KSxzdC5mbi5hbmRTZWxmPXN0LmZuLmFkZEJhY2ssImZ1bmN0aW9uIj09dHlwZW9mIHQmJnQuYW1kJiZ0KCJqcXVlcnkiLFtdLGZ1bmN0aW9uKCl7cmV0dXJuIHN0fSk7dmFyIEJlPWUualF1ZXJ5LExlPWUuJDtyZXR1cm4gc3Qubm9Db25mbGljdD1mdW5jdGlvbih0KXtyZXR1cm4gZS4kPT09c3QmJihlLiQ9TGUpLHQmJmUualF1ZXJ5PT09c3QmJihlLmpRdWVyeT1CZSksc3R9LHJ8fChlLmpRdWVyeT1lLiQ9c3QpLHN0fSl9LHt9XSxqc25sb2c6W2Z1bmN0aW9uKHQsZSxyKXtmdW5jdGlvbiBuKHQpe2lmKCF0KXJldHVybiBuLl9fO0FycmF5LnByb3RvdHlwZS5yZWR1Y2V8fChBcnJheS5wcm90b3R5cGUucmVkdWNlPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPWUsbj0wO248dGhpcy5sZW5ndGg7bisrKXI9dChyLHRoaXNbbl0sbix0aGlzKTtyZXR1cm4gcn0pO3ZhciBlPSIiLHI9KCIuIit0KS5zcGxpdCgiLiIpLnJlZHVjZShmdW5jdGlvbih0LHIsbyxpKXtlP2UrPSIuIityOmU9cjt2YXIgcz10WyJfXyIrZV07cmV0dXJuIHZvaWQgMD09PXMmJihuLkxvZ2dlci5wcm90b3R5cGU9dCxzPW5ldyBuLkxvZ2dlcihlKSx0WyJfXyIrZV09cyksc30sbi5fXyk7cmV0dXJuIHJ9LyogCiAqIEpTTkxvZyAyLjIwLjAKICogT3BlbiBzb3VyY2UgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLgogKiBDb3B5cmlnaHQgMjAxNiBNYXR0aWpzIFBlcmRlY2sgQWxsIHJpZ2h0cyByZXNlcnZlZC4KICovCnZhciBuLG89dGhpcyYmdGhpcy5fX2V4dGVuZHN8fGZ1bmN0aW9uKHQsZSl7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9dH1mb3IodmFyIG4gaW4gZSllLmhhc093blByb3BlcnR5KG4pJiYodFtuXT1lW25dKTt0LnByb3RvdHlwZT1udWxsPT09ZT9PYmplY3QuY3JlYXRlKGUpOihyLnByb3RvdHlwZT1lLnByb3RvdHlwZSxuZXcgcil9OyFmdW5jdGlvbih0KXtmdW5jdGlvbiBlKHQsZSxyKXtpZih2b2lkIDAhPT1lW3RdKXJldHVybiBudWxsPT09ZVt0XT92b2lkIGRlbGV0ZSByW3RdOnZvaWQoclt0XT1lW3RdKX1mdW5jdGlvbiByKGUpe2lmKG51bGwhPXQuZW5hYmxlZCYmIXQuZW5hYmxlZClyZXR1cm4hMTtpZihudWxsIT10Lm1heE1lc3NhZ2VzJiZ0Lm1heE1lc3NhZ2VzPDEpcmV0dXJuITE7dHJ5e2lmKGUudXNlckFnZW50UmVnZXgmJiFuZXcgUmVnRXhwKGUudXNlckFnZW50UmVnZXgpLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpcmV0dXJuITF9Y2F0Y2gocil7fXRyeXtpZihlLmlwUmVnZXgmJnQuY2xpZW50SVAmJiFuZXcgUmVnRXhwKGUuaXBSZWdleCkudGVzdCh0LmNsaWVudElQKSlyZXR1cm4hMX1jYXRjaChyKXt9cmV0dXJuITB9ZnVuY3Rpb24gbih0LGUpe3RyeXtpZih0LmRpc2FsbG93JiZuZXcgUmVnRXhwKHQuZGlzYWxsb3cpLnRlc3QoZSkpcmV0dXJuITF9Y2F0Y2gocil7fXJldHVybiEwfWZ1bmN0aW9uIGkodCl7cmV0dXJuImZ1bmN0aW9uIj09dHlwZW9mIHQ/dCBpbnN0YW5jZW9mIFJlZ0V4cD90LnRvU3RyaW5nKCk6dCgpOnR9ZnVuY3Rpb24gcyh0KXt2YXIgZSxyPWkodCk7c3dpdGNoKHR5cGVvZiByKXtjYXNlInN0cmluZyI6cmV0dXJuIG5ldyB2KHIsbnVsbCxyKTtjYXNlIm51bWJlciI6cmV0dXJuIGU9ci50b1N0cmluZygpLG5ldyB2KGUsbnVsbCxlKTtjYXNlImJvb2xlYW4iOnJldHVybiBlPXIudG9TdHJpbmcoKSxuZXcgdihlLG51bGwsZSk7Y2FzZSJ1bmRlZmluZWQiOnJldHVybiBuZXcgdigidW5kZWZpbmVkIixudWxsLCJ1bmRlZmluZWQiKTtjYXNlIm9iamVjdCI6cmV0dXJuIHIgaW5zdGFuY2VvZiBSZWdFeHB8fHIgaW5zdGFuY2VvZiBTdHJpbmd8fHIgaW5zdGFuY2VvZiBOdW1iZXJ8fHIgaW5zdGFuY2VvZiBCb29sZWFuPyhlPXIudG9TdHJpbmcoKSxuZXcgdihlLG51bGwsZSkpOm5ldyB2KG51bGwscixKU09OLnN0cmluZ2lmeShyKSk7ZGVmYXVsdDpyZXR1cm4gbmV3IHYoInVua25vd24iLG51bGwsInVua25vd24iKX19ZnVuY3Rpb24gYSh0KXtyZXR1cm4gZSgiZW5hYmxlZCIsdCx0aGlzKSxlKCJtYXhNZXNzYWdlcyIsdCx0aGlzKSxlKCJkZWZhdWx0QWpheFVybCIsdCx0aGlzKSxlKCJjbGllbnRJUCIsdCx0aGlzKSxlKCJyZXF1ZXN0SWQiLHQsdGhpcyksZSgiZGVmYXVsdEJlZm9yZVNlbmQiLHQsdGhpcyksdGhpc31mdW5jdGlvbiBsKCl7cmV0dXJuLTIxNDc0ODM2NDh9ZnVuY3Rpb24gdSgpe3JldHVybiAxZTN9ZnVuY3Rpb24gaCgpe3JldHVybiAyZTN9ZnVuY3Rpb24gYygpe3JldHVybiAzZTN9ZnVuY3Rpb24gcCgpe3JldHVybiA0ZTN9ZnVuY3Rpb24gXygpe3JldHVybiA1ZTN9ZnVuY3Rpb24gZCgpe3JldHVybiA2ZTN9ZnVuY3Rpb24gZigpe3JldHVybiAyMTQ3NDgzNjQ3fWZ1bmN0aW9uIG0odCl7cmV0dXJuIHQ8PTFlMz8idHJhY2UiOnQ8PTJlMz8iZGVidWciOnQ8PTNlMz8iaW5mbyI6dDw9NGUzPyJ3YXJuIjp0PD01ZTM/ImVycm9yIjoiZmF0YWwifWZ1bmN0aW9uIGcodCl7cmV0dXJuIG5ldyBNKHQpfWZ1bmN0aW9uIHkodCl7cmV0dXJuIG5ldyBrKHQpfXQucmVxdWVzdElkPSIiO3ZhciB2PWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCh0LGUscil7dGhpcy5tc2c9dCx0aGlzLm1ldGE9ZSx0aGlzLmZpbmFsU3RyaW5nPXJ9cmV0dXJuIHR9KCk7dC5zZXRPcHRpb25zPWEsdC5nZXRBbGxMZXZlbD1sLHQuZ2V0VHJhY2VMZXZlbD11LHQuZ2V0RGVidWdMZXZlbD1oLHQuZ2V0SW5mb0xldmVsPWMsdC5nZXRXYXJuTGV2ZWw9cCx0LmdldEVycm9yTGV2ZWw9Xyx0LmdldEZhdGFsTGV2ZWw9ZCx0LmdldE9mZkxldmVsPWY7dmFyIGI9ZnVuY3Rpb24oKXtmdW5jdGlvbiB0KHQsZSl7dGhpcy5pbm5lcj1lLHRoaXMubmFtZT0iSkwuRXhjZXB0aW9uIix0aGlzLm1lc3NhZ2U9cyh0KS5maW5hbFN0cmluZ31yZXR1cm4gdH0oKTt0LkV4Y2VwdGlvbj1iLGIucHJvdG90eXBlPW5ldyBFcnJvcjt2YXIgeD1mdW5jdGlvbigpe2Z1bmN0aW9uIHQodCxlLHIsbil7dGhpcy5sPXQsdGhpcy5tPWUsdGhpcy5uPXIsdGhpcy50PW59cmV0dXJuIHR9KCk7dC5Mb2dJdGVtPXg7dmFyIHc9ZnVuY3Rpb24oKXtmdW5jdGlvbiBvKGUscil7dGhpcy5hcHBlbmRlck5hbWU9ZSx0aGlzLnNlbmRMb2dJdGVtcz1yLHRoaXMubGV2ZWw9dC5nZXRUcmFjZUxldmVsKCksdGhpcy5zZW5kV2l0aEJ1ZmZlckxldmVsPTIxNDc0ODM2NDcsdGhpcy5zdG9yZUluQnVmZmVyTGV2ZWw9LTIxNDc0ODM2NDgsdGhpcy5idWZmZXJTaXplPTAsdGhpcy5iYXRjaFNpemU9MSx0aGlzLmJ1ZmZlcj1bXSx0aGlzLmJhdGNoQnVmZmVyPVtdfXJldHVybiBvLnByb3RvdHlwZS5zZXRPcHRpb25zPWZ1bmN0aW9uKHQpe3JldHVybiBlKCJsZXZlbCIsdCx0aGlzKSxlKCJpcFJlZ2V4Iix0LHRoaXMpLGUoInVzZXJBZ2VudFJlZ2V4Iix0LHRoaXMpLGUoImRpc2FsbG93Iix0LHRoaXMpLGUoInNlbmRXaXRoQnVmZmVyTGV2ZWwiLHQsdGhpcyksZSgic3RvcmVJbkJ1ZmZlckxldmVsIix0LHRoaXMpLGUoImJ1ZmZlclNpemUiLHQsdGhpcyksZSgiYmF0Y2hTaXplIix0LHRoaXMpLHRoaXMuYnVmZmVyU2l6ZTx0aGlzLmJ1ZmZlci5sZW5ndGgmJih0aGlzLmJ1ZmZlci5sZW5ndGg9dGhpcy5idWZmZXJTaXplKSx0aGlzfSxvLnByb3RvdHlwZS5sb2c9ZnVuY3Rpb24odCxlLG8saSxzLGEsbCl7dmFyIHU7aWYocih0aGlzKSYmbih0aGlzLGEpJiYhKHM8dGhpcy5zdG9yZUluQnVmZmVyTGV2ZWwpKXJldHVybiB1PW5ldyB4KHMsYSxsLChuZXcgRGF0ZSkuZ2V0VGltZSgpKSxzPHRoaXMubGV2ZWw/dm9pZCh0aGlzLmJ1ZmZlclNpemU+MCYmKHRoaXMuYnVmZmVyLnB1c2godSksdGhpcy5idWZmZXIubGVuZ3RoPnRoaXMuYnVmZmVyU2l6ZSYmdGhpcy5idWZmZXIuc2hpZnQoKSkpOihzPHRoaXMuc2VuZFdpdGhCdWZmZXJMZXZlbD90aGlzLmJhdGNoQnVmZmVyLnB1c2godSk6KHRoaXMuYnVmZmVyLmxlbmd0aCYmKHRoaXMuYmF0Y2hCdWZmZXI9dGhpcy5iYXRjaEJ1ZmZlci5jb25jYXQodGhpcy5idWZmZXIpLHRoaXMuYnVmZmVyLmxlbmd0aD0wKSx0aGlzLmJhdGNoQnVmZmVyLnB1c2godSkpLHRoaXMuYmF0Y2hCdWZmZXIubGVuZ3RoPj10aGlzLmJhdGNoU2l6ZT92b2lkIHRoaXMuc2VuZEJhdGNoKCk6dm9pZCAwKX0sby5wcm90b3R5cGUuc2VuZEJhdGNoPWZ1bmN0aW9uKCl7MCE9dGhpcy5iYXRjaEJ1ZmZlci5sZW5ndGgmJihudWxsIT10Lm1heE1lc3NhZ2VzJiZ0Lm1heE1lc3NhZ2VzPDF8fChudWxsIT10Lm1heE1lc3NhZ2VzJiYodC5tYXhNZXNzYWdlcy09dGhpcy5iYXRjaEJ1ZmZlci5sZW5ndGgpLHRoaXMuc2VuZExvZ0l0ZW1zKHRoaXMuYmF0Y2hCdWZmZXIpLHRoaXMuYmF0Y2hCdWZmZXIubGVuZ3RoPTApKX0sb30oKTt0LkFwcGVuZGVyPXc7dmFyIE09ZnVuY3Rpb24ocil7ZnVuY3Rpb24gbih0KXtyLmNhbGwodGhpcyx0LG4ucHJvdG90eXBlLnNlbmRMb2dJdGVtc0FqYXgpfXJldHVybiBvKG4sciksbi5wcm90b3R5cGUuc2V0T3B0aW9ucz1mdW5jdGlvbih0KXtyZXR1cm4gZSgidXJsIix0LHRoaXMpLGUoImJlZm9yZVNlbmQiLHQsdGhpcyksci5wcm90b3R5cGUuc2V0T3B0aW9ucy5jYWxsKHRoaXMsdCksdGhpc30sbi5wcm90b3R5cGUuc2VuZExvZ0l0ZW1zQWpheD1mdW5jdGlvbihlKXt0cnl7dmFyIHI9Ii9qc25sb2cubG9nZ2VyIjtudWxsIT10LmRlZmF1bHRBamF4VXJsJiYocj10LmRlZmF1bHRBamF4VXJsKSx0aGlzLnVybCYmKHI9dGhpcy51cmwpO3ZhciBuPXRoaXMuZ2V0WGhyKHIpLG89e3I6dC5yZXF1ZXN0SWQsbGc6ZX07ImZ1bmN0aW9uIj09dHlwZW9mIHRoaXMuYmVmb3JlU2VuZD90aGlzLmJlZm9yZVNlbmQuY2FsbCh0aGlzLG4sbyk6ImZ1bmN0aW9uIj09dHlwZW9mIHQuZGVmYXVsdEJlZm9yZVNlbmQmJnQuZGVmYXVsdEJlZm9yZVNlbmQuY2FsbCh0aGlzLG4sbyk7dmFyIGk9SlNPTi5zdHJpbmdpZnkobyk7bi5zZW5kKGkpfWNhdGNoKHMpe319LG4ucHJvdG90eXBlLmdldFhocj1mdW5jdGlvbihlKXt2YXIgcj1uZXcgWE1MSHR0cFJlcXVlc3Q7aWYoISgid2l0aENyZWRlbnRpYWxzImluIHIpJiYidW5kZWZpbmVkIiE9dHlwZW9mIFhEb21haW5SZXF1ZXN0KXt2YXIgbj1uZXcgWERvbWFpblJlcXVlc3Q7cmV0dXJuIG4ub3BlbigiUE9TVCIsZSksbn1yZXR1cm4gci5vcGVuKCJQT1NUIixlKSxyLnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtVHlwZSIsImFwcGxpY2F0aW9uL2pzb24iKSxyLnNldFJlcXVlc3RIZWFkZXIoIkpTTkxvZy1SZXF1ZXN0SWQiLHQucmVxdWVzdElkKSxyfSxufSh3KTt0LkFqYXhBcHBlbmRlcj1NO3ZhciBrPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIHIodCl7ZS5jYWxsKHRoaXMsdCxyLnByb3RvdHlwZS5zZW5kTG9nSXRlbXNDb25zb2xlKX1yZXR1cm4gbyhyLGUpLHIucHJvdG90eXBlLmNsb2c9ZnVuY3Rpb24odCl7Y29uc29sZS5sb2codCl9LHIucHJvdG90eXBlLmNlcnJvcj1mdW5jdGlvbih0KXtjb25zb2xlLmVycm9yP2NvbnNvbGUuZXJyb3IodCk6dGhpcy5jbG9nKHQpfSxyLnByb3RvdHlwZS5jd2Fybj1mdW5jdGlvbih0KXtjb25zb2xlLndhcm4/Y29uc29sZS53YXJuKHQpOnRoaXMuY2xvZyh0KX0sci5wcm90b3R5cGUuY2luZm89ZnVuY3Rpb24odCl7Y29uc29sZS5pbmZvP2NvbnNvbGUuaW5mbyh0KTp0aGlzLmNsb2codCl9LHIucHJvdG90eXBlLmNkZWJ1Zz1mdW5jdGlvbih0KXtjb25zb2xlLmRlYnVnP2NvbnNvbGUuZGVidWcodCk6dGhpcy5jaW5mbyh0KX0sci5wcm90b3R5cGUuc2VuZExvZ0l0ZW1zQ29uc29sZT1mdW5jdGlvbihlKXt0cnl7aWYoIWNvbnNvbGUpcmV0dXJuO3ZhciByO2ZvcihyPTA7cjxlLmxlbmd0aDsrK3Ipe3ZhciBuPWVbcl0sbz1uLm4rIjogIituLm07InVuZGVmaW5lZCI9PXR5cGVvZiB3aW5kb3cmJihvPW5ldyBEYXRlKG4udCkrIiB8ICIrbyksbi5sPD10LmdldERlYnVnTGV2ZWwoKT90aGlzLmNkZWJ1ZyhvKTpuLmw8PXQuZ2V0SW5mb0xldmVsKCk/dGhpcy5jaW5mbyhvKTpuLmw8PXQuZ2V0V2FybkxldmVsKCk/dGhpcy5jd2FybihvKTp0aGlzLmNlcnJvcihvKX19Y2F0Y2goaSl7fX0scn0odyk7dC5Db25zb2xlQXBwZW5kZXI9azt2YXIgaj1mdW5jdGlvbigpe2Z1bmN0aW9uIHQodCl7dGhpcy5sb2dnZXJOYW1lPXQsdGhpcy5zZWVuUmVnZXhlcz1bXX1yZXR1cm4gdC5wcm90b3R5cGUuc2V0T3B0aW9ucz1mdW5jdGlvbih0KXtyZXR1cm4gZSgibGV2ZWwiLHQsdGhpcyksZSgidXNlckFnZW50UmVnZXgiLHQsdGhpcyksZSgiZGlzYWxsb3ciLHQsdGhpcyksZSgiaXBSZWdleCIsdCx0aGlzKSxlKCJhcHBlbmRlcnMiLHQsdGhpcyksZSgib25jZU9ubHkiLHQsdGhpcyksdGhpcy5zZWVuUmVnZXhlcz1bXSx0aGlzfSx0LnByb3RvdHlwZS5idWlsZEV4Y2VwdGlvbk9iamVjdD1mdW5jdGlvbih0KXt2YXIgZT17fTtyZXR1cm4gdC5zdGFjaz9lLnN0YWNrPXQuc3RhY2s6ZS5lPXQsdC5tZXNzYWdlJiYoZS5tZXNzYWdlPXQubWVzc2FnZSksdC5uYW1lJiYoZS5uYW1lPXQubmFtZSksdC5kYXRhJiYoZS5kYXRhPXQuZGF0YSksdC5pbm5lciYmKGUuaW5uZXI9dGhpcy5idWlsZEV4Y2VwdGlvbk9iamVjdCh0LmlubmVyKSksZX0sdC5wcm90b3R5cGUubG9nPWZ1bmN0aW9uKHQsZSxvKXt2YXIgYSxsLHU9MDtpZighdGhpcy5hcHBlbmRlcnMpcmV0dXJuIHRoaXM7aWYodD49dGhpcy5sZXZlbCYmcih0aGlzKSYmKG8/KGw9dGhpcy5idWlsZEV4Y2VwdGlvbk9iamVjdChvKSxsLmxvZ0RhdGE9aShlKSk6bD1lLGE9cyhsKSxuKHRoaXMsYS5maW5hbFN0cmluZykpKXtpZih0aGlzLm9uY2VPbmx5KWZvcih1PXRoaXMub25jZU9ubHkubGVuZ3RoLTE7dT49MDspe2lmKG5ldyBSZWdFeHAodGhpcy5vbmNlT25seVt1XSkudGVzdChhLmZpbmFsU3RyaW5nKSl7aWYodGhpcy5zZWVuUmVnZXhlc1t1XSlyZXR1cm4gdGhpczt0aGlzLnNlZW5SZWdleGVzW3VdPSEwfXUtLX1mb3IoYS5tZXRhPWEubWV0YXx8e30sYS5tZXRhLmxvZ2dlck5hbWU9dGhpcy5sb2dnZXJOYW1lLHU9dGhpcy5hcHBlbmRlcnMubGVuZ3RoLTE7dT49MDspdGhpcy5hcHBlbmRlcnNbdV0ubG9nKG0odCksYS5tc2csYS5tZXRhLGZ1bmN0aW9uKCl7fSx0LGEuZmluYWxTdHJpbmcsdGhpcy5sb2dnZXJOYW1lKSx1LS19cmV0dXJuIHRoaXN9LHQucHJvdG90eXBlLnRyYWNlPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmxvZyh1KCksdCl9LHQucHJvdG90eXBlLmRlYnVnPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmxvZyhoKCksdCl9LHQucHJvdG90eXBlLmluZm89ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMubG9nKGMoKSx0KX0sdC5wcm90b3R5cGUud2Fybj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5sb2cocCgpLHQpfSx0LnByb3RvdHlwZS5lcnJvcj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5sb2coXygpLHQpfSx0LnByb3RvdHlwZS5mYXRhbD1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5sb2coZCgpLHQpfSx0LnByb3RvdHlwZS5mYXRhbEV4Y2VwdGlvbj1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmxvZyhkKCksdCxlKX0sdH0oKTt0LkxvZ2dlcj1qLHQuY3JlYXRlQWpheEFwcGVuZGVyPWcsdC5jcmVhdGVDb25zb2xlQXBwZW5kZXI9eTt2YXIgVD1uZXcgTSgiIik7InVuZGVmaW5lZCI9PXR5cGVvZiB3aW5kb3cmJihUPW5ldyBrKCIiKSksdC5fXz1uZXcgdC5Mb2dnZXIoIiIpLHQuX18uc2V0T3B0aW9ucyh7bGV2ZWw6dC5nZXREZWJ1Z0xldmVsKCksYXBwZW5kZXJzOltUXX0pfShufHwobj17fSkpLCJ1bmRlZmluZWQiIT10eXBlb2YgciYmKHIuSkw9bik7dmFyIGk7ImZ1bmN0aW9uIj09dHlwZW9mIGkmJmkuYW1kJiZpKCJqc25sb2ciLFtdLGZ1bmN0aW9uKCl7cmV0dXJuIG59KSwiZnVuY3Rpb24iPT10eXBlb2YgX19qc25sb2dfY29uZmlndXJlJiZfX2pzbmxvZ19jb25maWd1cmUobiksInVuZGVmaW5lZCI9PXR5cGVvZiB3aW5kb3d8fHdpbmRvdy5vbmVycm9yfHwod2luZG93Lm9uZXJyb3I9ZnVuY3Rpb24odCxlLHIsbyxpKXtyZXR1cm4gbigib25lcnJvckxvZ2dlciIpLmZhdGFsRXhjZXB0aW9uKHttc2c6IlVuY2F1Z2h0IEV4Y2VwdGlvbiIsZXJyb3JNc2c6dCx1cmw6ZSwibGluZSBudW1iZXIiOnIsY29sdW1uOm99LGkpLCExfSl9LHt9XSwibnVtYnJvL251bWJybyI6W2Z1bmN0aW9uKHQsZSxyKXtmdW5jdGlvbiBuKHQpe3RoaXMuX3ZhbHVlPXR9ZnVuY3Rpb24gbyh0KXt2YXIgZSxyPSIiO2ZvcihlPTA7ZTx0O2UrKylyKz0iMCI7cmV0dXJuIHJ9ZnVuY3Rpb24gaSh0LGUpe3ZhciByLG4saSxzLGE7cmV0dXJuIGE9dC50b1N0cmluZygpLHI9YS5zcGxpdCgiZSIpWzBdLHM9YS5zcGxpdCgiZSIpWzFdLG49ci5zcGxpdCgiLiIpWzBdLGk9ci5zcGxpdCgiLiIpWzFdfHwiIixhPW4raStvKHMtaS5sZW5ndGgpLGU+MCYmKGErPSIuIitvKGUpKSxhfWZ1bmN0aW9uIHModCxlLHIsbil7dmFyIG8scyxhPU1hdGgucG93KDEwLGUpO3JldHVybiBzPXQudG9GaXhlZCgwKS5zZWFyY2goImUiKT4tMT9pKHQsZSk6KHIodCphKS9hKS50b0ZpeGVkKGUpLG4mJihvPW5ldyBSZWdFeHAoIjB7MSwiK24rIn0kIikscz1zLnJlcGxhY2UobywiIikpLHN9ZnVuY3Rpb24gYSh0LGUscil7dmFyIG47cmV0dXJuIG49ZS5pbmRleE9mKCIkIik+LTE/bCh0LGUscik6ZS5pbmRleE9mKCIlIik+LTE/dSh0LGUscik6ZS5pbmRleE9mKCI6Iik+LTE/aCh0KTpjKHQsZSxyKX1mdW5jdGlvbiBsKHQsZSxyKXt2YXIgbixvLGk9ZSxzPWkuaW5kZXhPZigiJCIpLGE9aS5pbmRleE9mKCIoIiksbD1pLmluZGV4T2YoIisiKSx1PWkuaW5kZXhPZigiLSIpLGg9IiIscD0iIjtpZihpLmluZGV4T2YoIiQiKT09PS0xPyJpbmZpeCI9PT15W2JdLmN1cnJlbmN5LnBvc2l0aW9uPyhwPXlbYl0uY3VycmVuY3kuc3ltYm9sLHlbYl0uY3VycmVuY3kuc3BhY2VTZXBhcmF0ZWQmJihwPSIgIitwKyIgIikpOnlbYl0uY3VycmVuY3kuc3BhY2VTZXBhcmF0ZWQmJihoPSIgIik6aS5pbmRleE9mKCIgJCIpPi0xPyhoPSIgIixpPWkucmVwbGFjZSgiICQiLCIiKSk6aS5pbmRleE9mKCIkICIpPi0xPyhoPSIgIixpPWkucmVwbGFjZSgiJCAiLCIiKSk6aT1pLnJlcGxhY2UoIiQiLCIiKSxvPWModCxpLHIscCksZS5pbmRleE9mKCIkIik9PT0tMSlzd2l0Y2goeVtiXS5jdXJyZW5jeS5wb3NpdGlvbil7Y2FzZSJwb3N0Zml4IjpvLmluZGV4T2YoIikiKT4tMT8obz1vLnNwbGl0KCIiKSxvLnNwbGljZSgtMSwwLGgreVtiXS5jdXJyZW5jeS5zeW1ib2wpLG89by5qb2luKCIiKSk6bz1vK2greVtiXS5jdXJyZW5jeS5zeW1ib2w7YnJlYWs7Y2FzZSJpbmZpeCI6YnJlYWs7Y2FzZSJwcmVmaXgiOm8uaW5kZXhPZigiKCIpPi0xfHxvLmluZGV4T2YoIi0iKT4tMT8obz1vLnNwbGl0KCIiKSxuPU1hdGgubWF4KGEsdSkrMSxvLnNwbGljZShuLDAseVtiXS5jdXJyZW5jeS5zeW1ib2wraCksbz1vLmpvaW4oIiIpKTpvPXlbYl0uY3VycmVuY3kuc3ltYm9sK2grbzticmVhaztkZWZhdWx0OnRocm93IEVycm9yKCdDdXJyZW5jeSBwb3NpdGlvbiBzaG91bGQgYmUgYW1vbmcgWyJwcmVmaXgiLCAiaW5maXgiLCAicG9zdGZpeCJdJyl9ZWxzZSBzPD0xP28uaW5kZXhPZigiKCIpPi0xfHxvLmluZGV4T2YoIisiKT4tMXx8by5pbmRleE9mKCItIik+LTE/KG89by5zcGxpdCgiIiksbj0xLChzPGF8fHM8bHx8czx1KSYmKG49MCksby5zcGxpY2UobiwwLHlbYl0uY3VycmVuY3kuc3ltYm9sK2gpLG89by5qb2luKCIiKSk6bz15W2JdLmN1cnJlbmN5LnN5bWJvbCtoK286by5pbmRleE9mKCIpIik+LTE/KG89by5zcGxpdCgiIiksby5zcGxpY2UoLTEsMCxoK3lbYl0uY3VycmVuY3kuc3ltYm9sKSxvPW8uam9pbigiIikpOm89bytoK3lbYl0uY3VycmVuY3kuc3ltYm9sO3JldHVybiBvfWZ1bmN0aW9uIHUodCxlLHIpe3ZhciBuLG89IiI7cmV0dXJuIHQ9MTAwKnQsZS5pbmRleE9mKCIgJSIpPi0xPyhvPSIgIixlPWUucmVwbGFjZSgiICUiLCIiKSk6ZT1lLnJlcGxhY2UoIiUiLCIiKSxuPWModCxlLHIpLG4uaW5kZXhPZigiKSIpPi0xPyhuPW4uc3BsaXQoIiIpLG4uc3BsaWNlKC0xLDAsbysiJSIpLG49bi5qb2luKCIiKSk6bj1uK28rIiUiLG59ZnVuY3Rpb24gaCh0KXt2YXIgZT1NYXRoLmZsb29yKHQvNjAvNjApLHI9TWF0aC5mbG9vcigodC02MCplKjYwKS82MCksbj1NYXRoLnJvdW5kKHQtNjAqZSo2MC02MCpyKTtyZXR1cm4gZSsiOiIrKHI8MTA/IjAiK3I6cikrIjoiKyhuPDEwPyIwIituOm4pfWZ1bmN0aW9uIGModCxlLHIsbil7dmFyIG8saSxhLGwsdSxoLGMscCxfLGQsZixtLGcsdix3LE0sayxqLFQ9ITEsUz0hMSx6PSExLFA9IiIsRT0hMSxBPSExLEM9ITEsTj0hMSxPPSExLHE9IiIsRD0iIixJPU1hdGguYWJzKHQpLFI9WyJCIiwiS2lCIiwiTWlCIiwiR2lCIiwiVGlCIiwiUGlCIiwiRWlCIiwiWmlCIiwiWWlCIl0sRj1bIkIiLCJLQiIsIk1CIiwiR0IiLCJUQiIsIlBCIiwiRUIiLCJaQiIsIllCIl0sQj0iIixMPSExLEc9ITEsVj0iIjtpZigwPT09dCYmbnVsbCE9PXgpcmV0dXJuIHg7aWYoIWlzRmluaXRlKHQpKXJldHVybiIiK3Q7aWYoMD09PWUuaW5kZXhPZigieyIpKXt2YXIgVT1lLmluZGV4T2YoIn0iKTtpZihVPT09LTEpdGhyb3cgRXJyb3IoJ0Zvcm1hdCBzaG91bGQgYWxzbyBjb250YWluIGEgIn0iJyk7bT1lLnNsaWNlKDEsVSksZT1lLnNsaWNlKFUrMSl9ZWxzZSBtPSIiO2lmKGUuaW5kZXhPZigifSIpPT09ZS5sZW5ndGgtMSl7dmFyIFk9ZS5pbmRleE9mKCJ7Iik7aWYoWT09PS0xKXRocm93IEVycm9yKCdGb3JtYXQgc2hvdWxkIGFsc28gY29udGFpbiBhICJ7IicpO2c9ZS5zbGljZShZKzEsLTEpLGU9ZS5zbGljZSgwLFkrMSl9ZWxzZSBnPSIiO3ZhciBIO2lmKEg9ZS5pbmRleE9mKCIuIik9PT0tMT9lLm1hdGNoKC8oWzAtOV0rKS4qLyk6ZS5tYXRjaCgvKFswLTldKylcLi4qLyksaj1udWxsPT09SD8tMTpIWzFdLmxlbmd0aCxlLmluZGV4T2YoIi0iKSE9PS0xJiYoTD0hMCksZS5pbmRleE9mKCIoIik+LTE/KFQ9ITAsZT1lLnNsaWNlKDEsLTEpKTplLmluZGV4T2YoIisiKT4tMSYmKFM9ITAsZT1lLnJlcGxhY2UoL1wrL2csIiIpKSxlLmluZGV4T2YoImEiKT4tMSl7aWYoZD1lLnNwbGl0KCIuIilbMF0ubWF0Y2goL1swLTldKy9nKXx8WyIwIl0sZD1wYXJzZUludChkWzBdLDEwKSxFPWUuaW5kZXhPZigiYUsiKT49MCxBPWUuaW5kZXhPZigiYU0iKT49MCxDPWUuaW5kZXhPZigiYUIiKT49MCxOPWUuaW5kZXhPZigiYVQiKT49MCxPPUV8fEF8fEN8fE4sZS5pbmRleE9mKCIgYSIpPi0xPyhQPSIgIixlPWUucmVwbGFjZSgiIGEiLCIiKSk6ZT1lLnJlcGxhY2UoImEiLCIiKSx1PU1hdGguZmxvb3IoTWF0aC5sb2coSSkvTWF0aC5MTjEwKSsxLGM9dSUzLGM9MD09PWM/MzpjLGQmJjAhPT1JJiYoaD1NYXRoLmZsb29yKE1hdGgubG9nKEkpL01hdGguTE4xMCkrMS1kLHA9Myp+figoTWF0aC5taW4oZCx1KS1jKS8zKSxJLz1NYXRoLnBvdygxMCxwKSxlLmluZGV4T2YoIi4iKT09PS0xJiZkPjMpKWZvcihlKz0iWy5dIixNPTA9PT1oPzA6Myp+fihoLzMpLWgsTT1NPDA/TSszOk0sbz0wO288TTtvKyspZSs9IjAiO01hdGguZmxvb3IoTWF0aC5sb2coTWF0aC5hYnModCkpL01hdGguTE4xMCkrMSE9PWQmJihJPj1NYXRoLnBvdygxMCwxMikmJiFPfHxOPyhQKz15W2JdLmFiYnJldmlhdGlvbnMudHJpbGxpb24sdC89TWF0aC5wb3coMTAsMTIpKTpJPE1hdGgucG93KDEwLDEyKSYmST49TWF0aC5wb3coMTAsOSkmJiFPfHxDPyhQKz15W2JdLmFiYnJldmlhdGlvbnMuYmlsbGlvbix0Lz1NYXRoLnBvdygxMCw5KSk6STxNYXRoLnBvdygxMCw5KSYmST49TWF0aC5wb3coMTAsNikmJiFPfHxBPyhQKz15W2JdLmFiYnJldmlhdGlvbnMubWlsbGlvbix0Lz1NYXRoLnBvdygxMCw2KSk6KEk8TWF0aC5wb3coMTAsNikmJkk+PU1hdGgucG93KDEwLDMpJiYhT3x8RSkmJihQKz15W2JdLmFiYnJldmlhdGlvbnMudGhvdXNhbmQsdC89TWF0aC5wb3coMTAsMykpKX1pZihlLmluZGV4T2YoImIiKT4tMSlmb3IoZS5pbmRleE9mKCIgYiIpPi0xPyhxPSIgIixlPWUucmVwbGFjZSgiIGIiLCIiKSk6ZT1lLnJlcGxhY2UoImIiLCIiKSxsPTA7bDw9Ui5sZW5ndGg7bCsrKWlmKGk9TWF0aC5wb3coMTAyNCxsKSxhPU1hdGgucG93KDEwMjQsbCsxKSx0Pj1pJiZ0PGEpe3ErPVJbbF0saT4wJiYodC89aSk7YnJlYWt9aWYoZS5pbmRleE9mKCJkIik+LTEpZm9yKGUuaW5kZXhPZigiIGQiKT4tMT8ocT0iICIsZT1lLnJlcGxhY2UoIiBkIiwiIikpOmU9ZS5yZXBsYWNlKCJkIiwiIiksbD0wO2w8PUYubGVuZ3RoO2wrKylpZihpPU1hdGgucG93KDFlMyxsKSxhPU1hdGgucG93KDFlMyxsKzEpLHQ+PWkmJnQ8YSl7cSs9RltsXSxpPjAmJih0Lz1pKTticmVha31pZihlLmluZGV4T2YoIm8iKT4tMSYmKGUuaW5kZXhPZigiIG8iKT4tMT8oRD0iICIsZT1lLnJlcGxhY2UoIiBvIiwiIikpOmU9ZS5yZXBsYWNlKCJvIiwiIikseVtiXS5vcmRpbmFsJiYoRCs9eVtiXS5vcmRpbmFsKHQpKSksZS5pbmRleE9mKCJbLl0iKT4tMSYmKHo9ITAsZT1lLnJlcGxhY2UoIlsuXSIsIi4iKSksXz10LnRvU3RyaW5nKCkuc3BsaXQoIi4iKVswXSxmPWUuc3BsaXQoIi4iKVsxXSx2PWUuaW5kZXhPZigiLCIpLGYpe2lmKGYuaW5kZXhPZigiKiIpIT09LTE/Qj1zKHQsdC50b1N0cmluZygpLnNwbGl0KCIuIilbMV0ubGVuZ3RoLHIpOmYuaW5kZXhPZigiWyIpPi0xPyhmPWYucmVwbGFjZSgiXSIsIiIpLGY9Zi5zcGxpdCgiWyIpLEI9cyh0LGZbMF0ubGVuZ3RoK2ZbMV0ubGVuZ3RoLHIsZlsxXS5sZW5ndGgpKTpCPXModCxmLmxlbmd0aCxyKSxfPUIuc3BsaXQoIi4iKVswXSxCLnNwbGl0KCIuIilbMV0ubGVuZ3RoKXt2YXIgWD1uP1Arbjp5W2JdLmRlbGltaXRlcnMuZGVjaW1hbDtCPVgrQi5zcGxpdCgiLiIpWzFdfWVsc2UgQj0iIjt6JiYwPT09TnVtYmVyKEIuc2xpY2UoMSkpJiYoQj0iIil9ZWxzZSBfPXModCxudWxsLHIpO3JldHVybiBfLmluZGV4T2YoIi0iKT4tMSYmKF89Xy5zbGljZSgxKSxHPSEwKSxfLmxlbmd0aDxqJiYoXz1uZXcgQXJyYXkoai1fLmxlbmd0aCsxKS5qb2luKCIwIikrXyksdj4tMSYmKF89Xy50b1N0cmluZygpLnJlcGxhY2UoLyhcZCkoPz0oXGR7M30pKyg/IVxkKSkvZywiJDEiK3lbYl0uZGVsaW1pdGVycy50aG91c2FuZHMpKSwwPT09ZS5pbmRleE9mKCIuIikmJihfPSIiKSx3PWUuaW5kZXhPZigiKCIpLGs9ZS5pbmRleE9mKCItIiksVj13PGs/KFQmJkc/IigiOiIiKSsoTCYmR3x8IVQmJkc/Ii0iOiIiKTooTCYmR3x8IVQmJkc/Ii0iOiIiKSsoVCYmRz8iKCI6IiIpLG0rVisoIUcmJlMmJjAhPT10PyIrIjoiIikrXytCKyhEP0Q6IiIpKyhQJiYhbj9QOiIiKSsocT9xOiIiKSsoVCYmRz8iKSI6IiIpK2d9ZnVuY3Rpb24gcCh0LGUpe3lbdF09ZX1mdW5jdGlvbiBfKHQpe2I9dDt2YXIgZT15W3RdLmRlZmF1bHRzO2UmJmUuZm9ybWF0JiZmLmRlZmF1bHRGb3JtYXQoZS5mb3JtYXQpLGUmJmUuY3VycmVuY3lGb3JtYXQmJmYuZGVmYXVsdEN1cnJlbmN5Rm9ybWF0KGUuY3VycmVuY3lGb3JtYXQpfWZ1bmN0aW9uIGQodCxlLHIsbil7cmV0dXJuIG0uaXNTdHJpbmcocikmJnIhPT1mLmN1bHR1cmUoKSYmZi5zZXRDdWx0dXJlKHIpLGEoTnVtYmVyKHQpLG0uaXNTdHJpbmcoZSk/ZTp3LG0uaXNVbmRlZmluZWQobik/TWF0aC5yb3VuZDpuKX0vKiEKICogbnVtYnJvLmpzCiAqIHZlcnNpb24gOiAxLjYuMgogKiBhdXRob3IgOiBGw7ZyZXRhZ3NwbGF0c2VuIEFCCiAqIGxpY2Vuc2UgOiBNSVQKICogaHR0cDovL3d3dy5mb3JldGFnc3BsYXRzZW4uc2UKICovCnZhciBmLG09dCgidW5kZXJzY29yZSIpLGc9IjEuNi4yIix5PXt9LHY9eSxiPSJlbi1VUyIseD1udWxsLHc9IjAsMCIsTT0iMCQiLGs9KCJ1bmRlZmluZWQiIT10eXBlb2YgZSYmZS5leHBvcnRzLHtkZWxpbWl0ZXJzOnt0aG91c2FuZHM6IiwiLGRlY2ltYWw6Ii4ifSxhYmJyZXZpYXRpb25zOnt0aG91c2FuZDoiayIsbWlsbGlvbjoibSIsYmlsbGlvbjoiYiIsdHJpbGxpb246InQifSxvcmRpbmFsOmZ1bmN0aW9uKHQpe3ZhciBlPXQlMTA7cmV0dXJuIDE9PT1+fih0JTEwMC8xMCk/InRoIjoxPT09ZT8ic3QiOjI9PT1lPyJuZCI6Mz09PWU/InJkIjoidGgifSxjdXJyZW5jeTp7c3ltYm9sOiIkIixwb3NpdGlvbjoicHJlZml4In0sZGVmYXVsdHM6e2N1cnJlbmN5Rm9ybWF0OiIsMDAwMCBhIn0sZm9ybWF0czp7Zm91ckRpZ2l0czoiMDAwMCBhIixmdWxsV2l0aFR3b0RlY2ltYWxzOiIkICwwLjAwIixmdWxsV2l0aFR3b0RlY2ltYWxzTm9DdXJyZW5jeToiLDAuMDAifX0pO2Y9ZnVuY3Rpb24odCl7cmV0dXJuIGYuaXNOdW1icm8odCk/dD10LnZhbHVlKCk6MD09PXR8fCJ1bmRlZmluZWQiPT10eXBlb2YgdD90PTA6TnVtYmVyKHQpfHwodD1mLmZuLnVuZm9ybWF0KHQpKSxuZXcgbihOdW1iZXIodCkpfSxmLnZlcnNpb249ZyxmLmlzTnVtYnJvPWZ1bmN0aW9uKHQpe3JldHVybiB0IGluc3RhbmNlb2Ygbn0sZi5zZXRMYW5ndWFnZT1mdW5jdGlvbih0LGUpe2NvbnNvbGUud2FybigiYHNldExhbmd1YWdlYCBpcyBkZXByZWNhdGVkIHNpbmNlIHZlcnNpb24gMS42LjAuIFVzZSBgc2V0Q3VsdHVyZWAgaW5zdGVhZCIpO3ZhciByPXQsbj10LnNwbGl0KCItIilbMF0sbz1udWxsO3Zbcl18fChPYmplY3Qua2V5cyh2KS5mb3JFYWNoKGZ1bmN0aW9uKHQpe298fHQuc3BsaXQoIi0iKVswXSE9PW58fChvPXQpfSkscj1vfHxlfHwiZW4tVVMiKSxfKHIpfSxmLnNldEN1bHR1cmU9ZnVuY3Rpb24odCxlKXt2YXIgcj10LG49dC5zcGxpdCgiLSIpWzFdLG89bnVsbDt5W3JdfHwobiYmT2JqZWN0LmtleXMoeSkuZm9yRWFjaChmdW5jdGlvbih0KXtvfHx0LnNwbGl0KCItIilbMV0hPT1ufHwobz10KX0pLHI9b3x8ZXx8ImVuLVVTIiksXyhyKX0sZi5sYW5ndWFnZT1mdW5jdGlvbih0LGUpe2lmKGNvbnNvbGUud2FybigiYGxhbmd1YWdlYCBpcyBkZXByZWNhdGVkIHNpbmNlIHZlcnNpb24gMS42LjAuIFVzZSBgY3VsdHVyZWAgaW5zdGVhZCIpLCF0KXJldHVybiBiO2lmKHQmJiFlKXtpZighdlt0XSl0aHJvdyBuZXcgRXJyb3IoIlVua25vd24gbGFuZ3VhZ2UgOiAiK3QpO18odCl9cmV0dXJuIWUmJnZbdF18fHAodCxlKSxmfSxmLmN1bHR1cmU9ZnVuY3Rpb24odCxlKXtpZighdClyZXR1cm4gYjtpZih0JiYhZSl7aWYoIXlbdF0pdGhyb3cgbmV3IEVycm9yKCJVbmtub3duIGN1bHR1cmUgOiAiK3QpO18odCl9cmV0dXJuIWUmJnlbdF18fHAodCxlKSxmfSxmLmxhbmd1YWdlRGF0YT1mdW5jdGlvbih0KXtpZihjb25zb2xlLndhcm4oImBsYW5ndWFnZURhdGFgIGlzIGRlcHJlY2F0ZWQgc2luY2UgdmVyc2lvbiAxLjYuMC4gVXNlIGBjdWx0dXJlRGF0YWAgaW5zdGVhZCIpLCF0KXJldHVybiB2W2JdO2lmKCF2W3RdKXRocm93IG5ldyBFcnJvcigiVW5rbm93biBsYW5ndWFnZSA6ICIrdCk7cmV0dXJuIHZbdF19LGYuY3VsdHVyZURhdGE9ZnVuY3Rpb24odCl7aWYoIXQpcmV0dXJuIHlbYl07aWYoIXlbdF0pdGhyb3cgbmV3IEVycm9yKCJVbmtub3duIGN1bHR1cmUgOiAiK3QpO3JldHVybiB5W3RdfSxmLmN1bHR1cmUoImVuLVVTIixrKSxmLmxhbmd1YWdlcz1mdW5jdGlvbigpe3JldHVybiBjb25zb2xlLndhcm4oImBsYW5ndWFnZXNgIGlzIGRlcHJlY2F0ZWQgc2luY2UgdmVyc2lvbiAxLjYuMC4gVXNlIGBjdWx0dXJlc2AgaW5zdGVhZCIpLHZ9LGYuY3VsdHVyZXM9ZnVuY3Rpb24oKXtyZXR1cm4geX0sZi56ZXJvRm9ybWF0PWZ1bmN0aW9uKHQpe3g9InN0cmluZyI9PXR5cGVvZiB0P3Q6bnVsbH0sZi5kZWZhdWx0Rm9ybWF0PWZ1bmN0aW9uKHQpe3c9InN0cmluZyI9PXR5cGVvZiB0P3Q6IjAuMCJ9LGYuZGVmYXVsdEN1cnJlbmN5Rm9ybWF0PWZ1bmN0aW9uKHQpe009InN0cmluZyI9PXR5cGVvZiB0P3Q6IjAkIn0sZi52YWxpZGF0ZT1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpLHMsYSxsLHU7aWYoInN0cmluZyIhPXR5cGVvZiB0JiYodCs9IiIsY29uc29sZS53YXJuJiZjb25zb2xlLndhcm4oIk51bWJyby5qczogVmFsdWUgaXMgbm90IHN0cmluZy4gSXQgaGFzIGJlZW4gY28tZXJjZWQgdG86ICIsdCkpLHQ9dC50cmltKCksdC5tYXRjaCgvXlxkKyQvKSlyZXR1cm4hMDtpZigiIj09PXQpcmV0dXJuITE7dHJ5e2w9Zi5jdWx0dXJlRGF0YShlKX1jYXRjaChoKXtsPWYuY3VsdHVyZURhdGEoZi5jdWx0dXJlKCkpfXJldHVybiBvPWwuY3VycmVuY3kuc3ltYm9sLHM9bC5hYmJyZXZpYXRpb25zLHI9bC5kZWxpbWl0ZXJzLmRlY2ltYWwsbj0iLiI9PT1sLmRlbGltaXRlcnMudGhvdXNhbmRzPyJcXC4iOmwuZGVsaW1pdGVycy50aG91c2FuZHMsdT10Lm1hdGNoKC9eW15cZF0rLyksKG51bGw9PT11fHwodD10LnN1YnN0cigxKSx1WzBdPT09bykpJiYodT10Lm1hdGNoKC9bXlxkXSskLyksKG51bGw9PT11fHwodD10LnNsaWNlKDAsLTEpLHVbMF09PT1zLnRob3VzYW5kfHx1WzBdPT09cy5taWxsaW9ufHx1WzBdPT09cy5iaWxsaW9ufHx1WzBdPT09cy50cmlsbGlvbikpJiYoYT1uZXcgUmVnRXhwKG4rInsyfSIpLCF0Lm1hdGNoKC9bXlxkLixdL2cpJiYoaT10LnNwbGl0KHIpLCEoaS5sZW5ndGg+MikmJihpLmxlbmd0aDwyPyEhaVswXS5tYXRjaCgvXlxkKy4qXGQkLykmJiFpWzBdLm1hdGNoKGEpOjE9PT1pWzBdLmxlbmd0aD8hIWlbMF0ubWF0Y2goL15cZCskLykmJiFpWzBdLm1hdGNoKGEpJiYhIWlbMV0ubWF0Y2goL15cZCskLyk6ISFpWzBdLm1hdGNoKC9eXGQrLipcZCQvKSYmIWlbMF0ubWF0Y2goYSkmJiEhaVsxXS5tYXRjaCgvXlxkKyQvKSkpKSl9LGUuZXhwb3J0cz17Zm9ybWF0OmR9fSx7dW5kZXJzY29yZToidW5kZXJzY29yZSJ9XSwicHJvajQvbGliL1BvaW50IjpbZnVuY3Rpb24odCxlLHIpe2Z1bmN0aW9uIG4odCxlLHIpe2lmKCEodGhpcyBpbnN0YW5jZW9mIG4pKXJldHVybiBuZXcgbih0LGUscik7aWYoQXJyYXkuaXNBcnJheSh0KSl0aGlzLng9dFswXSx0aGlzLnk9dFsxXSx0aGlzLno9dFsyXXx8MDtlbHNlIGlmKCJvYmplY3QiPT10eXBlb2YgdCl0aGlzLng9dC54LHRoaXMueT10LnksdGhpcy56PXQuenx8MDtlbHNlIGlmKCJzdHJpbmciPT10eXBlb2YgdCYmInVuZGVmaW5lZCI9PXR5cGVvZiBlKXt2YXIgbz10LnNwbGl0KCIsIik7dGhpcy54PXBhcnNlRmxvYXQob1swXSwxMCksdGhpcy55PXBhcnNlRmxvYXQob1sxXSwxMCksdGhpcy56PXBhcnNlRmxvYXQob1syXSwxMCl8fDB9ZWxzZSB0aGlzLng9dCx0aGlzLnk9ZSx0aGlzLno9cnx8MDtjb25zb2xlLndhcm4oInByb2o0LlBvaW50IHdpbGwgYmUgcmVtb3ZlZCBpbiB2ZXJzaW9uIDMsIHVzZSBwcm9qNC50b1BvaW50Iil9dmFyIG89dCgibWdycyIpO24uZnJvbU1HUlM9ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBuKG8udG9Qb2ludCh0KSl9LG4ucHJvdG90eXBlLnRvTUdSUz1mdW5jdGlvbih0KXtyZXR1cm4gby5mb3J3YXJkKFt0aGlzLngsdGhpcy55XSx0KX0sZS5leHBvcnRzPW59LHttZ3JzOiJwcm9qNC9ub2RlX21vZHVsZXMvbWdycy9tZ3JzIn1dLCJwcm9qNC9saWIvUHJvaiI6W2Z1bmN0aW9uKHQsZSxyKXtmdW5jdGlvbiBuKHQsZSl7aWYoISh0aGlzIGluc3RhbmNlb2YgbikpcmV0dXJuIG5ldyBuKHQpO2U9ZXx8ZnVuY3Rpb24odCl7aWYodCl0aHJvdyB0fTt2YXIgcj1vKHQpO2lmKCJvYmplY3QiIT10eXBlb2YgcilyZXR1cm4gdm9pZCBlKHQpO3ZhciBzPWEociksbD1uLnByb2plY3Rpb25zLmdldChzLnByb2pOYW1lKTtsPyhpKHRoaXMscyksaSh0aGlzLGwpLHRoaXMuaW5pdCgpLGUobnVsbCx0aGlzKSk6ZSh0KX12YXIgbz10KCIuL3BhcnNlQ29kZSIpLGk9dCgiLi9leHRlbmQiKSxzPXQoIi4vcHJvamVjdGlvbnMiKSxhPXQoIi4vZGVyaXZlQ29uc3RhbnRzIik7bi5wcm9qZWN0aW9ucz1zLG4ucHJvamVjdGlvbnMuc3RhcnQoKSxlLmV4cG9ydHM9bn0seyIuL2Rlcml2ZUNvbnN0YW50cyI6InByb2o0L2xpYi9kZXJpdmVDb25zdGFudHMiLCIuL2V4dGVuZCI6InByb2o0L2xpYi9leHRlbmQiLCIuL3BhcnNlQ29kZSI6InByb2o0L2xpYi9wYXJzZUNvZGUiLCIuL3Byb2plY3Rpb25zIjoicHJvajQvbGliL3Byb2plY3Rpb25zIn1dLCJwcm9qNC9saWIvYWRqdXN0X2F4aXMiOltmdW5jdGlvbih0LGUscil7ZS5leHBvcnRzPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscz1yLngsYT1yLnksbD1yLnp8fDA7Zm9yKGk9MDtpPDM7aSsrKWlmKCFlfHwyIT09aXx8dm9pZCAwIT09ci56KXN3aXRjaCgwPT09aT8obj1zLG89IngiKToxPT09aT8obj1hLG89InkiKToobj1sLG89InoiKSx0LmF4aXNbaV0pe2Nhc2UiZSI6cltvXT1uO2JyZWFrO2Nhc2UidyI6cltvXT0tbjticmVhaztjYXNlIm4iOnJbb109bjticmVhaztjYXNlInMiOnJbb109LW47YnJlYWs7Y2FzZSJ1Ijp2b2lkIDAhPT1yW29dJiYoci56PW4pO2JyZWFrO2Nhc2UiZCI6dm9pZCAwIT09cltvXSYmKHIuej0tbik7YnJlYWs7ZGVmYXVsdDpyZXR1cm4gbnVsbH1yZXR1cm4gcn19LHt9XSwicHJvajQvbGliL2NvbW1vbi9hZGp1c3RfbGF0IjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPU1hdGguUEkvMixvPXQoIi4vc2lnbiIpO2UuZXhwb3J0cz1mdW5jdGlvbih0KXtyZXR1cm4gTWF0aC5hYnModCk8bj90OnQtbyh0KSpNYXRoLlBJfX0seyIuL3NpZ24iOiJwcm9qNC9saWIvY29tbW9uL3NpZ24ifV0sInByb2o0L2xpYi9jb21tb24vYWRqdXN0X2xvbiI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj0yKk1hdGguUEksbz0zLjE0MTU5MjY1MzU5LGk9dCgiLi9zaWduIik7ZS5leHBvcnRzPWZ1bmN0aW9uKHQpe3JldHVybiBNYXRoLmFicyh0KTw9bz90OnQtaSh0KSpufX0seyIuL3NpZ24iOiJwcm9qNC9saWIvY29tbW9uL3NpZ24ifV0sInByb2o0L2xpYi9jb21tb24vYXNpbnoiOltmdW5jdGlvbih0LGUscil7ZS5leHBvcnRzPWZ1bmN0aW9uKHQpe3JldHVybiBNYXRoLmFicyh0KT4xJiYodD10PjE/MTotMSksTWF0aC5hc2luKHQpfX0se31dLCJwcm9qNC9saWIvY29tbW9uL2UwZm4iOltmdW5jdGlvbih0LGUscil7ZS5leHBvcnRzPWZ1bmN0aW9uKHQpe3JldHVybiAxLS4yNSp0KigxK3QvMTYqKDMrMS4yNSp0KSl9fSx7fV0sInByb2o0L2xpYi9jb21tb24vZTFmbiI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9ZnVuY3Rpb24odCl7cmV0dXJuLjM3NSp0KigxKy4yNSp0KigxKy40Njg3NSp0KSl9fSx7fV0sInByb2o0L2xpYi9jb21tb24vZTJmbiI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9ZnVuY3Rpb24odCl7cmV0dXJuLjA1ODU5Mzc1KnQqdCooMSsuNzUqdCl9fSx7fV0sInByb2o0L2xpYi9jb21tb24vZTNmbiI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9ZnVuY3Rpb24odCl7cmV0dXJuIHQqdCp0KigzNS8zMDcyKX19LHt9XSwicHJvajQvbGliL2NvbW1vbi9nTiI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPWUqcjtyZXR1cm4gdC9NYXRoLnNxcnQoMS1uKm4pfX0se31dLCJwcm9qNC9saWIvY29tbW9uL2ltbGZuIjpbZnVuY3Rpb24odCxlLHIpe2UuZXhwb3J0cz1mdW5jdGlvbih0LGUscixuLG8pe3ZhciBpLHM7aT10L2U7Zm9yKHZhciBhPTA7YTwxNTthKyspaWYocz0odC0oZSppLXIqTWF0aC5zaW4oMippKStuKk1hdGguc2luKDQqaSktbypNYXRoLnNpbig2KmkpKSkvKGUtMipyKk1hdGguY29zKDIqaSkrNCpuKk1hdGguY29zKDQqaSktNipvKk1hdGguY29zKDYqaSkpLGkrPXMsTWF0aC5hYnMocyk8PTFlLTEwKXJldHVybiBpO3JldHVybiBOYU59fSx7fV0sInByb2o0L2xpYi9jb21tb24vaXFzZm56IjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPU1hdGguUEkvMjtlLmV4cG9ydHM9ZnVuY3Rpb24odCxlKXt2YXIgcj0xLSgxLXQqdCkvKDIqdCkqTWF0aC5sb2coKDEtdCkvKDErdCkpO2lmKE1hdGguYWJzKE1hdGguYWJzKGUpLXIpPDFlLTYpcmV0dXJuIGU8MD8tMSpuOm47Zm9yKHZhciBvLGkscyxhLGw9TWF0aC5hc2luKC41KmUpLHU9MDt1PDMwO3UrKylpZihpPU1hdGguc2luKGwpLHM9TWF0aC5jb3MobCksYT10Kmksbz1NYXRoLnBvdygxLWEqYSwyKS8oMipzKSooZS8oMS10KnQpLWkvKDEtYSphKSsuNS90Kk1hdGgubG9nKCgxLWEpLygxK2EpKSksbCs9byxNYXRoLmFicyhvKTw9MWUtMTApcmV0dXJuIGw7cmV0dXJuIE5hTn19LHt9XSwicHJvajQvbGliL2NvbW1vbi9tbGZuIjpbZnVuY3Rpb24odCxlLHIpe2UuZXhwb3J0cz1mdW5jdGlvbih0LGUscixuLG8pe3JldHVybiB0Km8tZSpNYXRoLnNpbigyKm8pK3IqTWF0aC5zaW4oNCpvKS1uKk1hdGguc2luKDYqbyl9fSx7fV0sInByb2o0L2xpYi9jb21tb24vbXNmbnoiOltmdW5jdGlvbih0LGUscil7ZS5leHBvcnRzPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbj10KmU7cmV0dXJuIHIvTWF0aC5zcXJ0KDEtbipuKX19LHt9XSwicHJvajQvbGliL2NvbW1vbi9waGkyeiI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj1NYXRoLlBJLzI7ZS5leHBvcnRzPWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByLG8saT0uNSp0LHM9bi0yKk1hdGguYXRhbihlKSxhPTA7YTw9MTU7YSsrKWlmKHI9dCpNYXRoLnNpbihzKSxvPW4tMipNYXRoLmF0YW4oZSpNYXRoLnBvdygoMS1yKS8oMStyKSxpKSktcyxzKz1vLE1hdGguYWJzKG8pPD0xZS0xMClyZXR1cm4gcztyZXR1cm4tOTk5OX19LHt9XSwicHJvajQvbGliL2NvbW1vbi9wal9lbmZuIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPTEsbz0uMjUsaT0uMDQ2ODc1LHM9LjAxOTUzMTI1LGE9LjAxMDY4MTE1MjM0Mzc1LGw9Ljc1LHU9LjQ2ODc1LGg9LjAxMzAyMDgzMzMzMzMzMzMzNCxjPS4wMDcxMjA3NjgyMjkxNjY2NjcscD0uMzY0NTgzMzMzMzMzMzMzMyxfPS4wMDU2OTY2MTQ1ODMzMzMzMzMsZD0uMzA3NjE3MTg3NTtlLmV4cG9ydHM9ZnVuY3Rpb24odCl7dmFyIGU9W107ZVswXT1uLXQqKG8rdCooaSt0KihzK3QqYSkpKSxlWzFdPXQqKGwtdCooaSt0KihzK3QqYSkpKTt2YXIgcj10KnQ7cmV0dXJuIGVbMl09cioodS10KihoK3QqYykpLHIqPXQsZVszXT1yKihwLXQqXyksZVs0XT1yKnQqZCxlfX0se31dLCJwcm9qNC9saWIvY29tbW9uL3BqX2ludl9tbGZuIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPXQoIi4vcGpfbWxmbiIpLG89MWUtMTAsaT0yMDtlLmV4cG9ydHM9ZnVuY3Rpb24odCxlLHIpe2Zvcih2YXIgcz0xLygxLWUpLGE9dCxsPWk7bDstLWwpe3ZhciB1PU1hdGguc2luKGEpLGg9MS1lKnUqdTtpZihoPShuKGEsdSxNYXRoLmNvcyhhKSxyKS10KSooaCpNYXRoLnNxcnQoaCkpKnMsYS09aCxNYXRoLmFicyhoKTxvKXJldHVybiBhfXJldHVybiBhfX0seyIuL3BqX21sZm4iOiJwcm9qNC9saWIvY29tbW9uL3BqX21sZm4ifV0sInByb2o0L2xpYi9jb21tb24vcGpfbWxmbiI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9ZnVuY3Rpb24odCxlLHIsbil7cmV0dXJuIHIqPWUsZSo9ZSxuWzBdKnQtciooblsxXStlKihuWzJdK2UqKG5bM10rZSpuWzRdKSkpfX0se31dLCJwcm9qNC9saWIvY29tbW9uL3FzZm56IjpbZnVuY3Rpb24odCxlLHIpe2UuZXhwb3J0cz1mdW5jdGlvbih0LGUpe3ZhciByO3JldHVybiB0PjFlLTc/KHI9dCplLCgxLXQqdCkqKGUvKDEtcipyKS0uNS90Kk1hdGgubG9nKCgxLXIpLygxK3IpKSkpOjIqZX19LHt9XSwicHJvajQvbGliL2NvbW1vbi9zaWduIjpbZnVuY3Rpb24odCxlLHIpe2UuZXhwb3J0cz1mdW5jdGlvbih0KXtyZXR1cm4gdDwwPy0xOjF9fSx7fV0sInByb2o0L2xpYi9jb21tb24vc3JhdCI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9ZnVuY3Rpb24odCxlKXtyZXR1cm4gTWF0aC5wb3coKDEtdCkvKDErdCksZSl9fSx7fV0sInByb2o0L2xpYi9jb21tb24vdG9Qb2ludCI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9ZnVuY3Rpb24odCl7dmFyIGU9e3g6dFswXSx5OnRbMV19O3JldHVybiB0Lmxlbmd0aD4yJiYoZS56PXRbMl0pLHQubGVuZ3RoPjMmJihlLm09dFszXSksZX19LHt9XSwicHJvajQvbGliL2NvbW1vbi90c2ZueiI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj1NYXRoLlBJLzI7ZS5leHBvcnRzPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbz10KnIsaT0uNSp0O3JldHVybiBvPU1hdGgucG93KCgxLW8pLygxK28pLGkpLE1hdGgudGFuKC41KihuLWUpKS9vfX0se31dLCJwcm9qNC9saWIvY29uc3RhbnRzL0RhdHVtIjpbZnVuY3Rpb24odCxlLHIpe3Iud2dzODQ9e3Rvd2dzODQ6IjAsMCwwIixlbGxpcHNlOiJXR1M4NCIsZGF0dW1OYW1lOiJXR1M4NCJ9LHIuY2gxOTAzPXt0b3dnczg0OiI2NzQuMzc0LDE1LjA1Niw0MDUuMzQ2IixlbGxpcHNlOiJiZXNzZWwiLGRhdHVtTmFtZToic3dpc3MifSxyLmdncnM4Nz17dG93Z3M4NDoiLTE5OS44Nyw3NC43OSwyNDYuNjIiLGVsbGlwc2U6IkdSUzgwIixkYXR1bU5hbWU6IkdyZWVrX0dlb2RldGljX1JlZmVyZW5jZV9TeXN0ZW1fMTk4NyJ9LHIubmFkODM9e3Rvd2dzODQ6IjAsMCwwIixlbGxpcHNlOiJHUlM4MCIsZGF0dW1OYW1lOiJOb3J0aF9BbWVyaWNhbl9EYXR1bV8xOTgzIn0sci5uYWQyNz17bmFkZ3JpZHM6IkBjb251cyxAYWxhc2thLEBudHYyXzAuZ3NiLEBudHYxX2Nhbi5kYXQiLGVsbGlwc2U6ImNscms2NiIsZGF0dW1OYW1lOiJOb3J0aF9BbWVyaWNhbl9EYXR1bV8xOTI3In0sci5wb3RzZGFtPXt0b3dnczg0OiI2MDYuMCwyMy4wLDQxMy4wIixlbGxpcHNlOiJiZXNzZWwiLGRhdHVtTmFtZToiUG90c2RhbSBSYXVlbmJlcmcgMTk1MCBESEROIn0sci5jYXJ0aGFnZT17dG93Z3M4NDoiLTI2My4wLDYuMCw0MzEuMCIsZWxsaXBzZToiY2xhcms4MCIsZGF0dW1OYW1lOiJDYXJ0aGFnZSAxOTM0IFR1bmlzaWEifSxyLmhlcm1hbm5za29nZWw9e3Rvd2dzODQ6IjY1My4wLC0yMTIuMCw0NDkuMCIsZWxsaXBzZToiYmVzc2VsIixkYXR1bU5hbWU6Ikhlcm1hbm5za29nZWwifSxyLmlyZTY1PXt0b3dnczg0OiI0ODIuNTMwLC0xMzAuNTk2LDU2NC41NTcsLTEuMDQyLC0wLjIxNCwtMC42MzEsOC4xNSIsZWxsaXBzZToibW9kX2FpcnkiLGRhdHVtTmFtZToiSXJlbGFuZCAxOTY1In0sci5yYXNzYWRpcmFuPXt0b3dnczg0OiItMTMzLjYzLC0xNTcuNSwtMTU4LjYyIixlbGxpcHNlOiJpbnRsIixkYXR1bU5hbWU6IlJhc3NhZGlyYW4ifSxyLm56Z2Q0OT17dG93Z3M4NDoiNTkuNDcsLTUuMDQsMTg3LjQ0LDAuNDcsLTAuMSwxLjAyNCwtNC41OTkzIixlbGxpcHNlOiJpbnRsIixkYXR1bU5hbWU6Ik5ldyBaZWFsYW5kIEdlb2RldGljIERhdHVtIDE5NDkifSxyLm9zZ2IzNj17dG93Z3M4NDoiNDQ2LjQ0OCwtMTI1LjE1Nyw1NDIuMDYwLDAuMTUwMiwwLjI0NzAsMC44NDIxLC0yMC40ODk0IixlbGxpcHNlOiJhaXJ5IixkYXR1bU5hbWU6IkFpcnkgMTgzMCJ9LHIuc19qdHNrPXt0b3dnczg0OiI1ODksNzYsNDgwIixlbGxpcHNlOiJiZXNzZWwiLGRhdHVtTmFtZToiUy1KVFNLIChGZXJybykifSxyLmJlZHVhcmFtPXt0b3dnczg0OiItMTA2LC04NywxODgiLGVsbGlwc2U6ImNscms4MCIsZGF0dW1OYW1lOiJCZWR1YXJhbSJ9LHIuZ3VudW5nX3NlZ2FyYT17dG93Z3M4NDoiLTQwMyw2ODQsNDEiLGVsbGlwc2U6ImJlc3NlbCIsZGF0dW1OYW1lOiJHdW51bmcgU2VnYXJhIEpha2FydGEifSxyLnJuYjcyPXt0b3dnczg0OiIxMDYuODY5LC01Mi4yOTc4LDEwMy43MjQsLTAuMzM2NTcsMC40NTY5NTUsLTEuODQyMTgsMSIsZWxsaXBzZToiaW50bCIsZGF0dW1OYW1lOiJSZXNlYXUgTmF0aW9uYWwgQmVsZ2UgMTk3MiJ9fSx7fV0sInByb2o0L2xpYi9jb25zdGFudHMvRWxsaXBzb2lkIjpbZnVuY3Rpb24odCxlLHIpe3IuTUVSSVQ9e2E6NjM3ODEzNyxyZjoyOTguMjU3LGVsbGlwc2VOYW1lOiJNRVJJVCAxOTgzIn0sci5TR1M4NT17YTo2Mzc4MTM2LHJmOjI5OC4yNTcsZWxsaXBzZU5hbWU6IlNvdmlldCBHZW9kZXRpYyBTeXN0ZW0gODUifSxyLkdSUzgwPXthOjYzNzgxMzcscmY6Mjk4LjI1NzIyMjEwMSxlbGxpcHNlTmFtZToiR1JTIDE5ODAoSVVHRywgMTk4MCkifSxyLklBVTc2PXthOjYzNzgxNDAscmY6Mjk4LjI1NyxlbGxpcHNlTmFtZToiSUFVIDE5NzYifSxyLmFpcnk9e2E6NjM3NzU2My4zOTYsYjo2MzU2MjU2LjkxLGVsbGlwc2VOYW1lOiJBaXJ5IDE4MzAifSxyLkFQTDQ9e2E6NjM3ODEzNyxyZjoyOTguMjUsZWxsaXBzZU5hbWU6IkFwcGwuIFBoeXNpY3MuIDE5NjUifSxyLk5XTDlEPXthOjYzNzgxNDUscmY6Mjk4LjI1LGVsbGlwc2VOYW1lOiJOYXZhbCBXZWFwb25zIExhYi4sIDE5NjUifSxyLm1vZF9haXJ5PXthOjYzNzczNDAuMTg5LGI6NjM1NjAzNC40NDYsZWxsaXBzZU5hbWU6Ik1vZGlmaWVkIEFpcnkifSxyLmFuZHJhZT17YTo2Mzc3MTA0LjQzLHJmOjMwMCxlbGxpcHNlTmFtZToiQW5kcmFlIDE4NzYgKERlbi4sIEljbG5kLikifSxyLmF1c3RfU0E9e2E6NjM3ODE2MCxyZjoyOTguMjUsZWxsaXBzZU5hbWU6IkF1c3RyYWxpYW4gTmF0bCAmIFMuIEFtZXIuIDE5NjkifSxyLkdSUzY3PXthOjYzNzgxNjAscmY6Mjk4LjI0NzE2NzQyNyxlbGxpcHNlTmFtZToiR1JTIDY3KElVR0cgMTk2NykifSxyLmJlc3NlbD17YTo2Mzc3Mzk3LjE1NSxyZjoyOTkuMTUyODEyOCxlbGxpcHNlTmFtZToiQmVzc2VsIDE4NDEifSxyLmJlc3NfbmFtPXthOjYzNzc0ODMuODY1LHJmOjI5OS4xNTI4MTI4LGVsbGlwc2VOYW1lOiJCZXNzZWwgMTg0MSAoTmFtaWJpYSkifSxyLmNscms2Nj17YTo2Mzc4MjA2LjQsYjo2MzU2NTgzLjgsZWxsaXBzZU5hbWU6IkNsYXJrZSAxODY2In0sci5jbHJrODA9e2E6NjM3ODI0OS4xNDUscmY6MjkzLjQ2NjMsZWxsaXBzZU5hbWU6IkNsYXJrZSAxODgwIG1vZC4ifSxyLmNscms1OD17YTo2Mzc4MjkzLjY0NTIwODc1OSxyZjoyOTQuMjYwNjc2MzY5MjY1NCxlbGxpcHNlTmFtZToiQ2xhcmtlIDE4NTgifSxyLkNQTT17YTo2Mzc1NzM4LjcscmY6MzM0LjI5LGVsbGlwc2VOYW1lOiJDb21tLiBkZXMgUG9pZHMgZXQgTWVzdXJlcyAxNzk5In0sci5kZWxtYnI9e2E6NjM3NjQyOCxyZjozMTEuNSxlbGxpcHNlTmFtZToiRGVsYW1icmUgMTgxMCAoQmVsZ2l1bSkifSxyLmVuZ2VsaXM9e2E6NjM3ODEzNi4wNSxyZjoyOTguMjU2NixlbGxpcHNlTmFtZToiRW5nZWxpcyAxOTg1In0sci5ldnJzdDMwPXthOjYzNzcyNzYuMzQ1LHJmOjMwMC44MDE3LGVsbGlwc2VOYW1lOiJFdmVyZXN0IDE4MzAifSxyLmV2cnN0NDg9e2E6NjM3NzMwNC4wNjMscmY6MzAwLjgwMTcsZWxsaXBzZU5hbWU6IkV2ZXJlc3QgMTk0OCJ9LHIuZXZyc3Q1Nj17YTo2Mzc3MzAxLjI0MyxyZjozMDAuODAxNyxlbGxpcHNlTmFtZToiRXZlcmVzdCAxOTU2In0sci5ldnJzdDY5PXthOjYzNzcyOTUuNjY0LHJmOjMwMC44MDE3LGVsbGlwc2VOYW1lOiJFdmVyZXN0IDE5NjkifSxyLmV2cnN0U1M9e2E6NjM3NzI5OC41NTYscmY6MzAwLjgwMTcsZWxsaXBzZU5hbWU6IkV2ZXJlc3QgKFNhYmFoICYgU2FyYXdhaykifSxyLmZzY2hyNjA9e2E6NjM3ODE2NixyZjoyOTguMyxlbGxpcHNlTmFtZToiRmlzY2hlciAoTWVyY3VyeSBEYXR1bSkgMTk2MCJ9LHIuZnNjaHI2MG09e2E6NjM3ODE1NSxyZjoyOTguMyxlbGxpcHNlTmFtZToiRmlzY2hlciAxOTYwIn0sci5mc2NocjY4PXthOjYzNzgxNTAscmY6Mjk4LjMsZWxsaXBzZU5hbWU6IkZpc2NoZXIgMTk2OCJ9LHIuaGVsbWVydD17YTo2Mzc4MjAwLHJmOjI5OC4zLGVsbGlwc2VOYW1lOiJIZWxtZXJ0IDE5MDYifSxyLmhvdWdoPXthOjYzNzgyNzAscmY6Mjk3LGVsbGlwc2VOYW1lOiJIb3VnaCJ9LHIuaW50bD17YTo2Mzc4Mzg4LHJmOjI5NyxlbGxpcHNlTmFtZToiSW50ZXJuYXRpb25hbCAxOTA5IChIYXlmb3JkKSJ9LHIua2F1bGE9e2E6NjM3ODE2MyxyZjoyOTguMjQsZWxsaXBzZU5hbWU6IkthdWxhIDE5NjEifSxyLmxlcmNoPXthOjYzNzgxMzkscmY6Mjk4LjI1NyxlbGxpcHNlTmFtZToiTGVyY2ggMTk3OSJ9LHIubXBydHM9e2E6NjM5NzMwMCxyZjoxOTEsZWxsaXBzZU5hbWU6Ik1hdXBlcnRpdXMgMTczOCJ9LHIubmV3X2ludGw9e2E6NjM3ODE1Ny41LGI6NjM1Njc3Mi4yLGVsbGlwc2VOYW1lOiJOZXcgSW50ZXJuYXRpb25hbCAxOTY3In0sci5wbGVzc2lzPXthOjYzNzY1MjMscmY6NjM1NTg2MyxlbGxpcHNlTmFtZToiUGxlc3NpcyAxODE3IChGcmFuY2UpIn0sci5rcmFzcz17YTo2Mzc4MjQ1LHJmOjI5OC4zLGVsbGlwc2VOYW1lOiJLcmFzc292c2t5LCAxOTQyIn0sci5TRWFzaWE9e2E6NjM3ODE1NSxiOjYzNTY3NzMuMzIwNSxlbGxpcHNlTmFtZToiU291dGhlYXN0IEFzaWEifSxyLndhbGJlY2s9e2E6NjM3Njg5NixiOjYzNTU4MzQuODQ2NyxlbGxpcHNlTmFtZToiV2FsYmVjayJ9LHIuV0dTNjA9e2E6NjM3ODE2NSxyZjoyOTguMyxlbGxpcHNlTmFtZToiV0dTIDYwIn0sci5XR1M2Nj17YTo2Mzc4MTQ1LHJmOjI5OC4yNSxlbGxpcHNlTmFtZToiV0dTIDY2In0sci5XR1M3PXthOjYzNzgxMzUscmY6Mjk4LjI2LGVsbGlwc2VOYW1lOiJXR1MgNzIifSxyLldHUzg0PXthOjYzNzgxMzcscmY6Mjk4LjI1NzIyMzU2MyxlbGxpcHNlTmFtZToiV0dTIDg0In0sci5zcGhlcmU9e2E6NjM3MDk5NyxiOjYzNzA5OTcsZWxsaXBzZU5hbWU6Ik5vcm1hbCBTcGhlcmUgKHI9NjM3MDk5NykifX0se31dLCJwcm9qNC9saWIvY29uc3RhbnRzL1ByaW1lTWVyaWRpYW4iOltmdW5jdGlvbih0LGUscil7ci5ncmVlbndpY2g9MCxyLmxpc2Jvbj0tOS4xMzE5MDYxMTExMTEsci5wYXJpcz0yLjMzNzIyOTE2NjY2NyxyLmJvZ290YT0tNzQuMDgwOTE2NjY2NjY3LHIubWFkcmlkPS0zLjY4NzkzODg4ODg4OSxyLnJvbWU9MTIuNDUyMzMzMzMzMzMzLHIuYmVybj03LjQzOTU4MzMzMzMzMyxyLmpha2FydGE9MTA2LjgwNzcxOTQ0NDQ0NCxyLmZlcnJvPS0xNy42NjY2NjY2NjY2Njcsci5icnVzc2Vscz00LjM2Nzk3NSxyLnN0b2NraG9sbT0xOC4wNTgyNzc3Nzc3Nzgsci5hdGhlbnM9MjMuNzE2MzM3NSxyLm9zbG89MTAuNzIyOTE2NjY2NjY3fSx7fV0sInByb2o0L2xpYi9jb25zdGFudHMvdW5pdHMiOltmdW5jdGlvbih0LGUscil7ci5mdD17dG9fbWV0ZXI6LjMwNDh9LHJbInVzLWZ0Il09e3RvX21ldGVyOjEyMDAvMzkzN319LHt9XSwicHJvajQvbGliL2NvcmUiOltmdW5jdGlvbih0LGUscil7ZnVuY3Rpb24gbih0LGUscil7dmFyIG47cmV0dXJuIEFycmF5LmlzQXJyYXkocik/KG49YSh0LGUsciksMz09PXIubGVuZ3RoP1tuLngsbi55LG4uel06W24ueCxuLnldKTphKHQsZSxyKX1mdW5jdGlvbiBvKHQpe3JldHVybiB0IGluc3RhbmNlb2Ygcz90OnQub1Byb2o/dC5vUHJvajpzKHQpfWZ1bmN0aW9uIGkodCxlLHIpe3Q9byh0KTt2YXIgaSxzPSExO3JldHVybiJ1bmRlZmluZWQiPT10eXBlb2YgZT8oZT10LHQ9bCxzPSEwKTooInVuZGVmaW5lZCIhPXR5cGVvZiBlLnh8fEFycmF5LmlzQXJyYXkoZSkpJiYocj1lLGU9dCx0PWwscz0hMCksZT1vKGUpLHI/bih0LGUscik6KGk9e2ZvcndhcmQ6ZnVuY3Rpb24ocil7cmV0dXJuIG4odCxlLHIpfSxpbnZlcnNlOmZ1bmN0aW9uKHIpe3JldHVybiBuKGUsdCxyKX19LHMmJihpLm9Qcm9qPWUpLGkpfXZhciBzPXQoIi4vUHJvaiIpLGE9dCgiLi90cmFuc2Zvcm0iKSxsPXMoIldHUzg0Iik7ZS5leHBvcnRzPWl9LHsiLi9Qcm9qIjoicHJvajQvbGliL1Byb2oiLCIuL3RyYW5zZm9ybSI6InByb2o0L2xpYi90cmFuc2Zvcm0ifV0sInByb2o0L2xpYi9kYXR1bSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj1NYXRoLlBJLzIsbz0xLGk9MixzPTMsYT00LGw9NSx1PTQ4NDgxMzY4MTEwOTUzNmUtMjAsaD0xLjAwMjYsYz0uMzgyNjgzNDMyMzY1MDg5OCxwPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzIGluc3RhbmNlb2YgcD8odGhpcy5kYXR1bV90eXBlPWEsdm9pZCh0JiYodC5kYXR1bUNvZGUmJiJub25lIj09PXQuZGF0dW1Db2RlJiYodGhpcy5kYXR1bV90eXBlPWwpLHQuZGF0dW1fcGFyYW1zJiYodGhpcy5kYXR1bV9wYXJhbXM9dC5kYXR1bV9wYXJhbXMubWFwKHBhcnNlRmxvYXQpLDA9PT10aGlzLmRhdHVtX3BhcmFtc1swXSYmMD09PXRoaXMuZGF0dW1fcGFyYW1zWzFdJiYwPT09dGhpcy5kYXR1bV9wYXJhbXNbMl18fCh0aGlzLmRhdHVtX3R5cGU9byksdGhpcy5kYXR1bV9wYXJhbXMubGVuZ3RoPjMmJigwPT09dGhpcy5kYXR1bV9wYXJhbXNbM10mJjA9PT10aGlzLmRhdHVtX3BhcmFtc1s0XSYmMD09PXRoaXMuZGF0dW1fcGFyYW1zWzVdJiYwPT09dGhpcy5kYXR1bV9wYXJhbXNbNl18fCh0aGlzLmRhdHVtX3R5cGU9aSx0aGlzLmRhdHVtX3BhcmFtc1szXSo9dSx0aGlzLmRhdHVtX3BhcmFtc1s0XSo9dSx0aGlzLmRhdHVtX3BhcmFtc1s1XSo9dSx0aGlzLmRhdHVtX3BhcmFtc1s2XT10aGlzLmRhdHVtX3BhcmFtc1s2XS8xZTYrMSkpKSx0aGlzLmRhdHVtX3R5cGU9dC5ncmlkcz9zOnRoaXMuZGF0dW1fdHlwZSx0aGlzLmE9dC5hLHRoaXMuYj10LmIsdGhpcy5lcz10LmVzLHRoaXMuZXAyPXQuZXAyLHRoaXMuZGF0dW1fdHlwZT09PXMmJih0aGlzLmdyaWRzPXQuZ3JpZHMpKSkpOm5ldyBwKHQpfTtwLnByb3RvdHlwZT17Y29tcGFyZV9kYXR1bXM6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuZGF0dW1fdHlwZT09PXQuZGF0dW1fdHlwZSYmKCEodGhpcy5hIT09dC5hfHxNYXRoLmFicyh0aGlzLmVzLXQuZXMpPjVlLTExKSYmKHRoaXMuZGF0dW1fdHlwZT09PW8/dGhpcy5kYXR1bV9wYXJhbXNbMF09PT10LmRhdHVtX3BhcmFtc1swXSYmdGhpcy5kYXR1bV9wYXJhbXNbMV09PT10LmRhdHVtX3BhcmFtc1sxXSYmdGhpcy5kYXR1bV9wYXJhbXNbMl09PT10LmRhdHVtX3BhcmFtc1syXTp0aGlzLmRhdHVtX3R5cGU9PT1pP3RoaXMuZGF0dW1fcGFyYW1zWzBdPT09dC5kYXR1bV9wYXJhbXNbMF0mJnRoaXMuZGF0dW1fcGFyYW1zWzFdPT09dC5kYXR1bV9wYXJhbXNbMV0mJnRoaXMuZGF0dW1fcGFyYW1zWzJdPT09dC5kYXR1bV9wYXJhbXNbMl0mJnRoaXMuZGF0dW1fcGFyYW1zWzNdPT09dC5kYXR1bV9wYXJhbXNbM10mJnRoaXMuZGF0dW1fcGFyYW1zWzRdPT09dC5kYXR1bV9wYXJhbXNbNF0mJnRoaXMuZGF0dW1fcGFyYW1zWzVdPT09dC5kYXR1bV9wYXJhbXNbNV0mJnRoaXMuZGF0dW1fcGFyYW1zWzZdPT09dC5kYXR1bV9wYXJhbXNbNl06dGhpcy5kYXR1bV90eXBlIT09cyYmdC5kYXR1bV90eXBlIT09c3x8dGhpcy5uYWRncmlkcz09PXQubmFkZ3JpZHMpKX0sZ2VvZGV0aWNfdG9fZ2VvY2VudHJpYzpmdW5jdGlvbih0KXt2YXIgZSxyLG8saSxzLGEsbCx1PXQueCxoPXQueSxjPXQuej90Lno6MCxwPTA7aWYoaDwtbiYmaD4tMS4wMDEqbiloPS1uO2Vsc2UgaWYoaD5uJiZoPDEuMDAxKm4paD1uO2Vsc2UgaWYoaDwtbnx8aD5uKXJldHVybiBudWxsO3JldHVybiB1Pk1hdGguUEkmJih1LT0yKk1hdGguUEkpLHM9TWF0aC5zaW4oaCksbD1NYXRoLmNvcyhoKSxhPXMqcyxpPXRoaXMuYS9NYXRoLnNxcnQoMS10aGlzLmVzKmEpLGU9KGkrYykqbCpNYXRoLmNvcyh1KSxyPShpK2MpKmwqTWF0aC5zaW4odSksbz0oaSooMS10aGlzLmVzKStjKSpzLHQueD1lLHQueT1yLHQuej1vLHB9LGdlb2NlbnRyaWNfdG9fZ2VvZGV0aWM6ZnVuY3Rpb24odCl7dmFyIGUscixvLGkscyxhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2PTFlLTEyLGI9dip2LHg9MzAsdz10LngsTT10Lnksaz10Lno/dC56OjA7aWYoZD0hMSxlPU1hdGguc3FydCh3KncrTSpNKSxyPU1hdGguc3FydCh3KncrTSpNK2sqayksZS90aGlzLmE8dil7aWYoZD0hMCxtPTAsci90aGlzLmE8dilyZXR1cm4gZz1uLHZvaWQoeT0tdGhpcy5iKX1lbHNlIG09TWF0aC5hdGFuMihNLHcpO289ay9yLGk9ZS9yLHM9MS9NYXRoLnNxcnQoMS10aGlzLmVzKigyLXRoaXMuZXMpKmkqaSksdT1pKigxLXRoaXMuZXMpKnMsaD1vKnMsZj0wO2RvIGYrKyxsPXRoaXMuYS9NYXRoLnNxcnQoMS10aGlzLmVzKmgqaCkseT1lKnUraypoLWwqKDEtdGhpcy5lcypoKmgpLGE9dGhpcy5lcypsLyhsK3kpLHM9MS9NYXRoLnNxcnQoMS1hKigyLWEpKmkqaSksYz1pKigxLWEpKnMscD1vKnMsXz1wKnUtYypoLHU9YyxoPXA7d2hpbGUoXypfPmImJmY8eCk7cmV0dXJuIGc9TWF0aC5hdGFuKHAvTWF0aC5hYnMoYykpLHQueD1tLHQueT1nLHQuej15LHR9LGdlb2NlbnRyaWNfdG9fZ2VvZGV0aWNfbm9uaXRlcjpmdW5jdGlvbih0KXt2YXIgZSxyLG8saSxzLGEsbCx1LHAsXyxkLGYsbSxnLHksdixiLHg9dC54LHc9dC55LE09dC56P3QuejowO2lmKHg9cGFyc2VGbG9hdCh4KSx3PXBhcnNlRmxvYXQodyksTT1wYXJzZUZsb2F0KE0pLGI9ITEsMCE9PXgpZT1NYXRoLmF0YW4yKHcseCk7ZWxzZSBpZih3PjApZT1uO2Vsc2UgaWYodzwwKWU9LW47ZWxzZSBpZihiPSEwLGU9MCxNPjApcj1uO2Vsc2V7aWYoIShNPDApKXJldHVybiByPW4sdm9pZChvPS10aGlzLmIpO3I9LW59cmV0dXJuIHM9eCp4K3cqdyxpPU1hdGguc3FydChzKSxhPU0qaCx1PU1hdGguc3FydChhKmErcyksXz1hL3UsZj1pL3UsZD1fKl8qXyxsPU0rdGhpcy5iKnRoaXMuZXAyKmQsdj1pLXRoaXMuYSp0aGlzLmVzKmYqZipmLHA9TWF0aC5zcXJ0KGwqbCt2KnYpLG09bC9wLGc9di9wLHk9dGhpcy5hL01hdGguc3FydCgxLXRoaXMuZXMqbSptKSxvPWc+PWM/aS9nLXk6Zzw9LWM/aS8tZy15Ok0vbSt5Kih0aGlzLmVzLTEpLGI9PT0hMSYmKHI9TWF0aC5hdGFuKG0vZykpLHQueD1lLHQueT1yLHQuej1vLHR9LGdlb2NlbnRyaWNfdG9fd2dzODQ6ZnVuY3Rpb24odCl7aWYodGhpcy5kYXR1bV90eXBlPT09byl0LngrPXRoaXMuZGF0dW1fcGFyYW1zWzBdLHQueSs9dGhpcy5kYXR1bV9wYXJhbXNbMV0sdC56Kz10aGlzLmRhdHVtX3BhcmFtc1syXTtlbHNlIGlmKHRoaXMuZGF0dW1fdHlwZT09PWkpe3ZhciBlPXRoaXMuZGF0dW1fcGFyYW1zWzBdLHI9dGhpcy5kYXR1bV9wYXJhbXNbMV0sbj10aGlzLmRhdHVtX3BhcmFtc1syXSxzPXRoaXMuZGF0dW1fcGFyYW1zWzNdLGE9dGhpcy5kYXR1bV9wYXJhbXNbNF0sbD10aGlzLmRhdHVtX3BhcmFtc1s1XSx1PXRoaXMuZGF0dW1fcGFyYW1zWzZdLGg9dSoodC54LWwqdC55K2EqdC56KStlLGM9dSoobCp0LngrdC55LXMqdC56KStyLHA9dSooLWEqdC54K3MqdC55K3Queikrbjt0Lng9aCx0Lnk9Yyx0Lno9cH19LGdlb2NlbnRyaWNfZnJvbV93Z3M4NDpmdW5jdGlvbih0KXtpZih0aGlzLmRhdHVtX3R5cGU9PT1vKXQueC09dGhpcy5kYXR1bV9wYXJhbXNbMF0sdC55LT10aGlzLmRhdHVtX3BhcmFtc1sxXSx0LnotPXRoaXMuZGF0dW1fcGFyYW1zWzJdO2Vsc2UgaWYodGhpcy5kYXR1bV90eXBlPT09aSl7dmFyIGU9dGhpcy5kYXR1bV9wYXJhbXNbMF0scj10aGlzLmRhdHVtX3BhcmFtc1sxXSxuPXRoaXMuZGF0dW1fcGFyYW1zWzJdLHM9dGhpcy5kYXR1bV9wYXJhbXNbM10sYT10aGlzLmRhdHVtX3BhcmFtc1s0XSxsPXRoaXMuZGF0dW1fcGFyYW1zWzVdLHU9dGhpcy5kYXR1bV9wYXJhbXNbNl0saD0odC54LWUpL3UsYz0odC55LXIpL3UscD0odC56LW4pL3U7dC54PWgrbCpjLWEqcCx0Lnk9LWwqaCtjK3MqcCx0Lno9YSpoLXMqYytwfX19LGUuZXhwb3J0cz1wfSx7fV0sInByb2o0L2xpYi9kYXR1bV90cmFuc2Zvcm0iOltmdW5jdGlvbih0LGUscil7dmFyIG49MSxvPTIsaT0zLHM9NSxhPTYzNzgxMzcsbD0uMDA2Njk0Mzc5OTkwMTQxMzE2O2UuZXhwb3J0cz1mdW5jdGlvbih0LGUscil7ZnVuY3Rpb24gdSh0KXtyZXR1cm4gdD09PW58fHQ9PT1vfXZhciBoLGMscDtpZih0LmNvbXBhcmVfZGF0dW1zKGUpKXJldHVybiByO2lmKHQuZGF0dW1fdHlwZT09PXN8fGUuZGF0dW1fdHlwZT09PXMpcmV0dXJuIHI7dmFyIF89dC5hLGQ9dC5lcyxmPWUuYSxtPWUuZXMsZz10LmRhdHVtX3R5cGU7aWYoZz09PWkpaWYoMD09PXRoaXMuYXBwbHlfZ3JpZHNoaWZ0KHQsMCxyKSl0LmE9YSx0LmVzPWw7ZWxzZXtpZighdC5kYXR1bV9wYXJhbXMpcmV0dXJuIHQuYT1fLHQuZXM9dC5lcyxyO2ZvcihoPTEsYz0wLHA9dC5kYXR1bV9wYXJhbXMubGVuZ3RoO2M8cDtjKyspaCo9dC5kYXR1bV9wYXJhbXNbY107aWYoMD09PWgpcmV0dXJuIHQuYT1fLHQuZXM9dC5lcyxyO2c9dC5kYXR1bV9wYXJhbXMubGVuZ3RoPjM/bzpufXJldHVybiBlLmRhdHVtX3R5cGU9PT1pJiYoZS5hPWEsZS5lcz1sKSwodC5lcyE9PWUuZXN8fHQuYSE9PWUuYXx8dShnKXx8dShlLmRhdHVtX3R5cGUpKSYmKHQuZ2VvZGV0aWNfdG9fZ2VvY2VudHJpYyhyKSx1KHQuZGF0dW1fdHlwZSkmJnQuZ2VvY2VudHJpY190b193Z3M4NChyKSx1KGUuZGF0dW1fdHlwZSkmJmUuZ2VvY2VudHJpY19mcm9tX3dnczg0KHIpLGUuZ2VvY2VudHJpY190b19nZW9kZXRpYyhyKSksZS5kYXR1bV90eXBlPT09aSYmdGhpcy5hcHBseV9ncmlkc2hpZnQoZSwxLHIpLHQuYT1fLHQuZXM9ZCxlLmE9ZixlLmVzPW0scn19LHt9XSwicHJvajQvbGliL2RlZnMiOltmdW5jdGlvbih0LGUscil7ZnVuY3Rpb24gbih0KXt2YXIgZT10aGlzO2lmKDI9PT1hcmd1bWVudHMubGVuZ3RoKXt2YXIgcj1hcmd1bWVudHNbMV07InN0cmluZyI9PXR5cGVvZiByPyIrIj09PXIuY2hhckF0KDApP25bdF09aShhcmd1bWVudHNbMV0pOm5bdF09cyhhcmd1bWVudHNbMV0pOm5bdF09cn1lbHNlIGlmKDE9PT1hcmd1bWVudHMubGVuZ3RoKXtpZihBcnJheS5pc0FycmF5KHQpKXJldHVybiB0Lm1hcChmdW5jdGlvbih0KXtBcnJheS5pc0FycmF5KHQpP24uYXBwbHkoZSx0KTpuKHQpfSk7aWYoInN0cmluZyI9PXR5cGVvZiB0KXtpZih0IGluIG4pcmV0dXJuIG5bdF19ZWxzZSJFUFNHImluIHQ/blsiRVBTRzoiK3QuRVBTR109dDoiRVNSSSJpbiB0P25bIkVTUkk6Iit0LkVTUkldPXQ6IklBVTIwMDAiaW4gdD9uWyJJQVUyMDAwOiIrdC5JQVUyMDAwXT10OmNvbnNvbGUubG9nKHQpO3JldHVybn19dmFyIG89dCgiLi9nbG9iYWwiKSxpPXQoIi4vcHJvalN0cmluZyIpLHM9dCgiLi93a3QiKTtvKG4pLGUuZXhwb3J0cz1ufSx7Ii4vZ2xvYmFsIjoicHJvajQvbGliL2dsb2JhbCIsIi4vcHJvalN0cmluZyI6InByb2o0L2xpYi9wcm9qU3RyaW5nIiwiLi93a3QiOiJwcm9qNC9saWIvd2t0In1dLCJwcm9qNC9saWIvZGVyaXZlQ29uc3RhbnRzIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPXQoIi4vY29uc3RhbnRzL0RhdHVtIiksbz10KCIuL2NvbnN0YW50cy9FbGxpcHNvaWQiKSxpPXQoIi4vZXh0ZW5kIikscz10KCIuL2RhdHVtIiksYT0xZS0xMCxsPS4xNjY2NjY2NjY2NjY2NjY2Nix1PS4wNDcyMjIyMjIyMjIyMjIyMixoPS4wMjIxNTYwODQ2NTYwODQ2NTU7ZS5leHBvcnRzPWZ1bmN0aW9uKHQpe2lmKHQuZGF0dW1Db2RlJiYibm9uZSIhPT10LmRhdHVtQ29kZSl7dmFyIGU9blt0LmRhdHVtQ29kZV07ZSYmKHQuZGF0dW1fcGFyYW1zPWUudG93Z3M4ND9lLnRvd2dzODQuc3BsaXQoIiwiKTpudWxsLHQuZWxscHM9ZS5lbGxpcHNlLHQuZGF0dW1OYW1lPWUuZGF0dW1OYW1lP2UuZGF0dW1OYW1lOnQuZGF0dW1Db2RlKX1pZighdC5hKXt2YXIgcj1vW3QuZWxscHNdP29bdC5lbGxwc106by5XR1M4NDtpKHQscil9cmV0dXJuIHQucmYmJiF0LmImJih0LmI9KDEtMS90LnJmKSp0LmEpLCgwPT09dC5yZnx8TWF0aC5hYnModC5hLXQuYik8YSkmJih0LnNwaGVyZT0hMCx0LmI9dC5hKSx0LmEyPXQuYSp0LmEsdC5iMj10LmIqdC5iLHQuZXM9KHQuYTItdC5iMikvdC5hMix0LmU9TWF0aC5zcXJ0KHQuZXMpLHQuUl9BJiYodC5hKj0xLXQuZXMqKGwrdC5lcyoodSt0LmVzKmgpKSx0LmEyPXQuYSp0LmEsdC5iMj10LmIqdC5iLHQuZXM9MCksdC5lcDI9KHQuYTItdC5iMikvdC5iMix0LmswfHwodC5rMD0xKSx0LmF4aXN8fCh0LmF4aXM9ImVudSIpLHQuZGF0dW18fCh0LmRhdHVtPXModCkpLHR9fSx7Ii4vY29uc3RhbnRzL0RhdHVtIjoicHJvajQvbGliL2NvbnN0YW50cy9EYXR1bSIsIi4vY29uc3RhbnRzL0VsbGlwc29pZCI6InByb2o0L2xpYi9jb25zdGFudHMvRWxsaXBzb2lkIiwiLi9kYXR1bSI6InByb2o0L2xpYi9kYXR1bSIsIi4vZXh0ZW5kIjoicHJvajQvbGliL2V4dGVuZCJ9XSwicHJvajQvbGliL2V4dGVuZCI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9ZnVuY3Rpb24odCxlKXt0PXR8fHt9O3ZhciByLG47aWYoIWUpcmV0dXJuIHQ7Zm9yKG4gaW4gZSlyPWVbbl0sdm9pZCAwIT09ciYmKHRbbl09cik7cmV0dXJuIHR9fSx7fV0sInByb2o0L2xpYi9nbG9iYWwiOltmdW5jdGlvbih0LGUscil7ZS5leHBvcnRzPWZ1bmN0aW9uKHQpe3QoIkVQU0c6NDMyNiIsIit0aXRsZT1XR1MgODQgKGxvbmcvbGF0KSArcHJvaj1sb25nbGF0ICtlbGxwcz1XR1M4NCArZGF0dW09V0dTODQgK3VuaXRzPWRlZ3JlZXMiKSx0KCJFUFNHOjQyNjkiLCIrdGl0bGU9TkFEODMgKGxvbmcvbGF0KSArcHJvaj1sb25nbGF0ICthPTYzNzgxMzcuMCArYj02MzU2NzUyLjMxNDE0MDM2ICtlbGxwcz1HUlM4MCArZGF0dW09TkFEODMgK3VuaXRzPWRlZ3JlZXMiKSx0KCJFUFNHOjM4NTciLCIrdGl0bGU9V0dTIDg0IC8gUHNldWRvLU1lcmNhdG9yICtwcm9qPW1lcmMgK2E9NjM3ODEzNyArYj02Mzc4MTM3ICtsYXRfdHM9MC4wICtsb25fMD0wLjAgK3hfMD0wLjAgK3lfMD0wICtrPTEuMCArdW5pdHM9bSArbmFkZ3JpZHM9QG51bGwgK25vX2RlZnMiKSx0LldHUzg0PXRbIkVQU0c6NDMyNiJdLHRbIkVQU0c6Mzc4NSJdPXRbIkVQU0c6Mzg1NyJdLHQuR09PR0xFPXRbIkVQU0c6Mzg1NyJdLHRbIkVQU0c6OTAwOTEzIl09dFsiRVBTRzozODU3Il0sdFsiRVBTRzoxMDIxMTMiXT10WyJFUFNHOjM4NTciXX19LHt9XSwicHJvajQvbGliL2luY2x1ZGVkUHJvamVjdGlvbnMiOltmdW5jdGlvbih0LGUscil7dmFyIG49W3QoIi4vcHJvamVjdGlvbnMvdG1lcmMiKSx0KCIuL3Byb2plY3Rpb25zL3V0bSIpLHQoIi4vcHJvamVjdGlvbnMvc3RlcmVhIiksdCgiLi9wcm9qZWN0aW9ucy9zdGVyZSIpLHQoIi4vcHJvamVjdGlvbnMvc29tZXJjIiksdCgiLi9wcm9qZWN0aW9ucy9vbWVyYyIpLHQoIi4vcHJvamVjdGlvbnMvbGNjIiksdCgiLi9wcm9qZWN0aW9ucy9rcm92YWsiKSx0KCIuL3Byb2plY3Rpb25zL2Nhc3MiKSx0KCIuL3Byb2plY3Rpb25zL2xhZWEiKSx0KCIuL3Byb2plY3Rpb25zL2FlYSIpLHQoIi4vcHJvamVjdGlvbnMvZ25vbSIpLHQoIi4vcHJvamVjdGlvbnMvY2VhIiksdCgiLi9wcm9qZWN0aW9ucy9lcWMiKSx0KCIuL3Byb2plY3Rpb25zL3BvbHkiKSx0KCIuL3Byb2plY3Rpb25zL256bWciKSx0KCIuL3Byb2plY3Rpb25zL21pbGwiKSx0KCIuL3Byb2plY3Rpb25zL3NpbnUiKSx0KCIuL3Byb2plY3Rpb25zL21vbGwiKSx0KCIuL3Byb2plY3Rpb25zL2VxZGMiKSx0KCIuL3Byb2plY3Rpb25zL3ZhbmRnIiksdCgiLi9wcm9qZWN0aW9ucy9hZXFkIildO2UuZXhwb3J0cz1mdW5jdGlvbih0KXtuLmZvckVhY2goZnVuY3Rpb24oZSl7dC5Qcm9qLnByb2plY3Rpb25zLmFkZChlKX0pfX0seyIuL3Byb2plY3Rpb25zL2FlYSI6InByb2o0L2xpYi9wcm9qZWN0aW9ucy9hZWEiLCIuL3Byb2plY3Rpb25zL2FlcWQiOiJwcm9qNC9saWIvcHJvamVjdGlvbnMvYWVxZCIsIi4vcHJvamVjdGlvbnMvY2FzcyI6InByb2o0L2xpYi9wcm9qZWN0aW9ucy9jYXNzIiwiLi9wcm9qZWN0aW9ucy9jZWEiOiJwcm9qNC9saWIvcHJvamVjdGlvbnMvY2VhIiwiLi9wcm9qZWN0aW9ucy9lcWMiOiJwcm9qNC9saWIvcHJvamVjdGlvbnMvZXFjIiwiLi9wcm9qZWN0aW9ucy9lcWRjIjoicHJvajQvbGliL3Byb2plY3Rpb25zL2VxZGMiLCIuL3Byb2plY3Rpb25zL2dub20iOiJwcm9qNC9saWIvcHJvamVjdGlvbnMvZ25vbSIsIi4vcHJvamVjdGlvbnMva3JvdmFrIjoicHJvajQvbGliL3Byb2plY3Rpb25zL2tyb3ZhayIsIi4vcHJvamVjdGlvbnMvbGFlYSI6InByb2o0L2xpYi9wcm9qZWN0aW9ucy9sYWVhIiwiLi9wcm9qZWN0aW9ucy9sY2MiOiJwcm9qNC9saWIvcHJvamVjdGlvbnMvbGNjIiwiLi9wcm9qZWN0aW9ucy9taWxsIjoicHJvajQvbGliL3Byb2plY3Rpb25zL21pbGwiLCIuL3Byb2plY3Rpb25zL21vbGwiOiJwcm9qNC9saWIvcHJvamVjdGlvbnMvbW9sbCIsIi4vcHJvamVjdGlvbnMvbnptZyI6InByb2o0L2xpYi9wcm9qZWN0aW9ucy9uem1nIiwiLi9wcm9qZWN0aW9ucy9vbWVyYyI6InByb2o0L2xpYi9wcm9qZWN0aW9ucy9vbWVyYyIsIi4vcHJvamVjdGlvbnMvcG9seSI6InByb2o0L2xpYi9wcm9qZWN0aW9ucy9wb2x5IiwiLi9wcm9qZWN0aW9ucy9zaW51IjoicHJvajQvbGliL3Byb2plY3Rpb25zL3NpbnUiLCIuL3Byb2plY3Rpb25zL3NvbWVyYyI6InByb2o0L2xpYi9wcm9qZWN0aW9ucy9zb21lcmMiLCIuL3Byb2plY3Rpb25zL3N0ZXJlIjoicHJvajQvbGliL3Byb2plY3Rpb25zL3N0ZXJlIiwiLi9wcm9qZWN0aW9ucy9zdGVyZWEiOiJwcm9qNC9saWIvcHJvamVjdGlvbnMvc3RlcmVhIiwiLi9wcm9qZWN0aW9ucy90bWVyYyI6InByb2o0L2xpYi9wcm9qZWN0aW9ucy90bWVyYyIsIi4vcHJvamVjdGlvbnMvdXRtIjoicHJvajQvbGliL3Byb2plY3Rpb25zL3V0bSIsIi4vcHJvamVjdGlvbnMvdmFuZGciOiJwcm9qNC9saWIvcHJvamVjdGlvbnMvdmFuZGcifV0scHJvajQ6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj10KCIuL2NvcmUiKTtuLmRlZmF1bHREYXR1bT0iV0dTODQiLG4uUHJvaj10KCIuL1Byb2oiKSxuLldHUzg0PW5ldyBuLlByb2ooIldHUzg0Iiksbi5Qb2ludD10KCIuL1BvaW50Iiksbi50b1BvaW50PXQoIi4vY29tbW9uL3RvUG9pbnQiKSxuLmRlZnM9dCgiLi9kZWZzIiksbi50cmFuc2Zvcm09dCgiLi90cmFuc2Zvcm0iKSxuLm1ncnM9dCgibWdycyIpLG4udmVyc2lvbj10KCIuLi9wYWNrYWdlLmpzb24iKS52ZXJzaW9uLHQoIi4vaW5jbHVkZWRQcm9qZWN0aW9ucyIpKG4pLGUuZXhwb3J0cz1ufSx7Ii4uL3BhY2thZ2UuanNvbiI6InByb2o0L3BhY2thZ2UuanNvbiIsIi4vUG9pbnQiOiJwcm9qNC9saWIvUG9pbnQiLCIuL1Byb2oiOiJwcm9qNC9saWIvUHJvaiIsIi4vY29tbW9uL3RvUG9pbnQiOiJwcm9qNC9saWIvY29tbW9uL3RvUG9pbnQiLCIuL2NvcmUiOiJwcm9qNC9saWIvY29yZSIsIi4vZGVmcyI6InByb2o0L2xpYi9kZWZzIiwiLi9pbmNsdWRlZFByb2plY3Rpb25zIjoicHJvajQvbGliL2luY2x1ZGVkUHJvamVjdGlvbnMiLCIuL3RyYW5zZm9ybSI6InByb2o0L2xpYi90cmFuc2Zvcm0iLG1ncnM6InByb2o0L25vZGVfbW9kdWxlcy9tZ3JzL21ncnMifV0sInByb2o0L2xpYi9wYXJzZUNvZGUiOltmdW5jdGlvbih0LGUscil7ZnVuY3Rpb24gbih0KXtyZXR1cm4ic3RyaW5nIj09dHlwZW9mIHR9ZnVuY3Rpb24gbyh0KXtyZXR1cm4gdCBpbiBsfWZ1bmN0aW9uIGkodCl7dmFyIGU9WyJHRU9HQ1MiLCJHRU9DQ1MiLCJQUk9KQ1MiLCJMT0NBTF9DUyJdO3JldHVybiBlLnJlZHVjZShmdW5jdGlvbihlLHIpe3JldHVybiBlKzErdC5pbmRleE9mKHIpfSwwKX1mdW5jdGlvbiBzKHQpe3JldHVybiIrIj09PXRbMF19ZnVuY3Rpb24gYSh0KXtyZXR1cm4gbih0KT9vKHQpP2xbdF06aSh0KT91KHQpOnModCk/aCh0KTp2b2lkIDA6dH12YXIgbD10KCIuL2RlZnMiKSx1PXQoIi4vd2t0IiksaD10KCIuL3Byb2pTdHJpbmciKTtlLmV4cG9ydHM9YX0seyIuL2RlZnMiOiJwcm9qNC9saWIvZGVmcyIsIi4vcHJvalN0cmluZyI6InByb2o0L2xpYi9wcm9qU3RyaW5nIiwiLi93a3QiOiJwcm9qNC9saWIvd2t0In1dLCJwcm9qNC9saWIvcHJvalN0cmluZyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj0uMDE3NDUzMjkyNTE5OTQzMjk1LG89dCgiLi9jb25zdGFudHMvUHJpbWVNZXJpZGlhbiIpLGk9dCgiLi9jb25zdGFudHMvdW5pdHMiKTtlLmV4cG9ydHM9ZnVuY3Rpb24odCl7dmFyIGU9e30scj17fTt0LnNwbGl0KCIrIikubWFwKGZ1bmN0aW9uKHQpe3JldHVybiB0LnRyaW0oKX0pLmZpbHRlcihmdW5jdGlvbih0KXtyZXR1cm4gdH0pLmZvckVhY2goZnVuY3Rpb24odCl7dmFyIGU9dC5zcGxpdCgiPSIpO2UucHVzaCghMCkscltlWzBdLnRvTG93ZXJDYXNlKCldPWVbMV19KTt2YXIgcyxhLGwsdT17cHJvajoicHJvak5hbWUiLGRhdHVtOiJkYXR1bUNvZGUiLHJmOmZ1bmN0aW9uKHQpe2UucmY9cGFyc2VGbG9hdCh0KX0sbGF0XzA6ZnVuY3Rpb24odCl7ZS5sYXQwPXQqbn0sbGF0XzE6ZnVuY3Rpb24odCl7ZS5sYXQxPXQqbn0sbGF0XzI6ZnVuY3Rpb24odCl7ZS5sYXQyPXQqbn0sbGF0X3RzOmZ1bmN0aW9uKHQpe2UubGF0X3RzPXQqbn0sbG9uXzA6ZnVuY3Rpb24odCl7ZS5sb25nMD10Km59LGxvbl8xOmZ1bmN0aW9uKHQpe2UubG9uZzE9dCpufSxsb25fMjpmdW5jdGlvbih0KXtlLmxvbmcyPXQqbn0sYWxwaGE6ZnVuY3Rpb24odCl7ZS5hbHBoYT1wYXJzZUZsb2F0KHQpKm59LGxvbmM6ZnVuY3Rpb24odCl7ZS5sb25nYz10Km59LHhfMDpmdW5jdGlvbih0KXtlLngwPXBhcnNlRmxvYXQodCl9LHlfMDpmdW5jdGlvbih0KXtlLnkwPXBhcnNlRmxvYXQodCl9LGtfMDpmdW5jdGlvbih0KXtlLmswPXBhcnNlRmxvYXQodCl9LGs6ZnVuY3Rpb24odCl7ZS5rMD1wYXJzZUZsb2F0KHQpfSxhOmZ1bmN0aW9uKHQpe2UuYT1wYXJzZUZsb2F0KHQpfSxiOmZ1bmN0aW9uKHQpe2UuYj1wYXJzZUZsb2F0KHQpfSxyX2E6ZnVuY3Rpb24oKXtlLlJfQT0hMH0sem9uZTpmdW5jdGlvbih0KXtlLnpvbmU9cGFyc2VJbnQodCwxMCl9LHNvdXRoOmZ1bmN0aW9uKCl7ZS51dG1Tb3V0aD0hMH0sdG93Z3M4NDpmdW5jdGlvbih0KXtlLmRhdHVtX3BhcmFtcz10LnNwbGl0KCIsIikubWFwKGZ1bmN0aW9uKHQpe3JldHVybiBwYXJzZUZsb2F0KHQpfSl9LHRvX21ldGVyOmZ1bmN0aW9uKHQpe2UudG9fbWV0ZXI9cGFyc2VGbG9hdCh0KX0sdW5pdHM6ZnVuY3Rpb24odCl7ZS51bml0cz10LGlbdF0mJihlLnRvX21ldGVyPWlbdF0udG9fbWV0ZXIpfSxmcm9tX2dyZWVud2ljaDpmdW5jdGlvbih0KXtlLmZyb21fZ3JlZW53aWNoPXQqbn0scG06ZnVuY3Rpb24odCl7ZS5mcm9tX2dyZWVud2ljaD0ob1t0XT9vW3RdOnBhcnNlRmxvYXQodCkpKm59LG5hZGdyaWRzOmZ1bmN0aW9uKHQpeyJAbnVsbCI9PT10P2UuZGF0dW1Db2RlPSJub25lIjplLm5hZGdyaWRzPXR9LGF4aXM6ZnVuY3Rpb24odCl7dmFyIHI9ImV3bnN1ZCI7Mz09PXQubGVuZ3RoJiZyLmluZGV4T2YodC5zdWJzdHIoMCwxKSkhPT0tMSYmci5pbmRleE9mKHQuc3Vic3RyKDEsMSkpIT09LTEmJnIuaW5kZXhPZih0LnN1YnN0cigyLDEpKSE9PS0xJiYoZS5heGlzPXQpfX07Zm9yKHMgaW4gcilhPXJbc10scyBpbiB1PyhsPXVbc10sImZ1bmN0aW9uIj09dHlwZW9mIGw/bChhKTplW2xdPWEpOmVbc109YTtyZXR1cm4ic3RyaW5nIj09dHlwZW9mIGUuZGF0dW1Db2RlJiYiV0dTODQiIT09ZS5kYXR1bUNvZGUmJihlLmRhdHVtQ29kZT1lLmRhdHVtQ29kZS50b0xvd2VyQ2FzZSgpKSxlfX0seyIuL2NvbnN0YW50cy9QcmltZU1lcmlkaWFuIjoicHJvajQvbGliL2NvbnN0YW50cy9QcmltZU1lcmlkaWFuIiwiLi9jb25zdGFudHMvdW5pdHMiOiJwcm9qNC9saWIvY29uc3RhbnRzL3VuaXRzIn1dLCJwcm9qNC9saWIvcHJvamVjdGlvbnMiOltmdW5jdGlvbih0LGUscil7ZnVuY3Rpb24gbih0LGUpe3ZhciByPXMubGVuZ3RoO3JldHVybiB0Lm5hbWVzPyhzW3JdPXQsdC5uYW1lcy5mb3JFYWNoKGZ1bmN0aW9uKHQpe2lbdC50b0xvd2VyQ2FzZSgpXT1yfSksdGhpcyk6KGNvbnNvbGUubG9nKGUpLCEwKX12YXIgbz1bdCgiLi9wcm9qZWN0aW9ucy9tZXJjIiksdCgiLi9wcm9qZWN0aW9ucy9sb25nbGF0IildLGk9e30scz1bXTtyLmFkZD1uLHIuZ2V0PWZ1bmN0aW9uKHQpe2lmKCF0KXJldHVybiExO3ZhciBlPXQudG9Mb3dlckNhc2UoKTtyZXR1cm4idW5kZWZpbmVkIiE9dHlwZW9mIGlbZV0mJnNbaVtlXV0/c1tpW2VdXTp2b2lkIDB9LHIuc3RhcnQ9ZnVuY3Rpb24oKXtvLmZvckVhY2gobil9fSx7Ii4vcHJvamVjdGlvbnMvbG9uZ2xhdCI6InByb2o0L2xpYi9wcm9qZWN0aW9ucy9sb25nbGF0IiwiLi9wcm9qZWN0aW9ucy9tZXJjIjoicHJvajQvbGliL3Byb2plY3Rpb25zL21lcmMifV0sInByb2o0L2xpYi9wcm9qZWN0aW9ucy9hZWEiOltmdW5jdGlvbih0LGUscil7dmFyIG49MWUtMTAsbz10KCIuLi9jb21tb24vbXNmbnoiKSxpPXQoIi4uL2NvbW1vbi9xc2ZueiIpLHM9dCgiLi4vY29tbW9uL2FkanVzdF9sb24iKSxhPXQoIi4uL2NvbW1vbi9hc2lueiIpO3IuaW5pdD1mdW5jdGlvbigpe01hdGguYWJzKHRoaXMubGF0MSt0aGlzLmxhdDIpPG58fCh0aGlzLnRlbXA9dGhpcy5iL3RoaXMuYSx0aGlzLmVzPTEtTWF0aC5wb3codGhpcy50ZW1wLDIpLHRoaXMuZTM9TWF0aC5zcXJ0KHRoaXMuZXMpLHRoaXMuc2luX3BvPU1hdGguc2luKHRoaXMubGF0MSksdGhpcy5jb3NfcG89TWF0aC5jb3ModGhpcy5sYXQxKSx0aGlzLnQxPXRoaXMuc2luX3BvLHRoaXMuY29uPXRoaXMuc2luX3BvLHRoaXMubXMxPW8odGhpcy5lMyx0aGlzLnNpbl9wbyx0aGlzLmNvc19wbyksdGhpcy5xczE9aSh0aGlzLmUzLHRoaXMuc2luX3BvLHRoaXMuY29zX3BvKSx0aGlzLnNpbl9wbz1NYXRoLnNpbih0aGlzLmxhdDIpLHRoaXMuY29zX3BvPU1hdGguY29zKHRoaXMubGF0MiksdGhpcy50Mj10aGlzLnNpbl9wbyx0aGlzLm1zMj1vKHRoaXMuZTMsdGhpcy5zaW5fcG8sdGhpcy5jb3NfcG8pLHRoaXMucXMyPWkodGhpcy5lMyx0aGlzLnNpbl9wbyx0aGlzLmNvc19wbyksdGhpcy5zaW5fcG89TWF0aC5zaW4odGhpcy5sYXQwKSx0aGlzLmNvc19wbz1NYXRoLmNvcyh0aGlzLmxhdDApLHRoaXMudDM9dGhpcy5zaW5fcG8sdGhpcy5xczA9aSh0aGlzLmUzLHRoaXMuc2luX3BvLHRoaXMuY29zX3BvKSxNYXRoLmFicyh0aGlzLmxhdDEtdGhpcy5sYXQyKT5uP3RoaXMubnMwPSh0aGlzLm1zMSp0aGlzLm1zMS10aGlzLm1zMip0aGlzLm1zMikvKHRoaXMucXMyLXRoaXMucXMxKTp0aGlzLm5zMD10aGlzLmNvbix0aGlzLmM9dGhpcy5tczEqdGhpcy5tczErdGhpcy5uczAqdGhpcy5xczEsdGhpcy5yaD10aGlzLmEqTWF0aC5zcXJ0KHRoaXMuYy10aGlzLm5zMCp0aGlzLnFzMCkvdGhpcy5uczApfSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGU9dC54LHI9dC55O3RoaXMuc2luX3BoaT1NYXRoLnNpbihyKSx0aGlzLmNvc19waGk9TWF0aC5jb3Mocik7dmFyIG49aSh0aGlzLmUzLHRoaXMuc2luX3BoaSx0aGlzLmNvc19waGkpLG89dGhpcy5hKk1hdGguc3FydCh0aGlzLmMtdGhpcy5uczAqbikvdGhpcy5uczAsYT10aGlzLm5zMCpzKGUtdGhpcy5sb25nMCksbD1vKk1hdGguc2luKGEpK3RoaXMueDAsdT10aGlzLnJoLW8qTWF0aC5jb3MoYSkrdGhpcy55MDtyZXR1cm4gdC54PWwsdC55PXUsdH0sci5pbnZlcnNlPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGksYTtyZXR1cm4gdC54LT10aGlzLngwLHQueT10aGlzLnJoLXQueSt0aGlzLnkwLHRoaXMubnMwPj0wPyhlPU1hdGguc3FydCh0LngqdC54K3QueSp0LnkpLG49MSk6KGU9LU1hdGguc3FydCh0LngqdC54K3QueSp0LnkpLG49LTEpLG89MCwwIT09ZSYmKG89TWF0aC5hdGFuMihuKnQueCxuKnQueSkpLG49ZSp0aGlzLm5zMC90aGlzLmEsdGhpcy5zcGhlcmU/YT1NYXRoLmFzaW4oKHRoaXMuYy1uKm4pLygyKnRoaXMubnMwKSk6KHI9KHRoaXMuYy1uKm4pL3RoaXMubnMwLGE9dGhpcy5waGkxeih0aGlzLmUzLHIpKSxpPXMoby90aGlzLm5zMCt0aGlzLmxvbmcwKSx0Lng9aSx0Lnk9YSx0fSxyLnBoaTF6PWZ1bmN0aW9uKHQsZSl7dmFyIHIsbyxpLHMsbCx1PWEoLjUqZSk7aWYodDxuKXJldHVybiB1O2Zvcih2YXIgaD10KnQsYz0xO2M8PTI1O2MrKylpZihyPU1hdGguc2luKHUpLG89TWF0aC5jb3ModSksaT10KnIscz0xLWkqaSxsPS41KnMqcy9vKihlLygxLWgpLXIvcysuNS90Kk1hdGgubG9nKCgxLWkpLygxK2kpKSksdSs9bCxNYXRoLmFicyhsKTw9MWUtNylyZXR1cm4gdTtyZXR1cm4gbnVsbH0sci5uYW1lcz1bIkFsYmVyc19Db25pY19FcXVhbF9BcmVhIiwiQWxiZXJzIiwiYWVhIl19LHsiLi4vY29tbW9uL2FkanVzdF9sb24iOiJwcm9qNC9saWIvY29tbW9uL2FkanVzdF9sb24iLCIuLi9jb21tb24vYXNpbnoiOiJwcm9qNC9saWIvY29tbW9uL2FzaW56IiwiLi4vY29tbW9uL21zZm56IjoicHJvajQvbGliL2NvbW1vbi9tc2ZueiIsIi4uL2NvbW1vbi9xc2ZueiI6InByb2o0L2xpYi9jb21tb24vcXNmbnoifV0sInByb2o0L2xpYi9wcm9qZWN0aW9ucy9hZXFkIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPXQoIi4uL2NvbW1vbi9hZGp1c3RfbG9uIiksbz1NYXRoLlBJLzIsaT0xZS0xMCxzPXQoIi4uL2NvbW1vbi9tbGZuIiksYT10KCIuLi9jb21tb24vZTBmbiIpLGw9dCgiLi4vY29tbW9uL2UxZm4iKSx1PXQoIi4uL2NvbW1vbi9lMmZuIiksaD10KCIuLi9jb21tb24vZTNmbiIpLGM9dCgiLi4vY29tbW9uL2dOIikscD10KCIuLi9jb21tb24vYXNpbnoiKSxfPXQoIi4uL2NvbW1vbi9pbWxmbiIpO3IuaW5pdD1mdW5jdGlvbigpe3RoaXMuc2luX3AxMj1NYXRoLnNpbih0aGlzLmxhdDApLHRoaXMuY29zX3AxMj1NYXRoLmNvcyh0aGlzLmxhdDApfSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGUscixwLF8sZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTLHosUCxFLEEsQyxOPXQueCxPPXQueSxxPU1hdGguc2luKHQueSksRD1NYXRoLmNvcyh0LnkpLEk9bihOLXRoaXMubG9uZzApO3JldHVybiB0aGlzLnNwaGVyZT9NYXRoLmFicyh0aGlzLnNpbl9wMTItMSk8PWk/KHQueD10aGlzLngwK3RoaXMuYSooby1PKSpNYXRoLnNpbihJKSx0Lnk9dGhpcy55MC10aGlzLmEqKG8tTykqTWF0aC5jb3MoSSksdCk6TWF0aC5hYnModGhpcy5zaW5fcDEyKzEpPD1pPyh0Lng9dGhpcy54MCt0aGlzLmEqKG8rTykqTWF0aC5zaW4oSSksdC55PXRoaXMueTArdGhpcy5hKihvK08pKk1hdGguY29zKEkpLHQpOihTPXRoaXMuc2luX3AxMipxK3RoaXMuY29zX3AxMipEKk1hdGguY29zKEkpLGo9TWF0aC5hY29zKFMpLFQ9ai9NYXRoLnNpbihqKSx0Lng9dGhpcy54MCt0aGlzLmEqVCpEKk1hdGguc2luKEkpLHQueT10aGlzLnkwK3RoaXMuYSpUKih0aGlzLmNvc19wMTIqcS10aGlzLnNpbl9wMTIqRCpNYXRoLmNvcyhJKSksdCk6KGU9YSh0aGlzLmVzKSxyPWwodGhpcy5lcykscD11KHRoaXMuZXMpLF89aCh0aGlzLmVzKSxNYXRoLmFicyh0aGlzLnNpbl9wMTItMSk8PWk/KGQ9dGhpcy5hKnMoZSxyLHAsXyxvKSxmPXRoaXMuYSpzKGUscixwLF8sTyksdC54PXRoaXMueDArKGQtZikqTWF0aC5zaW4oSSksdC55PXRoaXMueTAtKGQtZikqTWF0aC5jb3MoSSksdCk6TWF0aC5hYnModGhpcy5zaW5fcDEyKzEpPD1pPyhkPXRoaXMuYSpzKGUscixwLF8sbyksZj10aGlzLmEqcyhlLHIscCxfLE8pLHQueD10aGlzLngwKyhkK2YpKk1hdGguc2luKEkpLHQueT10aGlzLnkwKyhkK2YpKk1hdGguY29zKEkpLHQpOihtPXEvRCxnPWModGhpcy5hLHRoaXMuZSx0aGlzLnNpbl9wMTIpLHk9Yyh0aGlzLmEsdGhpcy5lLHEpLHY9TWF0aC5hdGFuKCgxLXRoaXMuZXMpKm0rdGhpcy5lcypnKnRoaXMuc2luX3AxMi8oeSpEKSksYj1NYXRoLmF0YW4yKE1hdGguc2luKEkpLHRoaXMuY29zX3AxMipNYXRoLnRhbih2KS10aGlzLnNpbl9wMTIqTWF0aC5jb3MoSSkpLHo9MD09PWI/TWF0aC5hc2luKHRoaXMuY29zX3AxMipNYXRoLnNpbih2KS10aGlzLnNpbl9wMTIqTWF0aC5jb3ModikpOk1hdGguYWJzKE1hdGguYWJzKGIpLU1hdGguUEkpPD1pPy1NYXRoLmFzaW4odGhpcy5jb3NfcDEyKk1hdGguc2luKHYpLXRoaXMuc2luX3AxMipNYXRoLmNvcyh2KSk6TWF0aC5hc2luKE1hdGguc2luKEkpKk1hdGguY29zKHYpL01hdGguc2luKGIpKSx4PXRoaXMuZSp0aGlzLnNpbl9wMTIvTWF0aC5zcXJ0KDEtdGhpcy5lcyksdz10aGlzLmUqdGhpcy5jb3NfcDEyKk1hdGguY29zKGIpL01hdGguc3FydCgxLXRoaXMuZXMpLE09eCp3LGs9dyp3LFA9eip6LEU9UCp6LEE9RSp6LEM9QSp6LGo9Zyp6KigxLVAqayooMS1rKS82K0UvOCpNKigxLTIqaykrQS8xMjAqKGsqKDQtNyprKS0zKngqeCooMS03KmspKS1DLzQ4Kk0pLHQueD10aGlzLngwK2oqTWF0aC5zaW4oYiksdC55PXRoaXMueTAraipNYXRoLmNvcyhiKSx0KSl9LHIuaW52ZXJzZT1mdW5jdGlvbih0KXt0LngtPXRoaXMueDAsdC55LT10aGlzLnkwO3ZhciBlLHIsZCxmLG0sZyx5LHYsYix4LHcsTSxrLGosVCxTLHosUCxFLEEsQyxOLE87aWYodGhpcy5zcGhlcmUpe2lmKGU9TWF0aC5zcXJ0KHQueCp0LngrdC55KnQueSksZT4yKm8qdGhpcy5hKXJldHVybjtyZXR1cm4gcj1lL3RoaXMuYSxkPU1hdGguc2luKHIpLGY9TWF0aC5jb3MociksbT10aGlzLmxvbmcwLE1hdGguYWJzKGUpPD1pP2c9dGhpcy5sYXQwOihnPXAoZip0aGlzLnNpbl9wMTIrdC55KmQqdGhpcy5jb3NfcDEyL2UpLHk9TWF0aC5hYnModGhpcy5sYXQwKS1vLG09bihNYXRoLmFicyh5KTw9aT90aGlzLmxhdDA+PTA/dGhpcy5sb25nMCtNYXRoLmF0YW4yKHQueCwtdC55KTp0aGlzLmxvbmcwLU1hdGguYXRhbjIoLXQueCx0LnkpOnRoaXMubG9uZzArTWF0aC5hdGFuMih0LngqZCxlKnRoaXMuY29zX3AxMipmLXQueSp0aGlzLnNpbl9wMTIqZCkpKSx0Lng9bSx0Lnk9Zyx0fXJldHVybiB2PWEodGhpcy5lcyksYj1sKHRoaXMuZXMpLHg9dSh0aGlzLmVzKSx3PWgodGhpcy5lcyksTWF0aC5hYnModGhpcy5zaW5fcDEyLTEpPD1pPyhNPXRoaXMuYSpzKHYsYix4LHcsbyksZT1NYXRoLnNxcnQodC54KnQueCt0LnkqdC55KSxrPU0tZSxnPV8oay90aGlzLmEsdixiLHgsdyksbT1uKHRoaXMubG9uZzArTWF0aC5hdGFuMih0LngsLTEqdC55KSksdC54PW0sdC55PWcsdCk6TWF0aC5hYnModGhpcy5zaW5fcDEyKzEpPD1pPyhNPXRoaXMuYSpzKHYsYix4LHcsbyksZT1NYXRoLnNxcnQodC54KnQueCt0LnkqdC55KSxrPWUtTSxnPV8oay90aGlzLmEsdixiLHgsdyksbT1uKHRoaXMubG9uZzArTWF0aC5hdGFuMih0LngsdC55KSksdC54PW0sdC55PWcsdCk6KGU9TWF0aC5zcXJ0KHQueCp0LngrdC55KnQueSksUz1NYXRoLmF0YW4yKHQueCx0LnkpLGo9Yyh0aGlzLmEsdGhpcy5lLHRoaXMuc2luX3AxMiksej1NYXRoLmNvcyhTKSxQPXRoaXMuZSp0aGlzLmNvc19wMTIqeixFPS1QKlAvKDEtdGhpcy5lcyksQT0zKnRoaXMuZXMqKDEtRSkqdGhpcy5zaW5fcDEyKnRoaXMuY29zX3AxMip6LygxLXRoaXMuZXMpLEM9ZS9qLE49Qy1FKigxK0UpKk1hdGgucG93KEMsMykvNi1BKigxKzMqRSkqTWF0aC5wb3coQyw0KS8yNCxPPTEtRSpOKk4vMi1DKk4qTipOLzYsVD1NYXRoLmFzaW4odGhpcy5zaW5fcDEyKk1hdGguY29zKE4pK3RoaXMuY29zX3AxMipNYXRoLnNpbihOKSp6KSxtPW4odGhpcy5sb25nMCtNYXRoLmFzaW4oTWF0aC5zaW4oUykqTWF0aC5zaW4oTikvTWF0aC5jb3MoVCkpKSxnPU1hdGguYXRhbigoMS10aGlzLmVzKk8qdGhpcy5zaW5fcDEyL01hdGguc2luKFQpKSpNYXRoLnRhbihUKS8oMS10aGlzLmVzKSksdC54PW0sdC55PWcsdCl9LHIubmFtZXM9WyJBemltdXRoYWxfRXF1aWRpc3RhbnQiLCJhZXFkIl19LHsiLi4vY29tbW9uL2FkanVzdF9sb24iOiJwcm9qNC9saWIvY29tbW9uL2FkanVzdF9sb24iLCIuLi9jb21tb24vYXNpbnoiOiJwcm9qNC9saWIvY29tbW9uL2FzaW56IiwiLi4vY29tbW9uL2UwZm4iOiJwcm9qNC9saWIvY29tbW9uL2UwZm4iLCIuLi9jb21tb24vZTFmbiI6InByb2o0L2xpYi9jb21tb24vZTFmbiIsIi4uL2NvbW1vbi9lMmZuIjoicHJvajQvbGliL2NvbW1vbi9lMmZuIiwiLi4vY29tbW9uL2UzZm4iOiJwcm9qNC9saWIvY29tbW9uL2UzZm4iLCIuLi9jb21tb24vZ04iOiJwcm9qNC9saWIvY29tbW9uL2dOIiwiLi4vY29tbW9uL2ltbGZuIjoicHJvajQvbGliL2NvbW1vbi9pbWxmbiIsIi4uL2NvbW1vbi9tbGZuIjoicHJvajQvbGliL2NvbW1vbi9tbGZuIn1dLCJwcm9qNC9saWIvcHJvamVjdGlvbnMvY2FzcyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj10KCIuLi9jb21tb24vbWxmbiIpLG89dCgiLi4vY29tbW9uL2UwZm4iKSxpPXQoIi4uL2NvbW1vbi9lMWZuIikscz10KCIuLi9jb21tb24vZTJmbiIpLGE9dCgiLi4vY29tbW9uL2UzZm4iKSxsPXQoIi4uL2NvbW1vbi9nTiIpLHU9dCgiLi4vY29tbW9uL2FkanVzdF9sb24iKSxoPXQoIi4uL2NvbW1vbi9hZGp1c3RfbGF0IiksYz10KCIuLi9jb21tb24vaW1sZm4iKSxwPU1hdGguUEkvMixfPTFlLTEwO3IuaW5pdD1mdW5jdGlvbigpewp0aGlzLnNwaGVyZXx8KHRoaXMuZTA9byh0aGlzLmVzKSx0aGlzLmUxPWkodGhpcy5lcyksdGhpcy5lMj1zKHRoaXMuZXMpLHRoaXMuZTM9YSh0aGlzLmVzKSx0aGlzLm1sMD10aGlzLmEqbih0aGlzLmUwLHRoaXMuZTEsdGhpcy5lMix0aGlzLmUzLHRoaXMubGF0MCkpfSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGUscixvPXQueCxpPXQueTtpZihvPXUoby10aGlzLmxvbmcwKSx0aGlzLnNwaGVyZSllPXRoaXMuYSpNYXRoLmFzaW4oTWF0aC5jb3MoaSkqTWF0aC5zaW4obykpLHI9dGhpcy5hKihNYXRoLmF0YW4yKE1hdGgudGFuKGkpLE1hdGguY29zKG8pKS10aGlzLmxhdDApO2Vsc2V7dmFyIHM9TWF0aC5zaW4oaSksYT1NYXRoLmNvcyhpKSxoPWwodGhpcy5hLHRoaXMuZSxzKSxjPU1hdGgudGFuKGkpKk1hdGgudGFuKGkpLHA9bypNYXRoLmNvcyhpKSxfPXAqcCxkPXRoaXMuZXMqYSphLygxLXRoaXMuZXMpLGY9dGhpcy5hKm4odGhpcy5lMCx0aGlzLmUxLHRoaXMuZTIsdGhpcy5lMyxpKTtlPWgqcCooMS1fKmMqKDEvNi0oOC1jKzgqZCkqXy8xMjApKSxyPWYtdGhpcy5tbDAraCpzL2EqXyooLjUrKDUtYys2KmQpKl8vMjQpfXJldHVybiB0Lng9ZSt0aGlzLngwLHQueT1yK3RoaXMueTAsdH0sci5pbnZlcnNlPWZ1bmN0aW9uKHQpe3QueC09dGhpcy54MCx0LnktPXRoaXMueTA7dmFyIGUscixuPXQueC90aGlzLmEsbz10LnkvdGhpcy5hO2lmKHRoaXMuc3BoZXJlKXt2YXIgaT1vK3RoaXMubGF0MDtlPU1hdGguYXNpbihNYXRoLnNpbihpKSpNYXRoLmNvcyhuKSkscj1NYXRoLmF0YW4yKE1hdGgudGFuKG4pLE1hdGguY29zKGkpKX1lbHNle3ZhciBzPXRoaXMubWwwL3RoaXMuYStvLGE9YyhzLHRoaXMuZTAsdGhpcy5lMSx0aGlzLmUyLHRoaXMuZTMpO2lmKE1hdGguYWJzKE1hdGguYWJzKGEpLXApPD1fKXJldHVybiB0Lng9dGhpcy5sb25nMCx0Lnk9cCxvPDAmJih0LnkqPS0xKSx0O3ZhciBkPWwodGhpcy5hLHRoaXMuZSxNYXRoLnNpbihhKSksZj1kKmQqZC90aGlzLmEvdGhpcy5hKigxLXRoaXMuZXMpLG09TWF0aC5wb3coTWF0aC50YW4oYSksMiksZz1uKnRoaXMuYS9kLHk9ZypnO2U9YS1kKk1hdGgudGFuKGEpL2YqZypnKiguNS0oMSszKm0pKmcqZy8yNCkscj1nKigxLXkqKG0vMysoMSszKm0pKm0qeS8xNSkpL01hdGguY29zKGEpfXJldHVybiB0Lng9dShyK3RoaXMubG9uZzApLHQueT1oKGUpLHR9LHIubmFtZXM9WyJDYXNzaW5pIiwiQ2Fzc2luaV9Tb2xkbmVyIiwiY2FzcyJdfSx7Ii4uL2NvbW1vbi9hZGp1c3RfbGF0IjoicHJvajQvbGliL2NvbW1vbi9hZGp1c3RfbGF0IiwiLi4vY29tbW9uL2FkanVzdF9sb24iOiJwcm9qNC9saWIvY29tbW9uL2FkanVzdF9sb24iLCIuLi9jb21tb24vZTBmbiI6InByb2o0L2xpYi9jb21tb24vZTBmbiIsIi4uL2NvbW1vbi9lMWZuIjoicHJvajQvbGliL2NvbW1vbi9lMWZuIiwiLi4vY29tbW9uL2UyZm4iOiJwcm9qNC9saWIvY29tbW9uL2UyZm4iLCIuLi9jb21tb24vZTNmbiI6InByb2o0L2xpYi9jb21tb24vZTNmbiIsIi4uL2NvbW1vbi9nTiI6InByb2o0L2xpYi9jb21tb24vZ04iLCIuLi9jb21tb24vaW1sZm4iOiJwcm9qNC9saWIvY29tbW9uL2ltbGZuIiwiLi4vY29tbW9uL21sZm4iOiJwcm9qNC9saWIvY29tbW9uL21sZm4ifV0sInByb2o0L2xpYi9wcm9qZWN0aW9ucy9jZWEiOltmdW5jdGlvbih0LGUscil7dmFyIG49dCgiLi4vY29tbW9uL2FkanVzdF9sb24iKSxvPXQoIi4uL2NvbW1vbi9xc2ZueiIpLGk9dCgiLi4vY29tbW9uL21zZm56Iikscz10KCIuLi9jb21tb24vaXFzZm56Iik7ci5pbml0PWZ1bmN0aW9uKCl7dGhpcy5zcGhlcmV8fCh0aGlzLmswPWkodGhpcy5lLE1hdGguc2luKHRoaXMubGF0X3RzKSxNYXRoLmNvcyh0aGlzLmxhdF90cykpKX0sci5mb3J3YXJkPWZ1bmN0aW9uKHQpe3ZhciBlLHIsaT10Lngscz10LnksYT1uKGktdGhpcy5sb25nMCk7aWYodGhpcy5zcGhlcmUpZT10aGlzLngwK3RoaXMuYSphKk1hdGguY29zKHRoaXMubGF0X3RzKSxyPXRoaXMueTArdGhpcy5hKk1hdGguc2luKHMpL01hdGguY29zKHRoaXMubGF0X3RzKTtlbHNle3ZhciBsPW8odGhpcy5lLE1hdGguc2luKHMpKTtlPXRoaXMueDArdGhpcy5hKnRoaXMuazAqYSxyPXRoaXMueTArdGhpcy5hKmwqLjUvdGhpcy5rMH1yZXR1cm4gdC54PWUsdC55PXIsdH0sci5pbnZlcnNlPWZ1bmN0aW9uKHQpe3QueC09dGhpcy54MCx0LnktPXRoaXMueTA7dmFyIGUscjtyZXR1cm4gdGhpcy5zcGhlcmU/KGU9bih0aGlzLmxvbmcwK3QueC90aGlzLmEvTWF0aC5jb3ModGhpcy5sYXRfdHMpKSxyPU1hdGguYXNpbih0LnkvdGhpcy5hKk1hdGguY29zKHRoaXMubGF0X3RzKSkpOihyPXModGhpcy5lLDIqdC55KnRoaXMuazAvdGhpcy5hKSxlPW4odGhpcy5sb25nMCt0LngvKHRoaXMuYSp0aGlzLmswKSkpLHQueD1lLHQueT1yLHR9LHIubmFtZXM9WyJjZWEiXX0seyIuLi9jb21tb24vYWRqdXN0X2xvbiI6InByb2o0L2xpYi9jb21tb24vYWRqdXN0X2xvbiIsIi4uL2NvbW1vbi9pcXNmbnoiOiJwcm9qNC9saWIvY29tbW9uL2lxc2ZueiIsIi4uL2NvbW1vbi9tc2ZueiI6InByb2o0L2xpYi9jb21tb24vbXNmbnoiLCIuLi9jb21tb24vcXNmbnoiOiJwcm9qNC9saWIvY29tbW9uL3FzZm56In1dLCJwcm9qNC9saWIvcHJvamVjdGlvbnMvZXFjIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPXQoIi4uL2NvbW1vbi9hZGp1c3RfbG9uIiksbz10KCIuLi9jb21tb24vYWRqdXN0X2xhdCIpO3IuaW5pdD1mdW5jdGlvbigpe3RoaXMueDA9dGhpcy54MHx8MCx0aGlzLnkwPXRoaXMueTB8fDAsdGhpcy5sYXQwPXRoaXMubGF0MHx8MCx0aGlzLmxvbmcwPXRoaXMubG9uZzB8fDAsdGhpcy5sYXRfdHM9dGhpcy5sYXRfdHN8fDAsdGhpcy50aXRsZT10aGlzLnRpdGxlfHwiRXF1aWRpc3RhbnQgQ3lsaW5kcmljYWwgKFBsYXRlIENhcnJlKSIsdGhpcy5yYz1NYXRoLmNvcyh0aGlzLmxhdF90cyl9LHIuZm9yd2FyZD1mdW5jdGlvbih0KXt2YXIgZT10Lngscj10LnksaT1uKGUtdGhpcy5sb25nMCkscz1vKHItdGhpcy5sYXQwKTtyZXR1cm4gdC54PXRoaXMueDArdGhpcy5hKmkqdGhpcy5yYyx0Lnk9dGhpcy55MCt0aGlzLmEqcyx0fSxyLmludmVyc2U9ZnVuY3Rpb24odCl7dmFyIGU9dC54LHI9dC55O3JldHVybiB0Lng9bih0aGlzLmxvbmcwKyhlLXRoaXMueDApLyh0aGlzLmEqdGhpcy5yYykpLHQueT1vKHRoaXMubGF0MCsoci10aGlzLnkwKS90aGlzLmEpLHR9LHIubmFtZXM9WyJFcXVpcmVjdGFuZ3VsYXIiLCJFcXVpZGlzdGFudF9DeWxpbmRyaWNhbCIsImVxYyJdfSx7Ii4uL2NvbW1vbi9hZGp1c3RfbGF0IjoicHJvajQvbGliL2NvbW1vbi9hZGp1c3RfbGF0IiwiLi4vY29tbW9uL2FkanVzdF9sb24iOiJwcm9qNC9saWIvY29tbW9uL2FkanVzdF9sb24ifV0sInByb2o0L2xpYi9wcm9qZWN0aW9ucy9lcWRjIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPXQoIi4uL2NvbW1vbi9lMGZuIiksbz10KCIuLi9jb21tb24vZTFmbiIpLGk9dCgiLi4vY29tbW9uL2UyZm4iKSxzPXQoIi4uL2NvbW1vbi9lM2ZuIiksYT10KCIuLi9jb21tb24vbXNmbnoiKSxsPXQoIi4uL2NvbW1vbi9tbGZuIiksdT10KCIuLi9jb21tb24vYWRqdXN0X2xvbiIpLGg9dCgiLi4vY29tbW9uL2FkanVzdF9sYXQiKSxjPXQoIi4uL2NvbW1vbi9pbWxmbiIpLHA9MWUtMTA7ci5pbml0PWZ1bmN0aW9uKCl7TWF0aC5hYnModGhpcy5sYXQxK3RoaXMubGF0Mik8cHx8KHRoaXMubGF0Mj10aGlzLmxhdDJ8fHRoaXMubGF0MSx0aGlzLnRlbXA9dGhpcy5iL3RoaXMuYSx0aGlzLmVzPTEtTWF0aC5wb3codGhpcy50ZW1wLDIpLHRoaXMuZT1NYXRoLnNxcnQodGhpcy5lcyksdGhpcy5lMD1uKHRoaXMuZXMpLHRoaXMuZTE9byh0aGlzLmVzKSx0aGlzLmUyPWkodGhpcy5lcyksdGhpcy5lMz1zKHRoaXMuZXMpLHRoaXMuc2lucGhpPU1hdGguc2luKHRoaXMubGF0MSksdGhpcy5jb3NwaGk9TWF0aC5jb3ModGhpcy5sYXQxKSx0aGlzLm1zMT1hKHRoaXMuZSx0aGlzLnNpbnBoaSx0aGlzLmNvc3BoaSksdGhpcy5tbDE9bCh0aGlzLmUwLHRoaXMuZTEsdGhpcy5lMix0aGlzLmUzLHRoaXMubGF0MSksTWF0aC5hYnModGhpcy5sYXQxLXRoaXMubGF0Mik8cD90aGlzLm5zPXRoaXMuc2lucGhpOih0aGlzLnNpbnBoaT1NYXRoLnNpbih0aGlzLmxhdDIpLHRoaXMuY29zcGhpPU1hdGguY29zKHRoaXMubGF0MiksdGhpcy5tczI9YSh0aGlzLmUsdGhpcy5zaW5waGksdGhpcy5jb3NwaGkpLHRoaXMubWwyPWwodGhpcy5lMCx0aGlzLmUxLHRoaXMuZTIsdGhpcy5lMyx0aGlzLmxhdDIpLHRoaXMubnM9KHRoaXMubXMxLXRoaXMubXMyKS8odGhpcy5tbDItdGhpcy5tbDEpKSx0aGlzLmc9dGhpcy5tbDErdGhpcy5tczEvdGhpcy5ucyx0aGlzLm1sMD1sKHRoaXMuZTAsdGhpcy5lMSx0aGlzLmUyLHRoaXMuZTMsdGhpcy5sYXQwKSx0aGlzLnJoPXRoaXMuYSoodGhpcy5nLXRoaXMubWwwKSl9LHIuZm9yd2FyZD1mdW5jdGlvbih0KXt2YXIgZSxyPXQueCxuPXQueTtpZih0aGlzLnNwaGVyZSllPXRoaXMuYSoodGhpcy5nLW4pO2Vsc2V7dmFyIG89bCh0aGlzLmUwLHRoaXMuZTEsdGhpcy5lMix0aGlzLmUzLG4pO2U9dGhpcy5hKih0aGlzLmctbyl9dmFyIGk9dGhpcy5ucyp1KHItdGhpcy5sb25nMCkscz10aGlzLngwK2UqTWF0aC5zaW4oaSksYT10aGlzLnkwK3RoaXMucmgtZSpNYXRoLmNvcyhpKTtyZXR1cm4gdC54PXMsdC55PWEsdH0sci5pbnZlcnNlPWZ1bmN0aW9uKHQpe3QueC09dGhpcy54MCx0Lnk9dGhpcy5yaC10LnkrdGhpcy55MDt2YXIgZSxyLG4sbzt0aGlzLm5zPj0wPyhyPU1hdGguc3FydCh0LngqdC54K3QueSp0LnkpLGU9MSk6KHI9LU1hdGguc3FydCh0LngqdC54K3QueSp0LnkpLGU9LTEpO3ZhciBpPTA7aWYoMCE9PXImJihpPU1hdGguYXRhbjIoZSp0LngsZSp0LnkpKSx0aGlzLnNwaGVyZSlyZXR1cm4gbz11KHRoaXMubG9uZzAraS90aGlzLm5zKSxuPWgodGhpcy5nLXIvdGhpcy5hKSx0Lng9byx0Lnk9bix0O3ZhciBzPXRoaXMuZy1yL3RoaXMuYTtyZXR1cm4gbj1jKHMsdGhpcy5lMCx0aGlzLmUxLHRoaXMuZTIsdGhpcy5lMyksbz11KHRoaXMubG9uZzAraS90aGlzLm5zKSx0Lng9byx0Lnk9bix0fSxyLm5hbWVzPVsiRXF1aWRpc3RhbnRfQ29uaWMiLCJlcWRjIl19LHsiLi4vY29tbW9uL2FkanVzdF9sYXQiOiJwcm9qNC9saWIvY29tbW9uL2FkanVzdF9sYXQiLCIuLi9jb21tb24vYWRqdXN0X2xvbiI6InByb2o0L2xpYi9jb21tb24vYWRqdXN0X2xvbiIsIi4uL2NvbW1vbi9lMGZuIjoicHJvajQvbGliL2NvbW1vbi9lMGZuIiwiLi4vY29tbW9uL2UxZm4iOiJwcm9qNC9saWIvY29tbW9uL2UxZm4iLCIuLi9jb21tb24vZTJmbiI6InByb2o0L2xpYi9jb21tb24vZTJmbiIsIi4uL2NvbW1vbi9lM2ZuIjoicHJvajQvbGliL2NvbW1vbi9lM2ZuIiwiLi4vY29tbW9uL2ltbGZuIjoicHJvajQvbGliL2NvbW1vbi9pbWxmbiIsIi4uL2NvbW1vbi9tbGZuIjoicHJvajQvbGliL2NvbW1vbi9tbGZuIiwiLi4vY29tbW9uL21zZm56IjoicHJvajQvbGliL2NvbW1vbi9tc2ZueiJ9XSwicHJvajQvbGliL3Byb2plY3Rpb25zL2dhdXNzIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPU1hdGguUEkvNCxvPXQoIi4uL2NvbW1vbi9zcmF0IiksaT1NYXRoLlBJLzIscz0yMDtyLmluaXQ9ZnVuY3Rpb24oKXt2YXIgdD1NYXRoLnNpbih0aGlzLmxhdDApLGU9TWF0aC5jb3ModGhpcy5sYXQwKTtlKj1lLHRoaXMucmM9TWF0aC5zcXJ0KDEtdGhpcy5lcykvKDEtdGhpcy5lcyp0KnQpLHRoaXMuQz1NYXRoLnNxcnQoMSt0aGlzLmVzKmUqZS8oMS10aGlzLmVzKSksdGhpcy5waGljMD1NYXRoLmFzaW4odC90aGlzLkMpLHRoaXMucmF0ZXhwPS41KnRoaXMuQyp0aGlzLmUsdGhpcy5LPU1hdGgudGFuKC41KnRoaXMucGhpYzArbikvKE1hdGgucG93KE1hdGgudGFuKC41KnRoaXMubGF0MCtuKSx0aGlzLkMpKm8odGhpcy5lKnQsdGhpcy5yYXRleHApKX0sci5mb3J3YXJkPWZ1bmN0aW9uKHQpe3ZhciBlPXQueCxyPXQueTtyZXR1cm4gdC55PTIqTWF0aC5hdGFuKHRoaXMuSypNYXRoLnBvdyhNYXRoLnRhbiguNSpyK24pLHRoaXMuQykqbyh0aGlzLmUqTWF0aC5zaW4ociksdGhpcy5yYXRleHApKS1pLHQueD10aGlzLkMqZSx0fSxyLmludmVyc2U9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPTFlLTE0LHI9dC54L3RoaXMuQyxhPXQueSxsPU1hdGgucG93KE1hdGgudGFuKC41KmErbikvdGhpcy5LLDEvdGhpcy5DKSx1PXM7dT4wJiYoYT0yKk1hdGguYXRhbihsKm8odGhpcy5lKk1hdGguc2luKHQueSksLS41KnRoaXMuZSkpLWksIShNYXRoLmFicyhhLXQueSk8ZSkpOy0tdSl0Lnk9YTtyZXR1cm4gdT8odC54PXIsdC55PWEsdCk6bnVsbH0sci5uYW1lcz1bImdhdXNzIl19LHsiLi4vY29tbW9uL3NyYXQiOiJwcm9qNC9saWIvY29tbW9uL3NyYXQifV0sInByb2o0L2xpYi9wcm9qZWN0aW9ucy9nbm9tIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPXQoIi4uL2NvbW1vbi9hZGp1c3RfbG9uIiksbz0xZS0xMCxpPXQoIi4uL2NvbW1vbi9hc2lueiIpO3IuaW5pdD1mdW5jdGlvbigpe3RoaXMuc2luX3AxND1NYXRoLnNpbih0aGlzLmxhdDApLHRoaXMuY29zX3AxND1NYXRoLmNvcyh0aGlzLmxhdDApLHRoaXMuaW5maW5pdHlfZGlzdD0xZTMqdGhpcy5hLHRoaXMucmM9MX0sci5mb3J3YXJkPWZ1bmN0aW9uKHQpe3ZhciBlLHIsaSxzLGEsbCx1LGgsYz10LngscD10Lnk7cmV0dXJuIGk9bihjLXRoaXMubG9uZzApLGU9TWF0aC5zaW4ocCkscj1NYXRoLmNvcyhwKSxzPU1hdGguY29zKGkpLGw9dGhpcy5zaW5fcDE0KmUrdGhpcy5jb3NfcDE0KnIqcyxhPTEsbD4wfHxNYXRoLmFicyhsKTw9bz8odT10aGlzLngwK3RoaXMuYSphKnIqTWF0aC5zaW4oaSkvbCxoPXRoaXMueTArdGhpcy5hKmEqKHRoaXMuY29zX3AxNCplLXRoaXMuc2luX3AxNCpyKnMpL2wpOih1PXRoaXMueDArdGhpcy5pbmZpbml0eV9kaXN0KnIqTWF0aC5zaW4oaSksaD10aGlzLnkwK3RoaXMuaW5maW5pdHlfZGlzdCoodGhpcy5jb3NfcDE0KmUtdGhpcy5zaW5fcDE0KnIqcykpLHQueD11LHQueT1oLHR9LHIuaW52ZXJzZT1mdW5jdGlvbih0KXt2YXIgZSxyLG8scyxhLGw7cmV0dXJuIHQueD0odC54LXRoaXMueDApL3RoaXMuYSx0Lnk9KHQueS10aGlzLnkwKS90aGlzLmEsdC54Lz10aGlzLmswLHQueS89dGhpcy5rMCwoZT1NYXRoLnNxcnQodC54KnQueCt0LnkqdC55KSk/KHM9TWF0aC5hdGFuMihlLHRoaXMucmMpLHI9TWF0aC5zaW4ocyksbz1NYXRoLmNvcyhzKSxsPWkobyp0aGlzLnNpbl9wMTQrdC55KnIqdGhpcy5jb3NfcDE0L2UpLGE9TWF0aC5hdGFuMih0LngqcixlKnRoaXMuY29zX3AxNCpvLXQueSp0aGlzLnNpbl9wMTQqciksYT1uKHRoaXMubG9uZzArYSkpOihsPXRoaXMucGhpYzAsYT0wKSx0Lng9YSx0Lnk9bCx0fSxyLm5hbWVzPVsiZ25vbSJdfSx7Ii4uL2NvbW1vbi9hZGp1c3RfbG9uIjoicHJvajQvbGliL2NvbW1vbi9hZGp1c3RfbG9uIiwiLi4vY29tbW9uL2FzaW56IjoicHJvajQvbGliL2NvbW1vbi9hc2lueiJ9XSwicHJvajQvbGliL3Byb2plY3Rpb25zL2tyb3ZhayI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj10KCIuLi9jb21tb24vYWRqdXN0X2xvbiIpO3IuaW5pdD1mdW5jdGlvbigpe3RoaXMuYT02Mzc3Mzk3LjE1NSx0aGlzLmVzPS4wMDY2NzQzNzIyMzA2MTQsdGhpcy5lPU1hdGguc3FydCh0aGlzLmVzKSx0aGlzLmxhdDB8fCh0aGlzLmxhdDA9Ljg2MzkzNzk3OTczNzE5MyksdGhpcy5sb25nMHx8KHRoaXMubG9uZzA9LjQzMzQyMzQzMDkxMTkyNTEpLHRoaXMuazB8fCh0aGlzLmswPS45OTk5KSx0aGlzLnM0NT0uNzg1Mzk4MTYzMzk3NDQ4LHRoaXMuczkwPTIqdGhpcy5zNDUsdGhpcy5maTA9dGhpcy5sYXQwLHRoaXMuZTI9dGhpcy5lcyx0aGlzLmU9TWF0aC5zcXJ0KHRoaXMuZTIpLHRoaXMuYWxmYT1NYXRoLnNxcnQoMSt0aGlzLmUyKk1hdGgucG93KE1hdGguY29zKHRoaXMuZmkwKSw0KS8oMS10aGlzLmUyKSksdGhpcy51cT0xLjA0MjE2ODU2MzgwNDc0LHRoaXMudTA9TWF0aC5hc2luKE1hdGguc2luKHRoaXMuZmkwKS90aGlzLmFsZmEpLHRoaXMuZz1NYXRoLnBvdygoMSt0aGlzLmUqTWF0aC5zaW4odGhpcy5maTApKS8oMS10aGlzLmUqTWF0aC5zaW4odGhpcy5maTApKSx0aGlzLmFsZmEqdGhpcy5lLzIpLHRoaXMuaz1NYXRoLnRhbih0aGlzLnUwLzIrdGhpcy5zNDUpL01hdGgucG93KE1hdGgudGFuKHRoaXMuZmkwLzIrdGhpcy5zNDUpLHRoaXMuYWxmYSkqdGhpcy5nLHRoaXMuazE9dGhpcy5rMCx0aGlzLm4wPXRoaXMuYSpNYXRoLnNxcnQoMS10aGlzLmUyKS8oMS10aGlzLmUyKk1hdGgucG93KE1hdGguc2luKHRoaXMuZmkwKSwyKSksdGhpcy5zMD0xLjM3MDA4MzQ2MjgxNTU1LHRoaXMubj1NYXRoLnNpbih0aGlzLnMwKSx0aGlzLnJvMD10aGlzLmsxKnRoaXMubjAvTWF0aC50YW4odGhpcy5zMCksdGhpcy5hZD10aGlzLnM5MC10aGlzLnVxfSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGUscixvLGkscyxhLGwsdT10LngsaD10LnksYz1uKHUtdGhpcy5sb25nMCk7cmV0dXJuIGU9TWF0aC5wb3coKDErdGhpcy5lKk1hdGguc2luKGgpKS8oMS10aGlzLmUqTWF0aC5zaW4oaCkpLHRoaXMuYWxmYSp0aGlzLmUvMikscj0yKihNYXRoLmF0YW4odGhpcy5rKk1hdGgucG93KE1hdGgudGFuKGgvMit0aGlzLnM0NSksdGhpcy5hbGZhKS9lKS10aGlzLnM0NSksbz0tYyp0aGlzLmFsZmEsaT1NYXRoLmFzaW4oTWF0aC5jb3ModGhpcy5hZCkqTWF0aC5zaW4ocikrTWF0aC5zaW4odGhpcy5hZCkqTWF0aC5jb3MocikqTWF0aC5jb3MobykpLHM9TWF0aC5hc2luKE1hdGguY29zKHIpKk1hdGguc2luKG8pL01hdGguY29zKGkpKSxhPXRoaXMubipzLGw9dGhpcy5ybzAqTWF0aC5wb3coTWF0aC50YW4odGhpcy5zMC8yK3RoaXMuczQ1KSx0aGlzLm4pL01hdGgucG93KE1hdGgudGFuKGkvMit0aGlzLnM0NSksdGhpcy5uKSx0Lnk9bCpNYXRoLmNvcyhhKS8xLHQueD1sKk1hdGguc2luKGEpLzEsdGhpcy5jemVjaHx8KHQueSo9LTEsdC54Kj0tMSksdH0sci5pbnZlcnNlPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbixvLGkscyxhLGwsdT10Lng7dC54PXQueSx0Lnk9dSx0aGlzLmN6ZWNofHwodC55Kj0tMSx0LngqPS0xKSxzPU1hdGguc3FydCh0LngqdC54K3QueSp0LnkpLGk9TWF0aC5hdGFuMih0LnksdC54KSxvPWkvTWF0aC5zaW4odGhpcy5zMCksbj0yKihNYXRoLmF0YW4oTWF0aC5wb3codGhpcy5ybzAvcywxL3RoaXMubikqTWF0aC50YW4odGhpcy5zMC8yK3RoaXMuczQ1KSktdGhpcy5zNDUpLGU9TWF0aC5hc2luKE1hdGguY29zKHRoaXMuYWQpKk1hdGguc2luKG4pLU1hdGguc2luKHRoaXMuYWQpKk1hdGguY29zKG4pKk1hdGguY29zKG8pKSxyPU1hdGguYXNpbihNYXRoLmNvcyhuKSpNYXRoLnNpbihvKS9NYXRoLmNvcyhlKSksdC54PXRoaXMubG9uZzAtci90aGlzLmFsZmEsYT1lLGw9MDt2YXIgaD0wO2RvIHQueT0yKihNYXRoLmF0YW4oTWF0aC5wb3codGhpcy5rLC0xL3RoaXMuYWxmYSkqTWF0aC5wb3coTWF0aC50YW4oZS8yK3RoaXMuczQ1KSwxL3RoaXMuYWxmYSkqTWF0aC5wb3coKDErdGhpcy5lKk1hdGguc2luKGEpKS8oMS10aGlzLmUqTWF0aC5zaW4oYSkpLHRoaXMuZS8yKSktdGhpcy5zNDUpLE1hdGguYWJzKGEtdC55KTwxZS0xMCYmKGw9MSksYT10LnksaCs9MTt3aGlsZSgwPT09bCYmaDwxNSk7cmV0dXJuIGg+PTE1P251bGw6dH0sci5uYW1lcz1bIktyb3ZhayIsImtyb3ZhayJdfSx7Ii4uL2NvbW1vbi9hZGp1c3RfbG9uIjoicHJvajQvbGliL2NvbW1vbi9hZGp1c3RfbG9uIn1dLCJwcm9qNC9saWIvcHJvamVjdGlvbnMvbGFlYSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj1NYXRoLlBJLzIsbz1NYXRoLlBJLzQsaT0xZS0xMCxzPXQoIi4uL2NvbW1vbi9xc2ZueiIpLGE9dCgiLi4vY29tbW9uL2FkanVzdF9sb24iKTtyLlNfUE9MRT0xLHIuTl9QT0xFPTIsci5FUVVJVD0zLHIuT0JMSVE9NCxyLmluaXQ9ZnVuY3Rpb24oKXt2YXIgdD1NYXRoLmFicyh0aGlzLmxhdDApO2lmKE1hdGguYWJzKHQtbik8aT90aGlzLm1vZGU9dGhpcy5sYXQwPDA/dGhpcy5TX1BPTEU6dGhpcy5OX1BPTEU6TWF0aC5hYnModCk8aT90aGlzLm1vZGU9dGhpcy5FUVVJVDp0aGlzLm1vZGU9dGhpcy5PQkxJUSx0aGlzLmVzPjApe3ZhciBlO3N3aXRjaCh0aGlzLnFwPXModGhpcy5lLDEpLHRoaXMubW1mPS41LygxLXRoaXMuZXMpLHRoaXMuYXBhPXRoaXMuYXV0aHNldCh0aGlzLmVzKSx0aGlzLm1vZGUpe2Nhc2UgdGhpcy5OX1BPTEU6dGhpcy5kZD0xO2JyZWFrO2Nhc2UgdGhpcy5TX1BPTEU6dGhpcy5kZD0xO2JyZWFrO2Nhc2UgdGhpcy5FUVVJVDp0aGlzLnJxPU1hdGguc3FydCguNSp0aGlzLnFwKSx0aGlzLmRkPTEvdGhpcy5ycSx0aGlzLnhtZj0xLHRoaXMueW1mPS41KnRoaXMucXA7YnJlYWs7Y2FzZSB0aGlzLk9CTElROnRoaXMucnE9TWF0aC5zcXJ0KC41KnRoaXMucXApLGU9TWF0aC5zaW4odGhpcy5sYXQwKSx0aGlzLnNpbmIxPXModGhpcy5lLGUpL3RoaXMucXAsdGhpcy5jb3NiMT1NYXRoLnNxcnQoMS10aGlzLnNpbmIxKnRoaXMuc2luYjEpLHRoaXMuZGQ9TWF0aC5jb3ModGhpcy5sYXQwKS8oTWF0aC5zcXJ0KDEtdGhpcy5lcyplKmUpKnRoaXMucnEqdGhpcy5jb3NiMSksdGhpcy55bWY9KHRoaXMueG1mPXRoaXMucnEpL3RoaXMuZGQsdGhpcy54bWYqPXRoaXMuZGR9fWVsc2UgdGhpcy5tb2RlPT09dGhpcy5PQkxJUSYmKHRoaXMuc2lucGgwPU1hdGguc2luKHRoaXMubGF0MCksdGhpcy5jb3NwaDA9TWF0aC5jb3ModGhpcy5sYXQwKSl9LHIuZm9yd2FyZD1mdW5jdGlvbih0KXt2YXIgZSxyLGwsdSxoLGMscCxfLGQsZixtPXQueCxnPXQueTtpZihtPWEobS10aGlzLmxvbmcwKSx0aGlzLnNwaGVyZSl7aWYoaD1NYXRoLnNpbihnKSxmPU1hdGguY29zKGcpLGw9TWF0aC5jb3MobSksdGhpcy5tb2RlPT09dGhpcy5PQkxJUXx8dGhpcy5tb2RlPT09dGhpcy5FUVVJVCl7aWYocj10aGlzLm1vZGU9PT10aGlzLkVRVUlUPzErZipsOjErdGhpcy5zaW5waDAqaCt0aGlzLmNvc3BoMCpmKmwscjw9aSlyZXR1cm4gbnVsbDtyPU1hdGguc3FydCgyL3IpLGU9cipmKk1hdGguc2luKG0pLHIqPXRoaXMubW9kZT09PXRoaXMuRVFVSVQ/aDp0aGlzLmNvc3BoMCpoLXRoaXMuc2lucGgwKmYqbH1lbHNlIGlmKHRoaXMubW9kZT09PXRoaXMuTl9QT0xFfHx0aGlzLm1vZGU9PT10aGlzLlNfUE9MRSl7aWYodGhpcy5tb2RlPT09dGhpcy5OX1BPTEUmJihsPS1sKSxNYXRoLmFicyhnK3RoaXMucGhpMCk8aSlyZXR1cm4gbnVsbDtyPW8tLjUqZyxyPTIqKHRoaXMubW9kZT09PXRoaXMuU19QT0xFP01hdGguY29zKHIpOk1hdGguc2luKHIpKSxlPXIqTWF0aC5zaW4obSkscio9bH19ZWxzZXtzd2l0Y2gocD0wLF89MCxkPTAsbD1NYXRoLmNvcyhtKSx1PU1hdGguc2luKG0pLGg9TWF0aC5zaW4oZyksYz1zKHRoaXMuZSxoKSx0aGlzLm1vZGUhPT10aGlzLk9CTElRJiZ0aGlzLm1vZGUhPT10aGlzLkVRVUlUfHwocD1jL3RoaXMucXAsXz1NYXRoLnNxcnQoMS1wKnApKSx0aGlzLm1vZGUpe2Nhc2UgdGhpcy5PQkxJUTpkPTErdGhpcy5zaW5iMSpwK3RoaXMuY29zYjEqXypsO2JyZWFrO2Nhc2UgdGhpcy5FUVVJVDpkPTErXypsO2JyZWFrO2Nhc2UgdGhpcy5OX1BPTEU6ZD1uK2csYz10aGlzLnFwLWM7YnJlYWs7Y2FzZSB0aGlzLlNfUE9MRTpkPWctbixjPXRoaXMucXArY31pZihNYXRoLmFicyhkKTxpKXJldHVybiBudWxsO3N3aXRjaCh0aGlzLm1vZGUpe2Nhc2UgdGhpcy5PQkxJUTpjYXNlIHRoaXMuRVFVSVQ6ZD1NYXRoLnNxcnQoMi9kKSxyPXRoaXMubW9kZT09PXRoaXMuT0JMSVE/dGhpcy55bWYqZCoodGhpcy5jb3NiMSpwLXRoaXMuc2luYjEqXypsKTooZD1NYXRoLnNxcnQoMi8oMStfKmwpKSkqcCp0aGlzLnltZixlPXRoaXMueG1mKmQqXyp1O2JyZWFrO2Nhc2UgdGhpcy5OX1BPTEU6Y2FzZSB0aGlzLlNfUE9MRTpjPj0wPyhlPShkPU1hdGguc3FydChjKSkqdSxyPWwqKHRoaXMubW9kZT09PXRoaXMuU19QT0xFP2Q6LWQpKTplPXI9MH19cmV0dXJuIHQueD10aGlzLmEqZSt0aGlzLngwLHQueT10aGlzLmEqcit0aGlzLnkwLHR9LHIuaW52ZXJzZT1mdW5jdGlvbih0KXt0LngtPXRoaXMueDAsdC55LT10aGlzLnkwO3ZhciBlLHIsbyxzLGwsdSxoLGM9dC54L3RoaXMuYSxwPXQueS90aGlzLmE7aWYodGhpcy5zcGhlcmUpe3ZhciBfLGQ9MCxmPTA7aWYoXz1NYXRoLnNxcnQoYypjK3AqcCkscj0uNSpfLHI+MSlyZXR1cm4gbnVsbDtzd2l0Y2gocj0yKk1hdGguYXNpbihyKSx0aGlzLm1vZGUhPT10aGlzLk9CTElRJiZ0aGlzLm1vZGUhPT10aGlzLkVRVUlUfHwoZj1NYXRoLnNpbihyKSxkPU1hdGguY29zKHIpKSx0aGlzLm1vZGUpe2Nhc2UgdGhpcy5FUVVJVDpyPU1hdGguYWJzKF8pPD1pPzA6TWF0aC5hc2luKHAqZi9fKSxjKj1mLHA9ZCpfO2JyZWFrO2Nhc2UgdGhpcy5PQkxJUTpyPU1hdGguYWJzKF8pPD1pP3RoaXMucGhpMDpNYXRoLmFzaW4oZCp0aGlzLnNpbnBoMCtwKmYqdGhpcy5jb3NwaDAvXyksYyo9Zip0aGlzLmNvc3BoMCxwPShkLU1hdGguc2luKHIpKnRoaXMuc2lucGgwKSpfO2JyZWFrO2Nhc2UgdGhpcy5OX1BPTEU6cD0tcCxyPW4tcjticmVhaztjYXNlIHRoaXMuU19QT0xFOnItPW59ZT0wIT09cHx8dGhpcy5tb2RlIT09dGhpcy5FUVVJVCYmdGhpcy5tb2RlIT09dGhpcy5PQkxJUT9NYXRoLmF0YW4yKGMscCk6MH1lbHNle2lmKGg9MCx0aGlzLm1vZGU9PT10aGlzLk9CTElRfHx0aGlzLm1vZGU9PT10aGlzLkVRVUlUKXtpZihjLz10aGlzLmRkLHAqPXRoaXMuZGQsdT1NYXRoLnNxcnQoYypjK3AqcCksdTxpKXJldHVybiB0Lng9MCx0Lnk9dGhpcy5waGkwLHQ7cz0yKk1hdGguYXNpbiguNSp1L3RoaXMucnEpLG89TWF0aC5jb3MocyksYyo9cz1NYXRoLnNpbihzKSx0aGlzLm1vZGU9PT10aGlzLk9CTElRPyhoPW8qdGhpcy5zaW5iMStwKnMqdGhpcy5jb3NiMS91LGw9dGhpcy5xcCpoLHA9dSp0aGlzLmNvc2IxKm8tcCp0aGlzLnNpbmIxKnMpOihoPXAqcy91LGw9dGhpcy5xcCpoLHA9dSpvKX1lbHNlIGlmKHRoaXMubW9kZT09PXRoaXMuTl9QT0xFfHx0aGlzLm1vZGU9PT10aGlzLlNfUE9MRSl7aWYodGhpcy5tb2RlPT09dGhpcy5OX1BPTEUmJihwPS1wKSxsPWMqYytwKnAsIWwpcmV0dXJuIHQueD0wLHQueT10aGlzLnBoaTAsdDtoPTEtbC90aGlzLnFwLHRoaXMubW9kZT09PXRoaXMuU19QT0xFJiYoaD0taCl9ZT1NYXRoLmF0YW4yKGMscCkscj10aGlzLmF1dGhsYXQoTWF0aC5hc2luKGgpLHRoaXMuYXBhKX1yZXR1cm4gdC54PWEodGhpcy5sb25nMCtlKSx0Lnk9cix0fSxyLlAwMD0uMzMzMzMzMzMzMzMzMzMzMyxyLlAwMT0uMTcyMjIyMjIyMjIyMjIyMjIsci5QMDI9LjEwMjU3OTM2NTA3OTM2NTA4LHIuUDEwPS4wNjM4ODg4ODg4ODg4ODg4OCxyLlAxMT0uMDY2NDAyMTE2NDAyMTE2NCxyLlAyMD0uMDE2NDE1MDEyOTQyMTkxNTQzLHIuYXV0aHNldD1mdW5jdGlvbih0KXt2YXIgZSxyPVtdO3JldHVybiByWzBdPXQqdGhpcy5QMDAsZT10KnQsclswXSs9ZSp0aGlzLlAwMSxyWzFdPWUqdGhpcy5QMTAsZSo9dCxyWzBdKz1lKnRoaXMuUDAyLHJbMV0rPWUqdGhpcy5QMTEsclsyXT1lKnRoaXMuUDIwLHJ9LHIuYXV0aGxhdD1mdW5jdGlvbih0LGUpe3ZhciByPXQrdDtyZXR1cm4gdCtlWzBdKk1hdGguc2luKHIpK2VbMV0qTWF0aC5zaW4ocityKStlWzJdKk1hdGguc2luKHIrcityKX0sci5uYW1lcz1bIkxhbWJlcnQgQXppbXV0aGFsIEVxdWFsIEFyZWEiLCJMYW1iZXJ0X0F6aW11dGhhbF9FcXVhbF9BcmVhIiwibGFlYSJdfSx7Ii4uL2NvbW1vbi9hZGp1c3RfbG9uIjoicHJvajQvbGliL2NvbW1vbi9hZGp1c3RfbG9uIiwiLi4vY29tbW9uL3FzZm56IjoicHJvajQvbGliL2NvbW1vbi9xc2ZueiJ9XSwicHJvajQvbGliL3Byb2plY3Rpb25zL2xjYyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj0xZS0xMCxvPXQoIi4uL2NvbW1vbi9tc2ZueiIpLGk9dCgiLi4vY29tbW9uL3RzZm56Iikscz1NYXRoLlBJLzIsYT10KCIuLi9jb21tb24vc2lnbiIpLGw9dCgiLi4vY29tbW9uL2FkanVzdF9sb24iKSx1PXQoIi4uL2NvbW1vbi9waGkyeiIpO3IuaW5pdD1mdW5jdGlvbigpe2lmKHRoaXMubGF0Mnx8KHRoaXMubGF0Mj10aGlzLmxhdDEpLHRoaXMuazB8fCh0aGlzLmswPTEpLHRoaXMueDA9dGhpcy54MHx8MCx0aGlzLnkwPXRoaXMueTB8fDAsIShNYXRoLmFicyh0aGlzLmxhdDErdGhpcy5sYXQyKTxuKSl7dmFyIHQ9dGhpcy5iL3RoaXMuYTt0aGlzLmU9TWF0aC5zcXJ0KDEtdCp0KTt2YXIgZT1NYXRoLnNpbih0aGlzLmxhdDEpLHI9TWF0aC5jb3ModGhpcy5sYXQxKSxzPW8odGhpcy5lLGUsciksYT1pKHRoaXMuZSx0aGlzLmxhdDEsZSksbD1NYXRoLnNpbih0aGlzLmxhdDIpLHU9TWF0aC5jb3ModGhpcy5sYXQyKSxoPW8odGhpcy5lLGwsdSksYz1pKHRoaXMuZSx0aGlzLmxhdDIsbCkscD1pKHRoaXMuZSx0aGlzLmxhdDAsTWF0aC5zaW4odGhpcy5sYXQwKSk7TWF0aC5hYnModGhpcy5sYXQxLXRoaXMubGF0Mik+bj90aGlzLm5zPU1hdGgubG9nKHMvaCkvTWF0aC5sb2coYS9jKTp0aGlzLm5zPWUsaXNOYU4odGhpcy5ucykmJih0aGlzLm5zPWUpLHRoaXMuZjA9cy8odGhpcy5ucypNYXRoLnBvdyhhLHRoaXMubnMpKSx0aGlzLnJoPXRoaXMuYSp0aGlzLmYwKk1hdGgucG93KHAsdGhpcy5ucyksdGhpcy50aXRsZXx8KHRoaXMudGl0bGU9IkxhbWJlcnQgQ29uZm9ybWFsIENvbmljIil9fSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGU9dC54LHI9dC55O01hdGguYWJzKDIqTWF0aC5hYnMociktTWF0aC5QSSk8PW4mJihyPWEocikqKHMtMipuKSk7dmFyIG8sdSxoPU1hdGguYWJzKE1hdGguYWJzKHIpLXMpO2lmKGg+bilvPWkodGhpcy5lLHIsTWF0aC5zaW4ocikpLHU9dGhpcy5hKnRoaXMuZjAqTWF0aC5wb3cobyx0aGlzLm5zKTtlbHNle2lmKGg9cip0aGlzLm5zLGg8PTApcmV0dXJuIG51bGw7dT0wfXZhciBjPXRoaXMubnMqbChlLXRoaXMubG9uZzApO3JldHVybiB0Lng9dGhpcy5rMCoodSpNYXRoLnNpbihjKSkrdGhpcy54MCx0Lnk9dGhpcy5rMCoodGhpcy5yaC11Kk1hdGguY29zKGMpKSt0aGlzLnkwLHR9LHIuaW52ZXJzZT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLGE9KHQueC10aGlzLngwKS90aGlzLmswLGg9dGhpcy5yaC0odC55LXRoaXMueTApL3RoaXMuazA7dGhpcy5ucz4wPyhlPU1hdGguc3FydChhKmEraCpoKSxyPTEpOihlPS1NYXRoLnNxcnQoYSphK2gqaCkscj0tMSk7dmFyIGM9MDtpZigwIT09ZSYmKGM9TWF0aC5hdGFuMihyKmEscipoKSksMCE9PWV8fHRoaXMubnM+MCl7aWYocj0xL3RoaXMubnMsbj1NYXRoLnBvdyhlLyh0aGlzLmEqdGhpcy5mMCksciksbz11KHRoaXMuZSxuKSxvPT09LTk5OTkpcmV0dXJuIG51bGx9ZWxzZSBvPS1zO3JldHVybiBpPWwoYy90aGlzLm5zK3RoaXMubG9uZzApLHQueD1pLHQueT1vLHR9LHIubmFtZXM9WyJMYW1iZXJ0IFRhbmdlbnRpYWwgQ29uZm9ybWFsIENvbmljIFByb2plY3Rpb24iLCJMYW1iZXJ0X0NvbmZvcm1hbF9Db25pYyIsIkxhbWJlcnRfQ29uZm9ybWFsX0NvbmljXzJTUCIsImxjYyJdfSx7Ii4uL2NvbW1vbi9hZGp1c3RfbG9uIjoicHJvajQvbGliL2NvbW1vbi9hZGp1c3RfbG9uIiwiLi4vY29tbW9uL21zZm56IjoicHJvajQvbGliL2NvbW1vbi9tc2ZueiIsIi4uL2NvbW1vbi9waGkyeiI6InByb2o0L2xpYi9jb21tb24vcGhpMnoiLCIuLi9jb21tb24vc2lnbiI6InByb2o0L2xpYi9jb21tb24vc2lnbiIsIi4uL2NvbW1vbi90c2ZueiI6InByb2o0L2xpYi9jb21tb24vdHNmbnoifV0sInByb2o0L2xpYi9wcm9qZWN0aW9ucy9sb25nbGF0IjpbZnVuY3Rpb24odCxlLHIpe2Z1bmN0aW9uIG4odCl7cmV0dXJuIHR9ci5pbml0PWZ1bmN0aW9uKCl7fSxyLmZvcndhcmQ9bixyLmludmVyc2U9bixyLm5hbWVzPVsibG9uZ2xhdCIsImlkZW50aXR5Il19LHt9XSwicHJvajQvbGliL3Byb2plY3Rpb25zL21lcmMiOltmdW5jdGlvbih0LGUscil7dmFyIG49dCgiLi4vY29tbW9uL21zZm56Iiksbz1NYXRoLlBJLzIsaT0xZS0xMCxzPTU3LjI5NTc3OTUxMzA4MjMyLGE9dCgiLi4vY29tbW9uL2FkanVzdF9sb24iKSxsPU1hdGguUEkvNCx1PXQoIi4uL2NvbW1vbi90c2ZueiIpLGg9dCgiLi4vY29tbW9uL3BoaTJ6Iik7ci5pbml0PWZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5iL3RoaXMuYTt0aGlzLmVzPTEtdCp0LCJ4MCJpbiB0aGlzfHwodGhpcy54MD0wKSwieTAiaW4gdGhpc3x8KHRoaXMueTA9MCksdGhpcy5lPU1hdGguc3FydCh0aGlzLmVzKSx0aGlzLmxhdF90cz90aGlzLnNwaGVyZT90aGlzLmswPU1hdGguY29zKHRoaXMubGF0X3RzKTp0aGlzLmswPW4odGhpcy5lLE1hdGguc2luKHRoaXMubGF0X3RzKSxNYXRoLmNvcyh0aGlzLmxhdF90cykpOnRoaXMuazB8fCh0aGlzLms/dGhpcy5rMD10aGlzLms6dGhpcy5rMD0xKX0sci5mb3J3YXJkPWZ1bmN0aW9uKHQpe3ZhciBlPXQueCxyPXQueTtpZihyKnM+OTAmJnIqczwtOTAmJmUqcz4xODAmJmUqczwtMTgwKXJldHVybiBudWxsO3ZhciBuLGg7aWYoTWF0aC5hYnMoTWF0aC5hYnMociktbyk8PWkpcmV0dXJuIG51bGw7aWYodGhpcy5zcGhlcmUpbj10aGlzLngwK3RoaXMuYSp0aGlzLmswKmEoZS10aGlzLmxvbmcwKSxoPXRoaXMueTArdGhpcy5hKnRoaXMuazAqTWF0aC5sb2coTWF0aC50YW4obCsuNSpyKSk7ZWxzZXt2YXIgYz1NYXRoLnNpbihyKSxwPXUodGhpcy5lLHIsYyk7bj10aGlzLngwK3RoaXMuYSp0aGlzLmswKmEoZS10aGlzLmxvbmcwKSxoPXRoaXMueTAtdGhpcy5hKnRoaXMuazAqTWF0aC5sb2cocCl9cmV0dXJuIHQueD1uLHQueT1oLHR9LHIuaW52ZXJzZT1mdW5jdGlvbih0KXt2YXIgZSxyLG49dC54LXRoaXMueDAsaT10LnktdGhpcy55MDtpZih0aGlzLnNwaGVyZSlyPW8tMipNYXRoLmF0YW4oTWF0aC5leHAoLWkvKHRoaXMuYSp0aGlzLmswKSkpO2Vsc2V7dmFyIHM9TWF0aC5leHAoLWkvKHRoaXMuYSp0aGlzLmswKSk7aWYocj1oKHRoaXMuZSxzKSxyPT09LTk5OTkpcmV0dXJuIG51bGx9cmV0dXJuIGU9YSh0aGlzLmxvbmcwK24vKHRoaXMuYSp0aGlzLmswKSksdC54PWUsdC55PXIsdH0sci5uYW1lcz1bIk1lcmNhdG9yIiwiUG9wdWxhciBWaXN1YWxpc2F0aW9uIFBzZXVkbyBNZXJjYXRvciIsIk1lcmNhdG9yXzFTUCIsIk1lcmNhdG9yX0F1eGlsaWFyeV9TcGhlcmUiLCJtZXJjIl19LHsiLi4vY29tbW9uL2FkanVzdF9sb24iOiJwcm9qNC9saWIvY29tbW9uL2FkanVzdF9sb24iLCIuLi9jb21tb24vbXNmbnoiOiJwcm9qNC9saWIvY29tbW9uL21zZm56IiwiLi4vY29tbW9uL3BoaTJ6IjoicHJvajQvbGliL2NvbW1vbi9waGkyeiIsIi4uL2NvbW1vbi90c2ZueiI6InByb2o0L2xpYi9jb21tb24vdHNmbnoifV0sInByb2o0L2xpYi9wcm9qZWN0aW9ucy9taWxsIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPXQoIi4uL2NvbW1vbi9hZGp1c3RfbG9uIik7ci5pbml0PWZ1bmN0aW9uKCl7fSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGU9dC54LHI9dC55LG89bihlLXRoaXMubG9uZzApLGk9dGhpcy54MCt0aGlzLmEqbyxzPXRoaXMueTArdGhpcy5hKk1hdGgubG9nKE1hdGgudGFuKE1hdGguUEkvNCtyLzIuNSkpKjEuMjU7cmV0dXJuIHQueD1pLHQueT1zLHR9LHIuaW52ZXJzZT1mdW5jdGlvbih0KXt0LngtPXRoaXMueDAsdC55LT10aGlzLnkwO3ZhciBlPW4odGhpcy5sb25nMCt0LngvdGhpcy5hKSxyPTIuNSooTWF0aC5hdGFuKE1hdGguZXhwKC44KnQueS90aGlzLmEpKS1NYXRoLlBJLzQpO3JldHVybiB0Lng9ZSx0Lnk9cix0fSxyLm5hbWVzPVsiTWlsbGVyX0N5bGluZHJpY2FsIiwibWlsbCJdfSx7Ii4uL2NvbW1vbi9hZGp1c3RfbG9uIjoicHJvajQvbGliL2NvbW1vbi9hZGp1c3RfbG9uIn1dLCJwcm9qNC9saWIvcHJvamVjdGlvbnMvbW9sbCI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj10KCIuLi9jb21tb24vYWRqdXN0X2xvbiIpLG89MWUtMTA7ci5pbml0PWZ1bmN0aW9uKCl7fSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPXQueCxyPXQueSxpPW4oZS10aGlzLmxvbmcwKSxzPXIsYT1NYXRoLlBJKk1hdGguc2luKHIpLGw9MDshMDtsKyspe3ZhciB1PS0ocytNYXRoLnNpbihzKS1hKS8oMStNYXRoLmNvcyhzKSk7aWYocys9dSxNYXRoLmFicyh1KTxvKWJyZWFrfXMvPTIsTWF0aC5QSS8yLU1hdGguYWJzKHIpPG8mJihpPTApO3ZhciBoPS45MDAzMTYzMTYxNTgqdGhpcy5hKmkqTWF0aC5jb3MocykrdGhpcy54MCxjPTEuNDE0MjEzNTYyMzczMSp0aGlzLmEqTWF0aC5zaW4ocykrdGhpcy55MDtyZXR1cm4gdC54PWgsdC55PWMsdH0sci5pbnZlcnNlPWZ1bmN0aW9uKHQpe3ZhciBlLHI7dC54LT10aGlzLngwLHQueS09dGhpcy55MCxyPXQueS8oMS40MTQyMTM1NjIzNzMxKnRoaXMuYSksTWF0aC5hYnMocik+Ljk5OTk5OTk5OTk5OSYmKHI9Ljk5OTk5OTk5OTk5OSksZT1NYXRoLmFzaW4ocik7dmFyIG89bih0aGlzLmxvbmcwK3QueC8oLjkwMDMxNjMxNjE1OCp0aGlzLmEqTWF0aC5jb3MoZSkpKTtvPC1NYXRoLlBJJiYobz0tTWF0aC5QSSksbz5NYXRoLlBJJiYobz1NYXRoLlBJKSxyPSgyKmUrTWF0aC5zaW4oMiplKSkvTWF0aC5QSSxNYXRoLmFicyhyKT4xJiYocj0xKTt2YXIgaT1NYXRoLmFzaW4ocik7cmV0dXJuIHQueD1vLHQueT1pLHR9LHIubmFtZXM9WyJNb2xsd2VpZGUiLCJtb2xsIl19LHsiLi4vY29tbW9uL2FkanVzdF9sb24iOiJwcm9qNC9saWIvY29tbW9uL2FkanVzdF9sb24ifV0sInByb2o0L2xpYi9wcm9qZWN0aW9ucy9uem1nIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPTQ4NDgxMzY4MTEwOTUzNmUtMjA7ci5pdGVyYXRpb25zPTEsci5pbml0PWZ1bmN0aW9uKCl7dGhpcy5BPVtdLHRoaXMuQVsxXT0uNjM5OTE3NTA3Myx0aGlzLkFbMl09LS4xMzU4Nzk3NjEzLHRoaXMuQVszXT0uMDYzMjk0NDA5LHRoaXMuQVs0XT0tLjAyNTI2ODUzLHRoaXMuQVs1XT0uMDExNzg3OSx0aGlzLkFbNl09LS4wMDU1MTYxLHRoaXMuQVs3XT0uMDAyNjkwNix0aGlzLkFbOF09LS4wMDEzMzMsdGhpcy5BWzldPTY3ZS01LHRoaXMuQVsxMF09LTM0ZS01LHRoaXMuQl9yZT1bXSx0aGlzLkJfaW09W10sdGhpcy5CX3JlWzFdPS43NTU3ODUzMjI4LHRoaXMuQl9pbVsxXT0wLHRoaXMuQl9yZVsyXT0uMjQ5MjA0NjQ2LHRoaXMuQl9pbVsyXT0uMDAzMzcxNTA3LHRoaXMuQl9yZVszXT0tLjAwMTU0MTczOSx0aGlzLkJfaW1bM109LjA0MTA1ODU2LHRoaXMuQl9yZVs0XT0tLjEwMTYyOTA3LHRoaXMuQl9pbVs0XT0uMDE3Mjc2MDksdGhpcy5CX3JlWzVdPS0uMjY2MjM0ODksdGhpcy5CX2ltWzVdPS0uMzYyNDkyMTgsdGhpcy5CX3JlWzZdPS0uNjg3MDk4Myx0aGlzLkJfaW1bNl09LTEuMTY1MTk2Nyx0aGlzLkNfcmU9W10sdGhpcy5DX2ltPVtdLHRoaXMuQ19yZVsxXT0xLjMyMzEyNzA0MzksdGhpcy5DX2ltWzFdPTAsdGhpcy5DX3JlWzJdPS0uNTc3MjQ1Nzg5LHRoaXMuQ19pbVsyXT0tLjAwNzgwOTU5OCx0aGlzLkNfcmVbM109LjUwODMwNzUxMyx0aGlzLkNfaW1bM109LS4xMTIyMDg5NTIsdGhpcy5DX3JlWzRdPS0uMTUwOTQ3NjIsdGhpcy5DX2ltWzRdPS4xODIwMDYwMix0aGlzLkNfcmVbNV09MS4wMTQxODE3OSx0aGlzLkNfaW1bNV09MS42NDQ5NzY5Nix0aGlzLkNfcmVbNl09MS45NjYwNTQ5LHRoaXMuQ19pbVs2XT0yLjUxMjc2NDUsdGhpcy5EPVtdLHRoaXMuRFsxXT0xLjU2MjcwMTQyNDMsdGhpcy5EWzJdPS41MTg1NDA2Mzk4LHRoaXMuRFszXT0tLjAzMzMzMDk4LHRoaXMuRFs0XT0tLjEwNTI5MDYsdGhpcy5EWzVdPS0uMDM2ODU5NCx0aGlzLkRbNl09LjAwNzMxNyx0aGlzLkRbN109LjAxMjIsdGhpcy5EWzhdPS4wMDM5NCx0aGlzLkRbOV09LS4wMDEzfSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGUscj10Lngsbz10LnksaT1vLXRoaXMubGF0MCxzPXItdGhpcy5sb25nMCxhPWkvbioxZS01LGw9cyx1PTEsaD0wO2ZvcihlPTE7ZTw9MTA7ZSsrKXUqPWEsaCs9dGhpcy5BW2VdKnU7dmFyIGMscCxfPWgsZD1sLGY9MSxtPTAsZz0wLHk9MDtmb3IoZT0xO2U8PTY7ZSsrKWM9ZipfLW0qZCxwPW0qXytmKmQsZj1jLG09cCxnPWcrdGhpcy5CX3JlW2VdKmYtdGhpcy5CX2ltW2VdKm0seT15K3RoaXMuQl9pbVtlXSpmK3RoaXMuQl9yZVtlXSptO3JldHVybiB0Lng9eSp0aGlzLmErdGhpcy54MCx0Lnk9Zyp0aGlzLmErdGhpcy55MCx0fSxyLmludmVyc2U9ZnVuY3Rpb24odCl7dmFyIGUscixvLGk9dC54LHM9dC55LGE9aS10aGlzLngwLGw9cy10aGlzLnkwLHU9bC90aGlzLmEsaD1hL3RoaXMuYSxjPTEscD0wLF89MCxkPTA7Zm9yKGU9MTtlPD02O2UrKylyPWMqdS1wKmgsbz1wKnUrYypoLGM9cixwPW8sXz1fK3RoaXMuQ19yZVtlXSpjLXRoaXMuQ19pbVtlXSpwLGQ9ZCt0aGlzLkNfaW1bZV0qYyt0aGlzLkNfcmVbZV0qcDtmb3IodmFyIGY9MDtmPHRoaXMuaXRlcmF0aW9ucztmKyspe3ZhciBtLGcseT1fLHY9ZCxiPXUseD1oO2ZvcihlPTI7ZTw9NjtlKyspbT15Kl8tdipkLGc9dipfK3kqZCx5PW0sdj1nLGIrPShlLTEpKih0aGlzLkJfcmVbZV0qeS10aGlzLkJfaW1bZV0qdikseCs9KGUtMSkqKHRoaXMuQl9pbVtlXSp5K3RoaXMuQl9yZVtlXSp2KTt5PTEsdj0wO3ZhciB3PXRoaXMuQl9yZVsxXSxNPXRoaXMuQl9pbVsxXTtmb3IoZT0yO2U8PTY7ZSsrKW09eSpfLXYqZCxnPXYqXyt5KmQseT1tLHY9Zyx3Kz1lKih0aGlzLkJfcmVbZV0qeS10aGlzLkJfaW1bZV0qdiksTSs9ZSoodGhpcy5CX2ltW2VdKnkrdGhpcy5CX3JlW2VdKnYpO3ZhciBrPXcqdytNKk07Xz0oYip3K3gqTSkvayxkPSh4KnctYipNKS9rfXZhciBqPV8sVD1kLFM9MSx6PTA7Zm9yKGU9MTtlPD05O2UrKylTKj1qLHorPXRoaXMuRFtlXSpTO3ZhciBQPXRoaXMubGF0MCt6Km4qMWU1LEU9dGhpcy5sb25nMCtUO3JldHVybiB0Lng9RSx0Lnk9UCx0fSxyLm5hbWVzPVsiTmV3X1plYWxhbmRfTWFwX0dyaWQiLCJuem1nIl19LHt9XSwicHJvajQvbGliL3Byb2plY3Rpb25zL29tZXJjIjpbZnVuY3Rpb24odCxlLHIpe3ZhciBuPXQoIi4uL2NvbW1vbi90c2ZueiIpLG89dCgiLi4vY29tbW9uL2FkanVzdF9sb24iKSxpPXQoIi4uL2NvbW1vbi9waGkyeiIpLHM9TWF0aC5QSS8yLGE9TWF0aC5QSS80LGw9MWUtMTA7ci5pbml0PWZ1bmN0aW9uKCl7dGhpcy5ub19vZmY9dGhpcy5ub19vZmZ8fCExLHRoaXMubm9fcm90PXRoaXMubm9fcm90fHwhMSxpc05hTih0aGlzLmswKSYmKHRoaXMuazA9MSk7dmFyIHQ9TWF0aC5zaW4odGhpcy5sYXQwKSxlPU1hdGguY29zKHRoaXMubGF0MCkscj10aGlzLmUqdDt0aGlzLmJsPU1hdGguc3FydCgxK3RoaXMuZXMvKDEtdGhpcy5lcykqTWF0aC5wb3coZSw0KSksdGhpcy5hbD10aGlzLmEqdGhpcy5ibCp0aGlzLmswKk1hdGguc3FydCgxLXRoaXMuZXMpLygxLXIqcik7dmFyIGk9bih0aGlzLmUsdGhpcy5sYXQwLHQpLHM9dGhpcy5ibC9lKk1hdGguc3FydCgoMS10aGlzLmVzKS8oMS1yKnIpKTtzKnM8MSYmKHM9MSk7dmFyIGEsbDtpZihpc05hTih0aGlzLmxvbmdjKSl7dmFyIHU9bih0aGlzLmUsdGhpcy5sYXQxLE1hdGguc2luKHRoaXMubGF0MSkpLGg9bih0aGlzLmUsdGhpcy5sYXQyLE1hdGguc2luKHRoaXMubGF0MikpO3RoaXMubGF0MD49MD90aGlzLmVsPShzK01hdGguc3FydChzKnMtMSkpKk1hdGgucG93KGksdGhpcy5ibCk6dGhpcy5lbD0ocy1NYXRoLnNxcnQocypzLTEpKSpNYXRoLnBvdyhpLHRoaXMuYmwpO3ZhciBjPU1hdGgucG93KHUsdGhpcy5ibCkscD1NYXRoLnBvdyhoLHRoaXMuYmwpO2E9dGhpcy5lbC9jLGw9LjUqKGEtMS9hKTt2YXIgXz0odGhpcy5lbCp0aGlzLmVsLXAqYykvKHRoaXMuZWwqdGhpcy5lbCtwKmMpLGQ9KHAtYykvKHArYyksZj1vKHRoaXMubG9uZzEtdGhpcy5sb25nMik7dGhpcy5sb25nMD0uNSoodGhpcy5sb25nMSt0aGlzLmxvbmcyKS1NYXRoLmF0YW4oXypNYXRoLnRhbiguNSp0aGlzLmJsKmYpL2QpL3RoaXMuYmwsdGhpcy5sb25nMD1vKHRoaXMubG9uZzApO3ZhciBtPW8odGhpcy5sb25nMS10aGlzLmxvbmcwKTt0aGlzLmdhbW1hMD1NYXRoLmF0YW4oTWF0aC5zaW4odGhpcy5ibCptKS9sKSx0aGlzLmFscGhhPU1hdGguYXNpbihzKk1hdGguc2luKHRoaXMuZ2FtbWEwKSl9ZWxzZSBhPXRoaXMubGF0MD49MD9zK01hdGguc3FydChzKnMtMSk6cy1NYXRoLnNxcnQocypzLTEpLHRoaXMuZWw9YSpNYXRoLnBvdyhpLHRoaXMuYmwpLGw9LjUqKGEtMS9hKSx0aGlzLmdhbW1hMD1NYXRoLmFzaW4oTWF0aC5zaW4odGhpcy5hbHBoYSkvcyksdGhpcy5sb25nMD10aGlzLmxvbmdjLU1hdGguYXNpbihsKk1hdGgudGFuKHRoaXMuZ2FtbWEwKSkvdGhpcy5ibDt0aGlzLm5vX29mZj90aGlzLnVjPTA6dGhpcy5sYXQwPj0wP3RoaXMudWM9dGhpcy5hbC90aGlzLmJsKk1hdGguYXRhbjIoTWF0aC5zcXJ0KHMqcy0xKSxNYXRoLmNvcyh0aGlzLmFscGhhKSk6dGhpcy51Yz0tMSp0aGlzLmFsL3RoaXMuYmwqTWF0aC5hdGFuMihNYXRoLnNxcnQocypzLTEpLE1hdGguY29zKHRoaXMuYWxwaGEpKX0sci5mb3J3YXJkPWZ1bmN0aW9uKHQpe3ZhciBlLHIsaSx1PXQueCxoPXQueSxjPW8odS10aGlzLmxvbmcwKTtpZihNYXRoLmFicyhNYXRoLmFicyhoKS1zKTw9bClpPWg+MD8tMToxLHI9dGhpcy5hbC90aGlzLmJsKk1hdGgubG9nKE1hdGgudGFuKGEraSp0aGlzLmdhbW1hMCouNSkpLGU9LTEqaSpzKnRoaXMuYWwvdGhpcy5ibDtlbHNle3ZhciBwPW4odGhpcy5lLGgsTWF0aC5zaW4oaCkpLF89dGhpcy5lbC9NYXRoLnBvdyhwLHRoaXMuYmwpLGQ9LjUqKF8tMS9fKSxmPS41KihfKzEvXyksbT1NYXRoLnNpbih0aGlzLmJsKmMpLGc9KGQqTWF0aC5zaW4odGhpcy5nYW1tYTApLW0qTWF0aC5jb3ModGhpcy5nYW1tYTApKS9mO3I9TWF0aC5hYnMoTWF0aC5hYnMoZyktMSk8PWw/TnVtYmVyLlBPU0lUSVZFX0lORklOSVRZOi41KnRoaXMuYWwqTWF0aC5sb2coKDEtZykvKDErZykpL3RoaXMuYmwsZT1NYXRoLmFicyhNYXRoLmNvcyh0aGlzLmJsKmMpKTw9bD90aGlzLmFsKnRoaXMuYmwqYzp0aGlzLmFsKk1hdGguYXRhbjIoZCpNYXRoLmNvcyh0aGlzLmdhbW1hMCkrbSpNYXRoLnNpbih0aGlzLmdhbW1hMCksTWF0aC5jb3ModGhpcy5ibCpjKSkvdGhpcy5ibH1yZXR1cm4gdGhpcy5ub19yb3Q/KHQueD10aGlzLngwK2UsdC55PXRoaXMueTArcik6KGUtPXRoaXMudWMsdC54PXRoaXMueDArcipNYXRoLmNvcyh0aGlzLmFscGhhKStlKk1hdGguc2luKHRoaXMuYWxwaGEpLHQueT10aGlzLnkwK2UqTWF0aC5jb3ModGhpcy5hbHBoYSktcipNYXRoLnNpbih0aGlzLmFscGhhKSksdH0sci5pbnZlcnNlPWZ1bmN0aW9uKHQpe3ZhciBlLHI7dGhpcy5ub19yb3Q/KHI9dC55LXRoaXMueTAsZT10LngtdGhpcy54MCk6KHI9KHQueC10aGlzLngwKSpNYXRoLmNvcyh0aGlzLmFscGhhKS0odC55LXRoaXMueTApKk1hdGguc2luKHRoaXMuYWxwaGEpLGU9KHQueS10aGlzLnkwKSpNYXRoLmNvcyh0aGlzLmFscGhhKSsodC54LXRoaXMueDApKk1hdGguc2luKHRoaXMuYWxwaGEpLGUrPXRoaXMudWMpO3ZhciBuPU1hdGguZXhwKC0xKnRoaXMuYmwqci90aGlzLmFsKSxhPS41KihuLTEvbiksdT0uNSoobisxL24pLGg9TWF0aC5zaW4odGhpcy5ibCplL3RoaXMuYWwpLGM9KGgqTWF0aC5jb3ModGhpcy5nYW1tYTApK2EqTWF0aC5zaW4odGhpcy5nYW1tYTApKS91LHA9TWF0aC5wb3codGhpcy5lbC9NYXRoLnNxcnQoKDErYykvKDEtYykpLDEvdGhpcy5ibCk7cmV0dXJuIE1hdGguYWJzKGMtMSk8bD8odC54PXRoaXMubG9uZzAsdC55PXMpOk1hdGguYWJzKGMrMSk8bD8odC54PXRoaXMubG9uZzAsdC55PS0xKnMpOih0Lnk9aSh0aGlzLmUscCksdC54PW8odGhpcy5sb25nMC1NYXRoLmF0YW4yKGEqTWF0aC5jb3ModGhpcy5nYW1tYTApLWgqTWF0aC5zaW4odGhpcy5nYW1tYTApLE1hdGguY29zKHRoaXMuYmwqZS90aGlzLmFsKSkvdGhpcy5ibCkpLHR9LHIubmFtZXM9WyJIb3RpbmVfT2JsaXF1ZV9NZXJjYXRvciIsIkhvdGluZSBPYmxpcXVlIE1lcmNhdG9yIiwiSG90aW5lX09ibGlxdWVfTWVyY2F0b3JfQXppbXV0aF9OYXR1cmFsX09yaWdpbiIsIkhvdGluZV9PYmxpcXVlX01lcmNhdG9yX0F6aW11dGhfQ2VudGVyIiwib21lcmMiXX0seyIuLi9jb21tb24vYWRqdXN0X2xvbiI6InByb2o0L2xpYi9jb21tb24vYWRqdXN0X2xvbiIsIi4uL2NvbW1vbi9waGkyeiI6InByb2o0L2xpYi9jb21tb24vcGhpMnoiLCIuLi9jb21tb24vdHNmbnoiOiJwcm9qNC9saWIvY29tbW9uL3RzZm56In1dLCJwcm9qNC9saWIvcHJvamVjdGlvbnMvcG9seSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj10KCIuLi9jb21tb24vZTBmbiIpLG89dCgiLi4vY29tbW9uL2UxZm4iKSxpPXQoIi4uL2NvbW1vbi9lMmZuIikscz10KCIuLi9jb21tb24vZTNmbiIpLGE9dCgiLi4vY29tbW9uL2FkanVzdF9sb24iKSxsPXQoIi4uL2NvbW1vbi9hZGp1c3RfbGF0IiksdT10KCIuLi9jb21tb24vbWxmbiIpLGg9MWUtMTAsYz10KCIuLi9jb21tb24vZ04iKSxwPTIwO3IuaW5pdD1mdW5jdGlvbigpe3RoaXMudGVtcD10aGlzLmIvdGhpcy5hLHRoaXMuZXM9MS1NYXRoLnBvdyh0aGlzLnRlbXAsMiksdGhpcy5lPU1hdGguc3FydCh0aGlzLmVzKSx0aGlzLmUwPW4odGhpcy5lcyksdGhpcy5lMT1vKHRoaXMuZXMpLHRoaXMuZTI9aSh0aGlzLmVzKSx0aGlzLmUzPXModGhpcy5lcyksdGhpcy5tbDA9dGhpcy5hKnUodGhpcy5lMCx0aGlzLmUxLHRoaXMuZTIsdGhpcy5lMyx0aGlzLmxhdDApfSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG89dC54LGk9dC55LHM9YShvLXRoaXMubG9uZzApO2lmKG49cypNYXRoLnNpbihpKSx0aGlzLnNwaGVyZSlNYXRoLmFicyhpKTw9aD8oZT10aGlzLmEqcyxyPS0xKnRoaXMuYSp0aGlzLmxhdDApOihlPXRoaXMuYSpNYXRoLnNpbihuKS9NYXRoLnRhbihpKSxyPXRoaXMuYSoobChpLXRoaXMubGF0MCkrKDEtTWF0aC5jb3MobikpL01hdGgudGFuKGkpKSk7ZWxzZSBpZihNYXRoLmFicyhpKTw9aCllPXRoaXMuYSpzLHI9LTEqdGhpcy5tbDA7ZWxzZXt2YXIgcD1jKHRoaXMuYSx0aGlzLmUsTWF0aC5zaW4oaSkpL01hdGgudGFuKGkpO2U9cCpNYXRoLnNpbihuKSxyPXRoaXMuYSp1KHRoaXMuZTAsdGhpcy5lMSx0aGlzLmUyLHRoaXMuZTMsaSktdGhpcy5tbDArcCooMS1NYXRoLmNvcyhuKSl9cmV0dXJuIHQueD1lK3RoaXMueDAsdC55PXIrdGhpcy55MCx0fSxyLmludmVyc2U9ZnVuY3Rpb24odCl7dmFyIGUscixuLG8saSxzLGwsYyxfO2lmKG49dC54LXRoaXMueDAsbz10LnktdGhpcy55MCx0aGlzLnNwaGVyZSlpZihNYXRoLmFicyhvK3RoaXMuYSp0aGlzLmxhdDApPD1oKWU9YShuL3RoaXMuYSt0aGlzLmxvbmcwKSxyPTA7ZWxzZXtzPXRoaXMubGF0MCtvL3RoaXMuYSxsPW4qbi90aGlzLmEvdGhpcy5hK3MqcyxjPXM7dmFyIGQ7Zm9yKGk9cDtpOy0taSlpZihkPU1hdGgudGFuKGMpLF89LTEqKHMqKGMqZCsxKS1jLS41KihjKmMrbCkqZCkvKChjLXMpL2QtMSksYys9XyxNYXRoLmFicyhfKTw9aCl7cj1jO2JyZWFrfWU9YSh0aGlzLmxvbmcwK01hdGguYXNpbihuKk1hdGgudGFuKGMpL3RoaXMuYSkvTWF0aC5zaW4ocikpfWVsc2UgaWYoTWF0aC5hYnMobyt0aGlzLm1sMCk8PWgpcj0wLGU9YSh0aGlzLmxvbmcwK24vdGhpcy5hKTtlbHNle3M9KHRoaXMubWwwK28pL3RoaXMuYSxsPW4qbi90aGlzLmEvdGhpcy5hK3MqcyxjPXM7dmFyIGYsbSxnLHksdjtmb3IoaT1wO2k7LS1pKWlmKHY9dGhpcy5lKk1hdGguc2luKGMpLGY9TWF0aC5zcXJ0KDEtdip2KSpNYXRoLnRhbihjKSxtPXRoaXMuYSp1KHRoaXMuZTAsdGhpcy5lMSx0aGlzLmUyLHRoaXMuZTMsYyksZz10aGlzLmUwLTIqdGhpcy5lMSpNYXRoLmNvcygyKmMpKzQqdGhpcy5lMipNYXRoLmNvcyg0KmMpLTYqdGhpcy5lMypNYXRoLmNvcyg2KmMpLHk9bS90aGlzLmEsXz0ocyooZip5KzEpLXktLjUqZiooeSp5K2wpKS8odGhpcy5lcypNYXRoLnNpbigyKmMpKih5KnkrbC0yKnMqeSkvKDQqZikrKHMteSkqKGYqZy0yL01hdGguc2luKDIqYykpLWcpLGMtPV8sTWF0aC5hYnMoXyk8PWgpe3I9YzticmVha31mPU1hdGguc3FydCgxLXRoaXMuZXMqTWF0aC5wb3coTWF0aC5zaW4ociksMikpKk1hdGgudGFuKHIpLGU9YSh0aGlzLmxvbmcwK01hdGguYXNpbihuKmYvdGhpcy5hKS9NYXRoLnNpbihyKSl9cmV0dXJuIHQueD1lLHQueT1yLHR9LHIubmFtZXM9WyJQb2x5Y29uaWMiLCJwb2x5Il19LHsiLi4vY29tbW9uL2FkanVzdF9sYXQiOiJwcm9qNC9saWIvY29tbW9uL2FkanVzdF9sYXQiLCIuLi9jb21tb24vYWRqdXN0X2xvbiI6InByb2o0L2xpYi9jb21tb24vYWRqdXN0X2xvbiIsIi4uL2NvbW1vbi9lMGZuIjoicHJvajQvbGliL2NvbW1vbi9lMGZuIiwiLi4vY29tbW9uL2UxZm4iOiJwcm9qNC9saWIvY29tbW9uL2UxZm4iLCIuLi9jb21tb24vZTJmbiI6InByb2o0L2xpYi9jb21tb24vZTJmbiIsIi4uL2NvbW1vbi9lM2ZuIjoicHJvajQvbGliL2NvbW1vbi9lM2ZuIiwiLi4vY29tbW9uL2dOIjoicHJvajQvbGliL2NvbW1vbi9nTiIsIi4uL2NvbW1vbi9tbGZuIjoicHJvajQvbGliL2NvbW1vbi9tbGZuIn1dLCJwcm9qNC9saWIvcHJvamVjdGlvbnMvc2ludSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj10KCIuLi9jb21tb24vYWRqdXN0X2xvbiIpLG89dCgiLi4vY29tbW9uL2FkanVzdF9sYXQiKSxpPXQoIi4uL2NvbW1vbi9wal9lbmZuIikscz0yMCxhPXQoIi4uL2NvbW1vbi9wal9tbGZuIiksbD10KCIuLi9jb21tb24vcGpfaW52X21sZm4iKSx1PU1hdGguUEkvMixoPTFlLTEwLGM9dCgiLi4vY29tbW9uL2FzaW56Iik7ci5pbml0PWZ1bmN0aW9uKCl7dGhpcy5zcGhlcmU/KHRoaXMubj0xLHRoaXMubT0wLHRoaXMuZXM9MCx0aGlzLkNfeT1NYXRoLnNxcnQoKHRoaXMubSsxKS90aGlzLm4pLHRoaXMuQ194PXRoaXMuQ195Lyh0aGlzLm0rMSkpOnRoaXMuZW49aSh0aGlzLmVzKX0sci5mb3J3YXJkPWZ1bmN0aW9uKHQpe3ZhciBlLHIsbz10LngsaT10Lnk7aWYobz1uKG8tdGhpcy5sb25nMCksdGhpcy5zcGhlcmUpe2lmKHRoaXMubSlmb3IodmFyIGw9dGhpcy5uKk1hdGguc2luKGkpLHU9czt1Oy0tdSl7dmFyIGM9KHRoaXMubSppK01hdGguc2luKGkpLWwpLyh0aGlzLm0rTWF0aC5jb3MoaSkpO2lmKGktPWMsTWF0aC5hYnMoYyk8aClicmVha31lbHNlIGk9MSE9PXRoaXMubj9NYXRoLmFzaW4odGhpcy5uKk1hdGguc2luKGkpKTppO2U9dGhpcy5hKnRoaXMuQ194Km8qKHRoaXMubStNYXRoLmNvcyhpKSkscj10aGlzLmEqdGhpcy5DX3kqaX1lbHNle3ZhciBwPU1hdGguc2luKGkpLF89TWF0aC5jb3MoaSk7cj10aGlzLmEqYShpLHAsXyx0aGlzLmVuKSxlPXRoaXMuYSpvKl8vTWF0aC5zcXJ0KDEtdGhpcy5lcypwKnApfXJldHVybiB0Lng9ZSx0Lnk9cix0fSxyLmludmVyc2U9ZnVuY3Rpb24odCl7dmFyIGUscixpLHM7cmV0dXJuIHQueC09dGhpcy54MCxpPXQueC90aGlzLmEsdC55LT10aGlzLnkwLGU9dC55L3RoaXMuYSx0aGlzLnNwaGVyZT8oZS89dGhpcy5DX3ksaS89dGhpcy5DX3gqKHRoaXMubStNYXRoLmNvcyhlKSksdGhpcy5tP2U9YygodGhpcy5tKmUrTWF0aC5zaW4oZSkpL3RoaXMubik6MSE9PXRoaXMubiYmKGU9YyhNYXRoLnNpbihlKS90aGlzLm4pKSxpPW4oaSt0aGlzLmxvbmcwKSxlPW8oZSkpOihlPWwodC55L3RoaXMuYSx0aGlzLmVzLHRoaXMuZW4pLHM9TWF0aC5hYnMoZSksczx1PyhzPU1hdGguc2luKGUpLHI9dGhpcy5sb25nMCt0LngqTWF0aC5zcXJ0KDEtdGhpcy5lcypzKnMpLyh0aGlzLmEqTWF0aC5jb3MoZSkpLGk9bihyKSk6cy1oPHUmJihpPXRoaXMubG9uZzApKSx0Lng9aSx0Lnk9ZSx0fSxyLm5hbWVzPVsiU2ludXNvaWRhbCIsInNpbnUiXX0seyIuLi9jb21tb24vYWRqdXN0X2xhdCI6InByb2o0L2xpYi9jb21tb24vYWRqdXN0X2xhdCIsIi4uL2NvbW1vbi9hZGp1c3RfbG9uIjoicHJvajQvbGliL2NvbW1vbi9hZGp1c3RfbG9uIiwiLi4vY29tbW9uL2FzaW56IjoicHJvajQvbGliL2NvbW1vbi9hc2lueiIsIi4uL2NvbW1vbi9wal9lbmZuIjoicHJvajQvbGliL2NvbW1vbi9wal9lbmZuIiwiLi4vY29tbW9uL3BqX2ludl9tbGZuIjoicHJvajQvbGliL2NvbW1vbi9wal9pbnZfbWxmbiIsIi4uL2NvbW1vbi9wal9tbGZuIjoicHJvajQvbGliL2NvbW1vbi9wal9tbGZuIn1dLCJwcm9qNC9saWIvcHJvamVjdGlvbnMvc29tZXJjIjpbZnVuY3Rpb24odCxlLHIpe3IuaW5pdD1mdW5jdGlvbigpe3ZhciB0PXRoaXMubGF0MDt0aGlzLmxhbWJkYTA9dGhpcy5sb25nMDt2YXIgZT1NYXRoLnNpbih0KSxyPXRoaXMuYSxuPXRoaXMucmYsbz0xL24saT0yKm8tTWF0aC5wb3cobywyKSxzPXRoaXMuZT1NYXRoLnNxcnQoaSk7dGhpcy5SPXRoaXMuazAqcipNYXRoLnNxcnQoMS1pKS8oMS1pKk1hdGgucG93KGUsMikpLHRoaXMuYWxwaGE9TWF0aC5zcXJ0KDEraS8oMS1pKSpNYXRoLnBvdyhNYXRoLmNvcyh0KSw0KSksdGhpcy5iMD1NYXRoLmFzaW4oZS90aGlzLmFscGhhKTt2YXIgYT1NYXRoLmxvZyhNYXRoLnRhbihNYXRoLlBJLzQrdGhpcy5iMC8yKSksbD1NYXRoLmxvZyhNYXRoLnRhbihNYXRoLlBJLzQrdC8yKSksdT1NYXRoLmxvZygoMStzKmUpLygxLXMqZSkpO3RoaXMuSz1hLXRoaXMuYWxwaGEqbCt0aGlzLmFscGhhKnMvMip1fSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGU9TWF0aC5sb2coTWF0aC50YW4oTWF0aC5QSS80LXQueS8yKSkscj10aGlzLmUvMipNYXRoLmxvZygoMSt0aGlzLmUqTWF0aC5zaW4odC55KSkvKDEtdGhpcy5lKk1hdGguc2luKHQueSkpKSxuPS10aGlzLmFscGhhKihlK3IpK3RoaXMuSyxvPTIqKE1hdGguYXRhbihNYXRoLmV4cChuKSktTWF0aC5QSS80KSxpPXRoaXMuYWxwaGEqKHQueC10aGlzLmxhbWJkYTApLHM9TWF0aC5hdGFuKE1hdGguc2luKGkpLyhNYXRoLnNpbih0aGlzLmIwKSpNYXRoLnRhbihvKStNYXRoLmNvcyh0aGlzLmIwKSpNYXRoLmNvcyhpKSkpLGE9TWF0aC5hc2luKE1hdGguY29zKHRoaXMuYjApKk1hdGguc2luKG8pLU1hdGguc2luKHRoaXMuYjApKk1hdGguY29zKG8pKk1hdGguY29zKGkpKTtyZXR1cm4gdC55PXRoaXMuUi8yKk1hdGgubG9nKCgxK01hdGguc2luKGEpKS8oMS1NYXRoLnNpbihhKSkpK3RoaXMueTAsdC54PXRoaXMuUipzK3RoaXMueDAsdH0sci5pbnZlcnNlPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT10LngtdGhpcy54MCxyPXQueS10aGlzLnkwLG49ZS90aGlzLlIsbz0yKihNYXRoLmF0YW4oTWF0aC5leHAoci90aGlzLlIpKS1NYXRoLlBJLzQpLGk9TWF0aC5hc2luKE1hdGguY29zKHRoaXMuYjApKk1hdGguc2luKG8pK01hdGguc2luKHRoaXMuYjApKk1hdGguY29zKG8pKk1hdGguY29zKG4pKSxzPU1hdGguYXRhbihNYXRoLnNpbihuKS8oTWF0aC5jb3ModGhpcy5iMCkqTWF0aC5jb3MobiktTWF0aC5zaW4odGhpcy5iMCkqTWF0aC50YW4obykpKSxhPXRoaXMubGFtYmRhMCtzL3RoaXMuYWxwaGEsbD0wLHU9aSxoPS0xZTMsYz0wO01hdGguYWJzKHUtaCk+MWUtNzspe2lmKCsrYz4yMClyZXR1cm47bD0xL3RoaXMuYWxwaGEqKE1hdGgubG9nKE1hdGgudGFuKE1hdGguUEkvNCtpLzIpKS10aGlzLkspK3RoaXMuZSpNYXRoLmxvZyhNYXRoLnRhbihNYXRoLlBJLzQrTWF0aC5hc2luKHRoaXMuZSpNYXRoLnNpbih1KSkvMikpLGg9dSx1PTIqTWF0aC5hdGFuKE1hdGguZXhwKGwpKS1NYXRoLlBJLzJ9cmV0dXJuIHQueD1hLHQueT11LHR9LHIubmFtZXM9WyJzb21lcmMiXX0se31dLCJwcm9qNC9saWIvcHJvamVjdGlvbnMvc3RlcmUiOltmdW5jdGlvbih0LGUscil7dmFyIG49TWF0aC5QSS8yLG89MWUtMTAsaT10KCIuLi9jb21tb24vc2lnbiIpLHM9dCgiLi4vY29tbW9uL21zZm56IiksYT10KCIuLi9jb21tb24vdHNmbnoiKSxsPXQoIi4uL2NvbW1vbi9waGkyeiIpLHU9dCgiLi4vY29tbW9uL2FkanVzdF9sb24iKTtyLnNzZm5fPWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gZSo9cixNYXRoLnRhbiguNSoobit0KSkqTWF0aC5wb3coKDEtZSkvKDErZSksLjUqcil9LHIuaW5pdD1mdW5jdGlvbigpe3RoaXMuY29zbGF0MD1NYXRoLmNvcyh0aGlzLmxhdDApLHRoaXMuc2lubGF0MD1NYXRoLnNpbih0aGlzLmxhdDApLHRoaXMuc3BoZXJlPzE9PT10aGlzLmswJiYhaXNOYU4odGhpcy5sYXRfdHMpJiZNYXRoLmFicyh0aGlzLmNvc2xhdDApPD1vJiYodGhpcy5rMD0uNSooMStpKHRoaXMubGF0MCkqTWF0aC5zaW4odGhpcy5sYXRfdHMpKSk6KE1hdGguYWJzKHRoaXMuY29zbGF0MCk8PW8mJih0aGlzLmxhdDA+MD90aGlzLmNvbj0xOnRoaXMuY29uPS0xKSx0aGlzLmNvbnM9TWF0aC5zcXJ0KE1hdGgucG93KDErdGhpcy5lLDErdGhpcy5lKSpNYXRoLnBvdygxLXRoaXMuZSwxLXRoaXMuZSkpLDE9PT10aGlzLmswJiYhaXNOYU4odGhpcy5sYXRfdHMpJiZNYXRoLmFicyh0aGlzLmNvc2xhdDApPD1vJiYodGhpcy5rMD0uNSp0aGlzLmNvbnMqcyh0aGlzLmUsTWF0aC5zaW4odGhpcy5sYXRfdHMpLE1hdGguY29zKHRoaXMubGF0X3RzKSkvYSh0aGlzLmUsdGhpcy5jb24qdGhpcy5sYXRfdHMsdGhpcy5jb24qTWF0aC5zaW4odGhpcy5sYXRfdHMpKSksdGhpcy5tczE9cyh0aGlzLmUsdGhpcy5zaW5sYXQwLHRoaXMuY29zbGF0MCksdGhpcy5YMD0yKk1hdGguYXRhbih0aGlzLnNzZm5fKHRoaXMubGF0MCx0aGlzLnNpbmxhdDAsdGhpcy5lKSktbix0aGlzLmNvc1gwPU1hdGguY29zKHRoaXMuWDApLHRoaXMuc2luWDA9TWF0aC5zaW4odGhpcy5YMCkpfSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGUscixpLHMsbCxoLGM9dC54LHA9dC55LF89TWF0aC5zaW4ocCksZD1NYXRoLmNvcyhwKSxmPXUoYy10aGlzLmxvbmcwKTtyZXR1cm4gTWF0aC5hYnMoTWF0aC5hYnMoYy10aGlzLmxvbmcwKS1NYXRoLlBJKTw9byYmTWF0aC5hYnMocCt0aGlzLmxhdDApPD1vPyh0Lng9TmFOLHQueT1OYU4sdCk6dGhpcy5zcGhlcmU/KGU9Mip0aGlzLmswLygxK3RoaXMuc2lubGF0MCpfK3RoaXMuY29zbGF0MCpkKk1hdGguY29zKGYpKSx0Lng9dGhpcy5hKmUqZCpNYXRoLnNpbihmKSt0aGlzLngwLHQueT10aGlzLmEqZSoodGhpcy5jb3NsYXQwKl8tdGhpcy5zaW5sYXQwKmQqTWF0aC5jb3MoZikpK3RoaXMueTAsdCk6KHI9MipNYXRoLmF0YW4odGhpcy5zc2ZuXyhwLF8sdGhpcy5lKSktbixzPU1hdGguY29zKHIpLGk9TWF0aC5zaW4ociksTWF0aC5hYnModGhpcy5jb3NsYXQwKTw9bz8obD1hKHRoaXMuZSxwKnRoaXMuY29uLHRoaXMuY29uKl8pLGg9Mip0aGlzLmEqdGhpcy5rMCpsL3RoaXMuY29ucyx0Lng9dGhpcy54MCtoKk1hdGguc2luKGMtdGhpcy5sb25nMCksdC55PXRoaXMueTAtdGhpcy5jb24qaCpNYXRoLmNvcyhjLXRoaXMubG9uZzApLHQpOihNYXRoLmFicyh0aGlzLnNpbmxhdDApPG8/KGU9Mip0aGlzLmEqdGhpcy5rMC8oMStzKk1hdGguY29zKGYpKSx0Lnk9ZSppKTooZT0yKnRoaXMuYSp0aGlzLmswKnRoaXMubXMxLyh0aGlzLmNvc1gwKigxK3RoaXMuc2luWDAqaSt0aGlzLmNvc1gwKnMqTWF0aC5jb3MoZikpKSx0Lnk9ZSoodGhpcy5jb3NYMCppLXRoaXMuc2luWDAqcypNYXRoLmNvcyhmKSkrdGhpcy55MCksdC54PWUqcypNYXRoLnNpbihmKSt0aGlzLngwLHQpKX0sci5pbnZlcnNlPWZ1bmN0aW9uKHQpe3QueC09dGhpcy54MCx0LnktPXRoaXMueTA7dmFyIGUscixpLHMsYSxoPU1hdGguc3FydCh0LngqdC54K3QueSp0LnkpO2lmKHRoaXMuc3BoZXJlKXt2YXIgYz0yKk1hdGguYXRhbihoLyguNSp0aGlzLmEqdGhpcy5rMCkpO3JldHVybiBlPXRoaXMubG9uZzAscj10aGlzLmxhdDAsaDw9bz8odC54PWUsdC55PXIsdCk6KHI9TWF0aC5hc2luKE1hdGguY29zKGMpKnRoaXMuc2lubGF0MCt0LnkqTWF0aC5zaW4oYykqdGhpcy5jb3NsYXQwL2gpLGU9dShNYXRoLmFicyh0aGlzLmNvc2xhdDApPG8/dGhpcy5sYXQwPjA/dGhpcy5sb25nMCtNYXRoLmF0YW4yKHQueCwtMSp0LnkpOnRoaXMubG9uZzArTWF0aC5hdGFuMih0LngsdC55KTp0aGlzLmxvbmcwK01hdGguYXRhbjIodC54Kk1hdGguc2luKGMpLGgqdGhpcy5jb3NsYXQwKk1hdGguY29zKGMpLXQueSp0aGlzLnNpbmxhdDAqTWF0aC5zaW4oYykpKSx0Lng9ZSx0Lnk9cix0KX1pZihNYXRoLmFicyh0aGlzLmNvc2xhdDApPD1vKXtpZihoPD1vKXJldHVybiByPXRoaXMubGF0MCxlPXRoaXMubG9uZzAsCnQueD1lLHQueT1yLHQ7dC54Kj10aGlzLmNvbix0LnkqPXRoaXMuY29uLGk9aCp0aGlzLmNvbnMvKDIqdGhpcy5hKnRoaXMuazApLHI9dGhpcy5jb24qbCh0aGlzLmUsaSksZT10aGlzLmNvbip1KHRoaXMuY29uKnRoaXMubG9uZzArTWF0aC5hdGFuMih0LngsLTEqdC55KSl9ZWxzZSBzPTIqTWF0aC5hdGFuKGgqdGhpcy5jb3NYMC8oMip0aGlzLmEqdGhpcy5rMCp0aGlzLm1zMSkpLGU9dGhpcy5sb25nMCxoPD1vP2E9dGhpcy5YMDooYT1NYXRoLmFzaW4oTWF0aC5jb3MocykqdGhpcy5zaW5YMCt0LnkqTWF0aC5zaW4ocykqdGhpcy5jb3NYMC9oKSxlPXUodGhpcy5sb25nMCtNYXRoLmF0YW4yKHQueCpNYXRoLnNpbihzKSxoKnRoaXMuY29zWDAqTWF0aC5jb3MocyktdC55KnRoaXMuc2luWDAqTWF0aC5zaW4ocykpKSkscj0tMSpsKHRoaXMuZSxNYXRoLnRhbiguNSoobithKSkpO3JldHVybiB0Lng9ZSx0Lnk9cix0fSxyLm5hbWVzPVsic3RlcmUiLCJTdGVyZW9ncmFwaGljX1NvdXRoX1BvbGUiLCJQb2xhciBTdGVyZW9ncmFwaGljICh2YXJpYW50IEIpIl19LHsiLi4vY29tbW9uL2FkanVzdF9sb24iOiJwcm9qNC9saWIvY29tbW9uL2FkanVzdF9sb24iLCIuLi9jb21tb24vbXNmbnoiOiJwcm9qNC9saWIvY29tbW9uL21zZm56IiwiLi4vY29tbW9uL3BoaTJ6IjoicHJvajQvbGliL2NvbW1vbi9waGkyeiIsIi4uL2NvbW1vbi9zaWduIjoicHJvajQvbGliL2NvbW1vbi9zaWduIiwiLi4vY29tbW9uL3RzZm56IjoicHJvajQvbGliL2NvbW1vbi90c2ZueiJ9XSwicHJvajQvbGliL3Byb2plY3Rpb25zL3N0ZXJlYSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj10KCIuL2dhdXNzIiksbz10KCIuLi9jb21tb24vYWRqdXN0X2xvbiIpO3IuaW5pdD1mdW5jdGlvbigpe24uaW5pdC5hcHBseSh0aGlzKSx0aGlzLnJjJiYodGhpcy5zaW5jMD1NYXRoLnNpbih0aGlzLnBoaWMwKSx0aGlzLmNvc2MwPU1hdGguY29zKHRoaXMucGhpYzApLHRoaXMuUjI9Mip0aGlzLnJjLHRoaXMudGl0bGV8fCh0aGlzLnRpdGxlPSJPYmxpcXVlIFN0ZXJlb2dyYXBoaWMgQWx0ZXJuYXRpdmUiKSl9LHIuZm9yd2FyZD1mdW5jdGlvbih0KXt2YXIgZSxyLGkscztyZXR1cm4gdC54PW8odC54LXRoaXMubG9uZzApLG4uZm9yd2FyZC5hcHBseSh0aGlzLFt0XSksZT1NYXRoLnNpbih0LnkpLHI9TWF0aC5jb3ModC55KSxpPU1hdGguY29zKHQueCkscz10aGlzLmswKnRoaXMuUjIvKDErdGhpcy5zaW5jMCplK3RoaXMuY29zYzAqcippKSx0Lng9cypyKk1hdGguc2luKHQueCksdC55PXMqKHRoaXMuY29zYzAqZS10aGlzLnNpbmMwKnIqaSksdC54PXRoaXMuYSp0LngrdGhpcy54MCx0Lnk9dGhpcy5hKnQueSt0aGlzLnkwLHR9LHIuaW52ZXJzZT1mdW5jdGlvbih0KXt2YXIgZSxyLGkscyxhO2lmKHQueD0odC54LXRoaXMueDApL3RoaXMuYSx0Lnk9KHQueS10aGlzLnkwKS90aGlzLmEsdC54Lz10aGlzLmswLHQueS89dGhpcy5rMCxhPU1hdGguc3FydCh0LngqdC54K3QueSp0LnkpKXt2YXIgbD0yKk1hdGguYXRhbjIoYSx0aGlzLlIyKTtlPU1hdGguc2luKGwpLHI9TWF0aC5jb3MobCkscz1NYXRoLmFzaW4ocip0aGlzLnNpbmMwK3QueSplKnRoaXMuY29zYzAvYSksaT1NYXRoLmF0YW4yKHQueCplLGEqdGhpcy5jb3NjMCpyLXQueSp0aGlzLnNpbmMwKmUpfWVsc2Ugcz10aGlzLnBoaWMwLGk9MDtyZXR1cm4gdC54PWksdC55PXMsbi5pbnZlcnNlLmFwcGx5KHRoaXMsW3RdKSx0Lng9byh0LngrdGhpcy5sb25nMCksdH0sci5uYW1lcz1bIlN0ZXJlb2dyYXBoaWNfTm9ydGhfUG9sZSIsIk9ibGlxdWVfU3RlcmVvZ3JhcGhpYyIsIlBvbGFyX1N0ZXJlb2dyYXBoaWMiLCJzdGVyZWEiLCJPYmxpcXVlIFN0ZXJlb2dyYXBoaWMgQWx0ZXJuYXRpdmUiXX0seyIuLi9jb21tb24vYWRqdXN0X2xvbiI6InByb2o0L2xpYi9jb21tb24vYWRqdXN0X2xvbiIsIi4vZ2F1c3MiOiJwcm9qNC9saWIvcHJvamVjdGlvbnMvZ2F1c3MifV0sInByb2o0L2xpYi9wcm9qZWN0aW9ucy90bWVyYyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj10KCIuLi9jb21tb24vZTBmbiIpLG89dCgiLi4vY29tbW9uL2UxZm4iKSxpPXQoIi4uL2NvbW1vbi9lMmZuIikscz10KCIuLi9jb21tb24vZTNmbiIpLGE9dCgiLi4vY29tbW9uL21sZm4iKSxsPXQoIi4uL2NvbW1vbi9hZGp1c3RfbG9uIiksdT1NYXRoLlBJLzIsaD0xZS0xMCxjPXQoIi4uL2NvbW1vbi9zaWduIikscD10KCIuLi9jb21tb24vYXNpbnoiKTtyLmluaXQ9ZnVuY3Rpb24oKXt0aGlzLmUwPW4odGhpcy5lcyksdGhpcy5lMT1vKHRoaXMuZXMpLHRoaXMuZTI9aSh0aGlzLmVzKSx0aGlzLmUzPXModGhpcy5lcyksdGhpcy5tbDA9dGhpcy5hKmEodGhpcy5lMCx0aGlzLmUxLHRoaXMuZTIsdGhpcy5lMyx0aGlzLmxhdDApfSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG89dC54LGk9dC55LHM9bChvLXRoaXMubG9uZzApLHU9TWF0aC5zaW4oaSksaD1NYXRoLmNvcyhpKTtpZih0aGlzLnNwaGVyZSl7dmFyIGM9aCpNYXRoLnNpbihzKTtpZihNYXRoLmFicyhNYXRoLmFicyhjKS0xKTwxZS0xMClyZXR1cm4gOTM7cj0uNSp0aGlzLmEqdGhpcy5rMCpNYXRoLmxvZygoMStjKS8oMS1jKSksZT1NYXRoLmFjb3MoaCpNYXRoLmNvcyhzKS9NYXRoLnNxcnQoMS1jKmMpKSxpPDAmJihlPS1lKSxuPXRoaXMuYSp0aGlzLmswKihlLXRoaXMubGF0MCl9ZWxzZXt2YXIgcD1oKnMsXz1NYXRoLnBvdyhwLDIpLGQ9dGhpcy5lcDIqTWF0aC5wb3coaCwyKSxmPU1hdGgudGFuKGkpLG09TWF0aC5wb3coZiwyKTtlPTEtdGhpcy5lcypNYXRoLnBvdyh1LDIpO3ZhciBnPXRoaXMuYS9NYXRoLnNxcnQoZSkseT10aGlzLmEqYSh0aGlzLmUwLHRoaXMuZTEsdGhpcy5lMix0aGlzLmUzLGkpO3I9dGhpcy5rMCpnKnAqKDErXy82KigxLW0rZCtfLzIwKig1LTE4Km0rTWF0aC5wb3cobSwyKSs3MipkLTU4KnRoaXMuZXAyKSkpK3RoaXMueDAsbj10aGlzLmswKih5LXRoaXMubWwwK2cqZiooXyooLjUrXy8yNCooNS1tKzkqZCs0Kk1hdGgucG93KGQsMikrXy8zMCooNjEtNTgqbStNYXRoLnBvdyhtLDIpKzYwMCpkLTMzMCp0aGlzLmVwMikpKSkpK3RoaXMueTB9cmV0dXJuIHQueD1yLHQueT1uLHR9LHIuaW52ZXJzZT1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbyxpLHMsYT02O2lmKHRoaXMuc3BoZXJlKXt2YXIgXz1NYXRoLmV4cCh0LngvKHRoaXMuYSp0aGlzLmswKSksZD0uNSooXy0xL18pLGY9dGhpcy5sYXQwK3QueS8odGhpcy5hKnRoaXMuazApLG09TWF0aC5jb3MoZik7ZT1NYXRoLnNxcnQoKDEtbSptKS8oMStkKmQpKSxpPXAoZSksZjwwJiYoaT0taSkscz0wPT09ZCYmMD09PW0/dGhpcy5sb25nMDpsKE1hdGguYXRhbjIoZCxtKSt0aGlzLmxvbmcwKX1lbHNle3ZhciBnPXQueC10aGlzLngwLHk9dC55LXRoaXMueTA7Zm9yKGU9KHRoaXMubWwwK3kvdGhpcy5rMCkvdGhpcy5hLHI9ZSxvPTA7ITAmJihuPShlK3RoaXMuZTEqTWF0aC5zaW4oMipyKS10aGlzLmUyKk1hdGguc2luKDQqcikrdGhpcy5lMypNYXRoLnNpbig2KnIpKS90aGlzLmUwLXIscis9biwhKE1hdGguYWJzKG4pPD1oKSk7bysrKWlmKG8+PWEpcmV0dXJuIDk1O2lmKE1hdGguYWJzKHIpPHUpe3ZhciB2PU1hdGguc2luKHIpLGI9TWF0aC5jb3MocikseD1NYXRoLnRhbihyKSx3PXRoaXMuZXAyKk1hdGgucG93KGIsMiksTT1NYXRoLnBvdyh3LDIpLGs9TWF0aC5wb3coeCwyKSxqPU1hdGgucG93KGssMik7ZT0xLXRoaXMuZXMqTWF0aC5wb3codiwyKTt2YXIgVD10aGlzLmEvTWF0aC5zcXJ0KGUpLFM9VCooMS10aGlzLmVzKS9lLHo9Zy8oVCp0aGlzLmswKSxQPU1hdGgucG93KHosMik7aT1yLVQqeCpQL1MqKC41LVAvMjQqKDUrMyprKzEwKnctNCpNLTkqdGhpcy5lcDItUC8zMCooNjErOTAqaysyOTgqdys0NSpqLTI1Mip0aGlzLmVwMi0zKk0pKSkscz1sKHRoaXMubG9uZzAreiooMS1QLzYqKDErMiprK3ctUC8yMCooNS0yKncrMjgqay0zKk0rOCp0aGlzLmVwMisyNCpqKSkpL2IpfWVsc2UgaT11KmMoeSkscz10aGlzLmxvbmcwfXJldHVybiB0Lng9cyx0Lnk9aSx0fSxyLm5hbWVzPVsiVHJhbnN2ZXJzZV9NZXJjYXRvciIsIlRyYW5zdmVyc2UgTWVyY2F0b3IiLCJ0bWVyYyJdfSx7Ii4uL2NvbW1vbi9hZGp1c3RfbG9uIjoicHJvajQvbGliL2NvbW1vbi9hZGp1c3RfbG9uIiwiLi4vY29tbW9uL2FzaW56IjoicHJvajQvbGliL2NvbW1vbi9hc2lueiIsIi4uL2NvbW1vbi9lMGZuIjoicHJvajQvbGliL2NvbW1vbi9lMGZuIiwiLi4vY29tbW9uL2UxZm4iOiJwcm9qNC9saWIvY29tbW9uL2UxZm4iLCIuLi9jb21tb24vZTJmbiI6InByb2o0L2xpYi9jb21tb24vZTJmbiIsIi4uL2NvbW1vbi9lM2ZuIjoicHJvajQvbGliL2NvbW1vbi9lM2ZuIiwiLi4vY29tbW9uL21sZm4iOiJwcm9qNC9saWIvY29tbW9uL21sZm4iLCIuLi9jb21tb24vc2lnbiI6InByb2o0L2xpYi9jb21tb24vc2lnbiJ9XSwicHJvajQvbGliL3Byb2plY3Rpb25zL3V0bSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj0uMDE3NDUzMjkyNTE5OTQzMjk1LG89dCgiLi90bWVyYyIpO3IuZGVwZW5kc09uPSJ0bWVyYyIsci5pbml0PWZ1bmN0aW9uKCl7dGhpcy56b25lJiYodGhpcy5sYXQwPTAsdGhpcy5sb25nMD0oNipNYXRoLmFicyh0aGlzLnpvbmUpLTE4Mykqbix0aGlzLngwPTVlNSx0aGlzLnkwPXRoaXMudXRtU291dGg/MWU3OjAsdGhpcy5rMD0uOTk5NixvLmluaXQuYXBwbHkodGhpcyksdGhpcy5mb3J3YXJkPW8uZm9yd2FyZCx0aGlzLmludmVyc2U9by5pbnZlcnNlKX0sci5uYW1lcz1bIlVuaXZlcnNhbCBUcmFuc3ZlcnNlIE1lcmNhdG9yIFN5c3RlbSIsInV0bSJdfSx7Ii4vdG1lcmMiOiJwcm9qNC9saWIvcHJvamVjdGlvbnMvdG1lcmMifV0sInByb2o0L2xpYi9wcm9qZWN0aW9ucy92YW5kZyI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj10KCIuLi9jb21tb24vYWRqdXN0X2xvbiIpLG89TWF0aC5QSS8yLGk9MWUtMTAscz10KCIuLi9jb21tb24vYXNpbnoiKTtyLmluaXQ9ZnVuY3Rpb24oKXt0aGlzLlI9dGhpcy5hfSxyLmZvcndhcmQ9ZnVuY3Rpb24odCl7dmFyIGUscixhPXQueCxsPXQueSx1PW4oYS10aGlzLmxvbmcwKTtNYXRoLmFicyhsKTw9aSYmKGU9dGhpcy54MCt0aGlzLlIqdSxyPXRoaXMueTApO3ZhciBoPXMoMipNYXRoLmFicyhsL01hdGguUEkpKTsoTWF0aC5hYnModSk8PWl8fE1hdGguYWJzKE1hdGguYWJzKGwpLW8pPD1pKSYmKGU9dGhpcy54MCxyPWw+PTA/dGhpcy55MCtNYXRoLlBJKnRoaXMuUipNYXRoLnRhbiguNSpoKTp0aGlzLnkwK01hdGguUEkqdGhpcy5SKi1NYXRoLnRhbiguNSpoKSk7dmFyIGM9LjUqTWF0aC5hYnMoTWF0aC5QSS91LXUvTWF0aC5QSSkscD1jKmMsXz1NYXRoLnNpbihoKSxkPU1hdGguY29zKGgpLGY9ZC8oXytkLTEpLG09ZipmLGc9ZiooMi9fLTEpLHk9ZypnLHY9TWF0aC5QSSp0aGlzLlIqKGMqKGYteSkrTWF0aC5zcXJ0KHAqKGYteSkqKGYteSktKHkrcCkqKG0teSkpKS8oeStwKTt1PDAmJih2PS12KSxlPXRoaXMueDArdjt2YXIgYj1wK2Y7cmV0dXJuIHY9TWF0aC5QSSp0aGlzLlIqKGcqYi1jKk1hdGguc3FydCgoeStwKSoocCsxKS1iKmIpKS8oeStwKSxyPWw+PTA/dGhpcy55MCt2OnRoaXMueTAtdix0Lng9ZSx0Lnk9cix0fSxyLmludmVyc2U9ZnVuY3Rpb24odCl7dmFyIGUscixvLHMsYSxsLHUsaCxjLHAsXyxkLGY7cmV0dXJuIHQueC09dGhpcy54MCx0LnktPXRoaXMueTAsXz1NYXRoLlBJKnRoaXMuUixvPXQueC9fLHM9dC55L18sYT1vKm8rcypzLGw9LU1hdGguYWJzKHMpKigxK2EpLHU9bC0yKnMqcytvKm8saD0tMipsKzErMipzKnMrYSphLGY9cypzL2grKDIqdSp1KnUvaC9oL2gtOSpsKnUvaC9oKS8yNyxjPShsLXUqdS8zL2gpL2gscD0yKk1hdGguc3FydCgtYy8zKSxfPTMqZi9jL3AsTWF0aC5hYnMoXyk+MSYmKF89Xz49MD8xOi0xKSxkPU1hdGguYWNvcyhfKS8zLHI9dC55Pj0wPygtcCpNYXRoLmNvcyhkK01hdGguUEkvMyktdS8zL2gpKk1hdGguUEk6LSgtcCpNYXRoLmNvcyhkK01hdGguUEkvMyktdS8zL2gpKk1hdGguUEksZT1NYXRoLmFicyhvKTxpP3RoaXMubG9uZzA6bih0aGlzLmxvbmcwK01hdGguUEkqKGEtMStNYXRoLnNxcnQoMSsyKihvKm8tcypzKSthKmEpKS8yL28pLHQueD1lLHQueT1yLHR9LHIubmFtZXM9WyJWYW5fZGVyX0dyaW50ZW5fSSIsIlZhbkRlckdyaW50ZW4iLCJ2YW5kZyJdfSx7Ii4uL2NvbW1vbi9hZGp1c3RfbG9uIjoicHJvajQvbGliL2NvbW1vbi9hZGp1c3RfbG9uIiwiLi4vY29tbW9uL2FzaW56IjoicHJvajQvbGliL2NvbW1vbi9hc2lueiJ9XSwicHJvajQvbGliL3RyYW5zZm9ybSI6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbj0uMDE3NDUzMjkyNTE5OTQzMjk1LG89NTcuMjk1Nzc5NTEzMDgyMzIsaT0xLHM9MixhPXQoIi4vZGF0dW1fdHJhbnNmb3JtIiksbD10KCIuL2FkanVzdF9heGlzIiksdT10KCIuL1Byb2oiKSxoPXQoIi4vY29tbW9uL3RvUG9pbnQiKTtlLmV4cG9ydHM9ZnVuY3Rpb24gYyh0LGUscil7ZnVuY3Rpb24gcCh0LGUpe3JldHVybih0LmRhdHVtLmRhdHVtX3R5cGU9PT1pfHx0LmRhdHVtLmRhdHVtX3R5cGU9PT1zKSYmIldHUzg0IiE9PWUuZGF0dW1Db2RlfXZhciBfO3JldHVybiBBcnJheS5pc0FycmF5KHIpJiYocj1oKHIpKSx0LmRhdHVtJiZlLmRhdHVtJiYocCh0LGUpfHxwKGUsdCkpJiYoXz1uZXcgdSgiV0dTODQiKSxjKHQsXyxyKSx0PV8pLCJlbnUiIT09dC5heGlzJiZsKHQsITEsciksImxvbmdsYXQiPT09dC5wcm9qTmFtZT8oci54Kj1uLHIueSo9bik6KHQudG9fbWV0ZXImJihyLngqPXQudG9fbWV0ZXIsci55Kj10LnRvX21ldGVyKSx0LmludmVyc2UocikpLHQuZnJvbV9ncmVlbndpY2gmJihyLngrPXQuZnJvbV9ncmVlbndpY2gpLHI9YSh0LmRhdHVtLGUuZGF0dW0sciksZS5mcm9tX2dyZWVud2ljaCYmKHIueC09ZS5mcm9tX2dyZWVud2ljaCksImxvbmdsYXQiPT09ZS5wcm9qTmFtZT8oci54Kj1vLHIueSo9byk6KGUuZm9yd2FyZChyKSxlLnRvX21ldGVyJiYoci54Lz1lLnRvX21ldGVyLHIueS89ZS50b19tZXRlcikpLCJlbnUiIT09ZS5heGlzJiZsKGUsITAscikscn19LHsiLi9Qcm9qIjoicHJvajQvbGliL1Byb2oiLCIuL2FkanVzdF9heGlzIjoicHJvajQvbGliL2FkanVzdF9heGlzIiwiLi9jb21tb24vdG9Qb2ludCI6InByb2o0L2xpYi9jb21tb24vdG9Qb2ludCIsIi4vZGF0dW1fdHJhbnNmb3JtIjoicHJvajQvbGliL2RhdHVtX3RyYW5zZm9ybSJ9XSwicHJvajQvbGliL3drdCI6W2Z1bmN0aW9uKHQsZSxyKXtmdW5jdGlvbiBuKHQsZSxyKXt0W2VdPXIubWFwKGZ1bmN0aW9uKHQpe3ZhciBlPXt9O3JldHVybiBvKHQsZSksZX0pLnJlZHVjZShmdW5jdGlvbih0LGUpe3JldHVybiB1KHQsZSl9LHt9KX1mdW5jdGlvbiBvKHQsZSl7dmFyIHI7cmV0dXJuIEFycmF5LmlzQXJyYXkodCk/KHI9dC5zaGlmdCgpLCJQQVJBTUVURVIiPT09ciYmKHI9dC5zaGlmdCgpKSwxPT09dC5sZW5ndGg/QXJyYXkuaXNBcnJheSh0WzBdKT8oZVtyXT17fSxvKHRbMF0sZVtyXSkpOmVbcl09dFswXTp0Lmxlbmd0aD8iVE9XR1M4NCI9PT1yP2Vbcl09dDooZVtyXT17fSxbIlVOSVQiLCJQUklNRU0iLCJWRVJUX0RBVFVNIl0uaW5kZXhPZihyKT4tMT8oZVtyXT17bmFtZTp0WzBdLnRvTG93ZXJDYXNlKCksY29udmVydDp0WzFdfSwzPT09dC5sZW5ndGgmJihlW3JdLmF1dGg9dFsyXSkpOiJTUEhFUk9JRCI9PT1yPyhlW3JdPXtuYW1lOnRbMF0sYTp0WzFdLHJmOnRbMl19LDQ9PT10Lmxlbmd0aCYmKGVbcl0uYXV0aD10WzNdKSk6WyJHRU9HQ1MiLCJHRU9DQ1MiLCJEQVRVTSIsIlZFUlRfQ1MiLCJDT01QRF9DUyIsIkxPQ0FMX0NTIiwiRklUVEVEX0NTIiwiTE9DQUxfREFUVU0iXS5pbmRleE9mKHIpPi0xPyh0WzBdPVsibmFtZSIsdFswXV0sbihlLHIsdCkpOnQuZXZlcnkoZnVuY3Rpb24odCl7cmV0dXJuIEFycmF5LmlzQXJyYXkodCl9KT9uKGUscix0KTpvKHQsZVtyXSkpOmVbcl09ITAsdm9pZCAwKTp2b2lkKGVbdF09ITApfWZ1bmN0aW9uIGkodCxlKXt2YXIgcj1lWzBdLG49ZVsxXTshKHIgaW4gdCkmJm4gaW4gdCYmKHRbcl09dFtuXSwzPT09ZS5sZW5ndGgmJih0W3JdPWVbMl0odFtyXSkpKX1mdW5jdGlvbiBzKHQpe3JldHVybiB0Kmx9ZnVuY3Rpb24gYSh0KXtmdW5jdGlvbiBlKGUpe3ZhciByPXQudG9fbWV0ZXJ8fDE7cmV0dXJuIHBhcnNlRmxvYXQoZSwxMCkqcn0iR0VPR0NTIj09PXQudHlwZT90LnByb2pOYW1lPSJsb25nbGF0IjoiTE9DQUxfQ1MiPT09dC50eXBlPyh0LnByb2pOYW1lPSJpZGVudGl0eSIsdC5sb2NhbD0hMCk6Im9iamVjdCI9PXR5cGVvZiB0LlBST0pFQ1RJT04/dC5wcm9qTmFtZT1PYmplY3Qua2V5cyh0LlBST0pFQ1RJT04pWzBdOnQucHJvak5hbWU9dC5QUk9KRUNUSU9OLHQuVU5JVCYmKHQudW5pdHM9dC5VTklULm5hbWUudG9Mb3dlckNhc2UoKSwibWV0cmUiPT09dC51bml0cyYmKHQudW5pdHM9Im1ldGVyIiksdC5VTklULmNvbnZlcnQmJigiR0VPR0NTIj09PXQudHlwZT90LkRBVFVNJiZ0LkRBVFVNLlNQSEVST0lEJiYodC50b19tZXRlcj1wYXJzZUZsb2F0KHQuVU5JVC5jb252ZXJ0LDEwKSp0LkRBVFVNLlNQSEVST0lELmEpOnQudG9fbWV0ZXI9cGFyc2VGbG9hdCh0LlVOSVQuY29udmVydCwxMCkpKSx0LkdFT0dDUyYmKHQuR0VPR0NTLkRBVFVNP3QuZGF0dW1Db2RlPXQuR0VPR0NTLkRBVFVNLm5hbWUudG9Mb3dlckNhc2UoKTp0LmRhdHVtQ29kZT10LkdFT0dDUy5uYW1lLnRvTG93ZXJDYXNlKCksImRfIj09PXQuZGF0dW1Db2RlLnNsaWNlKDAsMikmJih0LmRhdHVtQ29kZT10LmRhdHVtQ29kZS5zbGljZSgyKSksIm5ld196ZWFsYW5kX2dlb2RldGljX2RhdHVtXzE5NDkiIT09dC5kYXR1bUNvZGUmJiJuZXdfemVhbGFuZF8xOTQ5IiE9PXQuZGF0dW1Db2RlfHwodC5kYXR1bUNvZGU9Im56Z2Q0OSIpLCJ3Z3NfMTk4NCI9PT10LmRhdHVtQ29kZSYmKCJNZXJjYXRvcl9BdXhpbGlhcnlfU3BoZXJlIj09PXQuUFJPSkVDVElPTiYmKHQuc3BoZXJlPSEwKSx0LmRhdHVtQ29kZT0id2dzODQiKSwiX2ZlcnJvIj09PXQuZGF0dW1Db2RlLnNsaWNlKC02KSYmKHQuZGF0dW1Db2RlPXQuZGF0dW1Db2RlLnNsaWNlKDAsLTYpKSwiX2pha2FydGEiPT09dC5kYXR1bUNvZGUuc2xpY2UoLTgpJiYodC5kYXR1bUNvZGU9dC5kYXR1bUNvZGUuc2xpY2UoMCwtOCkpLH50LmRhdHVtQ29kZS5pbmRleE9mKCJiZWxnZSIpJiYodC5kYXR1bUNvZGU9InJuYjcyIiksdC5HRU9HQ1MuREFUVU0mJnQuR0VPR0NTLkRBVFVNLlNQSEVST0lEJiYodC5lbGxwcz10LkdFT0dDUy5EQVRVTS5TUEhFUk9JRC5uYW1lLnJlcGxhY2UoIl8xOSIsIiIpLnJlcGxhY2UoL1tDY11sYXJrZVxfMTgvLCJjbHJrIiksImludGVybmF0aW9uYWwiPT09dC5lbGxwcy50b0xvd2VyQ2FzZSgpLnNsaWNlKDAsMTMpJiYodC5lbGxwcz0iaW50bCIpLHQuYT10LkdFT0dDUy5EQVRVTS5TUEhFUk9JRC5hLHQucmY9cGFyc2VGbG9hdCh0LkdFT0dDUy5EQVRVTS5TUEhFUk9JRC5yZiwxMCkpLH50LmRhdHVtQ29kZS5pbmRleE9mKCJvc2diXzE5MzYiKSYmKHQuZGF0dW1Db2RlPSJvc2diMzYiKSksdC5iJiYhaXNGaW5pdGUodC5iKSYmKHQuYj10LmEpO3ZhciByPWZ1bmN0aW9uKGUpe3JldHVybiBpKHQsZSl9LG49W1sic3RhbmRhcmRfcGFyYWxsZWxfMSIsIlN0YW5kYXJkX1BhcmFsbGVsXzEiXSxbInN0YW5kYXJkX3BhcmFsbGVsXzIiLCJTdGFuZGFyZF9QYXJhbGxlbF8yIl0sWyJmYWxzZV9lYXN0aW5nIiwiRmFsc2VfRWFzdGluZyJdLFsiZmFsc2Vfbm9ydGhpbmciLCJGYWxzZV9Ob3J0aGluZyJdLFsiY2VudHJhbF9tZXJpZGlhbiIsIkNlbnRyYWxfTWVyaWRpYW4iXSxbImxhdGl0dWRlX29mX29yaWdpbiIsIkxhdGl0dWRlX09mX09yaWdpbiJdLFsibGF0aXR1ZGVfb2Zfb3JpZ2luIiwiQ2VudHJhbF9QYXJhbGxlbCJdLFsic2NhbGVfZmFjdG9yIiwiU2NhbGVfRmFjdG9yIl0sWyJrMCIsInNjYWxlX2ZhY3RvciJdLFsibGF0aXR1ZGVfb2ZfY2VudGVyIiwiTGF0aXR1ZGVfb2ZfY2VudGVyIl0sWyJsYXQwIiwibGF0aXR1ZGVfb2ZfY2VudGVyIixzXSxbImxvbmdpdHVkZV9vZl9jZW50ZXIiLCJMb25naXR1ZGVfT2ZfQ2VudGVyIl0sWyJsb25nYyIsImxvbmdpdHVkZV9vZl9jZW50ZXIiLHNdLFsieDAiLCJmYWxzZV9lYXN0aW5nIixlXSxbInkwIiwiZmFsc2Vfbm9ydGhpbmciLGVdLFsibG9uZzAiLCJjZW50cmFsX21lcmlkaWFuIixzXSxbImxhdDAiLCJsYXRpdHVkZV9vZl9vcmlnaW4iLHNdLFsibGF0MCIsInN0YW5kYXJkX3BhcmFsbGVsXzEiLHNdLFsibGF0MSIsInN0YW5kYXJkX3BhcmFsbGVsXzEiLHNdLFsibGF0MiIsInN0YW5kYXJkX3BhcmFsbGVsXzIiLHNdLFsiYWxwaGEiLCJhemltdXRoIixzXSxbInNyc0NvZGUiLCJuYW1lIl1dO24uZm9yRWFjaChyKSx0LmxvbmcwfHwhdC5sb25nY3x8IkFsYmVyc19Db25pY19FcXVhbF9BcmVhIiE9PXQucHJvak5hbWUmJiJMYW1iZXJ0X0F6aW11dGhhbF9FcXVhbF9BcmVhIiE9PXQucHJvak5hbWV8fCh0LmxvbmcwPXQubG9uZ2MpLHQubGF0X3RzfHwhdC5sYXQxfHwiU3RlcmVvZ3JhcGhpY19Tb3V0aF9Qb2xlIiE9PXQucHJvak5hbWUmJiJQb2xhciBTdGVyZW9ncmFwaGljICh2YXJpYW50IEIpIiE9PXQucHJvak5hbWV8fCh0LmxhdDA9cyh0LmxhdDE+MD85MDotOTApLHQubGF0X3RzPXQubGF0MSl9dmFyIGw9LjAxNzQ1MzI5MjUxOTk0MzI5NSx1PXQoIi4vZXh0ZW5kIik7ZS5leHBvcnRzPWZ1bmN0aW9uKHQsZSl7dmFyIHI9SlNPTi5wYXJzZSgoIiwiK3QpLnJlcGxhY2UoL1xzKlwsXHMqKFtBLVpfMC05XSs/KShcWykvZywnLFsiJDEiLCcpLnNsaWNlKDEpLnJlcGxhY2UoL1xzKlwsXHMqKFtBLVpfMC05XSs/KVxdL2csJywiJDEiXScpLnJlcGxhY2UoLyxcWyJWRVJUQ1MiLisvLCIiKSksbj1yLnNoaWZ0KCksaT1yLnNoaWZ0KCk7ci51bnNoaWZ0KFsibmFtZSIsaV0pLHIudW5zaGlmdChbInR5cGUiLG5dKSxyLnVuc2hpZnQoIm91dHB1dCIpO3ZhciBzPXt9O3JldHVybiBvKHIscyksYShzLm91dHB1dCksdShlLHMub3V0cHV0KX19LHsiLi9leHRlbmQiOiJwcm9qNC9saWIvZXh0ZW5kIn1dLCJwcm9qNC9ub2RlX21vZHVsZXMvbWdycy9tZ3JzIjpbZnVuY3Rpb24odCxlLHIpe2Z1bmN0aW9uIG4odCl7cmV0dXJuIHQqKE1hdGguUEkvMTgwKX1mdW5jdGlvbiBvKHQpe3JldHVybiAxODAqKHQvTWF0aC5QSSl9ZnVuY3Rpb24gaSh0KXt2YXIgZSxyLG8saSxzLGwsdSxoLGMscD10LmxhdCxfPXQubG9uLGQ9NjM3ODEzNyxmPS4wMDY2OTQzOCxtPS45OTk2LGc9bihwKSx5PW4oXyk7Yz1NYXRoLmZsb29yKChfKzE4MCkvNikrMSwxODA9PT1fJiYoYz02MCkscD49NTYmJnA8NjQmJl8+PTMmJl88MTImJihjPTMyKSxwPj03MiYmcDw4NCYmKF8+PTAmJl88OT9jPTMxOl8+PTkmJl88MjE/Yz0zMzpfPj0yMSYmXzwzMz9jPTM1Ol8+PTMzJiZfPDQyJiYoYz0zNykpLGU9NiooYy0xKS0xODArMyxoPW4oZSkscj1mLygxLWYpLG89ZC9NYXRoLnNxcnQoMS1mKk1hdGguc2luKGcpKk1hdGguc2luKGcpKSxpPU1hdGgudGFuKGcpKk1hdGgudGFuKGcpLHM9cipNYXRoLmNvcyhnKSpNYXRoLmNvcyhnKSxsPU1hdGguY29zKGcpKih5LWgpLHU9ZCooKDEtZi80LTMqZipmLzY0LTUqZipmKmYvMjU2KSpnLSgzKmYvOCszKmYqZi8zMis0NSpmKmYqZi8xMDI0KSpNYXRoLnNpbigyKmcpKygxNSpmKmYvMjU2KzQ1KmYqZipmLzEwMjQpKk1hdGguc2luKDQqZyktMzUqZipmKmYvMzA3MipNYXRoLnNpbig2KmcpKTt2YXIgdj1tKm8qKGwrKDEtaStzKSpsKmwqbC82Kyg1LTE4KmkraSppKzcyKnMtNTgqcikqbCpsKmwqbCpsLzEyMCkrNWU1LGI9bSoodStvKk1hdGgudGFuKGcpKihsKmwvMisoNS1pKzkqcys0KnMqcykqbCpsKmwqbC8yNCsoNjEtNTgqaStpKmkrNjAwKnMtMzMwKnIpKmwqbCpsKmwqbCpsLzcyMCkpO3JldHVybiBwPDAmJihiKz0xZTcpLHtub3J0aGluZzpNYXRoLnJvdW5kKGIpLGVhc3Rpbmc6TWF0aC5yb3VuZCh2KSx6b25lTnVtYmVyOmMsem9uZUxldHRlcjphKHApfX1mdW5jdGlvbiBzKHQpe3ZhciBlPXQubm9ydGhpbmcscj10LmVhc3Rpbmcsbj10LnpvbmVMZXR0ZXIsaT10LnpvbmVOdW1iZXI7aWYoaTwwfHxpPjYwKXJldHVybiBudWxsO3ZhciBhLGwsdSxoLGMscCxfLGQsZixtLGc9Ljk5OTYseT02Mzc4MTM3LHY9LjAwNjY5NDM4LGI9KDEtTWF0aC5zcXJ0KDEtdikpLygxK01hdGguc3FydCgxLXYpKSx4PXItNWU1LHc9ZTtuPCJOIiYmKHctPTFlNyksZD02KihpLTEpLTE4MCszLGE9di8oMS12KSxfPXcvZyxmPV8vKHkqKDEtdi80LTMqdip2LzY0LTUqdip2KnYvMjU2KSksbT1mKygzKmIvMi0yNypiKmIqYi8zMikqTWF0aC5zaW4oMipmKSsoMjEqYipiLzE2LTU1KmIqYipiKmIvMzIpKk1hdGguc2luKDQqZikrMTUxKmIqYipiLzk2Kk1hdGguc2luKDYqZiksbD15L01hdGguc3FydCgxLXYqTWF0aC5zaW4obSkqTWF0aC5zaW4obSkpLHU9TWF0aC50YW4obSkqTWF0aC50YW4obSksaD1hKk1hdGguY29zKG0pKk1hdGguY29zKG0pLGM9eSooMS12KS9NYXRoLnBvdygxLXYqTWF0aC5zaW4obSkqTWF0aC5zaW4obSksMS41KSxwPXgvKGwqZyk7dmFyIE09bS1sKk1hdGgudGFuKG0pL2MqKHAqcC8yLSg1KzMqdSsxMCpoLTQqaCpoLTkqYSkqcCpwKnAqcC8yNCsoNjErOTAqdSsyOTgqaCs0NSp1KnUtMjUyKmEtMypoKmgpKnAqcCpwKnAqcCpwLzcyMCk7TT1vKE0pO3ZhciBrPShwLSgxKzIqdStoKSpwKnAqcC82Kyg1LTIqaCsyOCp1LTMqaCpoKzgqYSsyNCp1KnUpKnAqcCpwKnAqcC8xMjApL01hdGguY29zKG0pO2s9ZCtvKGspO3ZhciBqO2lmKHQuYWNjdXJhY3kpe3ZhciBUPXMoe25vcnRoaW5nOnQubm9ydGhpbmcrdC5hY2N1cmFjeSxlYXN0aW5nOnQuZWFzdGluZyt0LmFjY3VyYWN5LHpvbmVMZXR0ZXI6dC56b25lTGV0dGVyLHpvbmVOdW1iZXI6dC56b25lTnVtYmVyfSk7aj17dG9wOlQubGF0LHJpZ2h0OlQubG9uLGJvdHRvbTpNLGxlZnQ6a319ZWxzZSBqPXtsYXQ6TSxsb246a307cmV0dXJuIGp9ZnVuY3Rpb24gYSh0KXt2YXIgZT0iWiI7cmV0dXJuIDg0Pj10JiZ0Pj03Mj9lPSJYIjo3Mj50JiZ0Pj02ND9lPSJXIjo2ND50JiZ0Pj01Nj9lPSJWIjo1Nj50JiZ0Pj00OD9lPSJVIjo0OD50JiZ0Pj00MD9lPSJUIjo0MD50JiZ0Pj0zMj9lPSJTIjozMj50JiZ0Pj0yND9lPSJSIjoyND50JiZ0Pj0xNj9lPSJRIjoxNj50JiZ0Pj04P2U9IlAiOjg+dCYmdD49MD9lPSJOIjowPnQmJnQ+PS04P2U9Ik0iOi04PnQmJnQ+PS0xNj9lPSJMIjotMTY+dCYmdD49LTI0P2U9IksiOi0yND50JiZ0Pj0tMzI/ZT0iSiI6LTMyPnQmJnQ+PS00MD9lPSJIIjotNDA+dCYmdD49LTQ4P2U9IkciOi00OD50JiZ0Pj0tNTY/ZT0iRiI6LTU2PnQmJnQ+PS02ND9lPSJFIjotNjQ+dCYmdD49LTcyP2U9IkQiOi03Mj50JiZ0Pj0tODAmJihlPSJDIiksZX1mdW5jdGlvbiBsKHQsZSl7dmFyIHI9IjAwMDAwIit0LmVhc3Rpbmcsbj0iMDAwMDAiK3Qubm9ydGhpbmc7cmV0dXJuIHQuem9uZU51bWJlcit0LnpvbmVMZXR0ZXIrdSh0LmVhc3RpbmcsdC5ub3J0aGluZyx0LnpvbmVOdW1iZXIpK3Iuc3Vic3RyKHIubGVuZ3RoLTUsZSkrbi5zdWJzdHIobi5sZW5ndGgtNSxlKX1mdW5jdGlvbiB1KHQsZSxyKXt2YXIgbj1oKHIpLG89TWF0aC5mbG9vcih0LzFlNSksaT1NYXRoLmZsb29yKGUvMWU1KSUyMDtyZXR1cm4gYyhvLGksbil9ZnVuY3Rpb24gaCh0KXt2YXIgZT10JW07cmV0dXJuIDA9PT1lJiYoZT1tKSxlfWZ1bmN0aW9uIGModCxlLHIpe3ZhciBuPXItMSxvPWcuY2hhckNvZGVBdChuKSxpPXkuY2hhckNvZGVBdChuKSxzPW8rdC0xLGE9aStlLGw9ITE7cz5NJiYocz1zLU0rdi0xLGw9ITApLChzPT09Ynx8bzxiJiZzPmJ8fChzPmJ8fG88YikmJmwpJiZzKyssKHM9PT14fHxvPHgmJnM+eHx8KHM+eHx8bzx4KSYmbCkmJihzKysscz09PWImJnMrKykscz5NJiYocz1zLU0rdi0xKSxhPnc/KGE9YS13K3YtMSxsPSEwKTpsPSExLChhPT09Ynx8aTxiJiZhPmJ8fChhPmJ8fGk8YikmJmwpJiZhKyssKGE9PT14fHxpPHgmJmE+eHx8KGE+eHx8aTx4KSYmbCkmJihhKyssYT09PWImJmErKyksYT53JiYoYT1hLXcrdi0xKTt2YXIgdT1TdHJpbmcuZnJvbUNoYXJDb2RlKHMpK1N0cmluZy5mcm9tQ2hhckNvZGUoYSk7cmV0dXJuIHV9ZnVuY3Rpb24gcCh0KXtpZih0JiYwPT09dC5sZW5ndGgpdGhyb3ciTUdSU1BvaW50IGNvdmVydGluZyBmcm9tIG5vdGhpbmciO2Zvcih2YXIgZSxyPXQubGVuZ3RoLG49bnVsbCxvPSIiLGk9MDshL1tBLVpdLy50ZXN0KGU9dC5jaGFyQXQoaSkpOyl7aWYoaT49Mil0aHJvdyJNR1JTUG9pbnQgYmFkIGNvbnZlcnNpb24gZnJvbTogIit0O28rPWUsaSsrfXZhciBzPXBhcnNlSW50KG8sMTApO2lmKDA9PT1pfHxpKzM+cil0aHJvdyJNR1JTUG9pbnQgYmFkIGNvbnZlcnNpb24gZnJvbTogIit0O3ZhciBhPXQuY2hhckF0KGkrKyk7aWYoYTw9IkEifHwiQiI9PT1hfHwiWSI9PT1hfHxhPj0iWiJ8fCJJIj09PWF8fCJPIj09PWEpdGhyb3ciTUdSU1BvaW50IHpvbmUgbGV0dGVyICIrYSsiIG5vdCBoYW5kbGVkOiAiK3Q7bj10LnN1YnN0cmluZyhpLGkrPTIpO2Zvcih2YXIgbD1oKHMpLHU9XyhuLmNoYXJBdCgwKSxsKSxjPWQobi5jaGFyQXQoMSksbCk7YzxmKGEpOyljKz0yZTY7dmFyIHA9ci1pO2lmKHAlMiE9PTApdGhyb3ciTUdSU1BvaW50IGhhcyB0byBoYXZlIGFuIGV2ZW4gbnVtYmVyIFxub2YgZGlnaXRzIGFmdGVyIHRoZSB6b25lIGxldHRlciBhbmQgdHdvIDEwMGttIGxldHRlcnMgLSBmcm9udCBcbmhhbGYgZm9yIGVhc3RpbmcgbWV0ZXJzLCBzZWNvbmQgaGFsZiBmb3IgXG5ub3J0aGluZyBtZXRlcnMiK3Q7dmFyIG0sZyx5LHYsYix4PXAvMix3PTAsTT0wO3JldHVybiB4PjAmJihtPTFlNS9NYXRoLnBvdygxMCx4KSxnPXQuc3Vic3RyaW5nKGksaSt4KSx3PXBhcnNlRmxvYXQoZykqbSx5PXQuc3Vic3RyaW5nKGkreCksTT1wYXJzZUZsb2F0KHkpKm0pLHY9dyt1LGI9TStjLHtlYXN0aW5nOnYsbm9ydGhpbmc6Yix6b25lTGV0dGVyOmEsem9uZU51bWJlcjpzLGFjY3VyYWN5Om19fWZ1bmN0aW9uIF8odCxlKXtmb3IodmFyIHI9Zy5jaGFyQ29kZUF0KGUtMSksbj0xZTUsbz0hMTtyIT09dC5jaGFyQ29kZUF0KDApOyl7aWYocisrLHI9PT1iJiZyKysscj09PXgmJnIrKyxyPk0pe2lmKG8pdGhyb3ciQmFkIGNoYXJhY3RlcjogIit0O3I9dixvPSEwfW4rPTFlNX1yZXR1cm4gbn1mdW5jdGlvbiBkKHQsZSl7aWYodD4iViIpdGhyb3ciTUdSU1BvaW50IGdpdmVuIGludmFsaWQgTm9ydGhpbmcgIit0O2Zvcih2YXIgcj15LmNoYXJDb2RlQXQoZS0xKSxuPTAsbz0hMTtyIT09dC5jaGFyQ29kZUF0KDApOyl7aWYocisrLHI9PT1iJiZyKysscj09PXgmJnIrKyxyPncpe2lmKG8pdGhyb3ciQmFkIGNoYXJhY3RlcjogIit0O3I9dixvPSEwfW4rPTFlNX1yZXR1cm4gbn1mdW5jdGlvbiBmKHQpe3ZhciBlO3N3aXRjaCh0KXtjYXNlIkMiOmU9MTFlNTticmVhaztjYXNlIkQiOmU9MmU2O2JyZWFrO2Nhc2UiRSI6ZT0yOGU1O2JyZWFrO2Nhc2UiRiI6ZT0zN2U1O2JyZWFrO2Nhc2UiRyI6ZT00NmU1O2JyZWFrO2Nhc2UiSCI6ZT01NWU1O2JyZWFrO2Nhc2UiSiI6ZT02NGU1O2JyZWFrO2Nhc2UiSyI6ZT03M2U1O2JyZWFrO2Nhc2UiTCI6ZT04MmU1O2JyZWFrO2Nhc2UiTSI6ZT05MWU1O2JyZWFrO2Nhc2UiTiI6ZT0wO2JyZWFrO2Nhc2UiUCI6ZT04ZTU7YnJlYWs7Y2FzZSJRIjplPTE3ZTU7YnJlYWs7Y2FzZSJSIjplPTI2ZTU7YnJlYWs7Y2FzZSJTIjplPTM1ZTU7YnJlYWs7Y2FzZSJUIjplPTQ0ZTU7YnJlYWs7Y2FzZSJVIjplPTUzZTU7YnJlYWs7Y2FzZSJWIjplPTYyZTU7YnJlYWs7Y2FzZSJXIjplPTdlNjticmVhaztjYXNlIlgiOmU9NzllNTticmVhaztkZWZhdWx0OmU9LTF9aWYoZT49MClyZXR1cm4gZTt0aHJvdyJJbnZhbGlkIHpvbmUgbGV0dGVyOiAiK3R9dmFyIG09NixnPSJBSlNBSlMiLHk9IkFGQUZBRiIsdj02NSxiPTczLHg9Nzksdz04NixNPTkwO3IuZm9yd2FyZD1mdW5jdGlvbih0LGUpe3JldHVybiBlPWV8fDUsbChpKHtsYXQ6dFsxXSxsb246dFswXX0pLGUpfSxyLmludmVyc2U9ZnVuY3Rpb24odCl7dmFyIGU9cyhwKHQudG9VcHBlckNhc2UoKSkpO3JldHVybiBlLmxhdCYmZS5sb24/W2UubG9uLGUubGF0LGUubG9uLGUubGF0XTpbZS5sZWZ0LGUuYm90dG9tLGUucmlnaHQsZS50b3BdfSxyLnRvUG9pbnQ9ZnVuY3Rpb24odCl7dmFyIGU9cyhwKHQudG9VcHBlckNhc2UoKSkpO3JldHVybiBlLmxhdCYmZS5sb24/W2UubG9uLGUubGF0XTpbKGUubGVmdCtlLnJpZ2h0KS8yLChlLnRvcCtlLmJvdHRvbSkvMl19fSx7fV0sInByb2o0L3BhY2thZ2UuanNvbiI6W2Z1bmN0aW9uKHQsZSxyKXtlLmV4cG9ydHM9e25hbWU6InByb2o0Iix2ZXJzaW9uOiIyLjMuMTUiLGRlc2NyaXB0aW9uOiJQcm9qNGpzIGlzIGEgSmF2YVNjcmlwdCBsaWJyYXJ5IHRvIHRyYW5zZm9ybSBwb2ludCBjb29yZGluYXRlcyBmcm9tIG9uZSBjb29yZGluYXRlIHN5c3RlbSB0byBhbm90aGVyLCBpbmNsdWRpbmcgZGF0dW0gdHJhbnNmb3JtYXRpb25zLiIsbWFpbjoibGliL2luZGV4LmpzIixkaXJlY3Rvcmllczp7dGVzdDoidGVzdCIsZG9jOiJkb2NzIn0sc2NyaXB0czp7dGVzdDoiLi9ub2RlX21vZHVsZXMvaXN0YW5idWwvbGliL2NsaS5qcyB0ZXN0IC4vbm9kZV9tb2R1bGVzL21vY2hhL2Jpbi9fbW9jaGEgdGVzdC90ZXN0LmpzIn0scmVwb3NpdG9yeTp7dHlwZToiZ2l0Iix1cmw6ImdpdDovL2dpdGh1Yi5jb20vcHJvajRqcy9wcm9qNGpzLmdpdCJ9LGF1dGhvcjoiIixsaWNlbnNlOiJNSVQiLGphbTp7bWFpbjoiZGlzdC9wcm9qNC5qcyIsaW5jbHVkZTpbImRpc3QvcHJvajQuanMiLCJSRUFETUUubWQiLCJBVVRIT1JTIiwiTElDRU5TRS5tZCJdfSxkZXZEZXBlbmRlbmNpZXM6eyJncnVudC1jbGkiOiJ+MC4xLjEzIixncnVudDoifjAuNC4yIiwiZ3J1bnQtY29udHJpYi1jb25uZWN0IjoifjAuNi4wIiwiZ3J1bnQtY29udHJpYi1qc2hpbnQiOiJ+MC44LjAiLGNoYWk6In4xLjguMSIsbW9jaGE6In4xLjE3LjEiLCJncnVudC1tb2NoYS1waGFudG9tanMiOiJ+MC40LjAiLGJyb3dzZXJpZnk6In4xMi4wLjEiLCJncnVudC1icm93c2VyaWZ5IjoifjQuMC4xIiwiZ3J1bnQtY29udHJpYi11Z2xpZnkiOiJ+MC4xMS4xIixjdXJsOiJnaXQ6Ly9naXRodWIuY29tL2N1am9qcy9jdXJsLmdpdCIsaXN0YW5idWw6In4wLjIuNCIsdGluOiJ+MC40LjAifSxkZXBlbmRlbmNpZXM6e21ncnM6In4wLjAuMiJ9LGNvbnRyaWJ1dG9yczpbe25hbWU6Ik1pa2UgQWRhaXIiLGVtYWlsOiJtYWRhaXJAZG1zb2x1dGlvbnMuY2EifSx7bmFtZToiUmljaGFyZCBHcmVlbndvb2QiLGVtYWlsOiJyaWNoQGdyZWVud29vZG1hcC5jb20ifSx7bmFtZToiQ2FsdmluIE1ldGNhbGYiLGVtYWlsOiJjYWx2aW4ubWV0Y2FsZkBnbWFpbC5jb20ifSx7bmFtZToiUmljaGFyZCBNYXJzZGVuIix1cmw6Imh0dHA6Ly93d3cud2lud2FlZC5jb20ifSx7bmFtZToiVC4gTWl0dGFuIn0se25hbWU6IkQuIFN0ZWlud2FuZCJ9LHtuYW1lOiJTLiBOZWxzb24ifV0sZ2l0SGVhZDoiOWZhNTI0OWMxZjQxODNkNWRkZWUzYzQ3OTNkZmQ3YjlmMjlmMTg4NiIsYnVnczp7dXJsOiJodHRwczovL2dpdGh1Yi5jb20vcHJvajRqcy9wcm9qNGpzL2lzc3VlcyJ9LGhvbWVwYWdlOiJodHRwczovL2dpdGh1Yi5jb20vcHJvajRqcy9wcm9qNGpzI3JlYWRtZSIsX2lkOiJwcm9qNEAyLjMuMTUiLF9zaGFzdW06IjVhZDA2ZThiY2EzMGJlMGZmYTM4OWE0OWU0NTY1ZjUxZjA2ZDA4OWUiLF9mcm9tOiJwcm9qNEA+PTIuMy4xMCA8My4wLjAiLF9ucG1WZXJzaW9uOiIzLjguNiIsX25vZGVWZXJzaW9uOiI2LjEuMCIsX25wbVVzZXI6e25hbWU6ImFob2NldmFyIixlbWFpbDoiYW5kcmVhcy5ob2NldmFyQGdtYWlsLmNvbSJ9LGRpc3Q6e3NoYXN1bToiNWFkMDZlOGJjYTMwYmUwZmZhMzg5YTQ5ZTQ1NjVmNTFmMDZkMDg5ZSIsdGFyYmFsbDoiaHR0cHM6Ly9yZWdpc3RyeS5ucG1qcy5vcmcvcHJvajQvLS9wcm9qNC0yLjMuMTUudGd6In0sbWFpbnRhaW5lcnM6W3tuYW1lOiJjd21tYSIsZW1haWw6ImNhbHZpbi5tZXRjYWxmQGdtYWlsLmNvbSJ9LHtuYW1lOiJhaG9jZXZhciIsZW1haWw6ImFuZHJlYXMuaG9jZXZhckBnbWFpbC5jb20ifV0sX25wbU9wZXJhdGlvbmFsSW50ZXJuYWw6e2hvc3Q6InBhY2thZ2VzLTEyLXdlc3QuaW50ZXJuYWwubnBtanMuY29tIix0bXA6InRtcC9wcm9qNC0yLjMuMTUudGd6XzE0NzE4MDgyNjI1NDZfMC42NzUyMDYwMzM3NDU3ODA2In0sX3Jlc29sdmVkOiJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9wcm9qNC8tL3Byb2o0LTIuMy4xNS50Z3oifX0se31dLHJidXNoOltmdW5jdGlvbih0LGUscil7InVzZSBzdHJpY3QiO2Z1bmN0aW9uIG4odCxlKXtyZXR1cm4gdGhpcyBpbnN0YW5jZW9mIG4/KHRoaXMuX21heEVudHJpZXM9TWF0aC5tYXgoNCx0fHw5KSx0aGlzLl9taW5FbnRyaWVzPU1hdGgubWF4KDIsTWF0aC5jZWlsKC40KnRoaXMuX21heEVudHJpZXMpKSxlJiZ0aGlzLl9pbml0Rm9ybWF0KGUpLHZvaWQgdGhpcy5jbGVhcigpKTpuZXcgbih0LGUpfWZ1bmN0aW9uIG8odCxlLHIpe2lmKCFyKXJldHVybiBlLmluZGV4T2YodCk7Zm9yKHZhciBuPTA7bjxlLmxlbmd0aDtuKyspaWYocih0LGVbbl0pKXJldHVybiBuO3JldHVybi0xfWZ1bmN0aW9uIGkodCxlKXtzKHQsMCx0LmNoaWxkcmVuLmxlbmd0aCxlLHQpfWZ1bmN0aW9uIHModCxlLHIsbixvKXtvfHwobz1tKG51bGwpKSxvLm1pblg9MS8wLG8ubWluWT0xLzAsby5tYXhYPS0oMS8wKSxvLm1heFk9LSgxLzApO2Zvcih2YXIgaSxzPWU7czxyO3MrKylpPXQuY2hpbGRyZW5bc10sYShvLHQubGVhZj9uKGkpOmkpO3JldHVybiBvfWZ1bmN0aW9uIGEodCxlKXtyZXR1cm4gdC5taW5YPU1hdGgubWluKHQubWluWCxlLm1pblgpLHQubWluWT1NYXRoLm1pbih0Lm1pblksZS5taW5ZKSx0Lm1heFg9TWF0aC5tYXgodC5tYXhYLGUubWF4WCksdC5tYXhZPU1hdGgubWF4KHQubWF4WSxlLm1heFkpLHR9ZnVuY3Rpb24gbCh0LGUpe3JldHVybiB0Lm1pblgtZS5taW5YfWZ1bmN0aW9uIHUodCxlKXtyZXR1cm4gdC5taW5ZLWUubWluWX1mdW5jdGlvbiBoKHQpe3JldHVybih0Lm1heFgtdC5taW5YKSoodC5tYXhZLXQubWluWSl9ZnVuY3Rpb24gYyh0KXtyZXR1cm4gdC5tYXhYLXQubWluWCsodC5tYXhZLXQubWluWSl9ZnVuY3Rpb24gcCh0LGUpe3JldHVybihNYXRoLm1heChlLm1heFgsdC5tYXhYKS1NYXRoLm1pbihlLm1pblgsdC5taW5YKSkqKE1hdGgubWF4KGUubWF4WSx0Lm1heFkpLU1hdGgubWluKGUubWluWSx0Lm1pblkpKX1mdW5jdGlvbiBfKHQsZSl7dmFyIHI9TWF0aC5tYXgodC5taW5YLGUubWluWCksbj1NYXRoLm1heCh0Lm1pblksZS5taW5ZKSxvPU1hdGgubWluKHQubWF4WCxlLm1heFgpLGk9TWF0aC5taW4odC5tYXhZLGUubWF4WSk7cmV0dXJuIE1hdGgubWF4KDAsby1yKSpNYXRoLm1heCgwLGktbil9ZnVuY3Rpb24gZCh0LGUpe3JldHVybiB0Lm1pblg8PWUubWluWCYmdC5taW5ZPD1lLm1pblkmJmUubWF4WDw9dC5tYXhYJiZlLm1heFk8PXQubWF4WX1mdW5jdGlvbiBmKHQsZSl7cmV0dXJuIGUubWluWDw9dC5tYXhYJiZlLm1pblk8PXQubWF4WSYmZS5tYXhYPj10Lm1pblgmJmUubWF4WT49dC5taW5ZfWZ1bmN0aW9uIG0odCl7cmV0dXJue2NoaWxkcmVuOnQsaGVpZ2h0OjEsbGVhZjohMCxtaW5YOjEvMCxtaW5ZOjEvMCxtYXhYOi0oMS8wKSxtYXhZOi0oMS8wKX19ZnVuY3Rpb24gZyh0LGUscixuLG8pe2Zvcih2YXIgaSxzPVtlLHJdO3MubGVuZ3RoOylyPXMucG9wKCksZT1zLnBvcCgpLHItZTw9bnx8KGk9ZStNYXRoLmNlaWwoKHItZSkvbi8yKSpuLHkodCxpLGUscixvKSxzLnB1c2goZSxpLGkscikpfWUuZXhwb3J0cz1uO3ZhciB5PXQoInF1aWNrc2VsZWN0Iik7bi5wcm90b3R5cGU9e2FsbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLl9hbGwodGhpcy5kYXRhLFtdKX0sc2VhcmNoOmZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuZGF0YSxyPVtdLG49dGhpcy50b0JCb3g7aWYoIWYodCxlKSlyZXR1cm4gcjtmb3IodmFyIG8saSxzLGEsbD1bXTtlOyl7Zm9yKG89MCxpPWUuY2hpbGRyZW4ubGVuZ3RoO288aTtvKyspcz1lLmNoaWxkcmVuW29dLGE9ZS5sZWFmP24ocyk6cyxmKHQsYSkmJihlLmxlYWY/ci5wdXNoKHMpOmQodCxhKT90aGlzLl9hbGwocyxyKTpsLnB1c2gocykpO2U9bC5wb3AoKX1yZXR1cm4gcn0sY29sbGlkZXM6ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5kYXRhLHI9dGhpcy50b0JCb3g7aWYoIWYodCxlKSlyZXR1cm4hMTtmb3IodmFyIG4sbyxpLHMsYT1bXTtlOyl7Zm9yKG49MCxvPWUuY2hpbGRyZW4ubGVuZ3RoO248bztuKyspaWYoaT1lLmNoaWxkcmVuW25dLHM9ZS5sZWFmP3IoaSk6aSxmKHQscykpe2lmKGUubGVhZnx8ZCh0LHMpKXJldHVybiEwO2EucHVzaChpKX1lPWEucG9wKCl9cmV0dXJuITF9LGxvYWQ6ZnVuY3Rpb24odCl7aWYoIXR8fCF0Lmxlbmd0aClyZXR1cm4gdGhpcztpZih0Lmxlbmd0aDx0aGlzLl9taW5FbnRyaWVzKXtmb3IodmFyIGU9MCxyPXQubGVuZ3RoO2U8cjtlKyspdGhpcy5pbnNlcnQodFtlXSk7cmV0dXJuIHRoaXN9dmFyIG49dGhpcy5fYnVpbGQodC5zbGljZSgpLDAsdC5sZW5ndGgtMSwwKTtpZih0aGlzLmRhdGEuY2hpbGRyZW4ubGVuZ3RoKWlmKHRoaXMuZGF0YS5oZWlnaHQ9PT1uLmhlaWdodCl0aGlzLl9zcGxpdFJvb3QodGhpcy5kYXRhLG4pO2Vsc2V7aWYodGhpcy5kYXRhLmhlaWdodDxuLmhlaWdodCl7dmFyIG89dGhpcy5kYXRhO3RoaXMuZGF0YT1uLG49b310aGlzLl9pbnNlcnQobix0aGlzLmRhdGEuaGVpZ2h0LW4uaGVpZ2h0LTEsITApfWVsc2UgdGhpcy5kYXRhPW47cmV0dXJuIHRoaXN9LGluc2VydDpmdW5jdGlvbih0KXtyZXR1cm4gdCYmdGhpcy5faW5zZXJ0KHQsdGhpcy5kYXRhLmhlaWdodC0xKSx0aGlzfSxjbGVhcjpmdW5jdGlvbigpe3JldHVybiB0aGlzLmRhdGE9bShbXSksdGhpc30scmVtb3ZlOmZ1bmN0aW9uKHQsZSl7aWYoIXQpcmV0dXJuIHRoaXM7Zm9yKHZhciByLG4saSxzLGE9dGhpcy5kYXRhLGw9dGhpcy50b0JCb3godCksdT1bXSxoPVtdO2F8fHUubGVuZ3RoOyl7aWYoYXx8KGE9dS5wb3AoKSxuPXVbdS5sZW5ndGgtMV0scj1oLnBvcCgpLHM9ITApLGEubGVhZiYmKGk9byh0LGEuY2hpbGRyZW4sZSksaSE9PS0xKSlyZXR1cm4gYS5jaGlsZHJlbi5zcGxpY2UoaSwxKSx1LnB1c2goYSksdGhpcy5fY29uZGVuc2UodSksdGhpcztzfHxhLmxlYWZ8fCFkKGEsbCk/bj8ocisrLGE9bi5jaGlsZHJlbltyXSxzPSExKTphPW51bGw6KHUucHVzaChhKSxoLnB1c2gocikscj0wLG49YSxhPWEuY2hpbGRyZW5bMF0pfXJldHVybiB0aGlzfSx0b0JCb3g6ZnVuY3Rpb24odCl7cmV0dXJuIHR9LGNvbXBhcmVNaW5YOmwsY29tcGFyZU1pblk6dSx0b0pTT046ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kYXRhfSxmcm9tSlNPTjpmdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5kYXRhPXQsdGhpc30sX2FsbDpmdW5jdGlvbih0LGUpe2Zvcih2YXIgcj1bXTt0Oyl0LmxlYWY/ZS5wdXNoLmFwcGx5KGUsdC5jaGlsZHJlbik6ci5wdXNoLmFwcGx5KHIsdC5jaGlsZHJlbiksdD1yLnBvcCgpO3JldHVybiBlfSxfYnVpbGQ6ZnVuY3Rpb24odCxlLHIsbil7dmFyIG8scz1yLWUrMSxhPXRoaXMuX21heEVudHJpZXM7aWYoczw9YSlyZXR1cm4gbz1tKHQuc2xpY2UoZSxyKzEpKSxpKG8sdGhpcy50b0JCb3gpLG87bnx8KG49TWF0aC5jZWlsKE1hdGgubG9nKHMpL01hdGgubG9nKGEpKSxhPU1hdGguY2VpbChzL01hdGgucG93KGEsbi0xKSkpLG89bShbXSksby5sZWFmPSExLG8uaGVpZ2h0PW47dmFyIGwsdSxoLGMscD1NYXRoLmNlaWwocy9hKSxfPXAqTWF0aC5jZWlsKE1hdGguc3FydChhKSk7Zm9yKGcodCxlLHIsXyx0aGlzLmNvbXBhcmVNaW5YKSxsPWU7bDw9cjtsKz1fKWZvcihoPU1hdGgubWluKGwrXy0xLHIpLGcodCxsLGgscCx0aGlzLmNvbXBhcmVNaW5ZKSx1PWw7dTw9aDt1Kz1wKWM9TWF0aC5taW4odStwLTEsaCksby5jaGlsZHJlbi5wdXNoKHRoaXMuX2J1aWxkKHQsdSxjLG4tMSkpO3JldHVybiBpKG8sdGhpcy50b0JCb3gpLG99LF9jaG9vc2VTdWJ0cmVlOmZ1bmN0aW9uKHQsZSxyLG4pe2Zvcih2YXIgbyxpLHMsYSxsLHUsYyxfOzspe2lmKG4ucHVzaChlKSxlLmxlYWZ8fG4ubGVuZ3RoLTE9PT1yKWJyZWFrO2ZvcihjPV89MS8wLG89MCxpPWUuY2hpbGRyZW4ubGVuZ3RoO288aTtvKyspcz1lLmNoaWxkcmVuW29dLGw9aChzKSx1PXAodCxzKS1sLHU8Xz8oXz11LGM9bDxjP2w6YyxhPXMpOnU9PT1fJiZsPGMmJihjPWwsYT1zKTtlPWF8fGUuY2hpbGRyZW5bMF19cmV0dXJuIGV9LF9pbnNlcnQ6ZnVuY3Rpb24odCxlLHIpe3ZhciBuPXRoaXMudG9CQm94LG89cj90Om4odCksaT1bXSxzPXRoaXMuX2Nob29zZVN1YnRyZWUobyx0aGlzLmRhdGEsZSxpKTtmb3Iocy5jaGlsZHJlbi5wdXNoKHQpLGEocyxvKTtlPj0wJiZpW2VdLmNoaWxkcmVuLmxlbmd0aD50aGlzLl9tYXhFbnRyaWVzOyl0aGlzLl9zcGxpdChpLGUpLGUtLTt0aGlzLl9hZGp1c3RQYXJlbnRCQm94ZXMobyxpLGUpfSxfc3BsaXQ6ZnVuY3Rpb24odCxlKXt2YXIgcj10W2VdLG49ci5jaGlsZHJlbi5sZW5ndGgsbz10aGlzLl9taW5FbnRyaWVzO3RoaXMuX2Nob29zZVNwbGl0QXhpcyhyLG8sbik7dmFyIHM9dGhpcy5fY2hvb3NlU3BsaXRJbmRleChyLG8sbiksYT1tKHIuY2hpbGRyZW4uc3BsaWNlKHMsci5jaGlsZHJlbi5sZW5ndGgtcykpO2EuaGVpZ2h0PXIuaGVpZ2h0LGEubGVhZj1yLmxlYWYsaShyLHRoaXMudG9CQm94KSxpKGEsdGhpcy50b0JCb3gpLGU/dFtlLTFdLmNoaWxkcmVuLnB1c2goYSk6dGhpcy5fc3BsaXRSb290KHIsYSl9LF9zcGxpdFJvb3Q6ZnVuY3Rpb24odCxlKXt0aGlzLmRhdGE9bShbdCxlXSksdGhpcy5kYXRhLmhlaWdodD10LmhlaWdodCsxLHRoaXMuZGF0YS5sZWFmPSExLGkodGhpcy5kYXRhLHRoaXMudG9CQm94KX0sX2Nob29zZVNwbGl0SW5kZXg6ZnVuY3Rpb24odCxlLHIpe3ZhciBuLG8saSxhLGwsdSxjLHA7Zm9yKHU9Yz0xLzAsbj1lO248PXItZTtuKyspbz1zKHQsMCxuLHRoaXMudG9CQm94KSxpPXModCxuLHIsdGhpcy50b0JCb3gpLGE9XyhvLGkpLGw9aChvKStoKGkpLGE8dT8odT1hLHA9bixjPWw8Yz9sOmMpOmE9PT11JiZsPGMmJihjPWwscD1uKTtyZXR1cm4gcH0sX2Nob29zZVNwbGl0QXhpczpmdW5jdGlvbih0LGUscil7dmFyIG49dC5sZWFmP3RoaXMuY29tcGFyZU1pblg6bCxvPXQubGVhZj90aGlzLmNvbXBhcmVNaW5ZOnUsaT10aGlzLl9hbGxEaXN0TWFyZ2luKHQsZSxyLG4pLHM9dGhpcy5fYWxsRGlzdE1hcmdpbih0LGUscixvKTtpPHMmJnQuY2hpbGRyZW4uc29ydChuKX0sX2FsbERpc3RNYXJnaW46ZnVuY3Rpb24odCxlLHIsbil7dC5jaGlsZHJlbi5zb3J0KG4pO3ZhciBvLGksbD10aGlzLnRvQkJveCx1PXModCwwLGUsbCksaD1zKHQsci1lLHIsbCkscD1jKHUpK2MoaCk7Zm9yKG89ZTtvPHItZTtvKyspaT10LmNoaWxkcmVuW29dLGEodSx0LmxlYWY/bChpKTppKSxwKz1jKHUpO2ZvcihvPXItZS0xO28+PWU7by0tKWk9dC5jaGlsZHJlbltvXSxhKGgsdC5sZWFmP2woaSk6aSkscCs9YyhoKTtyZXR1cm4gcH0sX2FkanVzdFBhcmVudEJCb3hlczpmdW5jdGlvbih0LGUscil7Zm9yKHZhciBuPXI7bj49MDtuLS0pYShlW25dLHQpfSxfY29uZGVuc2U6ZnVuY3Rpb24odCl7Zm9yKHZhciBlLHI9dC5sZW5ndGgtMTtyPj0wO3ItLSkwPT09dFtyXS5jaGlsZHJlbi5sZW5ndGg/cj4wPyhlPXRbci0xXS5jaGlsZHJlbixlLnNwbGljZShlLmluZGV4T2YodFtyXSksMSkpOnRoaXMuY2xlYXIoKTppKHRbcl0sdGhpcy50b0JCb3gpfSxfaW5pdEZvcm1hdDpmdW5jdGlvbih0KXt2YXIgZT1bInJldHVybiBhIiwiIC0gYiIsIjsiXTt0aGlzLmNvbXBhcmVNaW5YPW5ldyBGdW5jdGlvbigiYSIsImIiLGUuam9pbih0WzBdKSksdGhpcy5jb21wYXJlTWluWT1uZXcgRnVuY3Rpb24oImEiLCJiIixlLmpvaW4odFsxXSkpLHRoaXMudG9CQm94PW5ldyBGdW5jdGlvbigiYSIsInJldHVybiB7bWluWDogYSIrdFswXSsiLCBtaW5ZOiBhIit0WzFdKyIsIG1heFg6IGEiK3RbMl0rIiwgbWF4WTogYSIrdFszXSsifTsiKX19fSx7cXVpY2tzZWxlY3Q6InJidXNoL25vZGVfbW9kdWxlcy9xdWlja3NlbGVjdC9pbmRleCJ9XSwicmJ1c2gvbm9kZV9tb2R1bGVzL3F1aWNrc2VsZWN0L2luZGV4IjpbZnVuY3Rpb24odCxlLHIpeyJ1c2Ugc3RyaWN0IjtmdW5jdGlvbiBuKHQsZSxyLHMsYSl7Zm9yKHI9cnx8MCxzPXN8fHQubGVuZ3RoLTEsYT1hfHxpO3M+cjspe2lmKHMtcj42MDApe3ZhciBsPXMtcisxLHU9ZS1yKzEsaD1NYXRoLmxvZyhsKSxjPS41Kk1hdGguZXhwKDIqaC8zKSxwPS41Kk1hdGguc3FydChoKmMqKGwtYykvbCkqKHUtbC8yPDA/LTE6MSksXz1NYXRoLm1heChyLE1hdGguZmxvb3IoZS11KmMvbCtwKSksZD1NYXRoLm1pbihzLE1hdGguZmxvb3IoZSsobC11KSpjL2wrcCkpO24odCxlLF8sZCxhKX12YXIgZj10W2VdLG09cixnPXM7Zm9yKG8odCxyLGUpLGEodFtzXSxmKT4wJiZvKHQscixzKTttPGc7KXtmb3Iobyh0LG0sZyksbSsrLGctLTthKHRbbV0sZik8MDspbSsrO2Zvcig7YSh0W2ddLGYpPjA7KWctLX0wPT09YSh0W3JdLGYpP28odCxyLGcpOihnKyssbyh0LGcscykpLGc8PWUmJihyPWcrMSksZTw9ZyYmKHM9Zy0xKX19ZnVuY3Rpb24gbyh0LGUscil7dmFyIG49dFtlXTt0W2VdPXRbcl0sdFtyXT1ufWZ1bmN0aW9uIGkodCxlKXtyZXR1cm4gdDxlPy0xOnQ+ZT8xOjB9ZS5leHBvcnRzPW59LHt9XSxzcHJpbnRmOltmdW5jdGlvbih0LGUscil7LyoqCnNwcmludGYoKSBmb3IgSmF2YVNjcmlwdCAwLjctYmV0YTEKaHR0cDovL3d3dy5kaXZlaW50b2phdmFzY3JpcHQuY29tL3Byb2plY3RzL2phdmFzY3JpcHQtc3ByaW50ZgoKQ29weXJpZ2h0IChjKSBBbGV4YW5kcnUgTWFyYXN0ZWFudSA8YWxleGFob2xpYyBbYXQpIGdtYWlsIChkb3RdIGNvbT4KQWxsIHJpZ2h0cyByZXNlcnZlZC4KClJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dAptb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDoKICAgICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQKICAgICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLgogICAgKiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodAogICAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlCiAgICAgIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uCiAgICAqIE5laXRoZXIgdGhlIG5hbWUgb2Ygc3ByaW50ZigpIGZvciBKYXZhU2NyaXB0IG5vciB0aGUKICAgICAgbmFtZXMgb2YgaXRzIGNvbnRyaWJ1dG9ycyBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMKICAgICAgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgd2l0aG91dCBzcGVjaWZpYyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uCgpUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTICJBUyBJUyIgQU5ECkFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVECldBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUKRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgQWxleGFuZHJ1IE1hcmFzdGVhbnUgQkUgTElBQkxFIEZPUiBBTlkKRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMKKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SIFNFUlZJQ0VTOwpMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSIENBVVNFRCBBTkQKT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQKKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVMKU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuCgoKQ2hhbmdlbG9nOgoyMDEwLjExLjA3IC0gMC43LWJldGExLW5vZGUKICAtIGNvbnZlcnRlZCBpdCB0byBhIG5vZGUuanMgY29tcGF0aWJsZSBtb2R1bGUKCjIwMTAuMDkuMDYgLSAwLjctYmV0YTEKICAtIGZlYXR1cmVzOiB2c3ByaW50Ziwgc3VwcG9ydCBmb3IgbmFtZWQgcGxhY2Vob2xkZXJzCiAgLSBlbmhhbmNlbWVudHM6IGZvcm1hdCBjYWNoZSwgcmVkdWNlZCBnbG9iYWwgbmFtZXNwYWNlIHBvbGx1dGlvbgoKMjAxMC4wNS4yMiAtIDAuNjoKIC0gcmV2ZXJ0ZWQgdG8gMC40IGFuZCBmaXhlZCB0aGUgYnVnIHJlZ2FyZGluZyB0aGUgc2lnbiBvZiB0aGUgbnVtYmVyIDAKIE5vdGU6CiBUaGFua3MgdG8gUmFwaGFlbCBQaWd1bGxhIDxyYXBoIChhdF0gbjNyZCBbZG90KSBvcmc+IChodHRwOi8vd3d3Lm4zcmQub3JnLykKIHdobyB3YXJuZWQgbWUgYWJvdXQgYSBidWcgaW4gMC41LCBJIGRpc2NvdmVyZWQgdGhhdCB0aGUgbGFzdCB1cGRhdGUgd2FzCiBhIHJlZ3Jlc3MuIEkgYXBwb2xvZ2l6ZSBmb3IgdGhhdC4KCjIwMTAuMDUuMDkgLSAwLjU6CiAtIGJ1ZyBmaXg6IDAgaXMgbm93IHByZWNlZWRlZCB3aXRoIGEgKyBzaWduCiAtIGJ1ZyBmaXg6IHRoZSBzaWduIHdhcyBub3QgYXQgdGhlIHJpZ2h0IHBvc2l0aW9uIG9uIHBhZGRlZCByZXN1bHRzIChLYW1hbCBBYmRhbGkpCiAtIHN3aXRjaGVkIGZyb20gR1BMIHRvIEJTRCBsaWNlbnNlCgoyMDA3LjEwLjIxIC0gMC40OgogLSB1bml0IHRlc3QgYW5kIHBhdGNoIChEYXZpZCBCYWlyZCkKCjIwMDcuMDkuMTcgLSAwLjM6CiAtIGJ1ZyBmaXg6IG5vIGxvbmdlciB0aHJvd3MgZXhjZXB0aW9uIG9uIGVtcHR5IHBhcmFtZW50ZXJzIChIYW5zIFB1ZmFsKQoKMjAwNy4wOS4xMSAtIDAuMjoKIC0gZmVhdHVyZTogYWRkZWQgYXJndW1lbnQgc3dhcHBpbmcKCjIwMDcuMDQuMDMgLSAwLjE6CiAtIGluaXRpYWwgcmVsZWFzZQoqKi8KdmFyIG49ZnVuY3Rpb24oKXtmdW5jdGlvbiB0KHQpe3JldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodCkuc2xpY2UoOCwtMSkudG9Mb3dlckNhc2UoKX1mdW5jdGlvbiBlKHQsZSl7Zm9yKHZhciByPVtdO2U+MDtyWy0tZV09dCk7cmV0dXJuIHIuam9pbigiIil9dmFyIHI9ZnVuY3Rpb24oKXtyZXR1cm4gci5jYWNoZS5oYXNPd25Qcm9wZXJ0eShhcmd1bWVudHNbMF0pfHwoci5jYWNoZVthcmd1bWVudHNbMF1dPXIucGFyc2UoYXJndW1lbnRzWzBdKSksci5mb3JtYXQuY2FsbChudWxsLHIuY2FjaGVbYXJndW1lbnRzWzBdXSxhcmd1bWVudHMpfTtyZXR1cm4gci5vYmplY3Rfc3RyaW5naWZ5PWZ1bmN0aW9uKHQsZSxuLG8pe3ZhciBpPSIiO2lmKG51bGwhPXQpc3dpdGNoKHR5cGVvZiB0KXtjYXNlImZ1bmN0aW9uIjpyZXR1cm4iW0Z1bmN0aW9uIisodC5uYW1lPyI6ICIrdC5uYW1lOiIiKSsiXSI7Y2FzZSJvYmplY3QiOmlmKHQgaW5zdGFuY2VvZiBFcnJvcilyZXR1cm4iWyIrdC50b1N0cmluZygpKyJdIjtpZihlPj1uKXJldHVybiJbT2JqZWN0XSI7aWYobyYmKG89by5zbGljZSgwKSxvLnB1c2godCkpLG51bGwhPXQubGVuZ3RoKXtpKz0iWyI7dmFyIHM9W107Zm9yKHZhciBhIGluIHQpbyYmby5pbmRleE9mKHRbYV0pPj0wP3MucHVzaCgiW0NpcmN1bGFyXSIpOnMucHVzaChyLm9iamVjdF9zdHJpbmdpZnkodFthXSxlKzEsbixvKSk7aSs9cy5qb2luKCIsICIpKyJdIn1lbHNle2lmKCJnZXRNb250aCJpbiB0KXJldHVybiJEYXRlKCIrdCsiKSI7aSs9InsiO3ZhciBzPVtdO2Zvcih2YXIgbCBpbiB0KXQuaGFzT3duUHJvcGVydHkobCkmJihvJiZvLmluZGV4T2YodFtsXSk+PTA/cy5wdXNoKGwrIjogW0NpcmN1bGFyXSIpOnMucHVzaChsKyI6ICIrci5vYmplY3Rfc3RyaW5naWZ5KHRbbF0sZSsxLG4sbykpKTtpKz1zLmpvaW4oIiwgIikrIn0ifXJldHVybiBpO2Nhc2Uic3RyaW5nIjpyZXR1cm4nIicrdCsnIid9cmV0dXJuIiIrdH0sci5mb3JtYXQ9ZnVuY3Rpb24obyxpKXt2YXIgcyxhLGwsdSxoLGMscCxfPTEsZD1vLmxlbmd0aCxmPSIiLG09W107Zm9yKGE9MDthPGQ7YSsrKWlmKGY9dChvW2FdKSwic3RyaW5nIj09PWYpbS5wdXNoKG9bYV0pO2Vsc2UgaWYoImFycmF5Ij09PWYpe2lmKHU9b1thXSx1WzJdKWZvcihzPWlbX10sbD0wO2w8dVsyXS5sZW5ndGg7bCsrKXtpZighcy5oYXNPd25Qcm9wZXJ0eSh1WzJdW2xdKSl0aHJvdyBuZXcgRXJyb3IobignW3NwcmludGZdIHByb3BlcnR5ICIlcyIgZG9lcyBub3QgZXhpc3QnLHVbMl1bbF0pKTtzPXNbdVsyXVtsXV19ZWxzZSBzPXVbMV0/aVt1WzFdXTppW18rK107aWYoL1tec09dLy50ZXN0KHVbOF0pJiYibnVtYmVyIiE9dChzKSl0aHJvdyBuZXcgRXJyb3IobignW3NwcmludGZdIGV4cGVjdGluZyBudW1iZXIgYnV0IGZvdW5kICVzICInK3MrJyInLHQocykpKTtzd2l0Y2godVs4XSl7Y2FzZSJiIjpzPXMudG9TdHJpbmcoMik7YnJlYWs7Y2FzZSJjIjpzPVN0cmluZy5mcm9tQ2hhckNvZGUocyk7YnJlYWs7Y2FzZSJkIjpzPXBhcnNlSW50KHMsMTApO2JyZWFrO2Nhc2UiZSI6cz11WzddP3MudG9FeHBvbmVudGlhbCh1WzddKTpzLnRvRXhwb25lbnRpYWwoKTticmVhaztjYXNlImYiOnM9dVs3XT9wYXJzZUZsb2F0KHMpLnRvRml4ZWQodVs3XSk6cGFyc2VGbG9hdChzKTticmVhaztjYXNlIk8iOnM9ci5vYmplY3Rfc3RyaW5naWZ5KHMsMCxwYXJzZUludCh1WzddKXx8NSk7YnJlYWs7Y2FzZSJvIjpzPXMudG9TdHJpbmcoOCk7YnJlYWs7Y2FzZSJzIjpzPShzPVN0cmluZyhzKSkmJnVbN10/cy5zdWJzdHJpbmcoMCx1WzddKTpzO2JyZWFrO2Nhc2UidSI6cz1NYXRoLmFicyhzKTticmVhaztjYXNlIngiOnM9cy50b1N0cmluZygxNik7YnJlYWs7Y2FzZSJYIjpzPXMudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCl9cz0vW2RlZl0vLnRlc3QodVs4XSkmJnVbM10mJnM+PTA/IisiK3M6cyxjPXVbNF0/IjAiPT11WzRdPyIwIjp1WzRdLmNoYXJBdCgxKToiICIscD11WzZdLVN0cmluZyhzKS5sZW5ndGgsaD11WzZdP2UoYyxwKToiIixtLnB1c2godVs1XT9zK2g6aCtzKX1yZXR1cm4gbS5qb2luKCIiKX0sci5jYWNoZT17fSxyLnBhcnNlPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT10LHI9W10sbj1bXSxvPTA7ZTspe2lmKG51bGwhPT0ocj0vXlteXHgyNV0rLy5leGVjKGUpKSluLnB1c2goclswXSk7ZWxzZSBpZihudWxsIT09KHI9L15ceDI1ezJ9Ly5leGVjKGUpKSluLnB1c2goIiUiKTtlbHNle2lmKG51bGw9PT0ocj0vXlx4MjUoPzooWzEtOV1cZCopXCR8XCgoW15cKV0rKVwpKT8oXCspPygwfCdbXiRdKT8oLSk/KFxkKyk/KD86XC4oXGQrKSk/KFtiLWZvc091eFhdKS8uZXhlYyhlKSkpdGhyb3cgbmV3IEVycm9yKCJbc3ByaW50Zl0gIitlKTtpZihyWzJdKXtvfD0xO3ZhciBpPVtdLHM9clsyXSxhPVtdO2lmKG51bGw9PT0oYT0vXihbYS16X11bYS16X1xkXSopL2kuZXhlYyhzKSkpdGhyb3cgbmV3IEVycm9yKCJbc3ByaW50Zl0gIitzKTtmb3IoaS5wdXNoKGFbMV0pOyIiIT09KHM9cy5zdWJzdHJpbmcoYVswXS5sZW5ndGgpKTspaWYobnVsbCE9PShhPS9eXC4oW2Etel9dW2Etel9cZF0qKS9pLmV4ZWMocykpKWkucHVzaChhWzFdKTtlbHNle2lmKG51bGw9PT0oYT0vXlxbKFxkKylcXS8uZXhlYyhzKSkpdGhyb3cgbmV3IEVycm9yKCJbc3ByaW50Zl0gIitzKTtpLnB1c2goYVsxXSl9clsyXT1pfWVsc2Ugb3w9MjtpZigzPT09byl0aHJvdyBuZXcgRXJyb3IoIltzcHJpbnRmXSBtaXhpbmcgcG9zaXRpb25hbCBhbmQgbmFtZWQgcGxhY2Vob2xkZXJzIGlzIG5vdCAoeWV0KSBzdXBwb3J0ZWQiKTtuLnB1c2gocil9ZT1lLnN1YnN0cmluZyhyWzBdLmxlbmd0aCl9cmV0dXJuIG59LHJ9KCksbz1mdW5jdGlvbih0LGUpe3ZhciByPWUuc2xpY2UoKTtyZXR1cm4gci51bnNoaWZ0KHQpLG4uYXBwbHkobnVsbCxyKX07ZS5leHBvcnRzPW4sbi5zcHJpbnRmPW4sbi52c3ByaW50Zj1vfSx7fV0sInRpbWV6b25lL2luZGV4IjpbZnVuY3Rpb24oZSxyLG4peyFmdW5jdGlvbihlKXsib2JqZWN0Ij09dHlwZW9mIHImJnIuZXhwb3J0cz9yLmV4cG9ydHM9ZSgpOiJmdW5jdGlvbiI9PXR5cGVvZiB0P3QoZSk6dGhpcy50ej1lKCl9KGZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCh0LGUscil7dmFyIG4sbz1lLmRheVsxXTtkbyBuPW5ldyBEYXRlKERhdGUuVVRDKHIsZS5tb250aCxNYXRoLmFicyhvKyspKSk7d2hpbGUoZS5kYXlbMF08NyYmbi5nZXRVVENEYXkoKSE9ZS5kYXlbMF0pO3JldHVybiBuPXtjbG9jazplLmNsb2NrLHNvcnQ6bi5nZXRUaW1lKCkscnVsZTplLHNhdmU6NmU0KmUuc2F2ZSxvZmZzZXQ6dC5vZmZzZXR9LG5bbi5jbG9ja109bi5zb3J0KzZlNCplLnRpbWUsbi5wb3NpeD9uLndhbGxjbG9jaz1uW24uY2xvY2tdKyh0Lm9mZnNldCtlLnNhdmVkKTpuLnBvc2l4PW5bbi5jbG9ja10tKHQub2Zmc2V0K2Uuc2F2ZWQpLG59ZnVuY3Rpb24gZShlLHIsbil7dmFyIG8saSxzLGEsbCx1LGgsYz1lW2Uuem9uZV0scD1bXSxfPW5ldyBEYXRlKG4pLmdldFVUQ0Z1bGxZZWFyKCksZD0xO2ZvcihvPTEsaT1jLmxlbmd0aDtvPGkmJiEoY1tvXVtyXTw9bik7bysrKTtpZihzPWNbb10scy5ydWxlcyl7Zm9yKHU9ZVtzLnJ1bGVzXSxoPV8rMTtoPj1fLWQ7LS1oKWZvcihvPTAsaT11Lmxlbmd0aDtvPGk7bysrKXVbb10uZnJvbTw9aCYmaDw9dVtvXS50bz9wLnB1c2godChzLHVbb10saCkpOnVbb10udG88aCYmMT09ZCYmKGQ9aC11W29dLnRvKTtmb3IocC5zb3J0KGZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQuc29ydC1lLnNvcnR9KSxvPTAsaT1wLmxlbmd0aDtvPGk7bysrKW4+PXBbb11bcl0mJnBbb11bcFtvXS5jbG9ja10+c1twW29dLmNsb2NrXSYmKGE9cFtvXSl9cmV0dXJuIGEmJigobD0vXiguKilcLyguKikkLy5leGVjKHMuZm9ybWF0KSk/YS5hYmJyZXY9bFthLnNhdmU/MjoxXTphLmFiYnJldj1zLmZvcm1hdC5yZXBsYWNlKC8lcy8sYS5ydWxlLmxldHRlcikpLGF8fHN9ZnVuY3Rpb24gcih0LHIpe3JldHVybiJVVEMiPT10LnpvbmU/cjoodC5lbnRyeT1lKHQsInBvc2l4IixyKSxyK3QuZW50cnkub2Zmc2V0K3QuZW50cnkuc2F2ZSl9ZnVuY3Rpb24gbih0LHIpe2lmKCJVVEMiPT10LnpvbmUpcmV0dXJuIHI7dmFyIG4sbztyZXR1cm4gdC5lbnRyeT1uPWUodCwid2FsbGNsb2NrIixyKSxvPXItbi53YWxsY2xvY2ssMDxvJiZvPG4uc2F2ZT9udWxsOnItbi5vZmZzZXQtbi5zYXZlfWZ1bmN0aW9uIG8odCxlLG8pe3ZhciBpLHM9KyhvWzFdKzEpLGE9b1syXSpzLGw9dS5pbmRleE9mKG9bM10udG9Mb3dlckNhc2UoKSk7aWYobD45KWUrPWEqY1tsLTEwXTtlbHNle2lmKGk9bmV3IERhdGUocih0LGUpKSxsPDcpZm9yKDthOylpLnNldFVUQ0RhdGUoaS5nZXRVVENEYXRlKCkrcyksaS5nZXRVVENEYXkoKT09bCYmKGEtPXMpO2Vsc2UgNz09bD9pLnNldFVUQ0Z1bGxZZWFyKGkuZ2V0VVRDRnVsbFllYXIoKSthKTo4PT1sP2kuc2V0VVRDTW9udGgoaS5nZXRVVENNb250aCgpK2EpOmkuc2V0VVRDRGF0ZShpLmdldFVUQ0RhdGUoKSthKTtudWxsPT0oZT1uKHQsaS5nZXRUaW1lKCkpKSYmKGU9bih0LGkuZ2V0VGltZSgpKzg2NGU1KnMpLTg2NGU1KnMpfXJldHVybiBlfWZ1bmN0aW9uIGkodCl7aWYoIXQubGVuZ3RoKXJldHVybiIwLjAuMzgiO3ZhciBlLGkscyxhLGwsdT1PYmplY3QuY3JlYXRlKHRoaXMpLGM9W107Zm9yKGU9MDtlPHQubGVuZ3RoO2UrKylpZihhPXRbZV0sQXJyYXkuaXNBcnJheShhKSllfHxpc05hTihhWzFdKT9hLnNwbGljZS5hcHBseSh0LFtlLS0sMV0uY29uY2F0KGEpKTpsPWE7ZWxzZSBpZihpc05hTihhKSl7aWYocz10eXBlb2YgYSwic3RyaW5nIj09cyl+YS5pbmRleE9mKCIlIik/dS5mb3JtYXQ9YTplfHwiKiIhPWE/IWUmJihzPS9eKFxkezR9KS0oXGR7Mn0pLShcZHsyfSkoPzpbVFxzXShcZHsyfSk6KFxkezJ9KSg/OjooXGR7Mn0pKD86XC4oXGQrKSk/KT8oWnwoKFsrLV0pKFxkezJ9KDpcZHsyfSl7MCwyfSkpKT8pPyQvLmV4ZWMoYSkpPyhsPVtdLGwucHVzaC5hcHBseShsLHMuc2xpY2UoMSw4KSksc1s5XT8obC5wdXNoKHNbMTBdKzEpLGwucHVzaC5hcHBseShsLHNbMTFdLnNwbGl0KC86LykpKTpzWzhdJiZsLnB1c2goMSkpOi9eXHd7MiwzfV9cd3syfSQvLnRlc3QoYSk/dS5sb2NhbGU9YToocz1oLmV4ZWMoYSkpP2MucHVzaChzKTp1LnpvbmU9YTpsPWE7ZWxzZSBpZigiZnVuY3Rpb24iPT1zKXtpZihzPWEuY2FsbCh1KSlyZXR1cm4gc31lbHNlIGlmKC9eXHd7MiwzfV9cd3syfSQvLnRlc3QoYS5uYW1lKSl1W2EubmFtZV09YTtlbHNlIGlmKGEuem9uZXMpe2ZvcihzIGluIGEuem9uZXMpdVtzXT1hLnpvbmVzW3NdO2ZvcihzIGluIGEucnVsZXMpdVtzXT1hLnJ1bGVzW3NdfX1lbHNlIGV8fChsPWEpO2lmKHVbdS5sb2NhbGVdfHxkZWxldGUgdS5sb2NhbGUsdVt1LnpvbmVdfHxkZWxldGUgdS56b25lLG51bGwhPWwpe2lmKCIqIj09bClsPXUuY2xvY2soKTtlbHNlIGlmKEFycmF5LmlzQXJyYXkobCkpe2ZvcihpPSFsWzddLGU9MDtlPDExO2UrKylsW2VdPSsobFtlXXx8MCk7LS1sWzFdLGw9RGF0ZS5VVEMuYXBwbHkoRGF0ZS5VVEMsbC5zbGljZSgwLDgpKSstbFs3XSooMzZlNSpsWzhdKzZlNCpsWzldKzFlMypsWzEwXSl9ZWxzZSBsPU1hdGguZmxvb3IobCk7aWYoIWlzTmFOKGwpKXtpZihpJiYobD1uKHUsbCkpLG51bGw9PWwpcmV0dXJuIGw7Zm9yKGU9MCxpPWMubGVuZ3RoO2U8aTtlKyspbD1vKHUsbCxjW2VdKTtyZXR1cm4gdS5mb3JtYXQ/KHM9bmV3IERhdGUocih1LGwpKSx1LmZvcm1hdC5yZXBsYWNlKC8lKFstMF9eXT8pKDp7MCwzfSkoXGQqKSguKS9nLGZ1bmN0aW9uKHQsZSxyLG4sbyl7dmFyIGksYSxoPSIwIjtpZihpPXVbb10pe2Zvcih0PVN0cmluZyhpLmNhbGwodSxzLGwsZSxyLmxlbmd0aCkpLCJfIj09KGV8fGkuc3R5bGUpJiYoaD0iICIpLGE9Ii0iPT1lPzA6aS5wYWR8fDA7dC5sZW5ndGg8YTspdD1oK3Q7Zm9yKGE9Ii0iPT1lPzA6bnx8aS5wYWQ7dC5sZW5ndGg8YTspdD1oK3Q7Ik4iPT1vJiZhPHQubGVuZ3RoJiYodD10LnNsaWNlKDAsYSkpLCJeIj09ZSYmKHQ9dC50b1VwcGVyQ2FzZSgpKX1yZXR1cm4gdH0pKTpsfX1yZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdS5jb252ZXJ0KGFyZ3VtZW50cyl9fWZ1bmN0aW9uIHModCxlKXt2YXIgcixuLG87cmV0dXJuIG49bmV3IERhdGUoRGF0ZS5VVEModC5nZXRVVENGdWxsWWVhcigpLDApKSxyPU1hdGguZmxvb3IoKHQuZ2V0VGltZSgpLW4uZ2V0VGltZSgpKS84NjRlNSksbi5nZXRVVENEYXkoKT09ZT9vPTA6KG89Ny1uLmdldFVUQ0RheSgpK2UsOD09byYmKG89MSkpLHI+PW8/TWF0aC5mbG9vcigoci1vKS83KSsxOjB9ZnVuY3Rpb24gYSh0KXt2YXIgZSxyLG47cmV0dXJuIHI9dC5nZXRVVENGdWxsWWVhcigpLGU9bmV3IERhdGUoRGF0ZS5VVEMociwwKSkuZ2V0VVRDRGF5KCksbj1zKHQsMSkrKGU+MSYmZTw9ND8xOjApLG4/NTMhPW58fDQ9PWV8fDM9PWUmJjI5PT1uZXcgRGF0ZShyLDEsMjkpLmdldERhdGUoKT9bbix0LmdldFVUQ0Z1bGxZZWFyKCldOlsxLHQuZ2V0VVRDRnVsbFllYXIoKSsxXToocj10LmdldFVUQ0Z1bGxZZWFyKCktMSxlPW5ldyBEYXRlKERhdGUuVVRDKHIsMCkpLmdldFVUQ0RheSgpLG49ND09ZXx8Mz09ZSYmMjk9PW5ldyBEYXRlKHIsMSwyOSkuZ2V0RGF0ZSgpPzUzOjUyLFtuLHQuZ2V0VVRDRnVsbFllYXIoKS0xXSl9dmFyIGw9e2Nsb2NrOmZ1bmN0aW9uKCl7cmV0dXJuK25ldyBEYXRlfSx6b25lOiJVVEMiLGVudHJ5OnthYmJyZXY6IlVUQyIsb2Zmc2V0OjAsc2F2ZTowfSxVVEM6MSx6OmZ1bmN0aW9uKHQsZSxyLG4pe3ZhciBvLGkscz10aGlzLmVudHJ5Lm9mZnNldCt0aGlzLmVudHJ5LnNhdmUsYT1NYXRoLmFicyhzLzFlMyksbD1bXSx1PTM2MDA7Zm9yKG89MDtvPDM7bysrKWwucHVzaCgoIjAiK01hdGguZmxvb3IoYS91KSkuc2xpY2UoLTIpKSxhJT11LHUvPTYwO3JldHVybiJeIiE9cnx8cz8oIl4iPT1yJiYobj0zKSwzPT1uPyhpPWwuam9pbigiOiIpLGk9aS5yZXBsYWNlKC86MDAkLywiIiksIl4iIT1yJiYoaT1pLnJlcGxhY2UoLzowMCQvLCIiKSkpOm4/KGk9bC5zbGljZSgwLG4rMSkuam9pbigiOiIpLCJeIj09ciYmKGk9aS5yZXBsYWNlKC86MDAkLywiIikpKTppPWwuc2xpY2UoMCwyKS5qb2luKCIiKSxpPShzPDA/Ii0iOiIrIikraSxpPWkucmVwbGFjZSgvKFstK10pKDApLyx7XzoiICQxIiwiLSI6IiQxIn1bcl18fCIkMSQyIikpOiJaIn0sIiUiOmZ1bmN0aW9uKHQpe3JldHVybiIlIn0sbjpmdW5jdGlvbih0KXtyZXR1cm4iXG4ifSx0OmZ1bmN0aW9uKHQpe3JldHVybiJcdCJ9LFU6ZnVuY3Rpb24odCl7cmV0dXJuIHModCwwKX0sVzpmdW5jdGlvbih0KXtyZXR1cm4gcyh0LDEpfSxWOmZ1bmN0aW9uKHQpe3JldHVybiBhKHQpWzBdfSxHOmZ1bmN0aW9uKHQpe3JldHVybiBhKHQpWzFdfSxnOmZ1bmN0aW9uKHQpe3JldHVybiBhKHQpWzFdJTEwMH0sajpmdW5jdGlvbih0KXtyZXR1cm4gTWF0aC5mbG9vcigodC5nZXRUaW1lKCktRGF0ZS5VVEModC5nZXRVVENGdWxsWWVhcigpLDApKS84NjRlNSkrMX0sczpmdW5jdGlvbih0KXtyZXR1cm4gTWF0aC5mbG9vcih0LmdldFRpbWUoKS8xZTMpfSxDOmZ1bmN0aW9uKHQpe3JldHVybiBNYXRoLmZsb29yKHQuZ2V0VVRDRnVsbFllYXIoKS8xMDApfSxOOmZ1bmN0aW9uKHQpe3JldHVybiB0LmdldFRpbWUoKSUxZTMqMWU2fSxtOmZ1bmN0aW9uKHQpe3JldHVybiB0LmdldFVUQ01vbnRoKCkrMX0sWTpmdW5jdGlvbih0KXtyZXR1cm4gdC5nZXRVVENGdWxsWWVhcigpfSx5OmZ1bmN0aW9uKHQpe3JldHVybiB0LmdldFVUQ0Z1bGxZZWFyKCklMTAwfSxIOmZ1bmN0aW9uKHQpe3JldHVybiB0LmdldFVUQ0hvdXJzKCl9LE06ZnVuY3Rpb24odCl7cmV0dXJuIHQuZ2V0VVRDTWludXRlcygpfSxTOmZ1bmN0aW9uKHQpe3JldHVybiB0LmdldFVUQ1NlY29uZHMoKX0sZTpmdW5jdGlvbih0KXtyZXR1cm4gdC5nZXRVVENEYXRlKCl9LGQ6ZnVuY3Rpb24odCl7cmV0dXJuIHQuZ2V0VVRDRGF0ZSgpfSx1OmZ1bmN0aW9uKHQpe3JldHVybiB0LmdldFVUQ0RheSgpfHw3fSx3OmZ1bmN0aW9uKHQpe3JldHVybiB0LmdldFVUQ0RheSgpfSxsOmZ1bmN0aW9uKHQpe3JldHVybiB0LmdldFVUQ0hvdXJzKCklMTJ8fDEyfSxJOmZ1bmN0aW9uKHQpe3JldHVybiB0LmdldFVUQ0hvdXJzKCklMTJ8fDEyfSxrOmZ1bmN0aW9uKHQpe3JldHVybiB0LmdldFVUQ0hvdXJzKCl9LFo6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuZW50cnkuYWJicmV2fSxhOmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzW3RoaXMubG9jYWxlXS5kYXkuYWJicmV2W3QuZ2V0VVRDRGF5KCldfSxBOmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzW3RoaXMubG9jYWxlXS5kYXkuZnVsbFt0LmdldFVUQ0RheSgpXX0saDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpc1t0aGlzLmxvY2FsZV0ubW9udGguYWJicmV2W3QuZ2V0VVRDTW9udGgoKV19LGI6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXNbdGhpcy5sb2NhbGVdLm1vbnRoLmFiYnJldlt0LmdldFVUQ01vbnRoKCldfSxCOmZ1bmN0aW9uKHQpe3JldHVybiB0aGlzW3RoaXMubG9jYWxlXS5tb250aC5mdWxsW3QuZ2V0VVRDTW9udGgoKV19LFA6ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXNbdGhpcy5sb2NhbGVdLm1lcmlkaWVtW01hdGguZmxvb3IodC5nZXRVVENIb3VycygpLzEyKV0udG9Mb3dlckNhc2UoKX0scDpmdW5jdGlvbih0KXtyZXR1cm4gdGhpc1t0aGlzLmxvY2FsZV0ubWVyaWRpZW1bTWF0aC5mbG9vcih0LmdldFVUQ0hvdXJzKCkvMTIpXX0sUjpmdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmNvbnZlcnQoW2UsIiVIOiVNIl0pfSxUOmZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuY29udmVydChbZSwiJUg6JU06JVMiXSl9LEQ6ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5jb252ZXJ0KFtlLCIlbS8lZC8leSJdKX0sRjpmdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmNvbnZlcnQoW2UsIiVZLSVtLSVkIl0pfSx4OmZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuY29udmVydChbZSx0aGlzW3RoaXMubG9jYWxlXS5kYXRlXSl9LHI6ZnVuY3Rpb24odCxlKXtyZXR1cm4gdGhpcy5jb252ZXJ0KFtlLHRoaXNbdGhpcy5sb2NhbGVdLnRpbWUxMnx8IiVJOiVNOiVTIl0pfSxYOmZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuY29udmVydChbZSx0aGlzW3RoaXMubG9jYWxlXS50aW1lMjRdKX0sYzpmdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmNvbnZlcnQoW2UsdGhpc1t0aGlzLmxvY2FsZV0uZGF0ZVRpbWVdKX0sY29udmVydDppLGxvY2FsZToiZW5fVVMiLGVuX1VTOntkYXRlOiIlbS8lZC8lWSIsdGltZTI0OiIlSTolTTolUyAlcCIsdGltZTEyOiIlSTolTTolUyAlcCIsZGF0ZVRpbWU6IiVhICVkICViICVZICVJOiVNOiVTICVwICVaIixtZXJpZGllbTpbIkFNIiwiUE0iXSxtb250aDp7YWJicmV2OiJKYW58RmVifE1hcnxBcHJ8TWF5fEp1bnxKdWx8QXVnfFNlcHxPY3R8Tm92fERlYyIuc3BsaXQoInwiKSxmdWxsOiJKYW51YXJ5fEZlYnJ1YXJ5fE1hcmNofEFwcmlsfE1heXxKdW5lfEp1bHl8QXVndXN0fFNlcHRlbWJlcnxPY3RvYmVyfE5vdmVtYmVyfERlY2VtYmVyIi5zcGxpdCgifCIpfSxkYXk6e2FiYnJldjoiU3VufE1vbnxUdWV8V2VkfFRodXxGcml8U2F0Ii5zcGxpdCgifCIpLGZ1bGw6IlN1bmRheXxNb25kYXl8VHVlc2RheXxXZWRuZXNkYXl8VGh1cnNkYXl8RnJpZGF5fFNhdHVyZGF5Ii5zcGxpdCgifCIpfX19LHU9IlN1bmRheXxNb25kYXl8VHVlc2RheXxXZWRuZXNkYXl8VGh1cnNkYXl8RnJpZGF5fFNhdHVyZGF5fHllYXJ8bW9udGh8ZGF5fGhvdXJ8bWludXRlfHNlY29uZHxtaWxsaXNlY29uZCIsaD1uZXcgUmVnRXhwKCJeXFxzKihbKy1dKShcXGQrKVxccysoIit1KyIpcz9cXHMqJCIsImkiKSxjPVszNmU1LDZlNCwxZTMsMV07cmV0dXJuIHU9dS50b0xvd2VyQ2FzZSgpLnNwbGl0KCJ8IiksImRlbG1ITVNVV1ZnQ0lreSIucmVwbGFjZSgvLi9nLGZ1bmN0aW9uKHQpe2xbdF0ucGFkPTJ9KSxsLk4ucGFkPTksbC5qLnBhZD0zLGwuay5zdHlsZT0iXyIsbC5sLnN0eWxlPSJfIixsLmUuc3R5bGU9Il8iLGZ1bmN0aW9uKCl7cmV0dXJuIGwuY29udmVydChhcmd1bWVudHMpfX0pfSx7fV0sdW5kZXJzY29yZTpbZnVuY3Rpb24oZSxyLG4pewovLyAgICAgKGMpIDIwMDktMjAxNSBKZXJlbXkgQXNoa2VuYXMsIERvY3VtZW50Q2xvdWQgYW5kIEludmVzdGlnYXRpdmUgUmVwb3J0ZXJzICYgRWRpdG9ycwovLyAgICAgVW5kZXJzY29yZSBtYXkgYmUgZnJlZWx5IGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBNSVQgbGljZW5zZS4KKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gZSh0KXtmdW5jdGlvbiBlKGUscixuLG8saSxzKXtmb3IoO2k+PTAmJmk8cztpKz10KXt2YXIgYT1vP29baV06aTtuPXIobixlW2FdLGEsZSl9cmV0dXJuIG59cmV0dXJuIGZ1bmN0aW9uKHIsbixvLGkpe249dyhuLGksNCk7dmFyIHM9IVAocikmJngua2V5cyhyKSxhPShzfHxyKS5sZW5ndGgsbD10PjA/MDphLTE7cmV0dXJuIGFyZ3VtZW50cy5sZW5ndGg8MyYmKG89cltzP3NbbF06bF0sbCs9dCksZShyLG4sbyxzLGwsYSl9fWZ1bmN0aW9uIG8odCl7cmV0dXJuIGZ1bmN0aW9uKGUscixuKXtyPU0ocixuKTtmb3IodmFyIG89eihlKSxpPXQ+MD8wOm8tMTtpPj0wJiZpPG87aSs9dClpZihyKGVbaV0saSxlKSlyZXR1cm4gaTtyZXR1cm4tMX19ZnVuY3Rpb24gaSh0LGUscil7cmV0dXJuIGZ1bmN0aW9uKG4sbyxpKXt2YXIgcz0wLGE9eihuKTtpZigibnVtYmVyIj09dHlwZW9mIGkpdD4wP3M9aT49MD9pOk1hdGgubWF4KGkrYSxzKTphPWk+PTA/TWF0aC5taW4oaSsxLGEpOmkrYSsxO2Vsc2UgaWYociYmaSYmYSlyZXR1cm4gaT1yKG4sbyksbltpXT09PW8/aTotMTtpZihvIT09bylyZXR1cm4gaT1lKF8uY2FsbChuLHMsYSkseC5pc05hTiksaT49MD9pK3M6LTE7Zm9yKGk9dD4wP3M6YS0xO2k+PTAmJmk8YTtpKz10KWlmKG5baV09PT1vKXJldHVybiBpO3JldHVybi0xfX1mdW5jdGlvbiBzKHQsZSl7dmFyIHI9Ty5sZW5ndGgsbj10LmNvbnN0cnVjdG9yLG89eC5pc0Z1bmN0aW9uKG4pJiZuLnByb3RvdHlwZXx8aCxpPSJjb25zdHJ1Y3RvciI7Zm9yKHguaGFzKHQsaSkmJiF4LmNvbnRhaW5zKGUsaSkmJmUucHVzaChpKTtyLS07KWk9T1tyXSxpIGluIHQmJnRbaV0hPT1vW2ldJiYheC5jb250YWlucyhlLGkpJiZlLnB1c2goaSl9dmFyIGE9dGhpcyxsPWEuXyx1PUFycmF5LnByb3RvdHlwZSxoPU9iamVjdC5wcm90b3R5cGUsYz1GdW5jdGlvbi5wcm90b3R5cGUscD11LnB1c2gsXz11LnNsaWNlLGQ9aC50b1N0cmluZyxmPWguaGFzT3duUHJvcGVydHksbT1BcnJheS5pc0FycmF5LGc9T2JqZWN0LmtleXMseT1jLmJpbmQsdj1PYmplY3QuY3JlYXRlLGI9ZnVuY3Rpb24oKXt9LHg9ZnVuY3Rpb24odCl7cmV0dXJuIHQgaW5zdGFuY2VvZiB4P3Q6dGhpcyBpbnN0YW5jZW9mIHg/dm9pZCh0aGlzLl93cmFwcGVkPXQpOm5ldyB4KHQpfTsidW5kZWZpbmVkIiE9dHlwZW9mIG4/KCJ1bmRlZmluZWQiIT10eXBlb2YgciYmci5leHBvcnRzJiYobj1yLmV4cG9ydHM9eCksbi5fPXgpOmEuXz14LHguVkVSU0lPTj0iMS44LjMiO3ZhciB3PWZ1bmN0aW9uKHQsZSxyKXtpZih2b2lkIDA9PT1lKXJldHVybiB0O3N3aXRjaChudWxsPT1yPzM6cil7Y2FzZSAxOnJldHVybiBmdW5jdGlvbihyKXtyZXR1cm4gdC5jYWxsKGUscil9O2Nhc2UgMjpyZXR1cm4gZnVuY3Rpb24ocixuKXtyZXR1cm4gdC5jYWxsKGUscixuKX07Y2FzZSAzOnJldHVybiBmdW5jdGlvbihyLG4sbyl7cmV0dXJuIHQuY2FsbChlLHIsbixvKX07Y2FzZSA0OnJldHVybiBmdW5jdGlvbihyLG4sbyxpKXtyZXR1cm4gdC5jYWxsKGUscixuLG8saSl9fXJldHVybiBmdW5jdGlvbigpe3JldHVybiB0LmFwcGx5KGUsYXJndW1lbnRzKX19LE09ZnVuY3Rpb24odCxlLHIpe3JldHVybiBudWxsPT10P3guaWRlbnRpdHk6eC5pc0Z1bmN0aW9uKHQpP3codCxlLHIpOnguaXNPYmplY3QodCk/eC5tYXRjaGVyKHQpOngucHJvcGVydHkodCl9O3guaXRlcmF0ZWU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gTSh0LGUsMS8wKX07dmFyIGs9ZnVuY3Rpb24odCxlKXtyZXR1cm4gZnVuY3Rpb24ocil7dmFyIG49YXJndW1lbnRzLmxlbmd0aDtpZihuPDJ8fG51bGw9PXIpcmV0dXJuIHI7Zm9yKHZhciBvPTE7bzxuO28rKylmb3IodmFyIGk9YXJndW1lbnRzW29dLHM9dChpKSxhPXMubGVuZ3RoLGw9MDtsPGE7bCsrKXt2YXIgdT1zW2xdO2UmJnZvaWQgMCE9PXJbdV18fChyW3VdPWlbdV0pfXJldHVybiByfX0saj1mdW5jdGlvbih0KXtpZigheC5pc09iamVjdCh0KSlyZXR1cm57fTtpZih2KXJldHVybiB2KHQpO2IucHJvdG90eXBlPXQ7dmFyIGU9bmV3IGI7cmV0dXJuIGIucHJvdG90eXBlPW51bGwsZX0sVD1mdW5jdGlvbih0KXtyZXR1cm4gZnVuY3Rpb24oZSl7cmV0dXJuIG51bGw9PWU/dm9pZCAwOmVbdF19fSxTPU1hdGgucG93KDIsNTMpLTEsej1UKCJsZW5ndGgiKSxQPWZ1bmN0aW9uKHQpe3ZhciBlPXoodCk7cmV0dXJuIm51bWJlciI9PXR5cGVvZiBlJiZlPj0wJiZlPD1TfTt4LmVhY2g9eC5mb3JFYWNoPWZ1bmN0aW9uKHQsZSxyKXtlPXcoZSxyKTt2YXIgbixvO2lmKFAodCkpZm9yKG49MCxvPXQubGVuZ3RoO248bztuKyspZSh0W25dLG4sdCk7ZWxzZXt2YXIgaT14LmtleXModCk7Zm9yKG49MCxvPWkubGVuZ3RoO248bztuKyspZSh0W2lbbl1dLGlbbl0sdCl9cmV0dXJuIHR9LHgubWFwPXguY29sbGVjdD1mdW5jdGlvbih0LGUscil7ZT1NKGUscik7Zm9yKHZhciBuPSFQKHQpJiZ4LmtleXModCksbz0obnx8dCkubGVuZ3RoLGk9QXJyYXkobykscz0wO3M8bztzKyspe3ZhciBhPW4/bltzXTpzO2lbc109ZSh0W2FdLGEsdCl9cmV0dXJuIGl9LHgucmVkdWNlPXguZm9sZGw9eC5pbmplY3Q9ZSgxKSx4LnJlZHVjZVJpZ2h0PXguZm9sZHI9ZSgtMSkseC5maW5kPXguZGV0ZWN0PWZ1bmN0aW9uKHQsZSxyKXt2YXIgbjtpZihuPVAodCk/eC5maW5kSW5kZXgodCxlLHIpOnguZmluZEtleSh0LGUsciksdm9pZCAwIT09biYmbiE9PS0xKXJldHVybiB0W25dfSx4LmZpbHRlcj14LnNlbGVjdD1mdW5jdGlvbih0LGUscil7dmFyIG49W107cmV0dXJuIGU9TShlLHIpLHguZWFjaCh0LGZ1bmN0aW9uKHQscixvKXtlKHQscixvKSYmbi5wdXNoKHQpfSksbn0seC5yZWplY3Q9ZnVuY3Rpb24odCxlLHIpe3JldHVybiB4LmZpbHRlcih0LHgubmVnYXRlKE0oZSkpLHIpfSx4LmV2ZXJ5PXguYWxsPWZ1bmN0aW9uKHQsZSxyKXtlPU0oZSxyKTtmb3IodmFyIG49IVAodCkmJngua2V5cyh0KSxvPShufHx0KS5sZW5ndGgsaT0wO2k8bztpKyspe3ZhciBzPW4/bltpXTppO2lmKCFlKHRbc10scyx0KSlyZXR1cm4hMX1yZXR1cm4hMH0seC5zb21lPXguYW55PWZ1bmN0aW9uKHQsZSxyKXtlPU0oZSxyKTtmb3IodmFyIG49IVAodCkmJngua2V5cyh0KSxvPShufHx0KS5sZW5ndGgsaT0wO2k8bztpKyspe3ZhciBzPW4/bltpXTppO2lmKGUodFtzXSxzLHQpKXJldHVybiEwfXJldHVybiExfSx4LmNvbnRhaW5zPXguaW5jbHVkZXM9eC5pbmNsdWRlPWZ1bmN0aW9uKHQsZSxyLG4pe3JldHVybiBQKHQpfHwodD14LnZhbHVlcyh0KSksKCJudW1iZXIiIT10eXBlb2Ygcnx8bikmJihyPTApLHguaW5kZXhPZih0LGUscik+PTB9LHguaW52b2tlPWZ1bmN0aW9uKHQsZSl7dmFyIHI9Xy5jYWxsKGFyZ3VtZW50cywyKSxuPXguaXNGdW5jdGlvbihlKTtyZXR1cm4geC5tYXAodCxmdW5jdGlvbih0KXt2YXIgbz1uP2U6dFtlXTtyZXR1cm4gbnVsbD09bz9vOm8uYXBwbHkodCxyKX0pfSx4LnBsdWNrPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHgubWFwKHQseC5wcm9wZXJ0eShlKSl9LHgud2hlcmU9ZnVuY3Rpb24odCxlKXtyZXR1cm4geC5maWx0ZXIodCx4Lm1hdGNoZXIoZSkpfSx4LmZpbmRXaGVyZT1mdW5jdGlvbih0LGUpe3JldHVybiB4LmZpbmQodCx4Lm1hdGNoZXIoZSkpfSx4Lm1heD1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpPS0oMS8wKSxzPS0oMS8wKTtpZihudWxsPT1lJiZudWxsIT10KXt0PVAodCk/dDp4LnZhbHVlcyh0KTtmb3IodmFyIGE9MCxsPXQubGVuZ3RoO2E8bDthKyspbj10W2FdLG4+aSYmKGk9bil9ZWxzZSBlPU0oZSxyKSx4LmVhY2godCxmdW5jdGlvbih0LHIsbil7bz1lKHQscixuKSwobz5zfHxvPT09LSgxLzApJiZpPT09LSgxLzApKSYmKGk9dCxzPW8pfSk7cmV0dXJuIGl9LHgubWluPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk9MS8wLHM9MS8wO2lmKG51bGw9PWUmJm51bGwhPXQpe3Q9UCh0KT90OngudmFsdWVzKHQpO2Zvcih2YXIgYT0wLGw9dC5sZW5ndGg7YTxsO2ErKyluPXRbYV0sbjxpJiYoaT1uKX1lbHNlIGU9TShlLHIpLHguZWFjaCh0LGZ1bmN0aW9uKHQscixuKXtvPWUodCxyLG4pLChvPHN8fG89PT0xLzAmJmk9PT0xLzApJiYoaT10LHM9byl9KTtyZXR1cm4gaX0seC5zaHVmZmxlPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZSxyPVAodCk/dDp4LnZhbHVlcyh0KSxuPXIubGVuZ3RoLG89QXJyYXkobiksaT0wO2k8bjtpKyspZT14LnJhbmRvbSgwLGkpLGUhPT1pJiYob1tpXT1vW2VdKSxvW2VdPXJbaV07cmV0dXJuIG99LHguc2FtcGxlPWZ1bmN0aW9uKHQsZSxyKXtyZXR1cm4gbnVsbD09ZXx8cj8oUCh0KXx8KHQ9eC52YWx1ZXModCkpLHRbeC5yYW5kb20odC5sZW5ndGgtMSldKTp4LnNodWZmbGUodCkuc2xpY2UoMCxNYXRoLm1heCgwLGUpKX0seC5zb3J0Qnk9ZnVuY3Rpb24odCxlLHIpe3JldHVybiBlPU0oZSxyKSx4LnBsdWNrKHgubWFwKHQsZnVuY3Rpb24odCxyLG4pe3JldHVybnt2YWx1ZTp0LGluZGV4OnIsY3JpdGVyaWE6ZSh0LHIsbil9fSkuc29ydChmdW5jdGlvbih0LGUpe3ZhciByPXQuY3JpdGVyaWEsbj1lLmNyaXRlcmlhO2lmKHIhPT1uKXtpZihyPm58fHZvaWQgMD09PXIpcmV0dXJuIDE7aWYocjxufHx2b2lkIDA9PT1uKXJldHVybi0xfXJldHVybiB0LmluZGV4LWUuaW5kZXh9KSwidmFsdWUiKX07dmFyIEU9ZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKGUscixuKXt2YXIgbz17fTtyZXR1cm4gcj1NKHIsbikseC5lYWNoKGUsZnVuY3Rpb24obixpKXt2YXIgcz1yKG4saSxlKTt0KG8sbixzKX0pLG99fTt4Lmdyb3VwQnk9RShmdW5jdGlvbih0LGUscil7eC5oYXModCxyKT90W3JdLnB1c2goZSk6dFtyXT1bZV19KSx4LmluZGV4Qnk9RShmdW5jdGlvbih0LGUscil7dFtyXT1lfSkseC5jb3VudEJ5PUUoZnVuY3Rpb24odCxlLHIpe3guaGFzKHQscik/dFtyXSsrOnRbcl09MX0pLHgudG9BcnJheT1mdW5jdGlvbih0KXtyZXR1cm4gdD94LmlzQXJyYXkodCk/Xy5jYWxsKHQpOlAodCk/eC5tYXAodCx4LmlkZW50aXR5KTp4LnZhbHVlcyh0KTpbXX0seC5zaXplPWZ1bmN0aW9uKHQpe3JldHVybiBudWxsPT10PzA6UCh0KT90Lmxlbmd0aDp4LmtleXModCkubGVuZ3RofSx4LnBhcnRpdGlvbj1mdW5jdGlvbih0LGUscil7ZT1NKGUscik7dmFyIG49W10sbz1bXTtyZXR1cm4geC5lYWNoKHQsZnVuY3Rpb24odCxyLGkpeyhlKHQscixpKT9uOm8pLnB1c2godCl9KSxbbixvXX0seC5maXJzdD14LmhlYWQ9eC50YWtlPWZ1bmN0aW9uKHQsZSxyKXtpZihudWxsIT10KXJldHVybiBudWxsPT1lfHxyP3RbMF06eC5pbml0aWFsKHQsdC5sZW5ndGgtZSl9LHguaW5pdGlhbD1mdW5jdGlvbih0LGUscil7cmV0dXJuIF8uY2FsbCh0LDAsTWF0aC5tYXgoMCx0Lmxlbmd0aC0obnVsbD09ZXx8cj8xOmUpKSl9LHgubGFzdD1mdW5jdGlvbih0LGUscil7aWYobnVsbCE9dClyZXR1cm4gbnVsbD09ZXx8cj90W3QubGVuZ3RoLTFdOngucmVzdCh0LE1hdGgubWF4KDAsdC5sZW5ndGgtZSkpfSx4LnJlc3Q9eC50YWlsPXguZHJvcD1mdW5jdGlvbih0LGUscil7cmV0dXJuIF8uY2FsbCh0LG51bGw9PWV8fHI/MTplKX0seC5jb21wYWN0PWZ1bmN0aW9uKHQpe3JldHVybiB4LmZpbHRlcih0LHguaWRlbnRpdHkpfTt2YXIgQT1mdW5jdGlvbih0LGUscixuKXtmb3IodmFyIG89W10saT0wLHM9bnx8MCxhPXoodCk7czxhO3MrKyl7dmFyIGw9dFtzXTtpZihQKGwpJiYoeC5pc0FycmF5KGwpfHx4LmlzQXJndW1lbnRzKGwpKSl7ZXx8KGw9QShsLGUscikpO3ZhciB1PTAsaD1sLmxlbmd0aDtmb3Ioby5sZW5ndGgrPWg7dTxoOylvW2krK109bFt1KytdfWVsc2Ugcnx8KG9baSsrXT1sKX1yZXR1cm4gb307eC5mbGF0dGVuPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIEEodCxlLCExKX0seC53aXRob3V0PWZ1bmN0aW9uKHQpe3JldHVybiB4LmRpZmZlcmVuY2UodCxfLmNhbGwoYXJndW1lbnRzLDEpKX0seC51bmlxPXgudW5pcXVlPWZ1bmN0aW9uKHQsZSxyLG4pe3guaXNCb29sZWFuKGUpfHwobj1yLHI9ZSxlPSExKSxudWxsIT1yJiYocj1NKHIsbikpO2Zvcih2YXIgbz1bXSxpPVtdLHM9MCxhPXoodCk7czxhO3MrKyl7dmFyIGw9dFtzXSx1PXI/cihsLHMsdCk6bDtlPyhzJiZpPT09dXx8by5wdXNoKGwpLGk9dSk6cj94LmNvbnRhaW5zKGksdSl8fChpLnB1c2godSksby5wdXNoKGwpKTp4LmNvbnRhaW5zKG8sbCl8fG8ucHVzaChsKX1yZXR1cm4gb30seC51bmlvbj1mdW5jdGlvbigpe3JldHVybiB4LnVuaXEoQShhcmd1bWVudHMsITAsITApKX0seC5pbnRlcnNlY3Rpb249ZnVuY3Rpb24odCl7Zm9yKHZhciBlPVtdLHI9YXJndW1lbnRzLmxlbmd0aCxuPTAsbz16KHQpO248bztuKyspe3ZhciBpPXRbbl07aWYoIXguY29udGFpbnMoZSxpKSl7Zm9yKHZhciBzPTE7czxyJiZ4LmNvbnRhaW5zKGFyZ3VtZW50c1tzXSxpKTtzKyspO3M9PT1yJiZlLnB1c2goaSl9fXJldHVybiBlfSx4LmRpZmZlcmVuY2U9ZnVuY3Rpb24odCl7dmFyIGU9QShhcmd1bWVudHMsITAsITAsMSk7cmV0dXJuIHguZmlsdGVyKHQsZnVuY3Rpb24odCl7cmV0dXJuIXguY29udGFpbnMoZSx0KX0pfSx4LnppcD1mdW5jdGlvbigpe3JldHVybiB4LnVuemlwKGFyZ3VtZW50cyl9LHgudW56aXA9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPXQmJngubWF4KHQseikubGVuZ3RofHwwLHI9QXJyYXkoZSksbj0wO248ZTtuKyspcltuXT14LnBsdWNrKHQsbik7cmV0dXJuIHJ9LHgub2JqZWN0PWZ1bmN0aW9uKHQsZSl7Zm9yKHZhciByPXt9LG49MCxvPXoodCk7bjxvO24rKyllP3JbdFtuXV09ZVtuXTpyW3Rbbl1bMF1dPXRbbl1bMV07cmV0dXJuIHJ9LHguZmluZEluZGV4PW8oMSkseC5maW5kTGFzdEluZGV4PW8oLTEpLHguc29ydGVkSW5kZXg9ZnVuY3Rpb24odCxlLHIsbil7cj1NKHIsbiwxKTtmb3IodmFyIG89cihlKSxpPTAscz16KHQpO2k8czspe3ZhciBhPU1hdGguZmxvb3IoKGkrcykvMik7cih0W2FdKTxvP2k9YSsxOnM9YX1yZXR1cm4gaX0seC5pbmRleE9mPWkoMSx4LmZpbmRJbmRleCx4LnNvcnRlZEluZGV4KSx4Lmxhc3RJbmRleE9mPWkoLTEseC5maW5kTGFzdEluZGV4KSx4LnJhbmdlPWZ1bmN0aW9uKHQsZSxyKXtudWxsPT1lJiYoZT10fHwwLHQ9MCkscj1yfHwxO2Zvcih2YXIgbj1NYXRoLm1heChNYXRoLmNlaWwoKGUtdCkvciksMCksbz1BcnJheShuKSxpPTA7aTxuO2krKyx0Kz1yKW9baV09dDtyZXR1cm4gb307dmFyIEM9ZnVuY3Rpb24odCxlLHIsbixvKXtpZighKG4gaW5zdGFuY2VvZiBlKSlyZXR1cm4gdC5hcHBseShyLG8pO3ZhciBpPWoodC5wcm90b3R5cGUpLHM9dC5hcHBseShpLG8pO3JldHVybiB4LmlzT2JqZWN0KHMpP3M6aX07eC5iaW5kPWZ1bmN0aW9uKHQsZSl7aWYoeSYmdC5iaW5kPT09eSlyZXR1cm4geS5hcHBseSh0LF8uY2FsbChhcmd1bWVudHMsMSkpO2lmKCF4LmlzRnVuY3Rpb24odCkpdGhyb3cgbmV3IFR5cGVFcnJvcigiQmluZCBtdXN0IGJlIGNhbGxlZCBvbiBhIGZ1bmN0aW9uIik7dmFyIHI9Xy5jYWxsKGFyZ3VtZW50cywyKSxuPWZ1bmN0aW9uKCl7cmV0dXJuIEModCxuLGUsdGhpcyxyLmNvbmNhdChfLmNhbGwoYXJndW1lbnRzKSkpfTtyZXR1cm4gbn0seC5wYXJ0aWFsPWZ1bmN0aW9uKHQpe3ZhciBlPV8uY2FsbChhcmd1bWVudHMsMSkscj1mdW5jdGlvbigpe2Zvcih2YXIgbj0wLG89ZS5sZW5ndGgsaT1BcnJheShvKSxzPTA7czxvO3MrKylpW3NdPWVbc109PT14P2FyZ3VtZW50c1tuKytdOmVbc107Zm9yKDtuPGFyZ3VtZW50cy5sZW5ndGg7KWkucHVzaChhcmd1bWVudHNbbisrXSk7cmV0dXJuIEModCxyLHRoaXMsdGhpcyxpKX07cmV0dXJuIHJ9LHguYmluZEFsbD1mdW5jdGlvbih0KXt2YXIgZSxyLG49YXJndW1lbnRzLmxlbmd0aDtpZihuPD0xKXRocm93IG5ldyBFcnJvcigiYmluZEFsbCBtdXN0IGJlIHBhc3NlZCBmdW5jdGlvbiBuYW1lcyIpO2ZvcihlPTE7ZTxuO2UrKylyPWFyZ3VtZW50c1tlXSx0W3JdPXguYmluZCh0W3JdLHQpO3JldHVybiB0fSx4Lm1lbW9pemU9ZnVuY3Rpb24odCxlKXt2YXIgcj1mdW5jdGlvbihuKXt2YXIgbz1yLmNhY2hlLGk9IiIrKGU/ZS5hcHBseSh0aGlzLGFyZ3VtZW50cyk6bik7cmV0dXJuIHguaGFzKG8saSl8fChvW2ldPXQuYXBwbHkodGhpcyxhcmd1bWVudHMpKSxvW2ldfTtyZXR1cm4gci5jYWNoZT17fSxyfSx4LmRlbGF5PWZ1bmN0aW9uKHQsZSl7dmFyIHI9Xy5jYWxsKGFyZ3VtZW50cywyKTtyZXR1cm4gc2V0VGltZW91dChmdW5jdGlvbigpe3JldHVybiB0LmFwcGx5KG51bGwscil9LGUpfSx4LmRlZmVyPXgucGFydGlhbCh4LmRlbGF5LHgsMSkseC50aHJvdHRsZT1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLHM9bnVsbCxhPTA7cnx8KHI9e30pO3ZhciBsPWZ1bmN0aW9uKCl7YT1yLmxlYWRpbmc9PT0hMT8wOngubm93KCkscz1udWxsLGk9dC5hcHBseShuLG8pLHN8fChuPW89bnVsbCl9O3JldHVybiBmdW5jdGlvbigpe3ZhciB1PXgubm93KCk7YXx8ci5sZWFkaW5nIT09ITF8fChhPXUpO3ZhciBoPWUtKHUtYSk7cmV0dXJuIG49dGhpcyxvPWFyZ3VtZW50cyxoPD0wfHxoPmU/KHMmJihjbGVhclRpbWVvdXQocykscz1udWxsKSxhPXUsaT10LmFwcGx5KG4sbyksc3x8KG49bz1udWxsKSk6c3x8ci50cmFpbGluZz09PSExfHwocz1zZXRUaW1lb3V0KGwsaCkpLGl9fSx4LmRlYm91bmNlPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGw9ZnVuY3Rpb24oKXt2YXIgdT14Lm5vdygpLXM7dTxlJiZ1Pj0wP249c2V0VGltZW91dChsLGUtdSk6KG49bnVsbCxyfHwoYT10LmFwcGx5KGksbyksbnx8KGk9bz1udWxsKSkpfTtyZXR1cm4gZnVuY3Rpb24oKXtpPXRoaXMsbz1hcmd1bWVudHMscz14Lm5vdygpO3ZhciB1PXImJiFuO3JldHVybiBufHwobj1zZXRUaW1lb3V0KGwsZSkpLHUmJihhPXQuYXBwbHkoaSxvKSxpPW89bnVsbCksYX19LHgud3JhcD1mdW5jdGlvbih0LGUpe3JldHVybiB4LnBhcnRpYWwoZSx0KX0seC5uZWdhdGU9ZnVuY3Rpb24odCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIXQuYXBwbHkodGhpcyxhcmd1bWVudHMpfX0seC5jb21wb3NlPWZ1bmN0aW9uKCl7dmFyIHQ9YXJndW1lbnRzLGU9dC5sZW5ndGgtMTtyZXR1cm4gZnVuY3Rpb24oKXtmb3IodmFyIHI9ZSxuPXRbZV0uYXBwbHkodGhpcyxhcmd1bWVudHMpO3ItLTspbj10W3JdLmNhbGwodGhpcyxuKTtyZXR1cm4gbn19LHguYWZ0ZXI9ZnVuY3Rpb24odCxlKXtyZXR1cm4gZnVuY3Rpb24oKXtpZigtLXQ8MSlyZXR1cm4gZS5hcHBseSh0aGlzLGFyZ3VtZW50cyl9fSx4LmJlZm9yZT1mdW5jdGlvbih0LGUpe3ZhciByO3JldHVybiBmdW5jdGlvbigpe3JldHVybi0tdD4wJiYocj1lLmFwcGx5KHRoaXMsYXJndW1lbnRzKSksdDw9MSYmKGU9bnVsbCkscn19LHgub25jZT14LnBhcnRpYWwoeC5iZWZvcmUsMik7dmFyIE49IXt0b1N0cmluZzpudWxsfS5wcm9wZXJ0eUlzRW51bWVyYWJsZSgidG9TdHJpbmciKSxPPVsidmFsdWVPZiIsImlzUHJvdG90eXBlT2YiLCJ0b1N0cmluZyIsInByb3BlcnR5SXNFbnVtZXJhYmxlIiwiaGFzT3duUHJvcGVydHkiLCJ0b0xvY2FsZVN0cmluZyJdO3gua2V5cz1mdW5jdGlvbih0KXtpZigheC5pc09iamVjdCh0KSlyZXR1cm5bXTtpZihnKXJldHVybiBnKHQpO3ZhciBlPVtdO2Zvcih2YXIgciBpbiB0KXguaGFzKHQscikmJmUucHVzaChyKTtyZXR1cm4gTiYmcyh0LGUpLGV9LHguYWxsS2V5cz1mdW5jdGlvbih0KXtpZigheC5pc09iamVjdCh0KSlyZXR1cm5bXTt2YXIgZT1bXTtmb3IodmFyIHIgaW4gdCllLnB1c2gocik7cmV0dXJuIE4mJnModCxlKSxlfSx4LnZhbHVlcz1mdW5jdGlvbih0KXtmb3IodmFyIGU9eC5rZXlzKHQpLHI9ZS5sZW5ndGgsbj1BcnJheShyKSxvPTA7bzxyO28rKyluW29dPXRbZVtvXV07cmV0dXJuIG59LHgubWFwT2JqZWN0PWZ1bmN0aW9uKHQsZSxyKXtlPU0oZSxyKTtmb3IodmFyIG4sbz14LmtleXModCksaT1vLmxlbmd0aCxzPXt9LGE9MDthPGk7YSsrKW49b1thXSxzW25dPWUodFtuXSxuLHQpO3JldHVybiBzfSx4LnBhaXJzPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT14LmtleXModCkscj1lLmxlbmd0aCxuPUFycmF5KHIpLG89MDtvPHI7bysrKW5bb109W2Vbb10sdFtlW29dXV07cmV0dXJuIG59LHguaW52ZXJ0PWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT17fSxyPXgua2V5cyh0KSxuPTAsbz1yLmxlbmd0aDtuPG87bisrKWVbdFtyW25dXV09cltuXTtyZXR1cm4gZX0seC5mdW5jdGlvbnM9eC5tZXRob2RzPWZ1bmN0aW9uKHQpe3ZhciBlPVtdO2Zvcih2YXIgciBpbiB0KXguaXNGdW5jdGlvbih0W3JdKSYmZS5wdXNoKHIpO3JldHVybiBlLnNvcnQoKX0seC5leHRlbmQ9ayh4LmFsbEtleXMpLHguZXh0ZW5kT3duPXguYXNzaWduPWsoeC5rZXlzKSx4LmZpbmRLZXk9ZnVuY3Rpb24odCxlLHIpe2U9TShlLHIpO2Zvcih2YXIgbixvPXgua2V5cyh0KSxpPTAscz1vLmxlbmd0aDtpPHM7aSsrKWlmKG49b1tpXSxlKHRbbl0sbix0KSlyZXR1cm4gbn0seC5waWNrPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk9e30scz10O2lmKG51bGw9PXMpcmV0dXJuIGk7eC5pc0Z1bmN0aW9uKGUpPyhvPXguYWxsS2V5cyhzKSxuPXcoZSxyKSk6KG89QShhcmd1bWVudHMsITEsITEsMSksbj1mdW5jdGlvbih0LGUscil7cmV0dXJuIGUgaW4gcn0scz1PYmplY3QocykpO2Zvcih2YXIgYT0wLGw9by5sZW5ndGg7YTxsO2ErKyl7dmFyIHU9b1thXSxoPXNbdV07bihoLHUscykmJihpW3VdPWgpfXJldHVybiBpfSx4Lm9taXQ9ZnVuY3Rpb24odCxlLHIpe2lmKHguaXNGdW5jdGlvbihlKSllPXgubmVnYXRlKGUpO2Vsc2V7dmFyIG49eC5tYXAoQShhcmd1bWVudHMsITEsITEsMSksU3RyaW5nKTtlPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIXguY29udGFpbnMobixlKX19cmV0dXJuIHgucGljayh0LGUscil9LHguZGVmYXVsdHM9ayh4LmFsbEtleXMsITApLHguY3JlYXRlPWZ1bmN0aW9uKHQsZSl7dmFyIHI9aih0KTtyZXR1cm4gZSYmeC5leHRlbmRPd24ocixlKSxyfSx4LmNsb25lPWZ1bmN0aW9uKHQpe3JldHVybiB4LmlzT2JqZWN0KHQpP3guaXNBcnJheSh0KT90LnNsaWNlKCk6eC5leHRlbmQoe30sdCk6dH0seC50YXA9ZnVuY3Rpb24odCxlKXtyZXR1cm4gZSh0KSx0fSx4LmlzTWF0Y2g9ZnVuY3Rpb24odCxlKXt2YXIgcj14LmtleXMoZSksbj1yLmxlbmd0aDtpZihudWxsPT10KXJldHVybiFuO2Zvcih2YXIgbz1PYmplY3QodCksaT0wO2k8bjtpKyspe3ZhciBzPXJbaV07aWYoZVtzXSE9PW9bc118fCEocyBpbiBvKSlyZXR1cm4hMX1yZXR1cm4hMH07dmFyIHE9ZnVuY3Rpb24odCxlLHIsbil7aWYodD09PWUpcmV0dXJuIDAhPT10fHwxL3Q9PT0xL2U7aWYobnVsbD09dHx8bnVsbD09ZSlyZXR1cm4gdD09PWU7dCBpbnN0YW5jZW9mIHgmJih0PXQuX3dyYXBwZWQpLGUgaW5zdGFuY2VvZiB4JiYoZT1lLl93cmFwcGVkKTt2YXIgbz1kLmNhbGwodCk7aWYobyE9PWQuY2FsbChlKSlyZXR1cm4hMTtzd2l0Y2gobyl7Y2FzZSJbb2JqZWN0IFJlZ0V4cF0iOmNhc2UiW29iamVjdCBTdHJpbmddIjpyZXR1cm4iIit0PT0iIitlO2Nhc2UiW29iamVjdCBOdW1iZXJdIjpyZXR1cm4rdCE9PSt0PytlIT09K2U6MD09PSt0PzEvK3Q9PT0xL2U6K3Q9PT0rZTtjYXNlIltvYmplY3QgRGF0ZV0iOmNhc2UiW29iamVjdCBCb29sZWFuXSI6cmV0dXJuK3Q9PT0rZX12YXIgaT0iW29iamVjdCBBcnJheV0iPT09bztpZighaSl7aWYoIm9iamVjdCIhPXR5cGVvZiB0fHwib2JqZWN0IiE9dHlwZW9mIGUpcmV0dXJuITE7dmFyIHM9dC5jb25zdHJ1Y3RvcixhPWUuY29uc3RydWN0b3I7aWYocyE9PWEmJiEoeC5pc0Z1bmN0aW9uKHMpJiZzIGluc3RhbmNlb2YgcyYmeC5pc0Z1bmN0aW9uKGEpJiZhIGluc3RhbmNlb2YgYSkmJiJjb25zdHJ1Y3RvciJpbiB0JiYiY29uc3RydWN0b3IiaW4gZSlyZXR1cm4hMX1yPXJ8fFtdLG49bnx8W107Zm9yKHZhciBsPXIubGVuZ3RoO2wtLTspaWYocltsXT09PXQpcmV0dXJuIG5bbF09PT1lO2lmKHIucHVzaCh0KSxuLnB1c2goZSksaSl7aWYobD10Lmxlbmd0aCxsIT09ZS5sZW5ndGgpcmV0dXJuITE7Zm9yKDtsLS07KWlmKCFxKHRbbF0sZVtsXSxyLG4pKXJldHVybiExfWVsc2V7dmFyIHUsaD14LmtleXModCk7aWYobD1oLmxlbmd0aCx4LmtleXMoZSkubGVuZ3RoIT09bClyZXR1cm4hMTtmb3IoO2wtLTspaWYodT1oW2xdLCF4LmhhcyhlLHUpfHwhcSh0W3VdLGVbdV0scixuKSlyZXR1cm4hMX1yZXR1cm4gci5wb3AoKSxuLnBvcCgpLCEwfTt4LmlzRXF1YWw9ZnVuY3Rpb24odCxlKXtyZXR1cm4gcSh0LGUpfSx4LmlzRW1wdHk9ZnVuY3Rpb24odCl7cmV0dXJuIG51bGw9PXR8fChQKHQpJiYoeC5pc0FycmF5KHQpfHx4LmlzU3RyaW5nKHQpfHx4LmlzQXJndW1lbnRzKHQpKT8wPT09dC5sZW5ndGg6MD09PXgua2V5cyh0KS5sZW5ndGgpfSx4LmlzRWxlbWVudD1mdW5jdGlvbih0KXtyZXR1cm4hKCF0fHwxIT09dC5ub2RlVHlwZSl9LHguaXNBcnJheT1tfHxmdW5jdGlvbih0KXtyZXR1cm4iW29iamVjdCBBcnJheV0iPT09ZC5jYWxsKHQpfSx4LmlzT2JqZWN0PWZ1bmN0aW9uKHQpe3ZhciBlPXR5cGVvZiB0O3JldHVybiJmdW5jdGlvbiI9PT1lfHwib2JqZWN0Ij09PWUmJiEhdH0seC5lYWNoKFsiQXJndW1lbnRzIiwiRnVuY3Rpb24iLCJTdHJpbmciLCJOdW1iZXIiLCJEYXRlIiwiUmVnRXhwIiwiRXJyb3IiXSxmdW5jdGlvbih0KXt4WyJpcyIrdF09ZnVuY3Rpb24oZSl7cmV0dXJuIGQuY2FsbChlKT09PSJbb2JqZWN0ICIrdCsiXSJ9fSkseC5pc0FyZ3VtZW50cyhhcmd1bWVudHMpfHwoeC5pc0FyZ3VtZW50cz1mdW5jdGlvbih0KXtyZXR1cm4geC5oYXModCwiY2FsbGVlIil9KSwiZnVuY3Rpb24iIT10eXBlb2YvLi8mJiJvYmplY3QiIT10eXBlb2YgSW50OEFycmF5JiYoeC5pc0Z1bmN0aW9uPWZ1bmN0aW9uKHQpe3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiB0fHwhMX0pLHguaXNGaW5pdGU9ZnVuY3Rpb24odCl7cmV0dXJuIGlzRmluaXRlKHQpJiYhaXNOYU4ocGFyc2VGbG9hdCh0KSl9LHguaXNOYU49ZnVuY3Rpb24odCl7cmV0dXJuIHguaXNOdW1iZXIodCkmJnQhPT0rdH0seC5pc0Jvb2xlYW49ZnVuY3Rpb24odCl7cmV0dXJuIHQ9PT0hMHx8dD09PSExfHwiW29iamVjdCBCb29sZWFuXSI9PT1kLmNhbGwodCl9LHguaXNOdWxsPWZ1bmN0aW9uKHQpe3JldHVybiBudWxsPT09dH0seC5pc1VuZGVmaW5lZD1mdW5jdGlvbih0KXtyZXR1cm4gdm9pZCAwPT09dH0seC5oYXM9ZnVuY3Rpb24odCxlKXtyZXR1cm4gbnVsbCE9dCYmZi5jYWxsKHQsZSl9LHgubm9Db25mbGljdD1mdW5jdGlvbigpe3JldHVybiBhLl89bCx0aGlzfSx4LmlkZW50aXR5PWZ1bmN0aW9uKHQpe3JldHVybiB0fSx4LmNvbnN0YW50PWZ1bmN0aW9uKHQpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiB0fX0seC5ub29wPWZ1bmN0aW9uKCl7fSx4LnByb3BlcnR5PVQseC5wcm9wZXJ0eU9mPWZ1bmN0aW9uKHQpe3JldHVybiBudWxsPT10P2Z1bmN0aW9uKCl7fTpmdW5jdGlvbihlKXtyZXR1cm4gdFtlXX19LHgubWF0Y2hlcj14Lm1hdGNoZXM9ZnVuY3Rpb24odCl7cmV0dXJuIHQ9eC5leHRlbmRPd24oe30sdCksZnVuY3Rpb24oZSl7cmV0dXJuIHguaXNNYXRjaChlLHQpfX0seC50aW1lcz1mdW5jdGlvbih0LGUscil7dmFyIG49QXJyYXkoTWF0aC5tYXgoMCx0KSk7ZT13KGUsciwxKTtmb3IodmFyIG89MDtvPHQ7bysrKW5bb109ZShvKTtyZXR1cm4gbn0seC5yYW5kb209ZnVuY3Rpb24odCxlKXtyZXR1cm4gbnVsbD09ZSYmKGU9dCx0PTApLHQrTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpKihlLXQrMSkpfSx4Lm5vdz1EYXRlLm5vd3x8ZnVuY3Rpb24oKXtyZXR1cm4obmV3IERhdGUpLmdldFRpbWUoKX07dmFyIEQ9eyImIjoiJmFtcDsiLCI8IjoiJmx0OyIsIj4iOiImZ3Q7IiwnIic6IiZxdW90OyIsIiciOiImI3gyNzsiLCJgIjoiJiN4NjA7In0sST14LmludmVydChEKSxSPWZ1bmN0aW9uKHQpe3ZhciBlPWZ1bmN0aW9uKGUpe3JldHVybiB0W2VdfSxyPSIoPzoiK3gua2V5cyh0KS5qb2luKCJ8IikrIikiLG49UmVnRXhwKHIpLG89UmVnRXhwKHIsImciKTtyZXR1cm4gZnVuY3Rpb24odCl7cmV0dXJuIHQ9bnVsbD09dD8iIjoiIit0LG4udGVzdCh0KT90LnJlcGxhY2UobyxlKTp0fX07eC5lc2NhcGU9UihEKSx4LnVuZXNjYXBlPVIoSSkseC5yZXN1bHQ9ZnVuY3Rpb24odCxlLHIpe3ZhciBuPW51bGw9PXQ/dm9pZCAwOnRbZV07cmV0dXJuIHZvaWQgMD09PW4mJihuPXIpLHguaXNGdW5jdGlvbihuKT9uLmNhbGwodCk6bn07dmFyIEY9MDt4LnVuaXF1ZUlkPWZ1bmN0aW9uKHQpe3ZhciBlPSsrRisiIjtyZXR1cm4gdD90K2U6ZX0seC50ZW1wbGF0ZVNldHRpbmdzPXtldmFsdWF0ZTovPCUoW1xzXFNdKz8pJT4vZyxpbnRlcnBvbGF0ZTovPCU9KFtcc1xTXSs/KSU+L2csZXNjYXBlOi88JS0oW1xzXFNdKz8pJT4vZ307dmFyIEI9LyguKV4vLEw9eyInIjoiJyIsIlxcIjoiXFwiLCJcciI6InIiLCJcbiI6Im4iLCJcdTIwMjgiOiJ1MjAyOCIsIlx1MjAyOSI6InUyMDI5In0sRz0vXFx8J3xccnxcbnxcdTIwMjh8XHUyMDI5L2csVj1mdW5jdGlvbih0KXtyZXR1cm4iXFwiK0xbdF19O3gudGVtcGxhdGU9ZnVuY3Rpb24odCxlLHIpeyFlJiZyJiYoZT1yKSxlPXguZGVmYXVsdHMoe30sZSx4LnRlbXBsYXRlU2V0dGluZ3MpO3ZhciBuPVJlZ0V4cChbKGUuZXNjYXBlfHxCKS5zb3VyY2UsKGUuaW50ZXJwb2xhdGV8fEIpLnNvdXJjZSwoZS5ldmFsdWF0ZXx8Qikuc291cmNlXS5qb2luKCJ8IikrInwkIiwiZyIpLG89MCxpPSJfX3ArPSciO3QucmVwbGFjZShuLGZ1bmN0aW9uKGUscixuLHMsYSl7cmV0dXJuIGkrPXQuc2xpY2UobyxhKS5yZXBsYWNlKEcsViksbz1hK2UubGVuZ3RoLHI/aSs9IicrXG4oKF9fdD0oIityKyIpKT09bnVsbD8nJzpfLmVzY2FwZShfX3QpKStcbiciOm4/aSs9IicrXG4oKF9fdD0oIituKyIpKT09bnVsbD8nJzpfX3QpK1xuJyI6cyYmKGkrPSInO1xuIitzKyJcbl9fcCs9JyIpLGV9KSxpKz0iJztcbiIsZS52YXJpYWJsZXx8KGk9IndpdGgob2JqfHx7fSl7XG4iK2krIn1cbiIpLGk9InZhciBfX3QsX19wPScnLF9faj1BcnJheS5wcm90b3R5cGUuam9pbixwcmludD1mdW5jdGlvbigpe19fcCs9X19qLmNhbGwoYXJndW1lbnRzLCcnKTt9O1xuIitpKyJyZXR1cm4gX19wO1xuIjt0cnl7dmFyIHM9bmV3IEZ1bmN0aW9uKGUudmFyaWFibGV8fCJvYmoiLCJfIixpKX1jYXRjaChhKXt0aHJvdyBhLnNvdXJjZT1pLGF9dmFyIGw9ZnVuY3Rpb24odCl7cmV0dXJuIHMuY2FsbCh0aGlzLHQseCl9LHU9ZS52YXJpYWJsZXx8Im9iaiI7cmV0dXJuIGwuc291cmNlPSJmdW5jdGlvbigiK3UrIil7XG4iK2krIn0iLGx9LHguY2hhaW49ZnVuY3Rpb24odCl7dmFyIGU9eCh0KTtyZXR1cm4gZS5fY2hhaW49ITAsZX07dmFyIFU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdC5fY2hhaW4/eChlKS5jaGFpbigpOmV9O3gubWl4aW49ZnVuY3Rpb24odCl7eC5lYWNoKHguZnVuY3Rpb25zKHQpLGZ1bmN0aW9uKGUpe3ZhciByPXhbZV09dFtlXTt4LnByb3RvdHlwZVtlXT1mdW5jdGlvbigpe3ZhciB0PVt0aGlzLl93cmFwcGVkXTtyZXR1cm4gcC5hcHBseSh0LGFyZ3VtZW50cyksVSh0aGlzLHIuYXBwbHkoeCx0KSl9fSl9LHgubWl4aW4oeCkseC5lYWNoKFsicG9wIiwicHVzaCIsInJldmVyc2UiLCJzaGlmdCIsInNvcnQiLCJzcGxpY2UiLCJ1bnNoaWZ0Il0sZnVuY3Rpb24odCl7dmFyIGU9dVt0XTt4LnByb3RvdHlwZVt0XT1mdW5jdGlvbigpe3ZhciByPXRoaXMuX3dyYXBwZWQ7cmV0dXJuIGUuYXBwbHkocixhcmd1bWVudHMpLCJzaGlmdCIhPT10JiYic3BsaWNlIiE9PXR8fDAhPT1yLmxlbmd0aHx8ZGVsZXRlIHJbMF0sVSh0aGlzLHIpfX0pLHguZWFjaChbImNvbmNhdCIsImpvaW4iLCJzbGljZSJdLGZ1bmN0aW9uKHQpe3ZhciBlPXVbdF07eC5wcm90b3R5cGVbdF09ZnVuY3Rpb24oKXtyZXR1cm4gVSh0aGlzLGUuYXBwbHkodGhpcy5fd3JhcHBlZCxhcmd1bWVudHMpKX19KSx4LnByb3RvdHlwZS52YWx1ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl93cmFwcGVkfSx4LnByb3RvdHlwZS52YWx1ZU9mPXgucHJvdG90eXBlLnRvSlNPTj14LnByb3RvdHlwZS52YWx1ZSx4LnByb3RvdHlwZS50b1N0cmluZz1mdW5jdGlvbigpe3JldHVybiIiK3RoaXMuX3dyYXBwZWR9LCJmdW5jdGlvbiI9PXR5cGVvZiB0JiZ0LmFtZCYmdCgidW5kZXJzY29yZSIsW10sZnVuY3Rpb24oKXtyZXR1cm4geH0pfSkuY2FsbCh0aGlzKX0se31dLCJib290c3RyYXAvZHJvcGRvd24iOltmdW5jdGlvbih0LGUscil7ZnVuY3Rpb24gbih0KXtpKHMpLnJlbW92ZSgpLGkoYSkuZWFjaChmdW5jdGlvbigpe3ZhciBlPW8oaSh0aGlzKSkscj17cmVsYXRlZFRhcmdldDp0aGlzfTtlLmhhc0NsYXNzKCJiay1icy1vcGVuIikmJihlLnRyaWdnZXIodD1pLkV2ZW50KCJoaWRlLmJrLWJzLmRyb3Bkb3duIixyKSksdC5pc0RlZmF1bHRQcmV2ZW50ZWQoKXx8ZS5yZW1vdmVDbGFzcygiYmstYnMtb3BlbiIpLnRyaWdnZXIoImhpZGRlbi5iay1icy5kcm9wZG93biIscikpfSl9ZnVuY3Rpb24gbyh0KXt2YXIgZT10LmF0dHIoImRhdGEtYmstYnMtdGFyZ2V0Iik7ZXx8KGU9dC5hdHRyKCJocmVmIiksZT1lJiYvI1tBLVphLXpdLy50ZXN0KGUpJiZlLnJlcGxhY2UoLy4qKD89I1teXHNdKiQpLywiIikpO3ZhciByPWUmJmkoZSk7cmV0dXJuIHImJnIubGVuZ3RoP3I6dC5wYXJlbnQoKX12YXIgaT10KCJqcXVlcnkiKSxzPSIuYmstYnMtZHJvcGRvd24tYmFja2Ryb3AiLGE9IltkYXRhLWJrLWJzLXRvZ2dsZT1kcm9wZG93bl0iLGw9ZnVuY3Rpb24odCl7aSh0KS5vbigiY2xpY2suYmstYnMuZHJvcGRvd24iLHRoaXMudG9nZ2xlKX07bC5wcm90b3R5cGUudG9nZ2xlPWZ1bmN0aW9uKHQpe3ZhciBlPWkodGhpcyk7aWYoIWUuaXMoIi5iay1icy1kaXNhYmxlZCwgOmRpc2FibGVkIikpe3ZhciByPW8oZSkscz1yLmhhc0NsYXNzKCJiay1icy1vcGVuIik7aWYobigpLCFzKXsib250b3VjaHN0YXJ0ImluIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCYmIXIuY2xvc2VzdCgiLmJrLWJzLW5hdmJhci1uYXYiKS5sZW5ndGgmJmkoJzxkaXYgY2xhc3M9ImJrLWJzLWRyb3Bkb3duLWJhY2tkcm9wIi8+JykuaW5zZXJ0QWZ0ZXIoaSh0aGlzKSkub24oImNsaWNrIixuKTt2YXIgYT17cmVsYXRlZFRhcmdldDp0aGlzfTtpZihyLnRyaWdnZXIodD1pLkV2ZW50KCJzaG93LmJrLWJzLmRyb3Bkb3duIixhKSksdC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSlyZXR1cm47ci50b2dnbGVDbGFzcygiYmstYnMtb3BlbiIpLnRyaWdnZXIoInNob3duLmJrLWJzLmRyb3Bkb3duIixhKSxlLmZvY3VzKCl9cmV0dXJuITF9fSxsLnByb3RvdHlwZS5rZXlkb3duPWZ1bmN0aW9uKHQpe2lmKC8oMzh8NDB8MjcpLy50ZXN0KHQua2V5Q29kZSkpe3ZhciBlPWkodGhpcyk7aWYodC5wcmV2ZW50RGVmYXVsdCgpLHQuc3RvcFByb3BhZ2F0aW9uKCksIWUuaXMoIi5iay1icy1kaXNhYmxlZCwgOmRpc2FibGVkIikpe3ZhciByPW8oZSksbj1yLmhhc0NsYXNzKCJiay1icy1vcGVuIik7aWYoIW58fG4mJjI3PT10LmtleUNvZGUpcmV0dXJuIDI3PT10LndoaWNoJiZyLmZpbmQoYSkuZm9jdXMoKSxlLmNsaWNrKCk7dmFyIHM9IiBsaTpub3QoLmJrLWJzLWRpdmlkZXIpOnZpc2libGUgYSIsbD1yLmZpbmQoIltyb2xlPW1lbnVdIitzKyIsIFtyb2xlPWxpc3Rib3hdIitzKTtpZihsLmxlbmd0aCl7dmFyIHU9bC5pbmRleChsLmZpbHRlcigiOmZvY3VzIikpOzM4PT10LmtleUNvZGUmJnU+MCYmdS0tLDQwPT10LmtleUNvZGUmJnU8bC5sZW5ndGgtMSYmdSsrLH51fHwodT0wKSxsLmVxKHUpLmZvY3VzKCl9fX19O3ZhciB1PWkuZm4uZHJvcGRvd247aS5mbi5kcm9wZG93bj1mdW5jdGlvbih0KXtyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCl7dmFyIGU9aSh0aGlzKSxyPWUuZGF0YSgiYmstYnMuZHJvcGRvd24iKTtyfHxlLmRhdGEoImJrLWJzLmRyb3Bkb3duIixyPW5ldyBsKHRoaXMpKSwic3RyaW5nIj09dHlwZW9mIHQmJnJbdF0uY2FsbChlKX0pfSxpLmZuLmRyb3Bkb3duLkNvbnN0cnVjdG9yPWwsaS5mbi5kcm9wZG93bi5ub0NvbmZsaWN0PWZ1bmN0aW9uKCl7cmV0dXJuIGkuZm4uZHJvcGRvd249dSx0aGlzfSxpKGRvY3VtZW50KS5vbigiY2xpY2suYmstYnMuZHJvcGRvd24uZGF0YS1hcGkiLG4pLm9uKCJjbGljay5iay1icy5kcm9wZG93bi5kYXRhLWFwaSIsIi5iay1icy1kcm9wZG93biBmb3JtIixmdW5jdGlvbih0KXt0LnN0b3BQcm9wYWdhdGlvbigpfSkub24oImNsaWNrLmJrLWJzLmRyb3Bkb3duLmRhdGEtYXBpIixhLGwucHJvdG90eXBlLnRvZ2dsZSkub24oImtleWRvd24uYmstYnMuZHJvcGRvd24uZGF0YS1hcGkiLGErIiwgW3JvbGU9bWVudV0sIFtyb2xlPWxpc3Rib3hdIixsLnByb3RvdHlwZS5rZXlkb3duKX0se2pxdWVyeToianF1ZXJ5In1dLGdlYXJfdXRpbHM6W2Z1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGk7IWZ1bmN0aW9uKCl7InVzZSBzdHJpY3QiO249ZnVuY3Rpb24odCxlLHIsbixvLGkpe2Z1bmN0aW9uIHModCxlKXt2YXIgcixuPTUwLG89MDtmb3Iocj0xO3I8PW47cisrKW8rPWUoTWF0aC5jb3MobSooci0uNSkvbikpKk1hdGguY29zKG0qdCooci0uNSkvbik7cmV0dXJuIDIqby9ufWZ1bmN0aW9uIGEodCxlKXt2YXIgcixuLG8saSxhPVtdLGw9W10sdT1bW10sW11dO2ZvcihyPTA7cjx0KzE7cisrKXVbMF1bcl09MCx1WzFdW3JdPTA7Zm9yKHVbMF1bMF09MSx1WzFdWzFdPTEsbz0xO288dCsxO28rKyl7Zm9yKHVbbysxXT1bMF0sbj0wO248dVtvXS5sZW5ndGgtMTtuKyspdVtvKzFdW24rMV09Mip1W29dW25dO2ZvcihuPTA7bjx1W28tMV0ubGVuZ3RoO24rKyl1W28rMV1bbl0tPXVbby0xXVtuXX1mb3Iobz0wO288PXQ7bysrKWxbb109cyhvLGUpLGFbb109MDtmb3Iobz0wO288PXQ7bysrKWZvcihpPTA7aTw9dDtpKyspYVtpXSs9bFtvXSp1W29dW2ldO3JldHVybiBhWzBdLT1zKDAsZSkvMixhfWZ1bmN0aW9uIGwodCl7dmFyIGU9Mip0LTEscj1lKihwLV8pLzIrKF8rcCkvMjtyZXR1cm4gdiooTWF0aC5jb3MocikrcipNYXRoLnNpbihyKSl9ZnVuY3Rpb24gdSh0KXt2YXIgZT0yKnQtMSxyPWUqKHAtXykvMisoXytwKS8yO3JldHVybiB2KihNYXRoLnNpbihyKS1yKk1hdGguY29zKHIpKX1mdW5jdGlvbiBoKHQsZSl7dmFyIHIsbj0xO2ZvcihyPXQtZSsxO3I8PXQ7cisrKW4qPXI7Zm9yKHI9MTtyPD1lO3IrKyluLz1yO3JldHVybiBufWZ1bmN0aW9uIGModCxlKXt2YXIgcixuLG89YSh4LGUpO2ZvcihyPTAsbj0wO248PXQ7bisrKXIrPWgodCxuKSpvW25dL2goeCxuKTtyZXR1cm4gcn12YXIgcCxfLGQsZixtPU1hdGguUEksZz10KmUvMix5PXJ8fDIwLHY9ZypNYXRoLmNvcyh5Km0vMTgwKSxiPWcrdCx4PW58fDMsdz1NYXRoLnNxcnQoYipiLXYqdikvdixNPWl8fDEsaz0uMDEsaj1bXTtmb3Iodm9pZCAwIT09byYmbzxNJiYoaz1vKSxwPU1hdGguc3FydChNKSp3LF89TWF0aC5zcXJ0KGspKncsZD0wO2Q8PXg7ZCsrKWY9e30sZi54PWMoZCxsKSxmLnk9YyhkLHUpLGoucHVzaChmKTtyZXR1cm4gan0sbz1mdW5jdGlvbih0LGUscil7ZnVuY3Rpb24gbyh0LGUpe3JldHVybiBNYXRoLnNxcnQoZSplLXQqdCkvdC1NYXRoLmFjb3ModC9lKX1mdW5jdGlvbiBpKHQsZSl7dmFyIHI9TWF0aC5zaW4oZSksbj1NYXRoLmNvcyhlKTtyZXR1cm57eDp0Lngqbi10Lnkqcix5OnQueCpyK3QueSpufX1mdW5jdGlvbiBzKHQsZSl7cmV0dXJue3g6dCpNYXRoLmNvcyhlKSx5OnQqTWF0aC5zaW4oZSl9fXZhciBhLGwsdSxoLGMscCxfLGQsZixtLGcseSx2LGIseCx3LE09dCxrPWUsaj1yfHwyMCxUPU0sUz0xLjI1Kk0sej1TLVQsUD1rKk0vMixFPVAqTWF0aC5jb3MoaipNYXRoLlBJLzE4MCksQT1QK1QsQz1QLVMsTj0xLjUqeixPPTIqTWF0aC5QSS9rLHE9byhFLFApLEQ9cSxJPU1hdGguYXRhbihOLyhOK0MpKTtmb3IoYT1NYXRoLnNxcnQoKEMrTikqKEMrTiktTipOKSxFPGEmJihhPUMreiksYT5FJiYoRC09byhFLGEpKSxsPTEsdT0uMDEsYT5FJiYodT0oYSphLUUqRSkvKEEqQS1FKkUpKSxoPXUrKGwtdSkvNCxjPW4oTSxrLGosMyx1LGgpLHA9bihNLGssaiwzLGgsbCksXz1jLmNvbmNhdChwLnNsaWNlKDEpKSxkPVtdLHg9MDt4PF8ubGVuZ3RoO3grKyliPWkoX1t4XSwtcS1PLzQpLF9beF09YixkW3hdPXt4OmIueCx5Oi1iLnl9O3JldHVybiBmPXMoYSwtTy80LUQpLG09e3g6Zi54LHk6LWYueX0seT1zKEMsTy80K0QrSSksdj1zKEMsMypPLzQtRC1JKSxnPWkoZixPKSx3PVtdLHcucHVzaCgiTSIsZi54LGYueSksYTxFJiZ3LnB1c2goIkwiLF9bMF0ueCxfWzBdLnkpLHcucHVzaCgiQyIsX1sxXS54LF9bMV0ueSxfWzJdLngsX1syXS55LF9bM10ueCxfWzNdLnksX1s0XS54LF9bNF0ueSxfWzVdLngsX1s1XS55LF9bNl0ueCxfWzZdLnkpLHcucHVzaCgiQSIsQSxBLDAsMCwwLGRbNl0ueCxkWzZdLnkpLHcucHVzaCgiQyIsZFs1XS54LGRbNV0ueSxkWzRdLngsZFs0XS55LGRbM10ueCxkWzNdLnksZFsyXS54LGRbMl0ueSxkWzFdLngsZFsxXS55LGRbMF0ueCxkWzBdLnkpLGE8RSYmdy5wdXNoKCJMIixtLngsbS55KSx2Lnk+eS55JiYody5wdXNoKCJBIixOLE4sMCwwLDEseS54LHkueSksdy5wdXNoKCJBIixDLEMsMCwwLDAsdi54LHYueSkpLHcucHVzaCgiQSIsTixOLDAsMCwxLGcueCxnLnkpLHd9LGk9ZnVuY3Rpb24odCxlLHIpe2Z1bmN0aW9uIG8odCxlKXtyZXR1cm4gTWF0aC5zcXJ0KGUqZS10KnQpL3QtTWF0aC5hY29zKHQvZSl9ZnVuY3Rpb24gaSh0LGUpe3ZhciByPU1hdGguc2luKGUpLG49TWF0aC5jb3MoZSk7cmV0dXJue3g6dC54Km4tdC55KnIseTp0Lngqcit0Lnkqbn19ZnVuY3Rpb24gcyh0LGUpe3JldHVybnt4OnQqTWF0aC5jb3MoZSkseTp0Kk1hdGguc2luKGUpfX12YXIgYSxsLHUsaCxjLHAsXyxkLGYsbSxnLHksdixiLHgsdyxNLGssaixULFMsej10LFA9ZSxFPXJ8fDIwLEE9LjYqeixDPTEuMjUqeixOPVAqei8yLE89TipNYXRoLmNvcyhFKk1hdGguUEkvMTgwKSxxPU4tQSxEPU4rQyxJPS4yNSp6LFI9RC1JLEY9MS41Kkk7Zm9yKGE9MipNYXRoLlBJL1AsbD1vKE8sTiksdT1sLHE+TyYmKHUtPW8oTyxxKSksaD1vKE8sUiktbCxjPTEuNDE0KkkvUixwPTEsXz0uMDEscT5PJiYoXz0ocSpxLU8qTykvKFIqUi1PKk8pKSxkPV8rKHAtXykvNCxmPW4oeixQLEUsMyxfLGQpLG09bih6LFAsRSwzLGQscCkseT1mLmNvbmNhdChtLnNsaWNlKDEpKSxnPVtdLGI9MDtiPHkubGVuZ3RoO2IrKyl2PWkoeVtiXSxhLzQtbCkseVtiXT12LGdbYl09e3g6di54LHk6LXYueX07cmV0dXJuIHc9e3g6Z1s2XS54LHk6Z1s2XS55fSxrPXMocSwtYS80K3UpLGo9e3g6ay54LHk6LWsueX0sVD1zKEQsYS80K2grYyksUz1zKEQsMyphLzQtaC1jKSxNPWkodyxhKSx4PVtdLHgucHVzaCgiTSIsZ1s2XS54LGdbNl0ueSkseC5wdXNoKCJDIixnWzVdLngsZ1s1XS55LGdbNF0ueCxnWzRdLnksZ1szXS54LGdbM10ueSxnWzJdLngsZ1syXS55LGdbMV0ueCxnWzFdLnksZ1swXS54LGdbMF0ueSkscTxPJiZ4LnB1c2goIkwiLGsueCxrLnkpLHgucHVzaCgiQSIscSxxLDAsMCwwLGoueCxqLnkpLHE8TyYmeC5wdXNoKCJMIix5WzBdLngseVswXS55KSx4LnB1c2goIkMiLHlbMV0ueCx5WzFdLnkseVsyXS54LHlbMl0ueSx5WzNdLngseVszXS55LHlbNF0ueCx5WzRdLnkseVs1XS54LHlbNV0ueSx5WzZdLngseVs2XS55KSxULnk8Uy55JiYoeC5wdXNoKCJBIixGLEYsMCwwLDAsVC54LFQueSkseC5wdXNoKCJBIixELEQsMCwwLDAsUy54LFMueSkpLHgucHVzaCgiQSIsRixGLDAsMCwwLE0ueCxNLnkpLHh9fSgpLGUuZXhwb3J0cz17Y3JlYXRlX2dlYXJfdG9vdGg6byxjcmVhdGVfaW50ZXJuYWxfZ2Vhcl90b290aDppfX0se31dLGdsb28yOltmdW5jdGlvbihlLHIsbil7KGZ1bmN0aW9uKGUpeyFmdW5jdGlvbihlLG8peyJmdW5jdGlvbiI9PXR5cGVvZiB0JiZ0LmFtZD90KFtdLG8pOiJ1bmRlZmluZWQiIT10eXBlb2Ygbj8oci5leHBvcnRzPW8oKSwidW5kZWZpbmVkIj09dHlwZW9mIHdpbmRvdyYmKGUuZ2xvbzI9ci5leHBvcnRzKSk6ZS5nbG9vMj1vKCl9KHRoaXMsZnVuY3Rpb24oKXt2YXIgdCxyLG4sbyxpLHMsYSxsLHUsaCxjPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIEFycmF5LmlzQXJyYXkodCkmJkFycmF5LmlzQXJyYXkoZSk/dC5jb25jYXQoZSk6dCtlfSxwPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT0wO2U8dC5sZW5ndGg7ZSsrKWlmKCFnKHRbZV0pKXJldHVybiExO3JldHVybiEwfSxfPWZ1bmN0aW9uKHQsZSl7aWYobnVsbD09ZSk7ZWxzZXtpZihBcnJheS5pc0FycmF5KGUpKXtmb3IodmFyIHI9MDtyPGUubGVuZ3RoO3IrKylpZihkKHQsZVtyXSkpcmV0dXJuITA7cmV0dXJuITF9aWYoZS5jb25zdHJ1Y3Rvcj09PU9iamVjdCl7Zm9yKHZhciBuIGluIGUpaWYodD09bilyZXR1cm4hMDtyZXR1cm4hMX1pZihlLmNvbnN0cnVjdG9yPT1TdHJpbmcpcmV0dXJuIGUuaW5kZXhPZih0KT49MH12YXIgbz1FcnJvcigiTm90IGEgY29udGFpbmVyOiAiK2UpO3Rocm93IG8ubmFtZT0iVHlwZUVycm9yIixvfSxkPWZ1bmN0aW9uIGoodCxlKXtpZihudWxsPT10fHxudWxsPT1lKTtlbHNle2lmKEFycmF5LmlzQXJyYXkodCkmJkFycmF5LmlzQXJyYXkoZSkpe2Zvcih2YXIgcj0wLG49dC5sZW5ndGg9PWUubGVuZ3RoO24mJnI8dC5sZW5ndGg7KW49aih0W3JdLGVbcl0pLHIrPTE7cmV0dXJuIG59aWYodC5jb25zdHJ1Y3Rvcj09PU9iamVjdCYmZS5jb25zdHJ1Y3Rvcj09PU9iamVjdCl7dmFyIG89T2JqZWN0LmtleXModCksaT1PYmplY3Qua2V5cyhlKTtvLnNvcnQoKSxpLnNvcnQoKTtmb3IodmFyIHMscj0wLG49aihvLGkpO24mJnI8by5sZW5ndGg7KXM9b1tyXSxuPWoodFtzXSxlW3NdKSxyKz0xO3JldHVybiBufX1yZXR1cm4gdD09ZX0sZj1mdW5jdGlvbih0LHIpe2lmKCJ1bmRlZmluZWQiPT10eXBlb2YgdHx8InVuZGVmaW5lZCIhPXR5cGVvZiB3aW5kb3cmJndpbmRvdz09PXR8fCJ1bmRlZmluZWQiIT10eXBlb2YgZSYmZT09PXQpdGhyb3ciQ2xhc3MgY29uc3RydWN0b3IgaXMgY2FsbGVkIGFzIGEgZnVuY3Rpb24uIjtmb3IodmFyIG4gaW4gdCl2b2lkIDAhPT1PYmplY3Rbbl18fCJmdW5jdGlvbiIhPXR5cGVvZiB0W25dfHx0W25dLm5vYmluZHx8KHRbbl09dFtuXS5iaW5kKHQpKTt0Ll9faW5pdF9fJiZ0Ll9faW5pdF9fLmFwcGx5KHQscil9LG09ZnVuY3Rpb24odCxlKXtpZigoIm51bWJlciI9PXR5cGVvZiB0KSsoIm51bWJlciI9PXR5cGVvZiBlKT09PTEpe2lmKHQuY29uc3RydWN0b3I9PT1TdHJpbmcpcmV0dXJuIE0uY2FsbCh0LGUpO2lmKGUuY29uc3RydWN0b3I9PT1TdHJpbmcpcmV0dXJuIE0uY2FsbChlLHQpO2lmKEFycmF5LmlzQXJyYXkoZSkpe3ZhciByPXQ7dD1lLGU9cn1pZihBcnJheS5pc0FycmF5KHQpKXtmb3IodmFyIG49W10sbz0wO288ZTtvKyspbj1uLmNvbmNhdCh0KTtyZXR1cm4gbn19cmV0dXJuIHQqZX0sZz1mdW5jdGlvbih0KXtyZXR1cm4gbnVsbD09PXR8fCJvYmplY3QiIT10eXBlb2YgdD90OnZvaWQgMCE9PXQubGVuZ3RoPyEhdC5sZW5ndGgmJnQ6dm9pZCAwIT09dC5ieXRlTGVuZ3RoPyEhdC5ieXRlTGVuZ3RoJiZ0OnQuY29uc3RydWN0b3IhPT1PYmplY3R8fCEhT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModCkubGVuZ3RoJiZ0fSx5PWZ1bmN0aW9uKHQpe3JldHVybiBBcnJheS5pc0FycmF5KHRoaXMpP3ZvaWQgdGhpcy5wdXNoKHQpOnRoaXMuYXBwZW5kLmFwcGx5KHRoaXMsYXJndW1lbnRzKX0sdj1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmNvbnN0cnVjdG9yIT09T2JqZWN0P3RoaXMuZ2V0LmFwcGx5KHRoaXMsYXJndW1lbnRzKTp2b2lkIDAhPT10aGlzW3RdP3RoaXNbdF06dm9pZCAwIT09ZT9lOm51bGx9LGI9ZnVuY3Rpb24oKXtyZXR1cm4iZnVuY3Rpb24iPT10eXBlb2YgdGhpcy5rZXlzP3RoaXMua2V5cy5hcHBseSh0aGlzLGFyZ3VtZW50cyk6T2JqZWN0LmtleXModGhpcyl9LHg9ZnVuY3Rpb24odCl7aWYodGhpcy5jb25zdHJ1Y3RvciE9PVN0cmluZylyZXR1cm4gdGhpcy5sc3RyaXAuYXBwbHkodGhpcyxhcmd1bWVudHMpO3Q9dm9pZCAwPT09dD8iIFx0XHJcbiI6dDtmb3IodmFyIGU9MDtlPHRoaXMubGVuZ3RoO2UrKylpZih0LmluZGV4T2YodGhpc1tlXSk8MClyZXR1cm4gdGhpcy5zbGljZShlKTtyZXR1cm4iIn0sdz1mdW5jdGlvbih0KXtpZighQXJyYXkuaXNBcnJheSh0aGlzKSlyZXR1cm4gdGhpcy5yZW1vdmUuYXBwbHkodGhpcyxhcmd1bWVudHMpO2Zvcih2YXIgZT0wO2U8dGhpcy5sZW5ndGg7ZSsrKWlmKGQodGhpc1tlXSx0KSlyZXR1cm4gdm9pZCB0aGlzLnNwbGljZShlLDEpO3ZhciByPUVycm9yKHQpO3Rocm93IHIubmFtZT0iVmFsdWVFcnJvciIscn0sTT1mdW5jdGlvbih0KXtpZih0aGlzLnJlcGVhdClyZXR1cm4gdGhpcy5yZXBlYXQodCk7aWYodDwxKXJldHVybiIiO2Zvcih2YXIgZT0iIixyPXRoaXMudmFsdWVPZigpO3Q+MTspMSZ0JiYoZSs9ciksdD4+PTEscis9cjtyZXR1cm4gZStyfSxrPWZ1bmN0aW9uKHQpe3JldHVybiB0aGlzLmNvbnN0cnVjdG9yIT09U3RyaW5nP3RoaXMuc3RhcnRzd2l0aC5hcHBseSh0aGlzLGFyZ3VtZW50cyk6MD09dGhpcy5pbmRleE9mKHQpfTtyZXR1cm4gaD13aW5kb3cuY29uc29sZSxsPSIwLjMiLHU9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG8saSxzLGEsbDtmb3IoZT12b2lkIDA9PT1lPyJwZXJpb2RpYyBjaGVjayI6ZSxpPVtdOzspe2lmKG49dC5nZXRFcnJvcigpLGQobix0Lk5PX0VSUk9SKXx8ZyhpKSYmZChuLGlbaS5sZW5ndGgtMV0pKWJyZWFrO3kuY2FsbChpLG4pfWlmKGkubGVuZ3RoKXtmb3Iocz0iIixhPWksIm9iamVjdCIhPXR5cGVvZiBhfHxBcnJheS5pc0FycmF5KGEpfHwoYT1PYmplY3Qua2V5cyhhKSksbD0wO2w8YS5sZW5ndGg7bCs9MSlyPWFbbF0scz1jKHMscik7dGhyb3cgbz1uZXcgRXJyb3IoIlJ1bnRpbWVFcnJvcjoiKygiT3BlbkdMIGdvdCBlcnJvcnMgKCIrZSsiKTogIitzKSksby5uYW1lPSJSdW50aW1lRXJyb3IiLG99cmV0dXJuIG51bGx9LHI9ZnVuY3Rpb24oKXtmKHRoaXMsYXJndW1lbnRzKX0sci5wcm90b3R5cGUuX2Jhc2VfY2xhc3M9T2JqZWN0LHIucHJvdG90eXBlLl9jbGFzc19uYW1lPSJHbG9vT2JqZWN0IixyLnByb3RvdHlwZS5fX2luaXRfXz1mdW5jdGlvbih0KXtpZih0aGlzLl9nbD10LHRoaXMuaGFuZGxlPW51bGwsdGhpcy5fY3JlYXRlKCksbnVsbD09PXRoaXMuaGFuZGxlKXRocm93IkFzc2VydGlvbkVycm9yOiB0aGlzLmhhbmRsZSAhPT0gbnVsbCI7cmV0dXJuIG51bGx9LHIucHJvdG90eXBlLl9jcmVhdGU9ZnVuY3Rpb24oKXt2YXIgdDt0aHJvdyB0PW5ldyBFcnJvcigiTm90SW1wbGVtZW50ZWRFcnJvcjoiKSx0Lm5hbWU9Ik5vdEltcGxlbWVudGVkRXJyb3IiLHR9LG89ZnVuY3Rpb24oKXtmKHRoaXMsYXJndW1lbnRzKX0sby5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShyLnByb3RvdHlwZSksby5wcm90b3R5cGUuX2Jhc2VfY2xhc3M9ci5wcm90b3R5cGUsby5wcm90b3R5cGUuX2NsYXNzX25hbWU9IlByb2dyYW0iLG8ucHJvdG90eXBlLlVUWVBFTUFQPXsiZmxvYXQiOiJ1bmlmb3JtMWZ2Iix2ZWMyOiJ1bmlmb3JtMmZ2Iix2ZWMzOiJ1bmlmb3JtM2Z2Iix2ZWM0OiJ1bmlmb3JtNGZ2IiwiaW50IjoidW5pZm9ybTFpdiIsaXZlYzI6InVuaWZvcm0yaXYiLGl2ZWMzOiJ1bmlmb3JtM2l2IixpdmVjNDoidW5pZm9ybTRpdiIsYm9vbDoidW5pZm9ybTFpdiIsYnZlYzI6InVuaWZvcm0yaXYiLGJ2ZWMzOiJ1bmlmb3JtM2l2IixidmVjNDoidW5pZm9ybTRpdiIsbWF0MjoidW5pZm9ybU1hdHJpeDJmdiIsbWF0MzoidW5pZm9ybU1hdHJpeDNmdiIsbWF0NDoidW5pZm9ybU1hdHJpeDRmdiIsc2FtcGxlcjFEOiJ1bmlmb3JtMWkiLHNhbXBsZXIyRDoidW5pZm9ybTFpIixzYW1wbGVyM0Q6InVuaWZvcm0xaSJ9LG8ucHJvdG90eXBlLkFUWVBFTUFQPXsiZmxvYXQiOiJ2ZXJ0ZXhBdHRyaWIxZiIsdmVjMjoidmVydGV4QXR0cmliMmYiLHZlYzM6InZlcnRleEF0dHJpYjNmIix2ZWM0OiJ2ZXJ0ZXhBdHRyaWI0ZiJ9LG8ucHJvdG90eXBlLkFUWVBFSU5GTz17ImZsb2F0IjpbMSw1MTI2XSx2ZWMyOlsyLDUxMjZdLHZlYzM6WzMsNTEyNl0sdmVjNDpbNCw1MTI2XX0sby5wcm90b3R5cGUuX2NyZWF0ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmhhbmRsZT10aGlzLl9nbC5jcmVhdGVQcm9ncmFtKCksdGhpcy5sb2NhdGlvbnM9e30sdGhpcy5fdW5zZXRfdmFyaWFibGVzPVtdLHRoaXMuX3ZhbGlkYXRlZD0hMSx0aGlzLl9zYW1wbGVycz17fSx0aGlzLl9hdHRyaWJ1dGVzPXt9LHRoaXMuX2tub3duX2ludmFsaWQ9W10sbnVsbH0sby5wcm90b3R5cGVbImRlbGV0ZSJdPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2dsLmRlbGV0ZVByb2dyYW0odGhpcy5oYW5kbGUpLG51bGx9LG8ucHJvdG90eXBlLmFjdGl2YXRlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2dsLnVzZVByb2dyYW0odGhpcy5oYW5kbGUpLG51bGx9LG8ucHJvdG90eXBlLmRlYWN0aXZhdGU9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fZ2wudXNlUHJvZ3JhbSgwKSxudWxsfSxvLnByb3RvdHlwZS5zZXRfc2hhZGVycz1mdW5jdGlvbih0LGUpe3ZhciByLG4sbyxpLHMsYSxsLHUsaCxwLF8sZCxmO2ZvcihhPXRoaXMuX2dsLHRoaXMuX2xpbmtlZD0hMSxmPWEuY3JlYXRlU2hhZGVyKGEuVkVSVEVYX1NIQURFUikscz1hLmNyZWF0ZVNoYWRlcihhLkZSQUdNRU5UX1NIQURFUiksXz1bW3QsZiwidmVydGV4Il0sW2UscywiZnJhZ21lbnQiXV0sdT0wO3U8Mjt1Kz0xKWlmKHA9X1t1XSxyPXBbMF0sbD1wWzFdLGQ9cFsyXSxhLnNoYWRlclNvdXJjZShsLHIpLGEuY29tcGlsZVNoYWRlcihsKSxoPWEuZ2V0U2hhZGVyUGFyYW1ldGVyKGwsYS5DT01QSUxFX1NUQVRVUyksIWcoaCkpdGhyb3cgaT1hLmdldFNoYWRlckluZm9Mb2cobCksbz1uZXcgRXJyb3IoIlJ1bnRpbWVFcnJvcjoiK2MoImVycm9ycyBpbiAiK2QrIiBzaGFkZXI6XG4iLGkpKSxvLm5hbWU9IlJ1bnRpbWVFcnJvciIsbztpZihhLmF0dGFjaFNoYWRlcih0aGlzLmhhbmRsZSxmKSxhLmF0dGFjaFNoYWRlcih0aGlzLmhhbmRsZSxzKSxhLmxpbmtQcm9ncmFtKHRoaXMuaGFuZGxlKSwhZyhhLmdldFByb2dyYW1QYXJhbWV0ZXIodGhpcy5oYW5kbGUsYS5MSU5LX1NUQVRVUykpKXRocm93IG49bmV3IEVycm9yKCJSdW50aW1lRXJyb3I6UHJvZ3JhbSBsaW5rIGVycm9yOlxuIithLmdldFByb2dyYW1JbmZvTG9nKHRoaXMuaGFuZGxlKSksbi5uYW1lPSJSdW50aW1lRXJyb3IiLG47cmV0dXJuIHRoaXMuX3Vuc2V0X3ZhcmlhYmxlcz10aGlzLl9nZXRfYWN0aXZlX2F0dHJpYnV0ZXNfYW5kX3VuaWZvcm1zKCksYS5kZXRhY2hTaGFkZXIodGhpcy5oYW5kbGUsZiksYS5kZXRhY2hTaGFkZXIodGhpcy5oYW5kbGUscyksYS5kZWxldGVTaGFkZXIoZiksYS5kZWxldGVTaGFkZXIocyksdGhpcy5fa25vd25faW52YWxpZD1bXSx0aGlzLl9saW5rZWQ9ITAsbnVsbH0sby5wcm90b3R5cGUuX2dldF9hY3RpdmVfYXR0cmlidXRlc19hbmRfdW5pZm9ybXM9ZnVuY3Rpb24oKXt2YXIgdCxlLHIsbixvLGkscyxhLGwsdSxoLHAsXyxkLGYsbSx2LGIseDtmb3IoYT10aGlzLl9nbCx0aGlzLmxvY2F0aW9ucz17fSxkPW5ldyB3aW5kb3cuUmVnRXhwKCIoXFx3KylcXHMqKFxcWyhcXGQrKVxcXSlcXHMqIiksbz1hLmdldFByb2dyYW1QYXJhbWV0ZXIodGhpcy5oYW5kbGUsYS5BQ1RJVkVfVU5JRk9STVMpLGU9YS5nZXRQcm9ncmFtUGFyYW1ldGVyKHRoaXMuaGFuZGxlLGEuQUNUSVZFX0FUVFJJQlVURVMpLHQ9W10sYj1bXSxtPVtbdCxlLGEuZ2V0QWN0aXZlQXR0cmliLGEuZ2V0QXR0cmliTG9jYXRpb25dLFtiLG8sYS5nZXRBY3RpdmVVbmlmb3JtLGEuZ2V0VW5pZm9ybUxvY2F0aW9uXV0sIm9iamVjdCIhPXR5cGVvZiBtfHxBcnJheS5pc0FycmF5KG0pfHwobT1PYmplY3Qua2V5cyhtKSksdj0wO3Y8bS5sZW5ndGg7dis9MSlmb3IoeD1tW3ZdLGY9eCxyPWZbMF0sbj1mWzFdLGk9ZlsyXSxzPWZbM10sbD0wO2w8bjtsKz0xKXtpZih1PWkuY2FsbChhLHRoaXMuaGFuZGxlLGwpLF89dS5uYW1lLHA9Xy5tYXRjaChkKSxnKHApKWZvcihfPXBbMV0saD0wO2g8dS5zaXplO2grPTEpeS5jYWxsKHIsWyIiK18rIlsiK2grIl0iLHUudHlwZV0pO2Vsc2UgeS5jYWxsKHIsW18sdS50eXBlXSk7dGhpcy5sb2NhdGlvbnNbX109cy5jYWxsKGEsdGhpcy5oYW5kbGUsXyl9cmV0dXJuIGMoZnVuY3Rpb24oKXt2YXIgZSxyLG4sbz1bXTtmb3Iocj10LCJvYmplY3QiIT10eXBlb2Ygcnx8QXJyYXkuaXNBcnJheShyKXx8KHI9T2JqZWN0LmtleXMocikpLG49MDtuPHIubGVuZ3RoO24rKyllPXJbbl0sby5wdXNoKGVbMF0pO3JldHVybiBvfS5hcHBseSh0aGlzKSxmdW5jdGlvbigpe3ZhciB0LGUscixuPVtdO2ZvcihlPWIsIm9iamVjdCIhPXR5cGVvZiBlfHxBcnJheS5pc0FycmF5KGUpfHwoZT1PYmplY3Qua2V5cyhlKSkscj0wO3I8ZS5sZW5ndGg7cisrKXQ9ZVtyXSxuLnB1c2godFswXSk7cmV0dXJuIG59LmFwcGx5KHRoaXMpKX0sby5wcm90b3R5cGUuc2V0X3RleHR1cmU9ZnVuY3Rpb24odCxlKXt2YXIgcixuLG87aWYoIWcodGhpcy5fbGlua2VkKSl0aHJvdyByPW5ldyBFcnJvcigiUnVudGltZUVycm9yOkNhbm5vdCBzZXQgdW5pZm9ybSB3aGVuIHByb2dyYW0gaGFzIG5vIGNvZGUiKSxyLm5hbWU9IlJ1bnRpbWVFcnJvciIscjtyZXR1cm4gbj12LmNhbGwodGhpcy5sb2NhdGlvbnMsdCwtMSksZyhuPDApPyhfKHQsdGhpcy5fa25vd25faW52YWxpZCl8fCh5LmNhbGwodGhpcy5fa25vd25faW52YWxpZCx0KSxoLmxvZygiVmFyaWFibGUgIit0KyIgaXMgbm90IGFuIGFjdGl2ZSB0ZXh0dXJlIikpLG51bGwpOihfKHQsdGhpcy5fdW5zZXRfdmFyaWFibGVzKSYmdy5jYWxsKHRoaXMuX3Vuc2V0X3ZhcmlhYmxlcyx0KSx0aGlzLmFjdGl2YXRlKCksbz1iLmNhbGwodGhpcy5fc2FtcGxlcnMpLmxlbmd0aCxfKHQsdGhpcy5fc2FtcGxlcnMpJiYobz10aGlzLl9zYW1wbGVyc1t0XVt0aGlzLl9zYW1wbGVyc1t0XS5sZW5ndGgtMV0pLHRoaXMuX3NhbXBsZXJzW3RdPVtlLl90YXJnZXQsZS5oYW5kbGUsb10sdGhpcy5fZ2wudW5pZm9ybTFpKG4sbyksbnVsbCl9LG8ucHJvdG90eXBlLnNldF91bmlmb3JtPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdTtpZighZyh0aGlzLl9saW5rZWQpKXRocm93IGk9bmV3IEVycm9yKCJSdW50aW1lRXJyb3I6Q2Fubm90IHNldCB1bmlmb3JtIHdoZW4gcHJvZ3JhbSBoYXMgbm8gY29kZSIpLGkubmFtZT0iUnVudGltZUVycm9yIixpO2lmKGE9di5jYWxsKHRoaXMubG9jYXRpb25zLHQsLTEpLGcoYTwwKSlyZXR1cm4gXyh0LHRoaXMuX2tub3duX2ludmFsaWQpfHwoeS5jYWxsKHRoaXMuX2tub3duX2ludmFsaWQsdCksaC5sb2coIlZhcmlhYmxlICIrdCsiIGlzIG5vdCBhbiBhY3RpdmUgdW5pZm9ybSIpKSxudWxsO2lmKF8odCx0aGlzLl91bnNldF92YXJpYWJsZXMpJiZ3LmNhbGwodGhpcy5fdW5zZXRfdmFyaWFibGVzLHQpLG89MSxrLmNhbGwoZSwibWF0Iil8fChuPXYuY2FsbCh7ImludCI6ImZsb2F0Iixib29sOiJmbG9hdCJ9LGUseC5jYWxsKGUsImliIikpLG89TWF0aC5mbG9vcihyLmxlbmd0aC90aGlzLkFUWVBFSU5GT1tuXVswXSkpLGcobz4xKSlmb3IobD0wO2w8bztsKz0xKV8oIiIrdCsiWyIrbCsiXSIsdGhpcy5fdW5zZXRfdmFyaWFibGVzKSYmKHU9IiIrdCsiWyIrbCsiXSIsXyh1LHRoaXMuX3Vuc2V0X3ZhcmlhYmxlcykmJncuY2FsbCh0aGlzLl91bnNldF92YXJpYWJsZXMsdSkpO3JldHVybiBzPXRoaXMuVVRZUEVNQVBbZV0sdGhpcy5hY3RpdmF0ZSgpLGsuY2FsbChlLCJtYXQiKT90aGlzLl9nbFtzXShhLCExLHIpOnRoaXMuX2dsW3NdKGEsciksbnVsbH0sby5wcm90b3R5cGUuc2V0X2F0dHJpYnV0ZT1mdW5jdGlvbih0LGUscixuLG8pe3ZhciBpLHMsbCx1LGMscCxkLGY7aWYobj12b2lkIDA9PT1uPzA6bixvPXZvaWQgMD09PW8/MDpvLCFnKHRoaXMuX2xpbmtlZCkpdGhyb3cgcz1uZXcgRXJyb3IoIlJ1bnRpbWVFcnJvcjpDYW5ub3Qgc2V0IGF0dHJpYnV0ZSB3aGVuIHByb2dyYW0gaGFzIG5vIGNvZGUiKSxzLm5hbWU9IlJ1bnRpbWVFcnJvciIscztyZXR1cm4gcD1yIGluc3RhbmNlb2YgYSxjPXYuY2FsbCh0aGlzLmxvY2F0aW9ucyx0LC0xKSxnKGM8MCk/KF8odCx0aGlzLl9rbm93bl9pbnZhbGlkKXx8KHkuY2FsbCh0aGlzLl9rbm93bl9pbnZhbGlkLHQpLGcocCkmJmcobz4wKXx8aC5sb2coIlZhcmlhYmxlICIrdCsiIGlzIG5vdCBhbiBhY3RpdmUgYXR0cmlidXRlIikpLG51bGwpOihfKHQsdGhpcy5fdW5zZXRfdmFyaWFibGVzKSYmdy5jYWxsKHRoaXMuX3Vuc2V0X3ZhcmlhYmxlcyx0KSx0aGlzLmFjdGl2YXRlKCksZyhwKT8oZj10aGlzLkFUWVBFSU5GT1tlXSxkPWZbMF0sdT1mWzFdLGw9InZlcnRleEF0dHJpYlBvaW50ZXIiLGk9W2QsdSx0aGlzLl9nbC5GQUxTRSxuLG9dLHRoaXMuX2F0dHJpYnV0ZXNbdF09W3IuaGFuZGxlLGMsbCxpXSk6KGw9dGhpcy5BVFlQRU1BUFtlXSx0aGlzLl9hdHRyaWJ1dGVzW3RdPVswLGMsbCxyXSksbnVsbCl9LG8ucHJvdG90eXBlLl9wcmVfZHJhdz1mdW5jdGlvbigpe3ZhciB0LGUscixuLG8saSxzLGEsbCx1LGgscDt0aGlzLmFjdGl2YXRlKCkscz10aGlzLl9zYW1wbGVycztmb3IocCBpbiBzKXMuaGFzT3duUHJvcGVydHkocCkmJihwPXNbcF0saT1wLGw9aVswXSxhPWlbMV0sdT1pWzJdLHRoaXMuX2dsLmFjdGl2ZVRleHR1cmUoYyh0aGlzLl9nbC5URVhUVVJFMCx1KSksdGhpcy5fZ2wuYmluZFRleHR1cmUobCxhKSk7bz10aGlzLl9hdHRyaWJ1dGVzO2ZvcihwIGluIG8pby5oYXNPd25Qcm9wZXJ0eShwKSYmKHA9b1twXSxuPXAsaD1uWzBdLGU9blsxXSxyPW5bMl0sdD1uWzNdLGcoaCk/KHRoaXMuX2dsLmJpbmRCdWZmZXIodGhpcy5fZ2wuQVJSQVlfQlVGRkVSLGgpLHRoaXMuX2dsLmVuYWJsZVZlcnRleEF0dHJpYkFycmF5KGUpLHRoaXMuX2dsW3JdLmFwcGx5KHRoaXMuX2dsLFtdLmNvbmNhdChbZV0sdCkpKToodGhpcy5fZ2wuYmluZEJ1ZmZlcih0aGlzLl9nbC5BUlJBWV9CVUZGRVIsbnVsbCksdGhpcy5fZ2wuZGlzYWJsZVZlcnRleEF0dHJpYkFycmF5KGUpLHRoaXMuX2dsW3JdLmFwcGx5KHRoaXMuX2dsLFtdLmNvbmNhdChbZV0sdCkpKSk7cmV0dXJuIGcodGhpcy5fdmFsaWRhdGVkKXx8KHRoaXMuX3ZhbGlkYXRlZD0hMCx0aGlzLl92YWxpZGF0ZSgpKSxudWxsfSxvLnByb3RvdHlwZS5fdmFsaWRhdGU9ZnVuY3Rpb24oKXt2YXIgdDtpZih0aGlzLl91bnNldF92YXJpYWJsZXMubGVuZ3RoJiZoLmxvZygiUHJvZ3JhbSBoYXMgdW5zZXQgdmFyaWFibGVzOiAiK3RoaXMuX3Vuc2V0X3ZhcmlhYmxlcyksdGhpcy5fZ2wudmFsaWRhdGVQcm9ncmFtKHRoaXMuaGFuZGxlKSwhZyh0aGlzLl9nbC5nZXRQcm9ncmFtUGFyYW1ldGVyKHRoaXMuaGFuZGxlLHRoaXMuX2dsLlZBTElEQVRFX1NUQVRVUykpKXRocm93IGgubG9nKHRoaXMuX2dsLmdldFByb2dyYW1JbmZvTG9nKHRoaXMuaGFuZGxlKSksdD1uZXcgRXJyb3IoIlJ1bnRpbWVFcnJvcjpQcm9ncmFtIHZhbGlkYXRpb24gZXJyb3IiKSx0Lm5hbWU9IlJ1bnRpbWVFcnJvciIsdDtyZXR1cm4gbnVsbH0sby5wcm90b3R5cGUuZHJhdz1mdW5jdGlvbih0LGUpe3ZhciByLG8saSxzLGE7aWYoIWcodGhpcy5fbGlua2VkKSl0aHJvdyBvPW5ldyBFcnJvcigiUnVudGltZUVycm9yOkNhbm5vdCBkcmF3IHByb2dyYW0gaWYgY29kZSBoYXMgbm90IGJlZW4gc2V0Iiksby5uYW1lPSJSdW50aW1lRXJyb3IiLG87cmV0dXJuIHUodGhpcy5fZ2wsImJlZm9yZSBkcmF3IiksZyhlIGluc3RhbmNlb2Ygbik/KHRoaXMuX3ByZV9kcmF3KCksZS5hY3RpdmF0ZSgpLHI9ZS5fYnVmZmVyX3NpemUvMixzPXRoaXMuX2dsLlVOU0lHTkVEX1NIT1JULHRoaXMuX2dsLmRyYXdFbGVtZW50cyh0LHIscywwKSxlLmRlYWN0aXZhdGUoKSk6KGE9ZSxpPWFbMF0scj1hWzFdLGcocikmJih0aGlzLl9wcmVfZHJhdygpLHRoaXMuX2dsLmRyYXdBcnJheXModCxpLHIpKSksdSh0aGlzLl9nbCwiYWZ0ZXIgZHJhdyIpLG51bGx9LHQ9ZnVuY3Rpb24oKXtmKHRoaXMsYXJndW1lbnRzKX0sdC5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShyLnByb3RvdHlwZSksdC5wcm90b3R5cGUuX2Jhc2VfY2xhc3M9ci5wcm90b3R5cGUsdC5wcm90b3R5cGUuX2NsYXNzX25hbWU9IkJ1ZmZlciIsCnQucHJvdG90eXBlLl90YXJnZXQ9bnVsbCx0LnByb3RvdHlwZS5fdXNhZ2U9MzUwNDgsdC5wcm90b3R5cGUuX2NyZWF0ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmhhbmRsZT10aGlzLl9nbC5jcmVhdGVCdWZmZXIoKSx0aGlzLl9idWZmZXJfc2l6ZT0wLG51bGx9LHQucHJvdG90eXBlWyJkZWxldGUiXT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9nbC5kZWxldGVCdWZmZXIodGhpcy5oYW5kbGUpLG51bGx9LHQucHJvdG90eXBlLmFjdGl2YXRlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2dsLmJpbmRCdWZmZXIodGhpcy5fdGFyZ2V0LHRoaXMuaGFuZGxlKSxudWxsfSx0LnByb3RvdHlwZS5kZWFjdGl2YXRlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2dsLmJpbmRCdWZmZXIodGhpcy5fdGFyZ2V0LG51bGwpLG51bGx9LHQucHJvdG90eXBlLnNldF9zaXplPWZ1bmN0aW9uKHQpe3JldHVybiBkKHQsdGhpcy5fYnVmZmVyX3NpemUpfHwodGhpcy5hY3RpdmF0ZSgpLHRoaXMuX2dsLmJ1ZmZlckRhdGEodGhpcy5fdGFyZ2V0LHQsdGhpcy5fdXNhZ2UpLHRoaXMuX2J1ZmZlcl9zaXplPXQpLG51bGx9LHQucHJvdG90eXBlLnNldF9kYXRhPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuYWN0aXZhdGUoKSx0aGlzLl9nbC5idWZmZXJTdWJEYXRhKHRoaXMuX3RhcmdldCx0LGUpLG51bGx9LGE9ZnVuY3Rpb24oKXtmKHRoaXMsYXJndW1lbnRzKX0sYS5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZSh0LnByb3RvdHlwZSksYS5wcm90b3R5cGUuX2Jhc2VfY2xhc3M9dC5wcm90b3R5cGUsYS5wcm90b3R5cGUuX2NsYXNzX25hbWU9IlZlcnRleEJ1ZmZlciIsYS5wcm90b3R5cGUuX3RhcmdldD0zNDk2MixuPWZ1bmN0aW9uKCl7Zih0aGlzLGFyZ3VtZW50cyl9LG4ucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodC5wcm90b3R5cGUpLG4ucHJvdG90eXBlLl9iYXNlX2NsYXNzPXQucHJvdG90eXBlLG4ucHJvdG90eXBlLl9jbGFzc19uYW1lPSJJbmRleEJ1ZmZlciIsbi5wcm90b3R5cGUuX3RhcmdldD0zNDk2MyxpPWZ1bmN0aW9uKCl7Zih0aGlzLGFyZ3VtZW50cyl9LGkucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoci5wcm90b3R5cGUpLGkucHJvdG90eXBlLl9iYXNlX2NsYXNzPXIucHJvdG90eXBlLGkucHJvdG90eXBlLl9jbGFzc19uYW1lPSJUZXh0dXJlMkQiLGkucHJvdG90eXBlLl90YXJnZXQ9MzU1MyxpLnByb3RvdHlwZS5fdHlwZXM9e0ludDhBcnJheTo1MTIwLFVpbnQ4QXJyYXk6NTEyMSxJbnQxNkFycmF5OjUxMjIsVWludDE2QXJyYXk6NTEyMyxJbnQzMkFycmF5OjUxMjQsVWludDMyQXJyYXk6NTEyNSxGbG9hdDMyQXJyYXk6NTEyNn0saS5wcm90b3R5cGUuX2NyZWF0ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLmhhbmRsZT10aGlzLl9nbC5jcmVhdGVUZXh0dXJlKCksdGhpcy5fc2hhcGVfZm9ybWF0PW51bGwsbnVsbH0saS5wcm90b3R5cGVbImRlbGV0ZSJdPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2dsLmRlbGV0ZVRleHR1cmUodGhpcy5oYW5kbGUpLG51bGx9LGkucHJvdG90eXBlLmFjdGl2YXRlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2dsLmJpbmRUZXh0dXJlKHRoaXMuX3RhcmdldCx0aGlzLmhhbmRsZSksbnVsbH0saS5wcm90b3R5cGUuZGVhY3RpdmF0ZT1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9nbC5iaW5kVGV4dHVyZSh0aGlzLl90YXJnZXQsMCksbnVsbH0saS5wcm90b3R5cGUuX2dldF9hbGlnbm1lbnQ9ZnVuY3Rpb24odCl7dmFyIGUscixuLG87Zm9yKHI9WzQsOCwyLDFdLG49ciwib2JqZWN0IiE9dHlwZW9mIG58fEFycmF5LmlzQXJyYXkobil8fChuPU9iamVjdC5rZXlzKG4pKSxvPTA7bzxuLmxlbmd0aDtvKz0xKWlmKGU9bltvXSxkKHQlZSwwKSlyZXR1cm4gZTtyZXR1cm4gbnVsbH0saS5wcm90b3R5cGUuc2V0X3dyYXBwaW5nPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRoaXMuYWN0aXZhdGUoKSx0aGlzLl9nbC50ZXhQYXJhbWV0ZXJmKHRoaXMuX3RhcmdldCx0aGlzLl9nbC5URVhUVVJFX1dSQVBfUyx0KSx0aGlzLl9nbC50ZXhQYXJhbWV0ZXJmKHRoaXMuX3RhcmdldCx0aGlzLl9nbC5URVhUVVJFX1dSQVBfVCxlKSxudWxsfSxpLnByb3RvdHlwZS5zZXRfaW50ZXJwb2xhdGlvbj1mdW5jdGlvbih0LGUpe3JldHVybiB0aGlzLmFjdGl2YXRlKCksdGhpcy5fZ2wudGV4UGFyYW1ldGVyZih0aGlzLl90YXJnZXQsdGhpcy5fZ2wuVEVYVFVSRV9NSU5fRklMVEVSLHQpLHRoaXMuX2dsLnRleFBhcmFtZXRlcmYodGhpcy5fdGFyZ2V0LHRoaXMuX2dsLlRFWFRVUkVfTUFHX0ZJTFRFUixlKSxudWxsfSxpLnByb3RvdHlwZS5zZXRfc2l6ZT1mdW5jdGlvbih0LGUpe3ZhciByLG4sbztyZXR1cm4gbj10LHI9blswXSxvPW5bMV0sZChbcixvLGVdLHRoaXMuX3NoYXBlX2Zvcm1hdCl8fCh0aGlzLl9zaGFwZV9mb3JtYXQ9W3IsbyxlXSx0aGlzLmFjdGl2YXRlKCksdGhpcy5fZ2wudGV4SW1hZ2UyRCh0aGlzLl90YXJnZXQsMCxlLG8sciwwLGUsdGhpcy5fZ2wuVU5TSUdORURfQllURSxudWxsKSksdGhpcy51X3NoYXBlPVtyLG9dLG51bGx9LGkucHJvdG90eXBlLnNldF9kYXRhPWZ1bmN0aW9uKHQsZSxyKXt2YXIgbixvLGkscyxhLGwsdSxoLGMscCxfO2lmKGQoZS5sZW5ndGgsMikmJihlPVtlWzBdLGVbMV0sMV0pLHRoaXMuYWN0aXZhdGUoKSxzPXRoaXMuX3NoYXBlX2Zvcm1hdFsyXSx1PWUsbD11WzBdLGM9dVsxXSxuPXVbMl0saD10LF89aFswXSxwPWhbMV0sYT12LmNhbGwodGhpcy5fdHlwZXMsci5jb25zdHJ1Y3Rvci5uYW1lLG51bGwpLG51bGw9PT1hKXRocm93IGk9bmV3IEVycm9yKCJWYWx1ZUVycm9yOiIrKCJUeXBlICIrci5jb25zdHJ1Y3Rvci5uYW1lKyIgbm90IGFsbG93ZWQgZm9yIHRleHR1cmUiKSksaS5uYW1lPSJWYWx1ZUVycm9yIixpO3JldHVybiBvPXRoaXMuX2dldF9hbGlnbm1lbnQobShlW2UubGVuZ3RoLTJdLGVbZS5sZW5ndGgtMV0pKSxkKG8sNCl8fHRoaXMuX2dsLnBpeGVsU3RvcmVpKHRoaXMuX2dsLlVOUEFDS19BTElHTk1FTlQsbyksdGhpcy5fZ2wudGV4U3ViSW1hZ2UyRCh0aGlzLl90YXJnZXQsMCxwLF8sYyxsLHMsYSxyKSxkKG8sNCl8fHRoaXMuX2dsLnBpeGVsU3RvcmVpKHRoaXMuX2dsLlVOUEFDS19BTElHTk1FTlQsNCksbnVsbH0scz1mdW5jdGlvbigpe2YodGhpcyxhcmd1bWVudHMpfSxzLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGkucHJvdG90eXBlKSxzLnByb3RvdHlwZS5fYmFzZV9jbGFzcz1pLnByb3RvdHlwZSxzLnByb3RvdHlwZS5fY2xhc3NfbmFtZT0iVGV4dHVyZTNETGlrZSIscy5wcm90b3R5cGUuR0xTTF9TQU1QTEVfTkVBUkVTVD0iXG4gICAgICAgIHZlYzQgc2FtcGxlM0Qoc2FtcGxlcjJEIHRleCwgdmVjMyB0ZXhjb29yZCwgdmVjMyBzaGFwZSwgdmVjMiB0aWxlcykge1xuICAgICAgICAgICAgc2hhcGUueHl6ID0gc2hhcGUuenl4OyAgLy8gc2lsbHkgcm93LW1ham9yIGNvbnZlbnRpb25cbiAgICAgICAgICAgIGZsb2F0IG5yb3dzID0gdGlsZXMueSwgbmNvbHMgPSB0aWxlcy54O1xuICAgICAgICAgICAgLy8gRG9uJ3QgbGV0IGFkamFjZW50IGZyYW1lcyBiZSBpbnRlcnBvbGF0ZWQgaW50byB0aGlzIG9uZVxuICAgICAgICAgICAgdGV4Y29vcmQueCA9IG1pbih0ZXhjb29yZC54ICogc2hhcGUueCwgc2hhcGUueCAtIDAuNSk7XG4gICAgICAgICAgICB0ZXhjb29yZC54ID0gbWF4KDAuNSwgdGV4Y29vcmQueCkgLyBzaGFwZS54O1xuICAgICAgICAgICAgdGV4Y29vcmQueSA9IG1pbih0ZXhjb29yZC55ICogc2hhcGUueSwgc2hhcGUueSAtIDAuNSk7XG4gICAgICAgICAgICB0ZXhjb29yZC55ID0gbWF4KDAuNSwgdGV4Y29vcmQueSkgLyBzaGFwZS55O1xuXG4gICAgICAgICAgICBmbG9hdCB6aW5kZXggPSBmbG9vcih0ZXhjb29yZC56ICogc2hhcGUueik7XG5cbiAgICAgICAgICAgIC8vIERvIGEgbG9va3VwIGluIHRoZSAyRCB0ZXh0dXJlXG4gICAgICAgICAgICBmbG9hdCB1ID0gKG1vZCh6aW5kZXgsIG5jb2xzKSArIHRleGNvb3JkLngpIC8gbmNvbHM7XG4gICAgICAgICAgICBmbG9hdCB2ID0gKGZsb29yKHppbmRleCAvIG5jb2xzKSArIHRleGNvb3JkLnkpIC8gbnJvd3M7XG5cbiAgICAgICAgICAgIHJldHVybiB0ZXh0dXJlMkQodGV4LCB2ZWMyKHUsdikpO1xuICAgICAgICB9XG4gICAgIixzLnByb3RvdHlwZS5HTFNMX1NBTVBMRV9MSU5FQVI9IlxuICAgICAgICB2ZWM0IHNhbXBsZTNEKHNhbXBsZXIyRCB0ZXgsIHZlYzMgdGV4Y29vcmQsIHZlYzMgc2hhcGUsIHZlYzIgdGlsZXMpIHtcbiAgICAgICAgICAgIHNoYXBlLnh5eiA9IHNoYXBlLnp5eDsgIC8vIHNpbGx5IHJvdy1tYWpvciBjb252ZW50aW9uXG4gICAgICAgICAgICBmbG9hdCBucm93cyA9IHRpbGVzLnksIG5jb2xzID0gdGlsZXMueDtcbiAgICAgICAgICAgIC8vIERvbid0IGxldCBhZGphY2VudCBmcmFtZXMgYmUgaW50ZXJwb2xhdGVkIGludG8gdGhpcyBvbmVcbiAgICAgICAgICAgIHRleGNvb3JkLnggPSBtaW4odGV4Y29vcmQueCAqIHNoYXBlLngsIHNoYXBlLnggLSAwLjUpO1xuICAgICAgICAgICAgdGV4Y29vcmQueCA9IG1heCgwLjUsIHRleGNvb3JkLngpIC8gc2hhcGUueDtcbiAgICAgICAgICAgIHRleGNvb3JkLnkgPSBtaW4odGV4Y29vcmQueSAqIHNoYXBlLnksIHNoYXBlLnkgLSAwLjUpO1xuICAgICAgICAgICAgdGV4Y29vcmQueSA9IG1heCgwLjUsIHRleGNvb3JkLnkpIC8gc2hhcGUueTtcblxuICAgICAgICAgICAgZmxvYXQgeiA9IHRleGNvb3JkLnogKiBzaGFwZS56O1xuICAgICAgICAgICAgZmxvYXQgemluZGV4MSA9IGZsb29yKHopO1xuICAgICAgICAgICAgZmxvYXQgdTEgPSAobW9kKHppbmRleDEsIG5jb2xzKSArIHRleGNvb3JkLngpIC8gbmNvbHM7XG4gICAgICAgICAgICBmbG9hdCB2MSA9IChmbG9vcih6aW5kZXgxIC8gbmNvbHMpICsgdGV4Y29vcmQueSkgLyBucm93cztcblxuICAgICAgICAgICAgZmxvYXQgemluZGV4MiA9IHppbmRleDEgKyAxLjA7XG4gICAgICAgICAgICBmbG9hdCB1MiA9IChtb2QoemluZGV4MiwgbmNvbHMpICsgdGV4Y29vcmQueCkgLyBuY29scztcbiAgICAgICAgICAgIGZsb2F0IHYyID0gKGZsb29yKHppbmRleDIgLyBuY29scykgKyB0ZXhjb29yZC55KSAvIG5yb3dzO1xuXG4gICAgICAgICAgICB2ZWM0IHMxID0gdGV4dHVyZTJEKHRleCwgdmVjMih1MSwgdjEpKTtcbiAgICAgICAgICAgIHZlYzQgczIgPSB0ZXh0dXJlMkQodGV4LCB2ZWMyKHUyLCB2MikpO1xuXG4gICAgICAgICAgICByZXR1cm4gczEgKiAoemluZGV4MiAtIHopICsgczIgKiAoeiAtIHppbmRleDEpO1xuICAgICAgICB9XG4gICAgIixzLnByb3RvdHlwZS5fZ2V0X3RpbGVfaW5mbz1mdW5jdGlvbih0KXt2YXIgZSxyLG4sbztpZihyPXRoaXMuX2dsLmdldFBhcmFtZXRlcih0aGlzLl9nbC5NQVhfVEVYVFVSRV9TSVpFKSxvPU1hdGguZmxvb3Ioci90WzFdKSxvPU1hdGgubWluKG8sdFswXSksbj13aW5kb3cuTWF0aC5jZWlsKHRbMF0vbyksZyhtKG4sdFsyXSk+cikpdGhyb3cgZT1uZXcgRXJyb3IoIlJ1bnRpbWVFcnJvcjoiKygiQ2Fubm90IGZpdCAzRCBkYXRhIHdpdGggc2hhcGUgIit0KyIgb250byBzaW11bGF0ZWQgMkQgdGV4dHVyZS4iKSksZS5uYW1lPSJSdW50aW1lRXJyb3IiLGU7cmV0dXJuW28sbl19LHMucHJvdG90eXBlLnNldF9zaXplPWZ1bmN0aW9uKHQsZSl7dmFyIHIsbixvLGk7cmV0dXJuIGk9dGhpcy5fZ2V0X3RpbGVfaW5mbyh0KSxuPWlbMF0scj1pWzFdLG89W20odFsxXSxuKSxtKHRbMl0scildLHMucHJvdG90eXBlLl9iYXNlX2NsYXNzLnNldF9zaXplLmNhbGwodGhpcyxvLGUpLHRoaXMudV9zaGFwZT1bdFswXSx0WzFdLHRbMl1dLHRoaXMudV90aWxlcz1bcixuXSxudWxsfSxzLnByb3RvdHlwZS5zZXRfZGF0YT1mdW5jdGlvbih0LGUscil7dmFyIG4sbyxpLGEsbCx1LGgsYyxfLGYsZyx5LHY7aWYoZChlLmxlbmd0aCwzKSYmKGU9W2VbMF0sZVsxXSxlWzJdLDFdKSwhcChmdW5jdGlvbigpe3ZhciBlLHIsbixvPVtdO2ZvcihyPXQsIm9iamVjdCIhPXR5cGVvZiByfHxBcnJheS5pc0FycmF5KHIpfHwocj1PYmplY3Qua2V5cyhyKSksbj0wO248ci5sZW5ndGg7bisrKWU9cltuXSxvLnB1c2goZChlLDApKTtyZXR1cm4gb30uYXBwbHkodGhpcykpKXRocm93IGE9bmV3IEVycm9yKCJWYWx1ZUVycm9yOlRleHR1cmUzRExpa2UgZG9lcyBub3Qgc3VwcG9ydCBub256ZXJvIG9mZnNldCAoZm9yIG5vdykiKSxhLm5hbWU9IlZhbHVlRXJyb3IiLGE7aWYoXz10aGlzLl9nZXRfdGlsZV9pbmZvKGUpLHU9X1swXSxsPV9bMV0sYz1bbShlWzFdLHUpLG0oZVsyXSxsKSxlWzNdXSxkKGwsMSkpcy5wcm90b3R5cGUuX2Jhc2VfY2xhc3Muc2V0X2RhdGEuY2FsbCh0aGlzLFswLDBdLGMscik7ZWxzZSBmb3Iobj1yLmNvbnN0cnVjdG9yLHY9bmV3IG4obShtKGNbMF0sY1sxXSksY1syXSkpLHMucHJvdG90eXBlLl9iYXNlX2NsYXNzLnNldF9kYXRhLmNhbGwodGhpcyxbMCwwXSxjLHYpLHk9MDt5PGVbMF07eSs9MSlmPVtNYXRoLmZsb29yKHkvbCkseSVsXSxoPWZbMF0sbz1mWzFdLGk9TWF0aC5mbG9vcihyLmxlbmd0aC9lWzBdKSxnPXIuc2xpY2UobSh5LGkpLG0oeSsxLGkpKSxzLnByb3RvdHlwZS5fYmFzZV9jbGFzcy5zZXRfZGF0YS5jYWxsKHRoaXMsW20oaCxlWzFdKSxtKG8sZVsyXSldLGUuc2xpY2UoMSksZyk7cmV0dXJuIG51bGx9LHtCdWZmZXI6dCxHbG9vT2JqZWN0OnIsSW5kZXhCdWZmZXI6bixQcm9ncmFtOm8sVGV4dHVyZTJEOmksVGV4dHVyZTNETGlrZTpzLFZlcnRleEJ1ZmZlcjphLGNoZWNrX2Vycm9yOnUsY29uc29sZTpofX0pfSkuY2FsbCh0aGlzLCJ1bmRlZmluZWQiIT10eXBlb2YgZ2xvYmFsP2dsb2JhbDoidW5kZWZpbmVkIiE9dHlwZW9mIHNlbGY/c2VsZjoidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdz93aW5kb3c6e30pfSx7fV0sa2l3aTpbZnVuY3Rpb24odCxlLHIpey8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KfCBDb3B5cmlnaHQgKGMpIDIwMTQsIE51Y2xlaWMgRGV2ZWxvcG1lbnQgVGVhbS4KfAp8IERpc3RyaWJ1dGVkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgTW9kaWZpZWQgQlNEIExpY2Vuc2UuCnwKfCBUaGUgZnVsbCBsaWNlbnNlIGlzIGluIHRoZSBmaWxlIENPUFlJTkcudHh0LCBkaXN0cmlidXRlZCB3aXRoIHRoaXMgc29mdHdhcmUuCnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KdmFyIG47IWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUodCl7cmV0dXJuIHQgaW5zdGFuY2VvZiBBcnJheT9uZXcgbCh0KTp0Ll9faXRlcl9fKCl9ZnVuY3Rpb24gcih0KXtyZXR1cm4gdCBpbnN0YW5jZW9mIEFycmF5P25ldyB1KHQpOnQuX19yZXZlcnNlZF9fKCl9ZnVuY3Rpb24gbih0KXtyZXR1cm4gdC5fX25leHRfXygpfWZ1bmN0aW9uIG8odCl7aWYodCBpbnN0YW5jZW9mIEFycmF5KXJldHVybiB0LnNsaWNlKCk7Zm9yKHZhciBlLHI9W10sbj10Ll9faXRlcl9fKCk7dm9pZCAwIT09KGU9bi5fX25leHRfXygpKTspci5wdXNoKGUpO3JldHVybiByfWZ1bmN0aW9uIGkodCxlKXtpZih0IGluc3RhbmNlb2YgQXJyYXkpe2Zvcih2YXIgcj0wLG49dC5sZW5ndGg7cjxuOysrcilpZihlKHRbcl0pPT09ITEpcmV0dXJufWVsc2UgZm9yKHZhciBvLGk9dC5fX2l0ZXJfXygpO3ZvaWQgMCE9PShvPWkuX19uZXh0X18oKSk7KWlmKGUobyk9PT0hMSlyZXR1cm59ZnVuY3Rpb24gcyh0LGUpe3ZhciByPVtdO2lmKHQgaW5zdGFuY2VvZiBBcnJheSlmb3IodmFyIG49MCxvPXQubGVuZ3RoO248bzsrK24pci5wdXNoKGUodFtuXSkpO2Vsc2UgZm9yKHZhciBpLHM9dC5fX2l0ZXJfXygpO3ZvaWQgMCE9PShpPXMuX19uZXh0X18oKSk7KXIucHVzaChlKGkpKTtyZXR1cm4gcn1mdW5jdGlvbiBhKHQsZSl7dmFyIHIsbj1bXTtpZih0IGluc3RhbmNlb2YgQXJyYXkpZm9yKHZhciBvPTAsaT10Lmxlbmd0aDtvPGk7KytvKXI9dFtvXSxlKHIpJiZuLnB1c2gocik7ZWxzZSBmb3IodmFyIHM9dC5fX2l0ZXJfXygpO3ZvaWQgMCE9PShyPXMuX19uZXh0X18oKSk7KWUocikmJm4ucHVzaChyKTtyZXR1cm4gbn12YXIgbD1mdW5jdGlvbigpe2Z1bmN0aW9uIHQodCxlKXsidW5kZWZpbmVkIj09dHlwZW9mIGUmJihlPTApLHRoaXMuX2FycmF5PXQsdGhpcy5faW5kZXg9TWF0aC5tYXgoMCxNYXRoLm1pbihlLHQubGVuZ3RoKSl9cmV0dXJuIHQucHJvdG90eXBlLl9fbmV4dF9fPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2FycmF5W3RoaXMuX2luZGV4KytdfSx0LnByb3RvdHlwZS5fX2l0ZXJfXz1mdW5jdGlvbigpe3JldHVybiB0aGlzfSx0fSgpO3QuQXJyYXlJdGVyYXRvcj1sO3ZhciB1PWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCh0LGUpeyJ1bmRlZmluZWQiPT10eXBlb2YgZSYmKGU9dC5sZW5ndGgpLHRoaXMuX2FycmF5PXQsdGhpcy5faW5kZXg9TWF0aC5tYXgoMCxNYXRoLm1pbihlLHQubGVuZ3RoKSl9cmV0dXJuIHQucHJvdG90eXBlLl9fbmV4dF9fPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2FycmF5Wy0tdGhpcy5faW5kZXhdfSx0LnByb3RvdHlwZS5fX2l0ZXJfXz1mdW5jdGlvbigpe3JldHVybiB0aGlzfSx0fSgpO3QuUmV2ZXJzZUFycmF5SXRlcmF0b3I9dSx0Lml0ZXI9ZSx0LnJldmVyc2VkPXIsdC5uZXh0PW4sdC5hc0FycmF5PW8sdC5mb3JFYWNoPWksdC5tYXA9cyx0LmZpbHRlcj1hfShufHwobj17fSkpOy8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KfCBDb3B5cmlnaHQgKGMpIDIwMTQsIE51Y2xlaWMgRGV2ZWxvcG1lbnQgVGVhbS4KfAp8IERpc3RyaWJ1dGVkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgTW9kaWZpZWQgQlNEIExpY2Vuc2UuCnwKfCBUaGUgZnVsbCBsaWNlbnNlIGlzIGluIHRoZSBmaWxlIENPUFlJTkcudHh0LCBkaXN0cmlidXRlZCB3aXRoIHRoaXMgc29mdHdhcmUuCnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KdmFyIG47IWZ1bmN0aW9uKHQpe3ZhciBlPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCh0LGUpe3RoaXMuZmlyc3Q9dCx0aGlzLnNlY29uZD1lfXJldHVybiB0LnByb3RvdHlwZS5jb3B5PWZ1bmN0aW9uKCl7cmV0dXJuIG5ldyB0KHRoaXMuZmlyc3QsdGhpcy5zZWNvbmQpfSx0fSgpO3QuUGFpcj1lfShufHwobj17fSkpOy8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KfCBDb3B5cmlnaHQgKGMpIDIwMTQsIE51Y2xlaWMgRGV2ZWxvcG1lbnQgVGVhbS4KfAp8IERpc3RyaWJ1dGVkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgTW9kaWZpZWQgQlNEIExpY2Vuc2UuCnwKfCBUaGUgZnVsbCBsaWNlbnNlIGlzIGluIHRoZSBmaWxlIENPUFlJTkcudHh0LCBkaXN0cmlidXRlZCB3aXRoIHRoaXMgc29mdHdhcmUuCnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KdmFyIG47IWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUodCxlLHIpe2Zvcih2YXIgbixvLGk9MCxzPXQubGVuZ3RoO3M+MDspbj1zPj4xLG89aStuLHIodFtvXSxlKTwwPyhpPW8rMSxzLT1uKzEpOnM9bjtyZXR1cm4gaX1mdW5jdGlvbiByKHQscixuKXt2YXIgbz1lKHQscixuKTtpZihvPT09dC5sZW5ndGgpcmV0dXJuLTE7dmFyIGk9dFtvXTtyZXR1cm4gMCE9PW4oaSxyKT8tMTpvfWZ1bmN0aW9uIG4odCxyLG4pe3ZhciBvPWUodCxyLG4pO2lmKG8hPT10Lmxlbmd0aCl7dmFyIGk9dFtvXTtpZigwPT09bihpLHIpKXJldHVybiBpfX1mdW5jdGlvbiBvKGUscil7dmFyIG49dC5hc0FycmF5KGUpLG89bi5sZW5ndGg7aWYobzw9MSlyZXR1cm4gbjtuLnNvcnQocik7Zm9yKHZhciBpPVtuWzBdXSxzPTEsYT0wO3M8bzsrK3Mpe3ZhciBsPW5bc107MCE9PXIoaVthXSxsKSYmKGkucHVzaChsKSwrK2EpfXJldHVybiBpfWZ1bmN0aW9uIGkodCxlLHIpe2Zvcih2YXIgbj0wLG89MCxpPXQubGVuZ3RoLHM9ZS5sZW5ndGg7bjxpJiZvPHM7KXt2YXIgYT1yKHRbbl0sZVtvXSk7aWYoYTwwKSsrbjtlbHNle2lmKCEoYT4wKSlyZXR1cm4hMTsrK299fXJldHVybiEwfWZ1bmN0aW9uIHModCxlLHIpe3ZhciBuPXQubGVuZ3RoLG89ZS5sZW5ndGg7aWYobj5vKXJldHVybiExO2Zvcih2YXIgaT0wLHM9MDtpPG4mJnM8bzspe3ZhciBhPXIodFtpXSxlW3NdKTtpZihhPDApcmV0dXJuITE7YT4wPysrczooKytpLCsrcyl9cmV0dXJuIShpPG4pfWZ1bmN0aW9uIGEodCxlLHIpe2Zvcih2YXIgbj0wLG89MCxpPXQubGVuZ3RoLHM9ZS5sZW5ndGgsYT1bXTtuPGkmJm88czspe3ZhciBsPXRbbl0sdT1lW29dLGg9cihsLHUpO2g8MD8oYS5wdXNoKGwpLCsrbik6aD4wPyhhLnB1c2godSksKytvKTooYS5wdXNoKGwpLCsrbiwrK28pfWZvcig7bjxpOylhLnB1c2godFtuXSksKytuO2Zvcig7bzxzOylhLnB1c2goZVtvXSksKytvO3JldHVybiBhfWZ1bmN0aW9uIGwodCxlLHIpe2Zvcih2YXIgbj0wLG89MCxpPXQubGVuZ3RoLHM9ZS5sZW5ndGgsYT1bXTtuPGkmJm88czspe3ZhciBsPXRbbl0sdT1lW29dLGg9cihsLHUpO2g8MD8rK246aD4wPysrbzooYS5wdXNoKGwpLCsrbiwrK28pfXJldHVybiBhfWZ1bmN0aW9uIHUodCxlLHIpe2Zvcih2YXIgbj0wLG89MCxpPXQubGVuZ3RoLHM9ZS5sZW5ndGgsYT1bXTtuPGkmJm88czspe3ZhciBsPXRbbl0sdT1lW29dLGg9cihsLHUpO2g8MD8oYS5wdXNoKGwpLCsrbik6aD4wPysrbzooKytuLCsrbyl9Zm9yKDtuPGk7KWEucHVzaCh0W25dKSwrK247cmV0dXJuIGF9ZnVuY3Rpb24gaCh0LGUscil7Zm9yKHZhciBuPTAsbz0wLGk9dC5sZW5ndGgscz1lLmxlbmd0aCxhPVtdO248aSYmbzxzOyl7dmFyIGw9dFtuXSx1PWVbb10saD1yKGwsdSk7aDwwPyhhLnB1c2gobCksKytuKTpoPjA/KGEucHVzaCh1KSwrK28pOigrK24sKytvKX1mb3IoO248aTspYS5wdXNoKHRbbl0pLCsrbjtmb3IoO288czspYS5wdXNoKGVbb10pLCsrbztyZXR1cm4gYX10Lmxvd2VyQm91bmQ9ZSx0LmJpbmFyeVNlYXJjaD1yLHQuYmluYXJ5RmluZD1uLHQuYXNTZXQ9byx0LnNldElzRGlzam9pbnQ9aSx0LnNldElzU3Vic2V0PXMsdC5zZXRVbmlvbj1hLHQuc2V0SW50ZXJzZWN0aW9uPWwsdC5zZXREaWZmZXJlbmNlPXUsdC5zZXRTeW1tZXRyaWNEaWZmZXJlbmNlPWh9KG58fChuPXt9KSk7LyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp8IENvcHlyaWdodCAoYykgMjAxNCwgTnVjbGVpYyBEZXZlbG9wbWVudCBUZWFtLgp8CnwgRGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBNb2RpZmllZCBCU0QgTGljZW5zZS4KfAp8IFRoZSBmdWxsIGxpY2Vuc2UgaXMgaW4gdGhlIGZpbGUgQ09QWUlORy50eHQsIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyBzb2Z0d2FyZS4KfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwp2YXIgbjshZnVuY3Rpb24odCl7dmFyIGU9ZnVuY3Rpb24oKXtmdW5jdGlvbiBlKCl7dGhpcy5fYXJyYXk9W119cmV0dXJuIGUucHJvdG90eXBlLnNpemU9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fYXJyYXkubGVuZ3RofSxlLnByb3RvdHlwZS5lbXB0eT1mdW5jdGlvbigpe3JldHVybiAwPT09dGhpcy5fYXJyYXkubGVuZ3RofSxlLnByb3RvdHlwZS5pdGVtQXQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2FycmF5W3RdfSxlLnByb3RvdHlwZS50YWtlQXQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2FycmF5LnNwbGljZSh0LDEpWzBdfSxlLnByb3RvdHlwZS5jbGVhcj1mdW5jdGlvbigpe3RoaXMuX2FycmF5PVtdfSxlLnByb3RvdHlwZS5zd2FwPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuX2FycmF5O3RoaXMuX2FycmF5PXQuX2FycmF5LHQuX2FycmF5PWV9LGUucHJvdG90eXBlLl9faXRlcl9fPWZ1bmN0aW9uKCl7cmV0dXJuIHQuaXRlcih0aGlzLl9hcnJheSl9LGUucHJvdG90eXBlLl9fcmV2ZXJzZWRfXz1mdW5jdGlvbigpe3JldHVybiB0LnJldmVyc2VkKHRoaXMuX2FycmF5KX0sZX0oKTt0LkFycmF5QmFzZT1lfShufHwobj17fSkpOy8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KfCBDb3B5cmlnaHQgKGMpIDIwMTQsIE51Y2xlaWMgRGV2ZWxvcG1lbnQgVGVhbS4KfAp8IERpc3RyaWJ1dGVkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgTW9kaWZpZWQgQlNEIExpY2Vuc2UuCnwKfCBUaGUgZnVsbCBsaWNlbnNlIGlzIGluIHRoZSBmaWxlIENPUFlJTkcudHh0LCBkaXN0cmlidXRlZCB3aXRoIHRoaXMgc29mdHdhcmUuCnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KdmFyIG4sbz10aGlzLl9fZXh0ZW5kc3x8ZnVuY3Rpb24odCxlKXtmdW5jdGlvbiByKCl7dGhpcy5jb25zdHJ1Y3Rvcj10fWZvcih2YXIgbiBpbiBlKWUuaGFzT3duUHJvcGVydHkobikmJih0W25dPWVbbl0pO3IucHJvdG90eXBlPWUucHJvdG90eXBlLHQucHJvdG90eXBlPW5ldyByfTshZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSh0KXtyZXR1cm4gZnVuY3Rpb24oZSxyKXtyZXR1cm4gdChlLmZpcnN0LHIpfX1mdW5jdGlvbiByKHQsZSxyKXtmb3IodmFyIG49MCxvPTAsaT10Lmxlbmd0aCxzPWUubGVuZ3RoLGE9W107bjxpJiZvPHM7KXt2YXIgbD10W25dLHU9ZVtvXSxoPXIobC5maXJzdCx1LmZpcnN0KTtoPDA/KGEucHVzaChsLmNvcHkoKSksKytuKTpoPjA/KGEucHVzaCh1LmNvcHkoKSksKytvKTooYS5wdXNoKHUuY29weSgpKSwrK24sKytvKX1mb3IoO248aTspYS5wdXNoKHRbbl0uY29weSgpKSwrK247Zm9yKDtvPHM7KWEucHVzaChlW29dLmNvcHkoKSksKytvO3JldHVybiBhfXZhciBuPWZ1bmN0aW9uKG4pe2Z1bmN0aW9uIGkodCl7bi5jYWxsKHRoaXMpLHRoaXMuX2NvbXBhcmU9dCx0aGlzLl93cmFwcGVkPWUodCl9cmV0dXJuIG8oaSxuKSxpLnByb3RvdHlwZS5jb21wYXJpdG9yPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NvbXBhcmV9LGkucHJvdG90eXBlLmluZGV4T2Y9ZnVuY3Rpb24oZSl7cmV0dXJuIHQuYmluYXJ5U2VhcmNoKHRoaXMuX2FycmF5LGUsdGhpcy5fd3JhcHBlZCl9LGkucHJvdG90eXBlLmNvbnRhaW5zPWZ1bmN0aW9uKGUpe3JldHVybiB0LmJpbmFyeVNlYXJjaCh0aGlzLl9hcnJheSxlLHRoaXMuX3dyYXBwZWQpPj0wfSxpLnByb3RvdHlwZS5maW5kPWZ1bmN0aW9uKGUpe3JldHVybiB0LmJpbmFyeUZpbmQodGhpcy5fYXJyYXksZSx0aGlzLl93cmFwcGVkKX0saS5wcm90b3R5cGUuc2V0RGVmYXVsdD1mdW5jdGlvbihlLHIpe3ZhciBuPXRoaXMuX2FycmF5LG89dC5sb3dlckJvdW5kKG4sZSx0aGlzLl93cmFwcGVkKTtpZihvPT09bi5sZW5ndGgpe3ZhciBpPW5ldyB0LlBhaXIoZSxyKCkpO3JldHVybiBuLnB1c2goaSksaX12YXIgcz1uW29dO2lmKDAhPT10aGlzLl9jb21wYXJlKHMuZmlyc3QsZSkpe3ZhciBpPW5ldyB0LlBhaXIoZSxyKCkpO3JldHVybiBuLnNwbGljZShvLDAsaSksaX1yZXR1cm4gc30saS5wcm90b3R5cGUuaW5zZXJ0PWZ1bmN0aW9uKGUscil7dmFyIG49dGhpcy5fYXJyYXksbz10Lmxvd2VyQm91bmQobixlLHRoaXMuX3dyYXBwZWQpO2lmKG89PT1uLmxlbmd0aCl7dmFyIGk9bmV3IHQuUGFpcihlLHIpO3JldHVybiBuLnB1c2goaSksaX12YXIgcz1uW29dO2lmKDAhPT10aGlzLl9jb21wYXJlKHMuZmlyc3QsZSkpe3ZhciBpPW5ldyB0LlBhaXIoZSxyKTtyZXR1cm4gbi5zcGxpY2UobywwLGkpLGl9cmV0dXJuIHMuc2Vjb25kPXIsc30saS5wcm90b3R5cGUudXBkYXRlPWZ1bmN0aW9uKGUpe3ZhciBuPXRoaXM7aWYoZSBpbnN0YW5jZW9mIGkpe3ZhciBvPWU7dGhpcy5fYXJyYXk9cih0aGlzLl9hcnJheSxvLl9hcnJheSx0aGlzLl9jb21wYXJlKX1lbHNlIHQuZm9yRWFjaChlLGZ1bmN0aW9uKHQpe24uaW5zZXJ0KHQuZmlyc3QsdC5zZWNvbmQpfSl9LGkucHJvdG90eXBlLmVyYXNlPWZ1bmN0aW9uKGUpe3ZhciByPXRoaXMuX2FycmF5LG49dC5iaW5hcnlTZWFyY2gocixlLHRoaXMuX3dyYXBwZWQpO2lmKCEobjwwKSlyZXR1cm4gci5zcGxpY2UobiwxKVswXX0saS5wcm90b3R5cGUuY29weT1mdW5jdGlvbigpe2Zvcih2YXIgdD1uZXcgaSh0aGlzLl9jb21wYXJlKSxlPXQuX2FycmF5LHI9dGhpcy5fYXJyYXksbj0wLG89ci5sZW5ndGg7bjxvOysrbillLnB1c2gocltuXS5jb3B5KCkpO3JldHVybiB0fSxpfSh0LkFycmF5QmFzZSk7dC5Bc3NvY2lhdGl2ZUFycmF5PW59KG58fChuPXt9KSk7LyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp8IENvcHlyaWdodCAoYykgMjAxNCwgTnVjbGVpYyBEZXZlbG9wbWVudCBUZWFtLgp8CnwgRGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBNb2RpZmllZCBCU0QgTGljZW5zZS4KfAp8IFRoZSBmdWxsIGxpY2Vuc2UgaXMgaW4gdGhlIGZpbGUgQ09QWUlORy50eHQsIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyBzb2Z0d2FyZS4KfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwp2YXIgbjshZnVuY3Rpb24odCl7ZnVuY3Rpb24gZShlLG4pe3JldHVybiBlIGluc3RhbmNlb2Ygcj9lLl9hcnJheTp0LmFzU2V0KGUsbil9dmFyIHI9ZnVuY3Rpb24ocil7ZnVuY3Rpb24gbih0KXtyLmNhbGwodGhpcyksdGhpcy5fY29tcGFyZT10fXJldHVybiBvKG4sciksbi5wcm90b3R5cGUuY29tcGFyaXRvcj1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9jb21wYXJlfSxuLnByb3RvdHlwZS5pbmRleE9mPWZ1bmN0aW9uKGUpe3JldHVybiB0LmJpbmFyeVNlYXJjaCh0aGlzLl9hcnJheSxlLHRoaXMuX2NvbXBhcmUpfSxuLnByb3RvdHlwZS5jb250YWlucz1mdW5jdGlvbihlKXtyZXR1cm4gdC5iaW5hcnlTZWFyY2godGhpcy5fYXJyYXksZSx0aGlzLl9jb21wYXJlKT49MH0sbi5wcm90b3R5cGUuaW5zZXJ0PWZ1bmN0aW9uKGUpe3ZhciByPXRoaXMuX2FycmF5LG49dC5sb3dlckJvdW5kKHIsZSx0aGlzLl9jb21wYXJlKTtyZXR1cm4gbj09PXIubGVuZ3RoPyhyLnB1c2goZSksITApOjAhPT10aGlzLl9jb21wYXJlKHJbbl0sZSkmJihyLnNwbGljZShuLDAsZSksITApfSxuLnByb3RvdHlwZS5lcmFzZT1mdW5jdGlvbihlKXt2YXIgcj10aGlzLl9hcnJheSxuPXQuYmluYXJ5U2VhcmNoKHIsZSx0aGlzLl9jb21wYXJlKTtyZXR1cm4hKG48MCkmJihyLnNwbGljZShuLDEpLCEwKX0sbi5wcm90b3R5cGUuY29weT1mdW5jdGlvbigpe3ZhciB0PW5ldyBuKHRoaXMuX2NvbXBhcmUpO3JldHVybiB0Ll9hcnJheT10aGlzLl9hcnJheS5zbGljZSgpLHR9LG4ucHJvdG90eXBlLmlzRGlzam9pbnQ9ZnVuY3Rpb24ocil7dmFyIG49dGhpcy5fY29tcGFyZSxvPWUocixuKTtyZXR1cm4gdC5zZXRJc0Rpc2pvaW50KHRoaXMuX2FycmF5LG8sbil9LG4ucHJvdG90eXBlLmlzU3Vic2V0PWZ1bmN0aW9uKHIpe3ZhciBuPXRoaXMuX2NvbXBhcmUsbz1lKHIsbik7cmV0dXJuIHQuc2V0SXNTdWJzZXQodGhpcy5fYXJyYXksbyxuKX0sbi5wcm90b3R5cGUuaXNTdXBlcnNldD1mdW5jdGlvbihyKXt2YXIgbj10aGlzLl9jb21wYXJlLG89ZShyLG4pO3JldHVybiB0LnNldElzU3Vic2V0KG8sdGhpcy5fYXJyYXksbil9LG4ucHJvdG90eXBlLnVuaW9uPWZ1bmN0aW9uKHIpe3ZhciBvPXRoaXMuX2NvbXBhcmUsaT1uZXcgbihvKSxzPWUocixvKTtyZXR1cm4gaS5fYXJyYXk9dC5zZXRVbmlvbih0aGlzLl9hcnJheSxzLG8pLGl9LG4ucHJvdG90eXBlLmludGVyc2VjdGlvbj1mdW5jdGlvbihyKXt2YXIgbz10aGlzLl9jb21wYXJlLGk9bmV3IG4obykscz1lKHIsbyk7cmV0dXJuIGkuX2FycmF5PXQuc2V0SW50ZXJzZWN0aW9uKHRoaXMuX2FycmF5LHMsbyksaX0sbi5wcm90b3R5cGUuZGlmZmVyZW5jZT1mdW5jdGlvbihyKXt2YXIgbz10aGlzLl9jb21wYXJlLGk9bmV3IG4obykscz1lKHIsbyk7cmV0dXJuIGkuX2FycmF5PXQuc2V0RGlmZmVyZW5jZSh0aGlzLl9hcnJheSxzLG8pLGl9LG4ucHJvdG90eXBlLnN5bW1ldHJpY0RpZmZlcmVuY2U9ZnVuY3Rpb24ocil7dmFyIG89dGhpcy5fY29tcGFyZSxpPW5ldyBuKG8pLHM9ZShyLG8pO3JldHVybiBpLl9hcnJheT10LnNldFN5bW1ldHJpY0RpZmZlcmVuY2UodGhpcy5fYXJyYXkscyxvKSxpfSxuLnByb3RvdHlwZS51bmlvblVwZGF0ZT1mdW5jdGlvbihyKXt2YXIgbj10aGlzLl9jb21wYXJlLG89ZShyLG4pO3RoaXMuX2FycmF5PXQuc2V0VW5pb24odGhpcy5fYXJyYXksbyxuKX0sbi5wcm90b3R5cGUuaW50ZXJzZWN0aW9uVXBkYXRlPWZ1bmN0aW9uKHIpe3ZhciBuPXRoaXMuX2NvbXBhcmUsbz1lKHIsbik7dGhpcy5fYXJyYXk9dC5zZXRJbnRlcnNlY3Rpb24odGhpcy5fYXJyYXksbyxuKX0sbi5wcm90b3R5cGUuZGlmZmVyZW5jZVVwZGF0ZT1mdW5jdGlvbihyKXt2YXIgbj10aGlzLl9jb21wYXJlLG89ZShyLG4pO3RoaXMuX2FycmF5PXQuc2V0RGlmZmVyZW5jZSh0aGlzLl9hcnJheSxvLG4pfSxuLnByb3RvdHlwZS5zeW1tZXRyaWNEaWZmZXJlbmNlVXBkYXRlPWZ1bmN0aW9uKHIpe3ZhciBuPXRoaXMuX2NvbXBhcmUsbz1lKHIsbik7dGhpcy5fYXJyYXk9dC5zZXRTeW1tZXRyaWNEaWZmZXJlbmNlKHRoaXMuX2FycmF5LG8sbil9LG59KHQuQXJyYXlCYXNlKTt0LlVuaXF1ZUFycmF5PXJ9KG58fChuPXt9KSk7LyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp8IENvcHlyaWdodCAoYykgMjAxNCwgTnVjbGVpYyBEZXZlbG9wbWVudCBUZWFtLgp8CnwgRGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBNb2RpZmllZCBCU0QgTGljZW5zZS4KfAp8IFRoZSBmdWxsIGxpY2Vuc2UgaXMgaW4gdGhlIGZpbGUgQ09QWUlORy50eHQsIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyBzb2Z0d2FyZS4KfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwovKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnwgQ29weXJpZ2h0IChjKSAyMDE0LCBOdWNsZWljIERldmVsb3BtZW50IFRlYW0uCnwKfCBEaXN0cmlidXRlZCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIE1vZGlmaWVkIEJTRCBMaWNlbnNlLgp8CnwgVGhlIGZ1bGwgbGljZW5zZSBpcyBpbiB0aGUgZmlsZSBDT1BZSU5HLnR4dCwgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzIHNvZnR3YXJlLgp8LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCnZhciBpOyFmdW5jdGlvbih0KXshZnVuY3Rpb24odCl7dFt0LkxlPTBdPSJMZSIsdFt0LkdlPTFdPSJHZSIsdFt0LkVxPTJdPSJFcSJ9KHQuT3BlcmF0b3J8fCh0Lk9wZXJhdG9yPXt9KSk7dmFyIGU9KHQuT3BlcmF0b3IsZnVuY3Rpb24oKXtmdW5jdGlvbiBlKGUsbixvKXsidW5kZWZpbmVkIj09dHlwZW9mIG8mJihvPXQuU3RyZW5ndGgucmVxdWlyZWQpLHRoaXMuX2lkPXIrKyx0aGlzLl9vcGVyYXRvcj1uLHRoaXMuX2V4cHJlc3Npb249ZSx0aGlzLl9zdHJlbmd0aD10LlN0cmVuZ3RoLmNsaXAobyl9cmV0dXJuIGUuQ29tcGFyZT1mdW5jdGlvbih0LGUpe3JldHVybiB0LmlkKCktZS5pZCgpfSxlLnByb3RvdHlwZS5pZD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9pZH0sZS5wcm90b3R5cGUuZXhwcmVzc2lvbj1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9leHByZXNzaW9ufSxlLnByb3RvdHlwZS5vcD1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9vcGVyYXRvcn0sZS5wcm90b3R5cGUuc3RyZW5ndGg9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fc3RyZW5ndGh9LGV9KCkpO3QuQ29uc3RyYWludD1lO3ZhciByPTB9KGl8fChpPXt9KSk7LyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp8IENvcHlyaWdodCAoYykgMjAxNCwgTnVjbGVpYyBEZXZlbG9wbWVudCBUZWFtLgp8CnwgRGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBNb2RpZmllZCBCU0QgTGljZW5zZS4KfAp8IFRoZSBmdWxsIGxpY2Vuc2UgaXMgaW4gdGhlIGZpbGUgQ09QWUlORy50eHQsIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyBzb2Z0d2FyZS4KfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwp2YXIgaTshZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSh0KXtyZXR1cm4gbmV3IG4uQXNzb2NpYXRpdmVBcnJheSh0KX10LmNyZWF0ZU1hcD1lfShpfHwoaT17fSkpOy8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KfCBDb3B5cmlnaHQgKGMpIDIwMTQsIE51Y2xlaWMgRGV2ZWxvcG1lbnQgVGVhbS4KfAp8IERpc3RyaWJ1dGVkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgTW9kaWZpZWQgQlNEIExpY2Vuc2UuCnwKfCBUaGUgZnVsbCBsaWNlbnNlIGlzIGluIHRoZSBmaWxlIENPUFlJTkcudHh0LCBkaXN0cmlidXRlZCB3aXRoIHRoaXMgc29mdHdhcmUuCnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KdmFyIGk7IWZ1bmN0aW9uKHQpe3ZhciBlPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gdCh0KXsidW5kZWZpbmVkIj09dHlwZW9mIHQmJih0PSIiKSx0aGlzLl92YWx1ZT0wLHRoaXMuX2NvbnRleHQ9bnVsbCx0aGlzLl9pZD1yKyssdGhpcy5fbmFtZT10fXJldHVybiB0LkNvbXBhcmU9ZnVuY3Rpb24odCxlKXtyZXR1cm4gdC5pZCgpLWUuaWQoKX0sdC5wcm90b3R5cGUuaWQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5faWR9LHQucHJvdG90eXBlLm5hbWU9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fbmFtZX0sdC5wcm90b3R5cGUuc2V0TmFtZT1mdW5jdGlvbih0KXt0aGlzLl9uYW1lPXR9LHQucHJvdG90eXBlLmNvbnRleHQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fY29udGV4dH0sdC5wcm90b3R5cGUuc2V0Q29udGV4dD1mdW5jdGlvbih0KXt0aGlzLl9jb250ZXh0PXR9LHQucHJvdG90eXBlLnZhbHVlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3ZhbHVlfSx0LnByb3RvdHlwZS5zZXRWYWx1ZT1mdW5jdGlvbih0KXt0aGlzLl92YWx1ZT10fSx0fSgpO3QuVmFyaWFibGU9ZTt2YXIgcj0wfShpfHwoaT17fSkpOy8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KfCBDb3B5cmlnaHQgKGMpIDIwMTQsIE51Y2xlaWMgRGV2ZWxvcG1lbnQgVGVhbS4KfAp8IERpc3RyaWJ1dGVkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgTW9kaWZpZWQgQlNEIExpY2Vuc2UuCnwKfCBUaGUgZnVsbCBsaWNlbnNlIGlzIGluIHRoZSBmaWxlIENPUFlJTkcudHh0LCBkaXN0cmlidXRlZCB3aXRoIHRoaXMgc29mdHdhcmUuCnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KdmFyIGk7IWZ1bmN0aW9uKHQpe2Z1bmN0aW9uIGUoZSl7Zm9yKHZhciByPTAsbj1mdW5jdGlvbigpe3JldHVybiAwfSxvPXQuY3JlYXRlTWFwKHQuVmFyaWFibGUuQ29tcGFyZSksaT0wLHM9ZS5sZW5ndGg7aTxzOysraSl7dmFyIGE9ZVtpXTtpZigibnVtYmVyIj09dHlwZW9mIGEpcis9YTtlbHNlIGlmKGEgaW5zdGFuY2VvZiB0LlZhcmlhYmxlKW8uc2V0RGVmYXVsdChhLG4pLnNlY29uZCs9MTtlbHNle2lmKCEoYSBpbnN0YW5jZW9mIEFycmF5KSl0aHJvdyBuZXcgRXJyb3IoImludmFsaWQgRXhwcmVzc2lvbiBhcmd1bWVudDogIithKTtpZigyIT09YS5sZW5ndGgpdGhyb3cgbmV3IEVycm9yKCJhcnJheSBtdXN0IGhhdmUgbGVuZ3RoIDIiKTt2YXIgbD1hWzBdLHU9YVsxXTtpZigibnVtYmVyIiE9dHlwZW9mIGwpdGhyb3cgbmV3IEVycm9yKCJhcnJheSBpdGVtIDAgbXVzdCBiZSBhIG51bWJlciIpO2lmKCEodSBpbnN0YW5jZW9mIHQuVmFyaWFibGUpKXRocm93IG5ldyBFcnJvcigiYXJyYXkgaXRlbSAxIG11c3QgYmUgYSB2YXJpYWJsZSIpO28uc2V0RGVmYXVsdCh1LG4pLnNlY29uZCs9bH19cmV0dXJue3Rlcm1zOm8sY29uc3RhbnQ6cn19dmFyIHI9ZnVuY3Rpb24oKXtmdW5jdGlvbiB0KCl7dmFyIHQ9ZShhcmd1bWVudHMpO3RoaXMuX3Rlcm1zPXQudGVybXMsdGhpcy5fY29uc3RhbnQ9dC5jb25zdGFudH1yZXR1cm4gdC5wcm90b3R5cGUudGVybXM9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fdGVybXN9LHQucHJvdG90eXBlLmNvbnN0YW50PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NvbnN0YW50fSx0LnByb3RvdHlwZS52YWx1ZT1mdW5jdGlvbigpe3ZhciB0PXRoaXMuX2NvbnN0YW50O3JldHVybiBuLmZvckVhY2godGhpcy5fdGVybXMsZnVuY3Rpb24oZSl7dCs9ZS5maXJzdC52YWx1ZSgpKmUuc2Vjb25kfSksdH0sdH0oKTt0LkV4cHJlc3Npb249cn0oaXx8KGk9e30pKTsvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnwgQ29weXJpZ2h0IChjKSAyMDE0LCBOdWNsZWljIERldmVsb3BtZW50IFRlYW0uCnwKfCBEaXN0cmlidXRlZCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIE1vZGlmaWVkIEJTRCBMaWNlbnNlLgp8CnwgVGhlIGZ1bGwgbGljZW5zZSBpcyBpbiB0aGUgZmlsZSBDT1BZSU5HLnR4dCwgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzIHNvZnR3YXJlLgp8LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCnZhciBpOyFmdW5jdGlvbih0KXshZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSh0LGUscixuKXsidW5kZWZpbmVkIj09dHlwZW9mIG4mJihuPTEpO3ZhciBvPTA7cmV0dXJuIG8rPTFlNipNYXRoLm1heCgwLE1hdGgubWluKDFlMyx0Km4pKSxvKz0xZTMqTWF0aC5tYXgoMCxNYXRoLm1pbigxZTMsZSpuKSksbys9TWF0aC5tYXgoMCxNYXRoLm1pbigxZTMscipuKSl9ZnVuY3Rpb24gcihlKXtyZXR1cm4gTWF0aC5tYXgoMCxNYXRoLm1pbih0LnJlcXVpcmVkLGUpKX10LmNyZWF0ZT1lLHQucmVxdWlyZWQ9ZSgxZTMsMWUzLDFlMyksdC5zdHJvbmc9ZSgxLDAsMCksdC5tZWRpdW09ZSgwLDEsMCksdC53ZWFrPWUoMCwwLDEpLHQuY2xpcD1yfSh0LlN0cmVuZ3RofHwodC5TdHJlbmd0aD17fSkpO3QuU3RyZW5ndGh9KGl8fChpPXt9KSk7LyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp8IENvcHlyaWdodCAoYykgMjAxNCwgTnVjbGVpYyBEZXZlbG9wbWVudCBUZWFtLgp8CnwgRGlzdHJpYnV0ZWQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBNb2RpZmllZCBCU0QgTGljZW5zZS4KfAp8IFRoZSBmdWxsIGxpY2Vuc2UgaXMgaW4gdGhlIGZpbGUgQ09QWUlORy50eHQsIGRpc3RyaWJ1dGVkIHdpdGggdGhpcyBzb2Z0d2FyZS4KfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qLwp2YXIgaTshZnVuY3Rpb24odCl7ZnVuY3Rpb24gZSh0KXt2YXIgZT0xZS04O3JldHVybiB0PDA/LXQ8ZTp0PGV9ZnVuY3Rpb24gcigpe3JldHVybiB0LmNyZWF0ZU1hcCh0LkNvbnN0cmFpbnQuQ29tcGFyZSl9ZnVuY3Rpb24gbigpe3JldHVybiB0LmNyZWF0ZU1hcChsLkNvbXBhcmUpfWZ1bmN0aW9uIG8oKXtyZXR1cm4gdC5jcmVhdGVNYXAodC5WYXJpYWJsZS5Db21wYXJlKX1mdW5jdGlvbiBpKCl7cmV0dXJuIHQuY3JlYXRlTWFwKHQuVmFyaWFibGUuQ29tcGFyZSl9dmFyIHM9ZnVuY3Rpb24oKXtmdW5jdGlvbiBzKCl7dGhpcy5fY25NYXA9cigpLHRoaXMuX3Jvd01hcD1uKCksdGhpcy5fdmFyTWFwPW8oKSx0aGlzLl9lZGl0TWFwPWkoKSx0aGlzLl9pbmZlYXNpYmxlUm93cz1bXSx0aGlzLl9vYmplY3RpdmU9bmV3IGgsdGhpcy5fYXJ0aWZpY2lhbD1udWxsLHRoaXMuX2lkVGljaz0wfXJldHVybiBzLnByb3RvdHlwZS5hZGRDb25zdHJhaW50PWZ1bmN0aW9uKHQpe3ZhciByPXRoaXMuX2NuTWFwLmZpbmQodCk7aWYodm9pZCAwIT09cil0aHJvdyBuZXcgRXJyb3IoImR1cGxpY2F0ZSBjb25zdHJhaW50Iik7dmFyIG49dGhpcy5fY3JlYXRlUm93KHQpLG89bi5yb3csaT1uLnRhZyxzPXRoaXMuX2Nob29zZVN1YmplY3QobyxpKTtpZigwPT09cy50eXBlKCkmJm8uYWxsRHVtbWllcygpKXtpZighZShvLmNvbnN0YW50KCkpKXRocm93IG5ldyBFcnJvcigidW5zYXRpc2ZpYWJsZSBjb25zdHJhaW50Iik7cz1pLm1hcmtlcn1pZigwPT09cy50eXBlKCkpe2lmKCF0aGlzLl9hZGRXaXRoQXJ0aWZpY2lhbFZhcmlhYmxlKG8pKXtmb3IodmFyIGEsbD0iIix1PTA7YT10Ll9leHByZXNzaW9uLl90ZXJtcy5fYXJyYXlbdV07dSsrKWwrPWEuZmlyc3QuX25hbWUsbCs9IiwgIjt2YXIgaD1bIkxFIiwiR0UiLCJFUSJdO3Rocm93IG5ldyBFcnJvcigiVW5zYXRpc2ZpYWJsZSBjb25zdHJhaW50IFsiK2wuc2xpY2UoMCwtMikrIl0gb3BlcmF0b3I6ICIraFt0Ll9vcGVyYXRvcl0pfX1lbHNlIG8uc29sdmVGb3IocyksdGhpcy5fc3Vic3RpdHV0ZShzLG8pLHRoaXMuX3Jvd01hcC5pbnNlcnQocyxvKTt0aGlzLl9jbk1hcC5pbnNlcnQodCxpKSx0aGlzLl9vcHRpbWl6ZSh0aGlzLl9vYmplY3RpdmUpfSxzLnByb3RvdHlwZS5yZW1vdmVDb25zdHJhaW50PWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuX2NuTWFwLmVyYXNlKHQpO2lmKHZvaWQgMD09PWUpdGhyb3cgbmV3IEVycm9yKCJ1bmtub3duIGNvbnN0cmFpbnQiKTt0aGlzLl9yZW1vdmVDb25zdHJhaW50RWZmZWN0cyh0LGUuc2Vjb25kKTt2YXIgcj1lLnNlY29uZC5tYXJrZXIsbj10aGlzLl9yb3dNYXAuZXJhc2Uocik7aWYodm9pZCAwPT09bil7dmFyIG89dGhpcy5fZ2V0TWFya2VyTGVhdmluZ1N5bWJvbChyKTtpZigwPT09by50eXBlKCkpdGhyb3cgbmV3IEVycm9yKCJmYWlsZWQgdG8gZmluZCBsZWF2aW5nIHJvdyIpO249dGhpcy5fcm93TWFwLmVyYXNlKG8pLG4uc2Vjb25kLnNvbHZlRm9yRXgobyxyKSx0aGlzLl9zdWJzdGl0dXRlKHIsbi5zZWNvbmQpfXRoaXMuX29wdGltaXplKHRoaXMuX29iamVjdGl2ZSl9LHMucHJvdG90eXBlLmhhc0NvbnN0cmFpbnQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2NuTWFwLmNvbnRhaW5zKHQpfSxzLnByb3RvdHlwZS5hZGRFZGl0VmFyaWFibGU9ZnVuY3Rpb24oZSxyKXt2YXIgbj10aGlzLl9lZGl0TWFwLmZpbmQoZSk7aWYodm9pZCAwIT09bil0aHJvdyBuZXcgRXJyb3IoImR1cGxpY2F0ZSBlZGl0IHZhcmlhYmxlIik7aWYocj10LlN0cmVuZ3RoLmNsaXAocikscj09PXQuU3RyZW5ndGgucmVxdWlyZWQpdGhyb3cgbmV3IEVycm9yKCJiYWQgcmVxdWlyZWQgc3RyZW5ndGgiKTt2YXIgbz1uZXcgdC5FeHByZXNzaW9uKGUpLGk9bmV3IHQuQ29uc3RyYWludChvLDIscik7dGhpcy5hZGRDb25zdHJhaW50KGkpO3ZhciBzPXRoaXMuX2NuTWFwLmZpbmQoaSkuc2Vjb25kLGE9e3RhZzpzLGNvbnN0cmFpbnQ6aSxjb25zdGFudDowfTt0aGlzLl9lZGl0TWFwLmluc2VydChlLGEpfSxzLnByb3RvdHlwZS5yZW1vdmVFZGl0VmFyaWFibGU9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcy5fZWRpdE1hcC5lcmFzZSh0KTtpZih2b2lkIDA9PT1lKXRocm93IG5ldyBFcnJvcigidW5rbm93biBlZGl0IHZhcmlhYmxlIik7dGhpcy5yZW1vdmVDb25zdHJhaW50KGUuc2Vjb25kLmNvbnN0cmFpbnQpfSxzLnByb3RvdHlwZS5oYXNFZGl0VmFyaWFibGU9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2VkaXRNYXAuY29udGFpbnModCl9LHMucHJvdG90eXBlLnN1Z2dlc3RWYWx1ZT1mdW5jdGlvbih0LGUpe3ZhciByPXRoaXMuX2VkaXRNYXAuZmluZCh0KTtpZih2b2lkIDA9PT1yKXRocm93IG5ldyBFcnJvcigidW5rbm93biBlZGl0IHZhcmlhYmxlIik7dmFyIG49dGhpcy5fcm93TWFwLG89ci5zZWNvbmQsaT1lLW8uY29uc3RhbnQ7by5jb25zdGFudD1lO3ZhciBzPW8udGFnLm1hcmtlcixhPW4uZmluZChzKTtpZih2b2lkIDAhPT1hKXJldHVybiBhLnNlY29uZC5hZGQoLWkpPDAmJnRoaXMuX2luZmVhc2libGVSb3dzLnB1c2gocyksdm9pZCB0aGlzLl9kdWFsT3B0aW1pemUoKTt2YXIgbD1vLnRhZy5vdGhlcixhPW4uZmluZChsKTtpZih2b2lkIDAhPT1hKXJldHVybiBhLnNlY29uZC5hZGQoaSk8MCYmdGhpcy5faW5mZWFzaWJsZVJvd3MucHVzaChsKSx2b2lkIHRoaXMuX2R1YWxPcHRpbWl6ZSgpO2Zvcih2YXIgdT0wLGg9bi5zaXplKCk7dTxoOysrdSl7dmFyIGE9bi5pdGVtQXQodSksYz1hLnNlY29uZCxwPWMuY29lZmZpY2llbnRGb3Iocyk7MCE9PXAmJmMuYWRkKGkqcCk8MCYmMSE9PWEuZmlyc3QudHlwZSgpJiZ0aGlzLl9pbmZlYXNpYmxlUm93cy5wdXNoKGEuZmlyc3QpfXRoaXMuX2R1YWxPcHRpbWl6ZSgpfSxzLnByb3RvdHlwZS51cGRhdGVWYXJpYWJsZXM9ZnVuY3Rpb24oKXtmb3IodmFyIHQ9dGhpcy5fdmFyTWFwLGU9dGhpcy5fcm93TWFwLHI9MCxuPXQuc2l6ZSgpO3I8bjsrK3Ipe3ZhciBvPXQuaXRlbUF0KHIpLGk9ZS5maW5kKG8uc2Vjb25kKTt2b2lkIDAhPT1pP28uZmlyc3Quc2V0VmFsdWUoaS5zZWNvbmQuY29uc3RhbnQoKSk6by5maXJzdC5zZXRWYWx1ZSgwKX19LHMucHJvdG90eXBlLl9nZXRWYXJTeW1ib2w9ZnVuY3Rpb24odCl7dmFyIGU9dGhpcyxyPWZ1bmN0aW9uKCl7cmV0dXJuIGUuX21ha2VTeW1ib2woMSl9O3JldHVybiB0aGlzLl92YXJNYXAuc2V0RGVmYXVsdCh0LHIpLnNlY29uZH0scy5wcm90b3R5cGUuX2NyZWF0ZVJvdz1mdW5jdGlvbihyKXtmb3IodmFyIG49ci5leHByZXNzaW9uKCksbz1uZXcgaChuLmNvbnN0YW50KCkpLGk9bi50ZXJtcygpLHM9MCxhPWkuc2l6ZSgpO3M8YTsrK3Mpe3ZhciBsPWkuaXRlbUF0KHMpO2lmKCFlKGwuc2Vjb25kKSl7dmFyIGM9dGhpcy5fZ2V0VmFyU3ltYm9sKGwuZmlyc3QpLHA9dGhpcy5fcm93TWFwLmZpbmQoYyk7dm9pZCAwIT09cD9vLmluc2VydFJvdyhwLnNlY29uZCxsLnNlY29uZCk6by5pbnNlcnRTeW1ib2woYyxsLnNlY29uZCl9fXZhciBfPXRoaXMuX29iamVjdGl2ZSxkPXIuc3RyZW5ndGgoKSxmPXttYXJrZXI6dSxvdGhlcjp1fTtzd2l0Y2goci5vcCgpKXtjYXNlIDA6Y2FzZSAxOnZhciBtPTA9PT1yLm9wKCk/MTotMSxnPXRoaXMuX21ha2VTeW1ib2woMik7aWYoZi5tYXJrZXI9ZyxvLmluc2VydFN5bWJvbChnLG0pLGQ8dC5TdHJlbmd0aC5yZXF1aXJlZCl7dmFyIHk9dGhpcy5fbWFrZVN5bWJvbCgzKTtmLm90aGVyPXksby5pbnNlcnRTeW1ib2woeSwtbSksXy5pbnNlcnRTeW1ib2woeSxkKX1icmVhaztjYXNlIDI6aWYoZDx0LlN0cmVuZ3RoLnJlcXVpcmVkKXt2YXIgdj10aGlzLl9tYWtlU3ltYm9sKDMpLGI9dGhpcy5fbWFrZVN5bWJvbCgzKTtmLm1hcmtlcj12LGYub3RoZXI9YixvLmluc2VydFN5bWJvbCh2LC0xKSxvLmluc2VydFN5bWJvbChiLDEpLF8uaW5zZXJ0U3ltYm9sKHYsZCksXy5pbnNlcnRTeW1ib2woYixkKX1lbHNle3ZhciB4PXRoaXMuX21ha2VTeW1ib2woNCk7Zi5tYXJrZXI9eCxvLmluc2VydFN5bWJvbCh4KX19cmV0dXJuIG8uY29uc3RhbnQoKTwwJiZvLnJldmVyc2VTaWduKCkse3JvdzpvLHRhZzpmfX0scy5wcm90b3R5cGUuX2Nob29zZVN1YmplY3Q9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9dC5jZWxscygpLG49MCxvPXIuc2l6ZSgpO248bzsrK24pe3ZhciBpPXIuaXRlbUF0KG4pO2lmKDE9PT1pLmZpcnN0LnR5cGUoKSlyZXR1cm4gaS5maXJzdH12YXIgcz1lLm1hcmtlci50eXBlKCk7cmV0dXJuKDI9PT1zfHwzPT09cykmJnQuY29lZmZpY2llbnRGb3IoZS5tYXJrZXIpPDA/ZS5tYXJrZXI6KHM9ZS5vdGhlci50eXBlKCksKDI9PT1zfHwzPT09cykmJnQuY29lZmZpY2llbnRGb3IoZS5vdGhlcik8MD9lLm90aGVyOnUpfSxzLnByb3RvdHlwZS5fYWRkV2l0aEFydGlmaWNpYWxWYXJpYWJsZT1mdW5jdGlvbih0KXt2YXIgcj10aGlzLl9tYWtlU3ltYm9sKDIpO3RoaXMuX3Jvd01hcC5pbnNlcnQocix0LmNvcHkoKSksdGhpcy5fYXJ0aWZpY2lhbD10LmNvcHkoKSx0aGlzLl9vcHRpbWl6ZSh0aGlzLl9hcnRpZmljaWFsKTt2YXIgbj1lKHRoaXMuX2FydGlmaWNpYWwuY29uc3RhbnQoKSk7dGhpcy5fYXJ0aWZpY2lhbD1udWxsO3ZhciBvPXRoaXMuX3Jvd01hcC5lcmFzZShyKTtpZih2b2lkIDAhPT1vKXt2YXIgaT1vLnNlY29uZDtpZihpLmlzQ29uc3RhbnQoKSlyZXR1cm4gbjt2YXIgcz10aGlzLl9hbnlQaXZvdGFibGVTeW1ib2woaSk7aWYoMD09PXMudHlwZSgpKXJldHVybiExO2kuc29sdmVGb3JFeChyLHMpLHRoaXMuX3N1YnN0aXR1dGUocyxpKSx0aGlzLl9yb3dNYXAuaW5zZXJ0KHMsaSl9Zm9yKHZhciBhPXRoaXMuX3Jvd01hcCxsPTAsdT1hLnNpemUoKTtsPHU7KytsKWEuaXRlbUF0KGwpLnNlY29uZC5yZW1vdmVTeW1ib2wocik7cmV0dXJuIHRoaXMuX29iamVjdGl2ZS5yZW1vdmVTeW1ib2wociksbn0scy5wcm90b3R5cGUuX3N1YnN0aXR1dGU9ZnVuY3Rpb24odCxlKXtmb3IodmFyIHI9dGhpcy5fcm93TWFwLG49MCxvPXIuc2l6ZSgpO248bzsrK24pe3ZhciBpPXIuaXRlbUF0KG4pO2kuc2Vjb25kLnN1YnN0aXR1dGUodCxlKSxpLnNlY29uZC5jb25zdGFudCgpPDAmJjEhPT1pLmZpcnN0LnR5cGUoKSYmdGhpcy5faW5mZWFzaWJsZVJvd3MucHVzaChpLmZpcnN0KX10aGlzLl9vYmplY3RpdmUuc3Vic3RpdHV0ZSh0LGUpLHRoaXMuX2FydGlmaWNpYWwmJnRoaXMuX2FydGlmaWNpYWwuc3Vic3RpdHV0ZSh0LGUpfSxzLnByb3RvdHlwZS5fb3B0aW1pemU9ZnVuY3Rpb24odCl7Zm9yKDs7KXt2YXIgZT10aGlzLl9nZXRFbnRlcmluZ1N5bWJvbCh0KTtpZigwPT09ZS50eXBlKCkpcmV0dXJuO3ZhciByPXRoaXMuX2dldExlYXZpbmdTeW1ib2woZSk7aWYoMD09PXIudHlwZSgpKXRocm93IG5ldyBFcnJvcigidGhlIG9iamVjdGl2ZSBpcyB1bmJvdW5kZWQiKTt2YXIgbj10aGlzLl9yb3dNYXAuZXJhc2Uocikuc2Vjb25kO24uc29sdmVGb3JFeChyLGUpLHRoaXMuX3N1YnN0aXR1dGUoZSxuKSx0aGlzLl9yb3dNYXAuaW5zZXJ0KGUsbil9fSxzLnByb3RvdHlwZS5fZHVhbE9wdGltaXplPWZ1bmN0aW9uKCl7Zm9yKHZhciB0PXRoaXMuX3Jvd01hcCxlPXRoaXMuX2luZmVhc2libGVSb3dzOzAhPT1lLmxlbmd0aDspe3ZhciByPWUucG9wKCksbj10LmZpbmQocik7aWYodm9pZCAwIT09biYmbi5zZWNvbmQuY29uc3RhbnQoKTwwKXt2YXIgbz10aGlzLl9nZXREdWFsRW50ZXJpbmdTeW1ib2wobi5zZWNvbmQpO2lmKDA9PT1vLnR5cGUoKSl0aHJvdyBuZXcgRXJyb3IoImR1YWwgb3B0aW1pemUgZmFpbGVkIik7dmFyIGk9bi5zZWNvbmQ7dC5lcmFzZShyKSxpLnNvbHZlRm9yRXgocixvKSx0aGlzLl9zdWJzdGl0dXRlKG8saSksdC5pbnNlcnQobyxpKX19fSxzLnByb3RvdHlwZS5fZ2V0RW50ZXJpbmdTeW1ib2w9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPXQuY2VsbHMoKSxyPTAsbj1lLnNpemUoKTtyPG47KytyKXt2YXIgbz1lLml0ZW1BdChyKSxpPW8uZmlyc3Q7aWYoby5zZWNvbmQ8MCYmNCE9PWkudHlwZSgpKXJldHVybiBpfXJldHVybiB1fSxzLnByb3RvdHlwZS5fZ2V0RHVhbEVudGVyaW5nU3ltYm9sPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT1OdW1iZXIuTUFYX1ZBTFVFLHI9dSxuPXQuY2VsbHMoKSxvPTAsaT1uLnNpemUoKTtvPGk7KytvKXt2YXIgcz1uLml0ZW1BdChvKSxhPXMuZmlyc3QsbD1zLnNlY29uZDtpZihsPjAmJjQhPT1hLnR5cGUoKSl7dmFyIGg9dGhpcy5fb2JqZWN0aXZlLmNvZWZmaWNpZW50Rm9yKGEpLGM9aC9sO2M8ZSYmKGU9YyxyPWEpfX1yZXR1cm4gcn0scy5wcm90b3R5cGUuX2dldExlYXZpbmdTeW1ib2w9ZnVuY3Rpb24odCl7Zm9yKHZhciBlPU51bWJlci5NQVhfVkFMVUUscj11LG49dGhpcy5fcm93TWFwLG89MCxpPW4uc2l6ZSgpO288aTsrK28pe3ZhciBzPW4uaXRlbUF0KG8pLGE9cy5maXJzdDtpZigxIT09YS50eXBlKCkpe3ZhciBsPXMuc2Vjb25kLGg9bC5jb2VmZmljaWVudEZvcih0KTtpZihoPDApe3ZhciBjPS1sLmNvbnN0YW50KCkvaDtjPGUmJihlPWMscj1hKX19fXJldHVybiByfSxzLnByb3RvdHlwZS5fZ2V0TWFya2VyTGVhdmluZ1N5bWJvbD1mdW5jdGlvbih0KXtmb3IodmFyIGU9TnVtYmVyLk1BWF9WQUxVRSxyPWUsbj1lLG89dSxpPW8scz1vLGE9byxsPXRoaXMuX3Jvd01hcCxoPTAsYz1sLnNpemUoKTtoPGM7KytoKXt2YXIgcD1sLml0ZW1BdChoKSxfPXAuc2Vjb25kLGQ9Xy5jb2VmZmljaWVudEZvcih0KTtpZigwIT09ZCl7dmFyIGY9cC5maXJzdDtpZigxPT09Zi50eXBlKCkpYT1mO2Vsc2UgaWYoZDwwKXt2YXIgbT0tXy5jb25zdGFudCgpL2Q7bTxyJiYocj1tLGk9Zil9ZWxzZXt2YXIgbT1fLmNvbnN0YW50KCkvZDttPG4mJihuPW0scz1mKX19fXJldHVybiBpIT09bz9pOnMhPT1vP3M6YX0scy5wcm90b3R5cGUuX3JlbW92ZUNvbnN0cmFpbnRFZmZlY3RzPWZ1bmN0aW9uKHQsZSl7Mz09PWUubWFya2VyLnR5cGUoKSYmdGhpcy5fcmVtb3ZlTWFya2VyRWZmZWN0cyhlLm1hcmtlcix0LnN0cmVuZ3RoKCkpLDM9PT1lLm90aGVyLnR5cGUoKSYmdGhpcy5fcmVtb3ZlTWFya2VyRWZmZWN0cyhlLm90aGVyLHQuc3RyZW5ndGgoKSl9LHMucHJvdG90eXBlLl9yZW1vdmVNYXJrZXJFZmZlY3RzPWZ1bmN0aW9uKHQsZSl7dmFyIHI9dGhpcy5fcm93TWFwLmZpbmQodCk7dm9pZCAwIT09cj90aGlzLl9vYmplY3RpdmUuaW5zZXJ0Um93KHIuc2Vjb25kLC1lKTp0aGlzLl9vYmplY3RpdmUuaW5zZXJ0U3ltYm9sKHQsLWUpfSxzLnByb3RvdHlwZS5fYW55UGl2b3RhYmxlU3ltYm9sPWZ1bmN0aW9uKHQpe2Zvcih2YXIgZT10LmNlbGxzKCkscj0wLG49ZS5zaXplKCk7cjxuOysrcil7dmFyIG89ZS5pdGVtQXQociksaT1vLmZpcnN0LnR5cGUoKTtpZigyPT09aXx8Mz09PWkpcmV0dXJuIG8uZmlyc3R9cmV0dXJuIHV9LHMucHJvdG90eXBlLl9tYWtlU3ltYm9sPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgbCh0LCh0aGlzLl9pZFRpY2srKykpfSxzfSgpO3QuU29sdmVyPXM7dmFyIGE7IWZ1bmN0aW9uKHQpe3RbdC5JbnZhbGlkPTBdPSJJbnZhbGlkIix0W3QuRXh0ZXJuYWw9MV09IkV4dGVybmFsIix0W3QuU2xhY2s9Ml09IlNsYWNrIix0W3QuRXJyb3I9M109IkVycm9yIix0W3QuRHVtbXk9NF09IkR1bW15In0oYXx8KGE9e30pKTt2YXIgbD1mdW5jdGlvbigpe2Z1bmN0aW9uIHQodCxlKXt0aGlzLl9pZD1lLHRoaXMuX3R5cGU9dH1yZXR1cm4gdC5Db21wYXJlPWZ1bmN0aW9uKHQsZSl7cmV0dXJuIHQuaWQoKS1lLmlkKCl9LHQucHJvdG90eXBlLmlkPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2lkfSx0LnByb3RvdHlwZS50eXBlPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX3R5cGV9LHR9KCksdT1uZXcgbCgwLCgtMSkpLGg9ZnVuY3Rpb24oKXtmdW5jdGlvbiByKGUpeyJ1bmRlZmluZWQiPT10eXBlb2YgZSYmKGU9MCksdGhpcy5fY2VsbE1hcD10LmNyZWF0ZU1hcChsLkNvbXBhcmUpLHRoaXMuX2NvbnN0YW50PWV9cmV0dXJuIHIucHJvdG90eXBlLmNlbGxzPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NlbGxNYXB9LHIucHJvdG90eXBlLmNvbnN0YW50PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NvbnN0YW50fSxyLnByb3RvdHlwZS5pc0NvbnN0YW50PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2NlbGxNYXAuZW1wdHkoKX0sci5wcm90b3R5cGUuYWxsRHVtbWllcz1mdW5jdGlvbigpe2Zvcih2YXIgdD10aGlzLl9jZWxsTWFwLGU9MCxyPXQuc2l6ZSgpO2U8cjsrK2Upe3ZhciBuPXQuaXRlbUF0KGUpO2lmKDQhPT1uLmZpcnN0LnR5cGUoKSlyZXR1cm4hMX1yZXR1cm4hMH0sci5wcm90b3R5cGUuY29weT1mdW5jdGlvbigpe3ZhciB0PW5ldyByKHRoaXMuX2NvbnN0YW50KTtyZXR1cm4gdC5fY2VsbE1hcD10aGlzLl9jZWxsTWFwLmNvcHkoKSx0fSxyLnByb3RvdHlwZS5hZGQ9ZnVuY3Rpb24odCl7cmV0dXJuIHRoaXMuX2NvbnN0YW50Kz10fSxyLnByb3RvdHlwZS5pbnNlcnRTeW1ib2w9ZnVuY3Rpb24odCxyKXsidW5kZWZpbmVkIj09dHlwZW9mIHImJihyPTEpO3ZhciBuPXRoaXMuX2NlbGxNYXAuc2V0RGVmYXVsdCh0LGZ1bmN0aW9uKCl7cmV0dXJuIDB9KTtlKG4uc2Vjb25kKz1yKSYmdGhpcy5fY2VsbE1hcC5lcmFzZSh0KX0sci5wcm90b3R5cGUuaW5zZXJ0Um93PWZ1bmN0aW9uKHQsZSl7InVuZGVmaW5lZCI9PXR5cGVvZiBlJiYoZT0xKSx0aGlzLl9jb25zdGFudCs9dC5fY29uc3RhbnQqZTtmb3IodmFyIHI9dC5fY2VsbE1hcCxuPTAsbz1yLnNpemUoKTtuPG87KytuKXt2YXIgaT1yLml0ZW1BdChuKTt0aGlzLmluc2VydFN5bWJvbChpLmZpcnN0LGkuc2Vjb25kKmUpfX0sci5wcm90b3R5cGUucmVtb3ZlU3ltYm9sPWZ1bmN0aW9uKHQpe3RoaXMuX2NlbGxNYXAuZXJhc2UodCl9LHIucHJvdG90eXBlLnJldmVyc2VTaWduPWZ1bmN0aW9uKCl7dGhpcy5fY29uc3RhbnQ9LXRoaXMuX2NvbnN0YW50O2Zvcih2YXIgdD10aGlzLl9jZWxsTWFwLGU9MCxyPXQuc2l6ZSgpO2U8cjsrK2Upe3ZhciBuPXQuaXRlbUF0KGUpO24uc2Vjb25kPS1uLnNlY29uZH19LHIucHJvdG90eXBlLnNvbHZlRm9yPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuX2NlbGxNYXAscj1lLmVyYXNlKHQpLG49LTEvci5zZWNvbmQ7dGhpcy5fY29uc3RhbnQqPW47Zm9yKHZhciBvPTAsaT1lLnNpemUoKTtvPGk7KytvKWUuaXRlbUF0KG8pLnNlY29uZCo9bn0sci5wcm90b3R5cGUuc29sdmVGb3JFeD1mdW5jdGlvbih0LGUpe3RoaXMuaW5zZXJ0U3ltYm9sKHQsLTEpLHRoaXMuc29sdmVGb3IoZSl9LHIucHJvdG90eXBlLmNvZWZmaWNpZW50Rm9yPWZ1bmN0aW9uKHQpe3ZhciBlPXRoaXMuX2NlbGxNYXAuZmluZCh0KTtyZXR1cm4gdm9pZCAwIT09ZT9lLnNlY29uZDowfSxyLnByb3RvdHlwZS5zdWJzdGl0dXRlPWZ1bmN0aW9uKHQsZSl7dmFyIHI9dGhpcy5fY2VsbE1hcC5lcmFzZSh0KTt2b2lkIDAhPT1yJiZ0aGlzLmluc2VydFJvdyhlLHIuc2Vjb25kKX0scn0oKX0oaXx8KGk9e30pKSwvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnwgQ29weXJpZ2h0IChjKSAyMDE0LCBOdWNsZWljIERldmVsb3BtZW50IFRlYW0uCnwKfCBEaXN0cmlidXRlZCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIE1vZGlmaWVkIEJTRCBMaWNlbnNlLgp8CnwgVGhlIGZ1bGwgbGljZW5zZSBpcyBpbiB0aGUgZmlsZSBDT1BZSU5HLnR4dCwgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzIHNvZnR3YXJlLgp8LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCmUuZXhwb3J0cz1pfSx7fV19LHt9LFsibWFpbiJdKX0oKTsvKgpDb3B5cmlnaHQgKGMpIDIwMTIsIENvbnRpbnV1bSBBbmFseXRpY3MsIEluYy4KQWxsIHJpZ2h0cyByZXNlcnZlZC4KClJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dCBtb2RpZmljYXRpb24sCmFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDoKClJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwKdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci4KClJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwKdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvbgphbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4KCk5laXRoZXIgdGhlIG5hbWUgb2YgQ29udGludXVtIEFuYWx5dGljcyBub3IgdGhlIG5hbWVzIG9mIGFueSBjb250cmlidXRvcnMKbWF5IGJlIHVzZWQgdG8gZW5kb3JzZSBvciBwcm9tb3RlIHByb2R1Y3RzIGRlcml2ZWQgZnJvbSB0aGlzIHNvZnR3YXJlIAp3aXRob3V0IHNwZWNpZmljIHByaW9yIHdyaXR0ZW4gcGVybWlzc2lvbi4KClRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgIkFTIElTIgpBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIApJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSAKQVJFIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgT1dORVIgT1IgQ09OVFJJQlVUT1JTIEJFIApMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIApDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiAKU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIApJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiAKQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgCkFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgClRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4KKi8K&#34;&gt;&lt;/script&gt;
&lt;script src=&#34;data:application/x-javascript;base64,SFRNTFdpZGdldHMud2lkZ2V0KHsKICBuYW1lOiAncmJva2VoJywKCiAgdHlwZTogJ291dHB1dCcsCgogIGluaXRpYWxpemU6IGZ1bmN0aW9uKGVsLCB3aWR0aCwgaGVpZ2h0KSB7CiAgICByZXR1cm4gewogICAgICBtb2RlbGlkOiAnJywKICAgICAgZWxlbWVudGlkOiAnJywKICAgICAgd2lkdGg6IHdpZHRoLAogICAgICBoZWlnaHQ6IGhlaWdodAogICAgfTsKICB9LAoKICByZW5kZXJWYWx1ZTogZnVuY3Rpb24oZWwsIHgsIGluc3RhbmNlKSB7CgogICAgLy9jbGVhciBlbCBmb3IgU2hpbnkvZHluYW1pYyBjb250ZXh0cwogICAgZWwuaW5uZXJIVE1MID0gJyc7CgogICAgaWYoeC5pc0pTT04gPT09IHRydWUpIHsKICAgICAgeC5kb2NzX2pzb24gPSBKU09OLnBhcnNlKHguZG9jc19qc29uKTsKICAgIH0KCiAgICB2YXIgcmVma2V5ID0gT2JqZWN0LmtleXMoeC5kb2NzX2pzb24pWzBdOwogICAgdmFyIHJlZnMgPSB4LmRvY3NfanNvbltyZWZrZXldLnJvb3RzLnJlZmVyZW5jZXM7CgogICAgaW5zdGFuY2UubW9kZWxpZCA9IHgubW9kZWxpZDsKICAgIGluc3RhbmNlLmVsZW1lbnRpZCA9IHguZWxlbWVudGlkOwoKICAgIGlmKHguZGVidWcgPT09IHRydWUpIHsKICAgICAgY29uc29sZS5sb2cocmVmcyk7CiAgICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KHJlZnMpKTsKICAgIH0KCiAgICAvLyBjaGFuZ2UgJ251bGxzJyBpbiBkYXRhIHRvIE5hTgogICAgZnVuY3Rpb24gdHJhdmVyc2VPYmplY3Qob2JqKSB7CiAgICAgIGZvcih2YXIga2V5IGluIG9iaikgewogICAgICAgIGlmKG9ialtrZXldLmNvbnN0cnVjdG9yID09PSBPYmplY3QpIHsKICAgICAgICAgIHRyYXZlcnNlT2JqZWN0KG9ialtrZXldKTsKICAgICAgICB9IGVsc2UgaWYob2JqW2tleV0uY29uc3RydWN0b3IgPT09IEFycmF5KSB7CiAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9ialtrZXldLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGlmKG9ialtrZXldW2ldID09PSBudWxsKQogICAgICAgICAgICAgIG9ialtrZXldW2ldID0gTmFOOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogICAgZm9yKHZhciBpID0gMDsgaSA8IHJlZnMubGVuZ3RoOyBpKyspIHsKICAgICAgaWYocmVmc1tpXS50eXBlID09PSAnQ29sdW1uRGF0YVNvdXJjZScpCiAgICAgICAgdHJhdmVyc2VPYmplY3QocmVmc1tpXS5hdHRyaWJ1dGVzLmRhdGEpOwogICAgfQoKICAgIHZhciBkdjEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgIGR2MS5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ2JrLXJvb3QnKTsKICAgIHZhciBzcGlubmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7CiAgICBzcGlubmVyLnNldEF0dHJpYnV0ZSgnY2xhc3MnLCAnYmstbG9hZGVyJyk7CiAgICBzcGlubmVyLnN0eWxlLm9wYWNpdHkgPSAwOwogICAgc3Bpbm5lci5zdHlsZS5sZWZ0ID0gKGluc3RhbmNlLndpZHRoIC8gMiAtIDM1KSArICdweCc7CiAgICBzcGlubmVyLnN0eWxlLnRvcCA9IChpbnN0YW5jZS5oZWlnaHQgLyAyIC0gMzUpICsgJ3B4JzsKCiAgICB2YXIgZHYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgIGR2LmlkID0geC5lbGVtZW50aWQ7CiAgICBkdi5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgJ3Bsb3RkaXYnKTsKICAgIGR2MS5hcHBlbmRDaGlsZChkdik7CiAgICBkdjEuYXBwZW5kQ2hpbGQoc3Bpbm5lcik7CiAgICBlbC5hcHBlbmRDaGlsZChkdjEpOwoKICAgIHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHNwaW5uZXIpLm9wYWNpdHk7CiAgICBzcGlubmVyLnN0eWxlLm9wYWNpdHkgPSAxOwoKICAgIHZhciByZW5kZXJfaXRlbXMgPSBbewogICAgICAnZG9jaWQnOiB4LmRvY2lkLAogICAgICAnZWxlbWVudGlkJzogeC5lbGVtZW50aWQsCiAgICAgICdtb2RlbGlkJzogeC5tb2RlbGlkCiAgICB9XTsKCiAgICBpZih4LmRlYnVnICE9PSB0cnVlKSB7CiAgICAgIEJva2VoLnNldF9sb2dfbGV2ZWwoJ2luZm8nKTsKICAgIH0KCiAgICBCb2tlaC5lbWJlZC5lbWJlZF9pdGVtcyh4LmRvY3NfanNvbiwgcmVuZGVyX2l0ZW1zKTsKCiAgICB2YXIgdGltZXIgPSBmdW5jdGlvbigpIHsKICAgICAgaWYgKGR2MS5jaGlsZE5vZGVzWzBdLmNoaWxkTm9kZXMubGVuZ3RoID4gMCkgewogICAgICAgIGR2MS5yZW1vdmVDaGlsZChzcGlubmVyKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB3aW5kb3cuc2V0VGltZW91dCh0aW1lciwgMjAwKTsKICAgICAgfQogICAgfTsKICAgIHRpbWVyKCk7CgogIH0sCgogIHJlc2l6ZTogZnVuY3Rpb24oZWwsIHdpZHRoLCBoZWlnaHQsIGluc3RhbmNlKSB7CiAgfQp9KTsKCg==&#34;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body style=&#34;background-color:white;&#34;&gt;
&lt;div id=&#34;htmlwidget_container&#34;&gt;
&lt;div id=&#34;htmlwidget-bb44db00724a24a98e0e&#34; class=&#34;rbokeh html-widget&#34; style=&#34;width:800px;height:445px;&#34;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;script type=&#34;application/json&#34; data-for=&#34;htmlwidget-bb44db00724a24a98e0e&#34;&gt;{&#34;x&#34;:{&#34;elementid&#34;:&#34;da9e35cae51d1f01ff9901388afcda02&#34;,&#34;modeltype&#34;:&#34;Plot&#34;,&#34;modelid&#34;:&#34;1326bd2fcc4ec1e393849bb25c261c41&#34;,&#34;docid&#34;:&#34;576a6165504d7e899f15b74782319f25&#34;,&#34;docs_json&#34;:{&#34;576a6165504d7e899f15b74782319f25&#34;:{&#34;version&#34;:&#34;0.12.2&#34;,&#34;title&#34;:&#34;Bokeh Figure&#34;,&#34;roots&#34;:{&#34;root_ids&#34;:[&#34;1326bd2fcc4ec1e393849bb25c261c41&#34;],&#34;references&#34;:[{&#34;type&#34;:&#34;Plot&#34;,&#34;id&#34;:&#34;1326bd2fcc4ec1e393849bb25c261c41&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;1326bd2fcc4ec1e393849bb25c261c41&#34;,&#34;plot_width&#34;:800,&#34;plot_height&#34;:445,&#34;sizing_mode&#34;:&#34;scale_both&#34;,&#34;x_range&#34;:{&#34;type&#34;:&#34;FactorRange&#34;,&#34;id&#34;:&#34;bbe638eb195f16928209286930ed836e&#34;},&#34;y_range&#34;:{&#34;type&#34;:&#34;FactorRange&#34;,&#34;id&#34;:&#34;87a5194a1046bdbe7658d35f9012e280&#34;},&#34;left&#34;:[{&#34;type&#34;:&#34;CategoricalAxis&#34;,&#34;id&#34;:&#34;cc6941546581f341b83a11be445d5a0f&#34;}],&#34;below&#34;:[{&#34;type&#34;:&#34;CategoricalAxis&#34;,&#34;id&#34;:&#34;c1540c8e7b35c4d514a8101df5141f4a&#34;}],&#34;right&#34;:[],&#34;above&#34;:[],&#34;renderers&#34;:[{&#34;type&#34;:&#34;GlyphRenderer&#34;,&#34;id&#34;:&#34;03d20c743cd8f64133f205e57e4678fd&#34;},{&#34;type&#34;:&#34;GlyphRenderer&#34;,&#34;id&#34;:&#34;07f0ce018b2ee1232eabf1fba21e84d9&#34;},{&#34;type&#34;:&#34;GlyphRenderer&#34;,&#34;id&#34;:&#34;f6e79cc8ce582d3c4f7263eba2fe67a5&#34;},{&#34;type&#34;:&#34;GlyphRenderer&#34;,&#34;id&#34;:&#34;fccd66fd77c1baddce8043fba79151ab&#34;},{&#34;type&#34;:&#34;GlyphRenderer&#34;,&#34;id&#34;:&#34;230ad7907e84c264bad8fbf326b5e5e2&#34;},{&#34;type&#34;:&#34;CategoricalAxis&#34;,&#34;id&#34;:&#34;c1540c8e7b35c4d514a8101df5141f4a&#34;},{&#34;type&#34;:&#34;CategoricalAxis&#34;,&#34;id&#34;:&#34;cc6941546581f341b83a11be445d5a0f&#34;}],&#34;extra_y_ranges&#34;:{},&#34;extra_x_ranges&#34;:{},&#34;tags&#34;:[],&#34;min_border_left&#34;:4,&#34;min_border_right&#34;:4,&#34;min_border_top&#34;:4,&#34;min_border_bottom&#34;:4,&#34;lod_threshold&#34;:null,&#34;toolbar&#34;:{&#34;type&#34;:&#34;Toolbar&#34;,&#34;id&#34;:&#34;ce7a8799cf7768bd840194847542c22c&#34;},&#34;tool_events&#34;:{&#34;type&#34;:&#34;ToolEvents&#34;,&#34;id&#34;:&#34;2ef2df53c3f07e0deb68b150fd85715e&#34;},&#34;title&#34;:{&#34;type&#34;:&#34;Title&#34;,&#34;id&#34;:&#34;0a9a4097f370c80da50a898507fbf133&#34;}},&#34;subtype&#34;:&#34;Figure&#34;},{&#34;type&#34;:&#34;Toolbar&#34;,&#34;id&#34;:&#34;ce7a8799cf7768bd840194847542c22c&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;ce7a8799cf7768bd840194847542c22c&#34;,&#34;tags&#34;:[],&#34;active_drag&#34;:&#34;auto&#34;,&#34;active_scroll&#34;:&#34;auto&#34;,&#34;active_tap&#34;:&#34;auto&#34;,&#34;tools&#34;:[{&#34;type&#34;:&#34;ResizeTool&#34;,&#34;id&#34;:&#34;86e2dab7e7ccc4337c0a98f64b5d7498&#34;},{&#34;type&#34;:&#34;HoverTool&#34;,&#34;id&#34;:&#34;74ff23d3f200cf0ae3f23976111ac3e0&#34;}],&#34;logo&#34;:null}},{&#34;type&#34;:&#34;ResizeTool&#34;,&#34;id&#34;:&#34;86e2dab7e7ccc4337c0a98f64b5d7498&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;86e2dab7e7ccc4337c0a98f64b5d7498&#34;,&#34;tags&#34;:[],&#34;plot&#34;:{&#34;type&#34;:&#34;Plot&#34;,&#34;id&#34;:&#34;1326bd2fcc4ec1e393849bb25c261c41&#34;,&#34;subtype&#34;:&#34;Figure&#34;}}},{&#34;type&#34;:&#34;ToolEvents&#34;,&#34;id&#34;:&#34;2ef2df53c3f07e0deb68b150fd85715e&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;2ef2df53c3f07e0deb68b150fd85715e&#34;,&#34;tags&#34;:[]},&#34;geometries&#34;:[]},{&#34;type&#34;:&#34;Title&#34;,&#34;id&#34;:&#34;0a9a4097f370c80da50a898507fbf133&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;0a9a4097f370c80da50a898507fbf133&#34;,&#34;tags&#34;:[],&#34;plot&#34;:null,&#34;text&#34;:&#34;Periodic Table of Damien Cornu&#39;s experience&#34;}},{&#34;type&#34;:&#34;HoverTool&#34;,&#34;id&#34;:&#34;74ff23d3f200cf0ae3f23976111ac3e0&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;74ff23d3f200cf0ae3f23976111ac3e0&#34;,&#34;tags&#34;:[],&#34;plot&#34;:{&#34;type&#34;:&#34;Plot&#34;,&#34;id&#34;:&#34;1326bd2fcc4ec1e393849bb25c261c41&#34;,&#34;subtype&#34;:&#34;Figure&#34;},&#34;renderers&#34;:[{&#34;type&#34;:&#34;GlyphRenderer&#34;,&#34;id&#34;:&#34;03d20c743cd8f64133f205e57e4678fd&#34;}],&#34;names&#34;:[],&#34;anchor&#34;:&#34;center&#34;,&#34;attachment&#34;:&#34;horizontal&#34;,&#34;line_policy&#34;:&#34;prev&#34;,&#34;mode&#34;:&#34;mouse&#34;,&#34;point_policy&#34;:&#34;snap_to_data&#34;,&#34;tooltips&#34;:[[&#34;name&#34;,&#34;@hover_col_1&#34;],[&#34;desc&#34;,&#34;@hover_col_2&#34;],[&#34;Place&#34;,&#34;@hover_col_3&#34;]]}},{&#34;type&#34;:&#34;ColumnDataSource&#34;,&#34;id&#34;:&#34;da27106e3688177fd01cf98e7d24c506&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;da27106e3688177fd01cf98e7d24c506&#34;,&#34;tags&#34;:[],&#34;column_names&#34;:[&#34;x&#34;,&#34;y&#34;,&#34;fill_color&#34;,&#34;line_color&#34;,&#34;hover_col_1&#34;,&#34;hover_col_2&#34;,&#34;hover_col_3&#34;],&#34;selected&#34;:[],&#34;data&#34;:{&#34;x&#34;:[&#34;1&#34;,&#34;18&#34;,&#34;1&#34;,&#34;2&#34;,&#34;13&#34;,&#34;14&#34;,&#34;15&#34;,&#34;16&#34;,&#34;17&#34;,&#34;18&#34;,&#34;1&#34;,&#34;2&#34;,&#34;13&#34;,&#34;14&#34;,&#34;15&#34;,&#34;16&#34;,&#34;17&#34;,&#34;18&#34;,&#34;1&#34;,&#34;2&#34;,&#34;3&#34;,&#34;4&#34;,&#34;5&#34;,&#34;6&#34;,&#34;7&#34;,&#34;8&#34;,&#34;9&#34;,&#34;10&#34;,&#34;11&#34;,&#34;12&#34;,&#34;13&#34;,&#34;14&#34;,&#34;15&#34;,&#34;16&#34;,&#34;17&#34;,&#34;18&#34;,&#34;1&#34;,&#34;2&#34;,&#34;3&#34;,&#34;4&#34;,&#34;5&#34;,&#34;6&#34;,&#34;7&#34;,&#34;8&#34;,&#34;9&#34;,&#34;10&#34;,&#34;11&#34;,&#34;12&#34;,&#34;13&#34;,&#34;14&#34;,&#34;15&#34;,&#34;16&#34;,&#34;17&#34;,&#34;18&#34;,&#34;1&#34;,&#34;2&#34;,&#34;3&#34;,&#34;4&#34;,&#34;5&#34;,&#34;6&#34;,&#34;7&#34;,&#34;8&#34;,&#34;9&#34;,&#34;10&#34;,&#34;11&#34;,&#34;12&#34;,&#34;13&#34;,&#34;14&#34;,&#34;15&#34;,&#34;16&#34;,&#34;17&#34;,&#34;18&#34;,&#34;1&#34;,&#34;2&#34;,&#34;3&#34;,&#34;4&#34;,&#34;5&#34;,&#34;6&#34;,&#34;7&#34;,&#34;8&#34;,&#34;9&#34;,&#34;10&#34;,&#34;11&#34;,&#34;12&#34;,&#34;14&#34;,&#34;16&#34;,&#34;13&#34;,&#34;15&#34;,&#34;17&#34;,&#34;18&#34;],&#34;y&#34;:[&#34;1&#34;,&#34;1&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;],&#34;fill_color&#34;:[&#34;#a6cee3&#34;,&#34;#1f78b4&#34;,&#34;#fdbf6f&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#a6cee3&#34;,&#34;#b2df8a&#34;,&#34;#a6cee3&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#33a02c&#34;,&#34;#bbbb88&#34;,&#34;#baa2a6&#34;,&#34;#e08e79&#34;,&#34;#e08e79&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#bbbb88&#34;,&#34;#e08e79&#34;,&#34;#e08e79&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#1f78b4&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#baa2a6&#34;,&#34;#e08e79&#34;,&#34;#e08e79&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#baa2a6&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#1f78b4&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#baa2a6&#34;,&#34;#1f78b4&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#1f78b4&#34;,&#34;#1f78b4&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#baa2a6&#34;,&#34;#e08e79&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#e08e79&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;#e08e79&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;,&#34;white&#34;],&#34;line_color&#34;:[&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;,&#34;grey&#34;],&#34;hover_col_1&#34;:[&#34;Hydrogen     &#34;,&#34;Helium       &#34;,&#34;Lithium      &#34;,&#34;Beryllium    &#34;,&#34;Boron        &#34;,&#34;Carbon       &#34;,&#34;Nitrogen     &#34;,&#34;Oxygen       &#34;,&#34;Fluorine     &#34;,&#34;Neon         &#34;,&#34;Sodium       &#34;,&#34;Magnesium    &#34;,&#34;Aluminum     &#34;,&#34;Silicon      &#34;,&#34;Phosphorus   &#34;,&#34;Sulfur       &#34;,&#34;Chlorine     &#34;,&#34;Argon        &#34;,&#34;Potassium    &#34;,&#34;Calcium      &#34;,&#34;Scandium     &#34;,&#34;Titanium     &#34;,&#34;Vanadium     &#34;,&#34;Chromium     &#34;,&#34;Manganese    &#34;,&#34;Iron         &#34;,&#34;Cobalt       &#34;,&#34;Nickel       &#34;,&#34;Copper       &#34;,&#34;Zinc         &#34;,&#34;Gallium      &#34;,&#34;Germanium    &#34;,&#34;Arsenic      &#34;,&#34;Selenium     &#34;,&#34;Bromine      &#34;,&#34;Krypton      &#34;,&#34;Rubidium     &#34;,&#34;Strontium    &#34;,&#34;Yttrium      &#34;,&#34;Zirconium    &#34;,&#34;Niobium      &#34;,&#34;Molybdenum   &#34;,&#34;Technetium   &#34;,&#34;Ruthenium    &#34;,&#34;Rhodium      &#34;,&#34;Palladium    &#34;,&#34;Silver       &#34;,&#34;Cadmium      &#34;,&#34;Indium       &#34;,&#34;Tin          &#34;,&#34;Antimony     &#34;,&#34;Tellurium    &#34;,&#34;Iodine       &#34;,&#34;Xenon        &#34;,&#34;Cesium       &#34;,&#34;Barium       &#34;,&#34;Lutetium     &#34;,&#34;Hafnium      &#34;,&#34;Tantalum     &#34;,&#34;Tungsten     &#34;,&#34;Rhenium      &#34;,&#34;Osmium       &#34;,&#34;Iridium      &#34;,&#34;Platinum     &#34;,&#34;Gold         &#34;,&#34;Mercury      &#34;,&#34;Thallium     &#34;,&#34;Lead         &#34;,&#34;Bismuth      &#34;,&#34;Polonium     &#34;,&#34;Astatine     &#34;,&#34;Radon        &#34;,&#34;Francium     &#34;,&#34;Radium       &#34;,&#34;Lawrencium   &#34;,&#34;Rutherfordium&#34;,&#34;Dubnium      &#34;,&#34;Seaborgium   &#34;,&#34;Bohrium      &#34;,&#34;Hassium      &#34;,&#34;Meitnerium   &#34;,&#34;Darmstadtium &#34;,&#34;Roentgenium  &#34;,&#34;Copernicium  &#34;,&#34;Ununquadium  &#34;,&#34;Ununhexium   &#34;,&#34;Nihonium     &#34;,&#34;Moscovium    &#34;,&#34;Tennessine   &#34;,&#34;Oganesson    &#34;],&#34;hover_col_2&#34;:[&#34;I am currently working on the hydrogenation of alkenes. And, well, H is everywhere!                                &#34;,&#34;It is not possible to cool large superconducting coils without liquid He.                                          &#34;,&#34;Butyl lithium is a very powerful base!                                                                             &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;I am currently working on the vibrations between carbon monoxide and metallic surfaces. And, well, C is everywhere!&#34;,&#34;Infrared spectrometer works much better in liquid nitrogen                                                         &#34;,&#34;I am currently working on the vibrations between carbon monoxide and metallic surfaces. And, well, O is everywhere!&#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;Adsorbed on MgO, Na increases its basicity                                                                         &#34;,&#34;Magnesium oxide is the solid I studied extensively, as a powder and as a thin film                                 &#34;,&#34;Alumina is a good oxide support for platinum                                                                       &#34;,&#34;Magnesium silicate is the best catalyst for transesterification!                                                   &#34;,&#34;Magnesium phosphate converts 2-methylbut-3-yn-2-ol towards an acidic route                                         &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;In a glove box, argon is the perfect atmosphere                                                                    &#34;,&#34;Adsorbed on MgO, K increases its basicity                                                                          &#34;,&#34;Adsorbed on MgO, Ca increases its basicity                                                                         &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;Cr3+ is paramagnetic and create defects in MgO                                                                     &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;Nickel can hydrogenate alkenes                                                                                     &#34;,&#34;Copper particle properties can be influenced by the support. And, you know, wires...                               &#34;,&#34;Zinc silicates are good catalyst for transesterification                                                           &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;Zinc selenate does not adsorb too much in infra-red                                                                &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;A good support for MgO                                                                                             &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;A good catalyst for alkenes hydrogenation and to adsorb CO                                                         &#34;,&#34;A good support for MgO                                                                                             &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;Type C thermocouple is not magnetic.                                                                               &#34;,&#34;Type C thermocouple is not magnetic.                                                                               &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;A good catalyst for alkenes hydrogenation and to adsorb CO                                                         &#34;,&#34;Gold particles are very interesting for catalysis                                                                  &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;No, I didn&#39;t use it, but I did a lot of outreach about the life of Marie Sklodowska Curie                          &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;No, I didn&#39;t use it, but I did a lot of outreach about the life of Marie Sklodowska Curie                          &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;,&#34;                                                                                                                   &#34;],&#34;hover_col_3&#34;:[&#34;Hangzhou, Paris, Berlin, Tarragona&#34;,&#34;Berlin                            &#34;,&#34;Hangzhou                          &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Hangzhou, Paris, Berlin, Tarragona&#34;,&#34;Paris, Berlin, Tarragona          &#34;,&#34;Hangzhou, Paris, Berlin, Tarragona&#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Hangzhou, Paris                   &#34;,&#34;Paris, Berlin                     &#34;,&#34;Tarragona                         &#34;,&#34;Paris                             &#34;,&#34;Paris                             &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Paris, Berlin                     &#34;,&#34;Paris                             &#34;,&#34;Paris                             &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Berlin                            &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Tarragona                         &#34;,&#34;Paris                             &#34;,&#34;Paris                             &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Tarragona                         &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Berlin                            &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Tarragona                         &#34;,&#34;Berlin                            &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Berlin                            &#34;,&#34;Berlin                            &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Tarragona                         &#34;,&#34;Paris                             &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Paris                             &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;Paris                             &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;,&#34;                                  &#34;]}}},{&#34;type&#34;:&#34;Rect&#34;,&#34;id&#34;:&#34;872a658bad0a241d550a26c19a93c312&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;872a658bad0a241d550a26c19a93c312&#34;,&#34;tags&#34;:[],&#34;width&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:0.9},&#34;height&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:0.9},&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;dilate&#34;:false,&#34;visible&#34;:true,&#34;fill_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:0.6},&#34;line_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;fill_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;fill_color&#34;},&#34;line_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;line_color&#34;}}},{&#34;type&#34;:&#34;Rect&#34;,&#34;id&#34;:&#34;dc1416593a84839bcdcf8d2b5e8a5760&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;dc1416593a84839bcdcf8d2b5e8a5760&#34;,&#34;tags&#34;:[],&#34;width&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:0.9},&#34;height&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:0.9},&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;dilate&#34;:false,&#34;visible&#34;:true,&#34;fill_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:0.6},&#34;line_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;fill_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;#e1e1e1&#34;},&#34;line_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;#e1e1e1&#34;}}},{&#34;type&#34;:&#34;Rect&#34;,&#34;id&#34;:&#34;acee0b44ac8a1dd8119157b1ed451528&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;acee0b44ac8a1dd8119157b1ed451528&#34;,&#34;tags&#34;:[],&#34;width&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:0.9},&#34;height&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:0.9},&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;dilate&#34;:false,&#34;visible&#34;:true,&#34;fill_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;line_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;fill_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;fill_color&#34;},&#34;line_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;line_color&#34;}}},{&#34;type&#34;:&#34;GlyphRenderer&#34;,&#34;id&#34;:&#34;03d20c743cd8f64133f205e57e4678fd&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;03d20c743cd8f64133f205e57e4678fd&#34;,&#34;tags&#34;:[],&#34;selection_glyph&#34;:null,&#34;nonselection_glyph&#34;:{&#34;type&#34;:&#34;Rect&#34;,&#34;id&#34;:&#34;dc1416593a84839bcdcf8d2b5e8a5760&#34;},&#34;hover_glyph&#34;:{&#34;type&#34;:&#34;Rect&#34;,&#34;id&#34;:&#34;acee0b44ac8a1dd8119157b1ed451528&#34;},&#34;name&#34;:null,&#34;data_source&#34;:{&#34;type&#34;:&#34;ColumnDataSource&#34;,&#34;id&#34;:&#34;da27106e3688177fd01cf98e7d24c506&#34;},&#34;glyph&#34;:{&#34;type&#34;:&#34;Rect&#34;,&#34;id&#34;:&#34;872a658bad0a241d550a26c19a93c312&#34;}}},{&#34;type&#34;:&#34;ColumnDataSource&#34;,&#34;id&#34;:&#34;309fafc59bec0286e46562de99dc9016&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;309fafc59bec0286e46562de99dc9016&#34;,&#34;tags&#34;:[],&#34;column_names&#34;:[&#34;x&#34;,&#34;y&#34;,&#34;text&#34;,&#34;text_color&#34;,&#34;text_font_size&#34;],&#34;selected&#34;:[],&#34;data&#34;:{&#34;x&#34;:[&#34;1:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;14:0.1&#34;,&#34;16:0.1&#34;,&#34;13:0.1&#34;,&#34;15:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;],&#34;y&#34;:[&#34;1&#34;,&#34;1&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;2&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;3&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;4&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;5&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;6&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;,&#34;7&#34;],&#34;text&#34;:[&#34;H&#34;,&#34;He&#34;,&#34;Li&#34;,&#34;Be&#34;,&#34;B&#34;,&#34;C&#34;,&#34;N&#34;,&#34;O&#34;,&#34;F&#34;,&#34;Ne&#34;,&#34;Na&#34;,&#34;Mg&#34;,&#34;Al&#34;,&#34;Si&#34;,&#34;P&#34;,&#34;S&#34;,&#34;Cl&#34;,&#34;Ar&#34;,&#34;K&#34;,&#34;Ca&#34;,&#34;Sc&#34;,&#34;Ti&#34;,&#34;V&#34;,&#34;Cr&#34;,&#34;Mn&#34;,&#34;Fe&#34;,&#34;Co&#34;,&#34;Ni&#34;,&#34;Cu&#34;,&#34;Zn&#34;,&#34;Ga&#34;,&#34;Ge&#34;,&#34;As&#34;,&#34;Se&#34;,&#34;Br&#34;,&#34;Kr&#34;,&#34;Rb&#34;,&#34;Sr&#34;,&#34;Y&#34;,&#34;Zr&#34;,&#34;Nb&#34;,&#34;Mo&#34;,&#34;Tc&#34;,&#34;Ru&#34;,&#34;Rh&#34;,&#34;Pd&#34;,&#34;Ag&#34;,&#34;Cd&#34;,&#34;In&#34;,&#34;Sn&#34;,&#34;Sb&#34;,&#34;Te&#34;,&#34;I&#34;,&#34;Xe&#34;,&#34;Cs&#34;,&#34;Ba&#34;,&#34;Lu&#34;,&#34;Hf&#34;,&#34;Ta&#34;,&#34;W&#34;,&#34;Re&#34;,&#34;Os&#34;,&#34;Ir&#34;,&#34;Pt&#34;,&#34;Au&#34;,&#34;Hg&#34;,&#34;Tl&#34;,&#34;Pb&#34;,&#34;Bi&#34;,&#34;Po&#34;,&#34;At&#34;,&#34;Rn&#34;,&#34;Fr&#34;,&#34;Ra&#34;,&#34;Lr&#34;,&#34;Rf&#34;,&#34;Db&#34;,&#34;Sg&#34;,&#34;Bh&#34;,&#34;Hs&#34;,&#34;Mt&#34;,&#34;Ds&#34;,&#34;Rg&#34;,&#34;Cn&#34;,&#34;Uuq&#34;,&#34;Uuh&#34;,&#34;Nh&#34;,&#34;Mc&#34;,&#34;Ts&#34;,&#34;Og&#34;],&#34;text_color&#34;:[&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;],&#34;text_font_size&#34;:[&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;,&#34;10pt&#34;]}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;0c7dc8748314120605ba92e44ba566a3&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;0c7dc8748314120605ba92e44ba566a3&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_font_style&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;bold&#34;},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_color&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;70b415f45a992e5010e320b85bd92f83&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;70b415f45a992e5010e320b85bd92f83&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_font_style&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;bold&#34;},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;#e1e1e1&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;dea7de79d1b4e0ab184dc55c8fac922e&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;dea7de79d1b4e0ab184dc55c8fac922e&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_font_style&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;bold&#34;},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_color&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;GlyphRenderer&#34;,&#34;id&#34;:&#34;07f0ce018b2ee1232eabf1fba21e84d9&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;07f0ce018b2ee1232eabf1fba21e84d9&#34;,&#34;tags&#34;:[],&#34;selection_glyph&#34;:null,&#34;nonselection_glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;70b415f45a992e5010e320b85bd92f83&#34;},&#34;hover_glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;dea7de79d1b4e0ab184dc55c8fac922e&#34;},&#34;name&#34;:null,&#34;data_source&#34;:{&#34;type&#34;:&#34;ColumnDataSource&#34;,&#34;id&#34;:&#34;309fafc59bec0286e46562de99dc9016&#34;},&#34;glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;0c7dc8748314120605ba92e44ba566a3&#34;}}},{&#34;type&#34;:&#34;ColumnDataSource&#34;,&#34;id&#34;:&#34;02efbd990e893e91bafc65c21f2d83c0&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;02efbd990e893e91bafc65c21f2d83c0&#34;,&#34;tags&#34;:[],&#34;column_names&#34;:[&#34;x&#34;,&#34;y&#34;,&#34;text&#34;,&#34;text_color&#34;,&#34;text_font_size&#34;],&#34;selected&#34;:[],&#34;data&#34;:{&#34;x&#34;:[&#34;1:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;14:0.1&#34;,&#34;16:0.1&#34;,&#34;13:0.1&#34;,&#34;15:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;],&#34;y&#34;:[&#34;1:0.8&#34;,&#34;1:0.8&#34;,&#34;2:0.8&#34;,&#34;2:0.8&#34;,&#34;2:0.8&#34;,&#34;2:0.8&#34;,&#34;2:0.8&#34;,&#34;2:0.8&#34;,&#34;2:0.8&#34;,&#34;2:0.8&#34;,&#34;3:0.8&#34;,&#34;3:0.8&#34;,&#34;3:0.8&#34;,&#34;3:0.8&#34;,&#34;3:0.8&#34;,&#34;3:0.8&#34;,&#34;3:0.8&#34;,&#34;3:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;4:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;5:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;6:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;,&#34;7:0.8&#34;],&#34;text&#34;:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,103,104,105,106,107,108,109,110,111,112,114,116,113,115,117,118],&#34;text_color&#34;:[&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;],&#34;text_font_size&#34;:[&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;,&#34;6pt&#34;]}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;f817f8b7604609840c0ef1385080128e&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;f817f8b7604609840c0ef1385080128e&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_color&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;e47e85df143808c6e826fc7e5c5d7d70&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;e47e85df143808c6e826fc7e5c5d7d70&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;#e1e1e1&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;b19bec94e7017cb681197d3bbaf2ec8a&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;b19bec94e7017cb681197d3bbaf2ec8a&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_color&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;GlyphRenderer&#34;,&#34;id&#34;:&#34;f6e79cc8ce582d3c4f7263eba2fe67a5&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;f6e79cc8ce582d3c4f7263eba2fe67a5&#34;,&#34;tags&#34;:[],&#34;selection_glyph&#34;:null,&#34;nonselection_glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;e47e85df143808c6e826fc7e5c5d7d70&#34;},&#34;hover_glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;b19bec94e7017cb681197d3bbaf2ec8a&#34;},&#34;name&#34;:null,&#34;data_source&#34;:{&#34;type&#34;:&#34;ColumnDataSource&#34;,&#34;id&#34;:&#34;02efbd990e893e91bafc65c21f2d83c0&#34;},&#34;glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;f817f8b7604609840c0ef1385080128e&#34;}}},{&#34;type&#34;:&#34;ColumnDataSource&#34;,&#34;id&#34;:&#34;5f20412b078a76b411df5d8cd31ca4a1&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;5f20412b078a76b411df5d8cd31ca4a1&#34;,&#34;tags&#34;:[],&#34;column_names&#34;:[&#34;x&#34;,&#34;y&#34;,&#34;text&#34;,&#34;text_color&#34;,&#34;text_font_size&#34;],&#34;selected&#34;:[],&#34;data&#34;:{&#34;x&#34;:[&#34;1:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;14:0.1&#34;,&#34;16:0.1&#34;,&#34;13:0.1&#34;,&#34;15:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;],&#34;y&#34;:[&#34;1:0.3&#34;,&#34;1:0.3&#34;,&#34;2:0.3&#34;,&#34;2:0.3&#34;,&#34;2:0.3&#34;,&#34;2:0.3&#34;,&#34;2:0.3&#34;,&#34;2:0.3&#34;,&#34;2:0.3&#34;,&#34;2:0.3&#34;,&#34;3:0.3&#34;,&#34;3:0.3&#34;,&#34;3:0.3&#34;,&#34;3:0.3&#34;,&#34;3:0.3&#34;,&#34;3:0.3&#34;,&#34;3:0.3&#34;,&#34;3:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;4:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;5:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;6:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;,&#34;7:0.3&#34;],&#34;text&#34;:[&#34;Hydrogen&#34;,&#34;Helium&#34;,&#34;Lithium&#34;,&#34;Beryllium&#34;,&#34;Boron&#34;,&#34;Carbon&#34;,&#34;Nitrogen&#34;,&#34;Oxygen&#34;,&#34;Fluorine&#34;,&#34;Neon&#34;,&#34;Sodium&#34;,&#34;Magnesium&#34;,&#34;Aluminum&#34;,&#34;Silicon&#34;,&#34;Phosphorus&#34;,&#34;Sulfur&#34;,&#34;Chlorine&#34;,&#34;Argon&#34;,&#34;Potassium&#34;,&#34;Calcium&#34;,&#34;Scandium&#34;,&#34;Titanium&#34;,&#34;Vanadium&#34;,&#34;Chromium&#34;,&#34;Manganese&#34;,&#34;Iron&#34;,&#34;Cobalt&#34;,&#34;Nickel&#34;,&#34;Copper&#34;,&#34;Zinc&#34;,&#34;Gallium&#34;,&#34;Germanium&#34;,&#34;Arsenic&#34;,&#34;Selenium&#34;,&#34;Bromine&#34;,&#34;Krypton&#34;,&#34;Rubidium&#34;,&#34;Strontium&#34;,&#34;Yttrium&#34;,&#34;Zirconium&#34;,&#34;Niobium&#34;,&#34;Molybdenum&#34;,&#34;Technetium&#34;,&#34;Ruthenium&#34;,&#34;Rhodium&#34;,&#34;Palladium&#34;,&#34;Silver&#34;,&#34;Cadmium&#34;,&#34;Indium&#34;,&#34;Tin&#34;,&#34;Antimony&#34;,&#34;Tellurium&#34;,&#34;Iodine&#34;,&#34;Xenon&#34;,&#34;Cesium&#34;,&#34;Barium&#34;,&#34;Lutetium&#34;,&#34;Hafnium&#34;,&#34;Tantalum&#34;,&#34;Tungsten&#34;,&#34;Rhenium&#34;,&#34;Osmium&#34;,&#34;Iridium&#34;,&#34;Platinum&#34;,&#34;Gold&#34;,&#34;Mercury&#34;,&#34;Thallium&#34;,&#34;Lead&#34;,&#34;Bismuth&#34;,&#34;Polonium&#34;,&#34;Astatine&#34;,&#34;Radon&#34;,&#34;Francium&#34;,&#34;Radium&#34;,&#34;Lawrencium&#34;,&#34;Rutherfordium&#34;,&#34;Dubnium&#34;,&#34;Seaborgium&#34;,&#34;Bohrium&#34;,&#34;Hassium&#34;,&#34;Meitnerium&#34;,&#34;Darmstadtium&#34;,&#34;Roentgenium&#34;,&#34;Copernicium&#34;,&#34;Ununquadium&#34;,&#34;Ununhexium&#34;,&#34;Nihonium&#34;,&#34;Moscovium&#34;,&#34;Tennessine&#34;,&#34;Oganesson&#34;],&#34;text_color&#34;:[&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;],&#34;text_font_size&#34;:[&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;]}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;28ba3a53bf6473989bea5fa2556e2bc3&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;28ba3a53bf6473989bea5fa2556e2bc3&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_color&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;931cecc035ad1c8d61eee6542f9063e6&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;931cecc035ad1c8d61eee6542f9063e6&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;#e1e1e1&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;2beae8f4391954ff59ef6b626915f8b9&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;2beae8f4391954ff59ef6b626915f8b9&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_color&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;GlyphRenderer&#34;,&#34;id&#34;:&#34;fccd66fd77c1baddce8043fba79151ab&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;fccd66fd77c1baddce8043fba79151ab&#34;,&#34;tags&#34;:[],&#34;selection_glyph&#34;:null,&#34;nonselection_glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;931cecc035ad1c8d61eee6542f9063e6&#34;},&#34;hover_glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;2beae8f4391954ff59ef6b626915f8b9&#34;},&#34;name&#34;:null,&#34;data_source&#34;:{&#34;type&#34;:&#34;ColumnDataSource&#34;,&#34;id&#34;:&#34;5f20412b078a76b411df5d8cd31ca4a1&#34;},&#34;glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;28ba3a53bf6473989bea5fa2556e2bc3&#34;}}},{&#34;type&#34;:&#34;ColumnDataSource&#34;,&#34;id&#34;:&#34;654a2758565133a5c0efba384713f6c6&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;654a2758565133a5c0efba384713f6c6&#34;,&#34;tags&#34;:[],&#34;column_names&#34;:[&#34;x&#34;,&#34;y&#34;,&#34;text&#34;,&#34;text_color&#34;,&#34;text_font_size&#34;],&#34;selected&#34;:[],&#34;data&#34;:{&#34;x&#34;:[&#34;1:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;13:0.1&#34;,&#34;14:0.1&#34;,&#34;15:0.1&#34;,&#34;16:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;,&#34;1:0.1&#34;,&#34;2:0.1&#34;,&#34;3:0.1&#34;,&#34;4:0.1&#34;,&#34;5:0.1&#34;,&#34;6:0.1&#34;,&#34;7:0.1&#34;,&#34;8:0.1&#34;,&#34;9:0.1&#34;,&#34;10:0.1&#34;,&#34;11:0.1&#34;,&#34;12:0.1&#34;,&#34;14:0.1&#34;,&#34;16:0.1&#34;,&#34;13:0.1&#34;,&#34;15:0.1&#34;,&#34;17:0.1&#34;,&#34;18:0.1&#34;],&#34;y&#34;:[&#34;1:0.15&#34;,&#34;1:0.15&#34;,&#34;2:0.15&#34;,&#34;2:0.15&#34;,&#34;2:0.15&#34;,&#34;2:0.15&#34;,&#34;2:0.15&#34;,&#34;2:0.15&#34;,&#34;2:0.15&#34;,&#34;2:0.15&#34;,&#34;3:0.15&#34;,&#34;3:0.15&#34;,&#34;3:0.15&#34;,&#34;3:0.15&#34;,&#34;3:0.15&#34;,&#34;3:0.15&#34;,&#34;3:0.15&#34;,&#34;3:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;4:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;5:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;6:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;,&#34;7:0.15&#34;],&#34;text&#34;:[&#34;1.00794&#34;,&#34;4.002602&#34;,&#34;6.941&#34;,&#34;9.012182&#34;,&#34;10.811&#34;,&#34;12.0107&#34;,&#34;14.0067&#34;,&#34;15.9994&#34;,&#34;18.9984032&#34;,&#34;20.1797&#34;,&#34;22.98976928&#34;,&#34;24.3050&#34;,&#34;26.9815386&#34;,&#34;28.0855&#34;,&#34;30.973762&#34;,&#34;32.065&#34;,&#34;35.453&#34;,&#34;39.948&#34;,&#34;39.0983&#34;,&#34;40.078&#34;,&#34;44.955912&#34;,&#34;47.867&#34;,&#34;50.9415&#34;,&#34;51.9961&#34;,&#34;54.938045&#34;,&#34;55.845&#34;,&#34;58.933195&#34;,&#34;58.6934&#34;,&#34;63.546&#34;,&#34;65.38&#34;,&#34;69.723&#34;,&#34;72.64&#34;,&#34;74.92160&#34;,&#34;78.96&#34;,&#34;79.904&#34;,&#34;83.798&#34;,&#34;85.4678&#34;,&#34;87.62&#34;,&#34;88.90585&#34;,&#34;91.224&#34;,&#34;92.90638&#34;,&#34;95.96&#34;,&#34;[98]&#34;,&#34;101.07&#34;,&#34;102.90550&#34;,&#34;106.42&#34;,&#34;107.8682&#34;,&#34;112.411&#34;,&#34;114.818&#34;,&#34;118.710&#34;,&#34;121.760&#34;,&#34;127.60&#34;,&#34;126.90447&#34;,&#34;131.293&#34;,&#34;132.9054519&#34;,&#34;137.327&#34;,&#34;174.9668&#34;,&#34;178.49&#34;,&#34;180.94788&#34;,&#34;183.84&#34;,&#34;186.207&#34;,&#34;190.23&#34;,&#34;192.217&#34;,&#34;195.084&#34;,&#34;196.966569&#34;,&#34;200.59&#34;,&#34;204.3833&#34;,&#34;207.2&#34;,&#34;208.98040&#34;,&#34;[209]&#34;,&#34;[210]&#34;,&#34;[222]&#34;,&#34;[223]&#34;,&#34;[226]&#34;,&#34;[262]&#34;,&#34;[267]&#34;,&#34;[268]&#34;,&#34;[271]&#34;,&#34;[272]&#34;,&#34;[270]&#34;,&#34;[276]&#34;,&#34;[281]&#34;,&#34;[280]&#34;,&#34;[285]&#34;,&#34;[289]&#34;,&#34;[293]&#34;,&#34;[284]&#34;,&#34;[288]&#34;,&#34;[294]&#34;,&#34;[294]&#34;],&#34;text_color&#34;:[&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;,&#34;black&#34;],&#34;text_font_size&#34;:[&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;,&#34;4pt&#34;]}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;2f57098042e1e4bbc731bacaeb81d051&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;2f57098042e1e4bbc731bacaeb81d051&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_color&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;2310ade99e76f153b3973ebf16c1ff75&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;2310ade99e76f153b3973ebf16c1ff75&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;#e1e1e1&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;de682c705e3ab5c3c25db1e940a047dd&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;de682c705e3ab5c3c25db1e940a047dd&#34;,&#34;tags&#34;:[],&#34;angle&#34;:{&#34;units&#34;:&#34;rad&#34;,&#34;value&#34;:0},&#34;text_alpha&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:1},&#34;text_align&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;left&#34;},&#34;text_baseline&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;value&#34;:&#34;middle&#34;},&#34;visible&#34;:true,&#34;x&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;x&#34;},&#34;y&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;y&#34;},&#34;text&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text&#34;},&#34;text_color&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_color&#34;},&#34;text_font_size&#34;:{&#34;units&#34;:&#34;data&#34;,&#34;field&#34;:&#34;text_font_size&#34;}}},{&#34;type&#34;:&#34;GlyphRenderer&#34;,&#34;id&#34;:&#34;230ad7907e84c264bad8fbf326b5e5e2&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;230ad7907e84c264bad8fbf326b5e5e2&#34;,&#34;tags&#34;:[],&#34;selection_glyph&#34;:null,&#34;nonselection_glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;2310ade99e76f153b3973ebf16c1ff75&#34;},&#34;hover_glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;de682c705e3ab5c3c25db1e940a047dd&#34;},&#34;name&#34;:null,&#34;data_source&#34;:{&#34;type&#34;:&#34;ColumnDataSource&#34;,&#34;id&#34;:&#34;654a2758565133a5c0efba384713f6c6&#34;},&#34;glyph&#34;:{&#34;type&#34;:&#34;Text&#34;,&#34;id&#34;:&#34;2f57098042e1e4bbc731bacaeb81d051&#34;}}},{&#34;type&#34;:&#34;FactorRange&#34;,&#34;id&#34;:&#34;bbe638eb195f16928209286930ed836e&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;bbe638eb195f16928209286930ed836e&#34;,&#34;tags&#34;:[],&#34;factors&#34;:[&#34;1&#34;,&#34;2&#34;,&#34;3&#34;,&#34;4&#34;,&#34;5&#34;,&#34;6&#34;,&#34;7&#34;,&#34;8&#34;,&#34;9&#34;,&#34;10&#34;,&#34;11&#34;,&#34;12&#34;,&#34;13&#34;,&#34;14&#34;,&#34;15&#34;,&#34;16&#34;,&#34;17&#34;,&#34;18&#34;]}},{&#34;type&#34;:&#34;FactorRange&#34;,&#34;id&#34;:&#34;87a5194a1046bdbe7658d35f9012e280&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;87a5194a1046bdbe7658d35f9012e280&#34;,&#34;tags&#34;:[],&#34;factors&#34;:[&#34;7&#34;,&#34;6&#34;,&#34;5&#34;,&#34;4&#34;,&#34;3&#34;,&#34;2&#34;,&#34;1&#34;]}},{&#34;type&#34;:&#34;CategoricalAxis&#34;,&#34;id&#34;:&#34;c1540c8e7b35c4d514a8101df5141f4a&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;c1540c8e7b35c4d514a8101df5141f4a&#34;,&#34;tags&#34;:[],&#34;plot&#34;:{&#34;type&#34;:&#34;Plot&#34;,&#34;id&#34;:&#34;1326bd2fcc4ec1e393849bb25c261c41&#34;,&#34;subtype&#34;:&#34;Figure&#34;},&#34;axis_label&#34;:&#34;&#34;,&#34;formatter&#34;:{&#34;type&#34;:&#34;CategoricalTickFormatter&#34;,&#34;id&#34;:&#34;b6d096b90dfa0226f97c99351f12bdd4&#34;},&#34;ticker&#34;:{&#34;type&#34;:&#34;CategoricalTicker&#34;,&#34;id&#34;:&#34;81a9edcc023702be7cbef53e7ad9fb19&#34;},&#34;visible&#34;:true,&#34;axis_label_text_font_size&#34;:&#34;12pt&#34;}},{&#34;type&#34;:&#34;CategoricalTickFormatter&#34;,&#34;id&#34;:&#34;b6d096b90dfa0226f97c99351f12bdd4&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;b6d096b90dfa0226f97c99351f12bdd4&#34;,&#34;tags&#34;:[]}},{&#34;type&#34;:&#34;CategoricalTicker&#34;,&#34;id&#34;:&#34;81a9edcc023702be7cbef53e7ad9fb19&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;81a9edcc023702be7cbef53e7ad9fb19&#34;,&#34;tags&#34;:[]}},{&#34;type&#34;:&#34;CategoricalAxis&#34;,&#34;id&#34;:&#34;cc6941546581f341b83a11be445d5a0f&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;cc6941546581f341b83a11be445d5a0f&#34;,&#34;tags&#34;:[],&#34;plot&#34;:{&#34;type&#34;:&#34;Plot&#34;,&#34;id&#34;:&#34;1326bd2fcc4ec1e393849bb25c261c41&#34;,&#34;subtype&#34;:&#34;Figure&#34;},&#34;axis_label&#34;:&#34;&#34;,&#34;formatter&#34;:{&#34;type&#34;:&#34;CategoricalTickFormatter&#34;,&#34;id&#34;:&#34;1c4bc382007944f1dd5e4833e8511102&#34;},&#34;ticker&#34;:{&#34;type&#34;:&#34;CategoricalTicker&#34;,&#34;id&#34;:&#34;6ab57ac91704ef62906e5ccccadee686&#34;},&#34;visible&#34;:true,&#34;axis_label_text_font_size&#34;:&#34;12pt&#34;}},{&#34;type&#34;:&#34;CategoricalTickFormatter&#34;,&#34;id&#34;:&#34;1c4bc382007944f1dd5e4833e8511102&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;1c4bc382007944f1dd5e4833e8511102&#34;,&#34;tags&#34;:[]}},{&#34;type&#34;:&#34;CategoricalTicker&#34;,&#34;id&#34;:&#34;6ab57ac91704ef62906e5ccccadee686&#34;,&#34;attributes&#34;:{&#34;id&#34;:&#34;6ab57ac91704ef62906e5ccccadee686&#34;,&#34;tags&#34;:[]}}]}}},&#34;debug&#34;:false},&#34;evals&#34;:[],&#34;jsHooks&#34;:[]}&lt;/script&gt;
&lt;script type=&#34;application/htmlwidget-sizing&#34; data-for=&#34;htmlwidget-bb44db00724a24a98e0e&#34;&gt;{&#34;viewer&#34;:{&#34;width&#34;:800,&#34;height&#34;:445,&#34;padding&#34;:15,&#34;fill&#34;:false},&#34;browser&#34;:{&#34;width&#34;:800,&#34;height&#34;:445,&#34;padding&#34;:40,&#34;fill&#34;:false}}&lt;/script&gt;
&lt;p&gt;Note: this period table of elements doesn&amp;rsquo;t show the lanthanides and actinides.&lt;/p&gt;
&lt;p&gt;Now you can browse the periodic table of my husband&amp;rsquo;s experience, which he&amp;rsquo;ll soon include &lt;a href=&#34;http://dacornu.github.io/&#34;&gt;on his website&lt;/a&gt; as a visual CV. It includes his research but also the fact that he was a guide for tours about Marie Curie&amp;rsquo;s life. I&amp;rsquo;m happy for him not to use radioactive elements for real, and of course for him to support women in science (I&amp;rsquo;ll get him &lt;a href=&#34;https://twitter.com/alice_data/status/826929489447890945&#34;&gt;this pretty sticker&lt;/a&gt; if Alice ends up printing it).&lt;/p&gt;
&lt;p&gt;Now it&amp;rsquo;s your turn to create an interactive periodic table for the chemist in your life! I&amp;rsquo;d also be curious of how to map one&amp;rsquo;s experience in other fields than chemistry. I made a &lt;a href=&#34;https://rstudio.github.io/leaflet/&#34;&gt;&lt;code&gt;leaflet&lt;/code&gt;&lt;/a&gt; map for Damien and my websites with places where we studied or worked (you now know he really didn&amp;rsquo;t marry me for my good looks) which is a pretty straightforward &amp;ldquo;experience-mapping&amp;rdquo; method but maybe one could imagine a phylogenetic tree for a biologist? You tell me!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>The Rt of naming your blog</title>
      <link>https://masalmon.eu/2017/01/29/rbloggersnames/</link>
      <pubDate>Sun, 29 Jan 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/01/29/rbloggersnames/</guid>
      <description>&lt;p&gt;In this post, I&amp;rsquo;m sharing a brand-new analysis! The reason for this is my blog being added to &lt;a href=&#34;https://www.r-bloggers.com/&#34;&gt;R-bloggers&lt;/a&gt; by Tal Galili after I filled &lt;a href=&#34;https://www.r-bloggers.com/add-your-blog/&#34;&gt;this form&lt;/a&gt;. R-bloggers is a collection of blogs about R, whose new posts get added to the website via the magic of RSS feeds. R-bloggers even has a &lt;a href=&#34;https://twitter.com/Rbloggers&#34;&gt;Twitter account&lt;/a&gt;. As a reader of R-bloggers you get exposed to many different analyses and ideas, as a R-blogger you reach a wider audience, so really it&amp;rsquo;s an useful website. Tal does a great job maintaining R-bloggers and understandably likes seeing R-bloggers mentioning the website on their blog, which I already do in the &lt;a href=&#34;https://masalmon.eu/about/&#34;&gt;About section&lt;/a&gt;, and in one article, which I&amp;rsquo;ve consistently failed to do in the last two posts because I got too caught up about the article at hand to think about anything else. So I&amp;rsquo;ve figured out the best way not to forget to thank Tal for his work was to do an analysis &lt;em&gt;about&lt;/em&gt; R-bloggers! Genius, I know. I&amp;rsquo;ve scraped the &lt;a href=&#34;https://www.r-bloggers.com/blogs-list/&#34;&gt;full list of contributing blogs&lt;/a&gt; and had a look at their names and addresses.&lt;/p&gt;
&lt;h1 id=&#34;scraping-and-transforming-the-list-of-blogs&#34;&gt;Scraping and transforming the list of blogs&lt;/h1&gt;
&lt;p&gt;The list of contributing blogs is not an html table which makes me things more interesting. I had to look a bit at the source of the html page to come up with a solution to transform it. I wasn&amp;rsquo;t too slow because I&amp;rsquo;ve done something similar with Wikipedia data in the past, something that&amp;rsquo;s still an unfinished building, of course, but whose code I could re-use.&lt;/p&gt;
&lt;p&gt;I used &lt;a href=&#34;https://github.com/hadley/rvest&#34;&gt;&lt;code&gt;rvest&lt;/code&gt;&lt;/a&gt; for first scraping the data but also &lt;a href=&#34;https://github.com/tidyverse/stringr&#34;&gt;&lt;code&gt;stringr&lt;/code&gt;&lt;/a&gt; for manipulating strings. What I like the most about &lt;code&gt;stringr&lt;/code&gt; compared to manipulating strings with base R are the names of functions, that reflect what they do so well, and the order of arguments, with the &lt;code&gt;character&lt;/code&gt; vector first. &lt;a href=&#34;https://twitter.com/nj_tierney&#34;&gt;Nick&lt;/a&gt;, who has &lt;a href=&#34;http://www.njtierney.com/&#34;&gt;a great R blog&lt;/a&gt; by the way, told me in the comments &lt;a href=&#34;https://masalmon.eu/2017/01/26/morewater/&#34;&gt;of one post&lt;/a&gt; I had &amp;ldquo;some pretty ninja grep skills&amp;rdquo;. Although I think he exaggerates a little bit, I&amp;rsquo;ll try not to disappoint him!&lt;/p&gt;
&lt;p&gt;First I wanted to get a &lt;code&gt;character&lt;/code&gt; vector for each blog.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;rvest&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purrr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tibble&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;stringr&amp;#34;&lt;/span&gt;)
blogs_list &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;read_html&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;https://www.r-bloggers.com/blogs-list/&amp;#34;&lt;/span&gt;)
blogs_list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## {xml_document}
## &amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot; lang=&amp;quot;en-US&amp;quot; prefix=&amp;quot;og: http://ogp.me/ns#&amp;quot; itemscope=&amp;quot;&amp;quot; itemtype=&amp;quot;http://schema.org/WebSite&amp;quot;&amp;gt;
## [1] &amp;lt;head profile=&amp;quot;http://gmpg.org/xfn/11&amp;quot;&amp;gt;\n  &amp;lt;meta http-equiv=&amp;quot;Content ...
## [2] &amp;lt;body class=&amp;quot;page page-id-16581 page-template page-template-page-lin ...
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;blogs_list &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;html_nodes&lt;/span&gt;(blogs_list, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ul&amp;#34;&lt;/span&gt;) 
blogs_list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## {xml_nodeset (10)}
##  [1] &amp;lt;ul id=&amp;quot;menu-top-nav&amp;quot; class=&amp;quot;sf-menu&amp;quot;&amp;gt;&amp;lt;li id=&amp;quot;menu-item-48314&amp;quot; clas ...
##  [2] &amp;lt;ul class=&amp;quot;sub-menu&amp;quot;&amp;gt;&amp;lt;li id=&amp;quot;menu-item-76945&amp;quot; class=&amp;quot;menu-item menu ...
##  [3] &amp;lt;ul&amp;gt;\n  &amp;lt;li&amp;gt;\n    &amp;lt;a class=&amp;quot;rsswidget&amp;quot; href=&amp;quot;http://feedproxy.googl ...
##  [4] &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;https://www.r-bloggers.com/search/git&amp;quot;&amp;gt;git&amp;lt;/a&amp;gt;&amp;lt;/li ...
##  [5] &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;\n\t\t\t\t&amp;lt;a href=&amp;quot;https://www.r-bloggers.com/trumpworld-an ...
##  [6] &amp;lt;ul class=&amp;quot;xoxo blogroll&amp;quot;&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://www.proc-x.com/&amp;quot; oncl ...
##  [7] &amp;lt;ul class=&amp;quot;xoxo blogroll&amp;quot;&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;\n&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;# ...
##  [8] &amp;lt;ul class=&amp;quot;xoxo blogroll&amp;quot;&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;https://www.r-users.com/&amp;quot; on ...
##  [9] &amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;\n\t\t\t\t\t\t\t\t\t\t&amp;lt;a href=&amp;quot;https://www.r-bloggers.com/v ...
## [10] &amp;lt;ul&amp;gt;\n  &amp;lt;li&amp;gt;\n    &amp;lt;a class=&amp;quot;rsswidget&amp;quot; href=&amp;quot;http://feedproxy.googl ...
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;blogs_list &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; blogs_list&lt;span style=&#34;color:#06287e&#34;&gt;[str_detect&lt;/span&gt;(blogs_list, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;xoxo blogroll&amp;#34;&lt;/span&gt;)][2]
blogs_list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## {xml_nodeset (1)}
## [1] &amp;lt;ul class=&amp;quot;xoxo blogroll&amp;quot;&amp;gt;&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;\n&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot; ...
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;blogs_list &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(blogs_list)
blogs_list &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(blogs_list, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;lt;li&amp;gt;&amp;lt;a&amp;#34;&lt;/span&gt;, simplify &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# it starts from 6&lt;/span&gt;
blogs_list &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; blogs_list[6&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(blogs_list)]
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(blogs_list)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot; href=\&amp;quot;http://dmlc.ml\&amp;quot; onclick=\&amp;quot;_gaq.push([&#39;_trackEvent&#39;, &#39;outbound-widget&#39;, &#39;http://dmlc.ml&#39;, &#39; R stats&#39;]);\&amp;quot;&amp;gt; R stats&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;\n&amp;quot;                                                                                         
## [2] &amp;quot; href=\&amp;quot;http://lionel-.github.io\&amp;quot; onclick=\&amp;quot;_gaq.push([&#39;_trackEvent&#39;, &#39;outbound-widget&#39;, &#39;http://lionel-.github.io&#39;, &#39; rstats&#39;]);\&amp;quot;&amp;gt; rstats&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;\n&amp;quot;                                                                       
## [3] &amp;quot; href=\&amp;quot;https://jean9208.github.io/rss-R.xml\&amp;quot; onclick=\&amp;quot;_gaq.push([&#39;_trackEvent&#39;, &#39;outbound-widget&#39;, &#39;https://jean9208.github.io/rss-R.xml&#39;, &#39;Jean Arreola&#39;]);\&amp;quot;&amp;gt;Jean Arreola&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;\n&amp;quot;                                   
## [4] &amp;quot; href=\&amp;quot;http://ryouready.wordpress.com\&amp;quot; onclick=\&amp;quot;_gaq.push([&#39;_trackEvent&#39;, &#39;outbound-widget&#39;, &#39;http://ryouready.wordpress.com&#39;, &#39;R you ready?&#39;]);\&amp;quot; title=\&amp;quot;My advances in R  a learners diary\&amp;quot;&amp;gt;R you ready?&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;\n&amp;quot;
## [5] &amp;quot; href=\&amp;quot;https://rveryday.wordpress.com/\&amp;quot; onclick=\&amp;quot;_gaq.push([&#39;_trackEvent&#39;, &#39;outbound-widget&#39;, &#39;https://rveryday.wordpress.com/&#39;, &#39;(R)very Day&#39;]);\&amp;quot;&amp;gt;(R)very Day&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;\n&amp;quot;                                                   
## [6] &amp;quot; href=\&amp;quot;http://www.talyarkoni.org/blog\&amp;quot; onclick=\&amp;quot;_gaq.push([&#39;_trackEvent&#39;, &#39;outbound-widget&#39;, &#39;http://www.talyarkoni.org/blog&#39;, &#39;[citation needed] » R&#39;]);\&amp;quot;&amp;gt;[citation needed] » R&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;\n&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OK so now from each element of &lt;code&gt;blogs_list&lt;/code&gt; I want to extract the name of the blog, e.g. &amp;lsquo;– R stats&amp;rsquo;, and its address, e.g. &amp;lsquo;&lt;a href=&#34;http://dmlc.ml&#34;&gt;http://dmlc.ml&lt;/a&gt;&amp;rsquo;. I&amp;rsquo;ll first extract the links because using the link it&amp;rsquo;ll be easier to extract the blog name. Note the use of &lt;code&gt;map_chr&lt;/code&gt;: using this variant of &lt;code&gt;purrr&lt;/code&gt; function &lt;code&gt;map&lt;/code&gt;, you directly get a &lt;code&gt;character&lt;/code&gt; vector instead of a list.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;extract_link &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x){
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(x, 
                   pattern &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;href=\\\&amp;#34;&amp;#34;&lt;/span&gt;,
                   replacement &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(x, 
                   pattern &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\\&amp;#34; onclick=.*\\n&amp;#34;&lt;/span&gt;,
                   replacement &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_trim&lt;/span&gt;(x)
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(x)
}

blogs_address &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map_chr&lt;/span&gt;(blogs_list, extract_link)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# the last one is a special snowflake&lt;/span&gt;
blogs_address&lt;span style=&#34;color:#06287e&#34;&gt;[length&lt;/span&gt;(blogs_address)] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(blogs_address&lt;span style=&#34;color:#06287e&#34;&gt;[length&lt;/span&gt;(blogs_address)],
                                                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\\n\\\t&amp;lt;\\/ul&amp;gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)

&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(blogs_address)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;http://dmlc.ml&amp;quot;                      
## [2] &amp;quot;http://lionel-.github.io&amp;quot;            
## [3] &amp;quot;https://jean9208.github.io/rss-R.xml&amp;quot;
## [4] &amp;quot;http://ryouready.wordpress.com&amp;quot;      
## [5] &amp;quot;https://rveryday.wordpress.com/&amp;quot;     
## [6] &amp;quot;http://www.talyarkoni.org/blog&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So let&amp;rsquo;s now extract names!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;extract_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(x, address){
  address &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(address, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\/&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\\\\\/&amp;#34;&lt;/span&gt;)
  address &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(address, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\.&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\\\\\.&amp;#34;&lt;/span&gt;)
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(x, &lt;span style=&#34;color:#06287e&#34;&gt;paste0&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.*&amp;#34;&lt;/span&gt;, address, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#39;, &amp;#39;&amp;#34;&lt;/span&gt;), &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(x, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;]\\)\\;.*\\\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(x, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#39;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(x)
}

blogs_names &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;map2_chr&lt;/span&gt;(blogs_list, blogs_address, extract_names)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# last one is a special snowflake again&lt;/span&gt;
blogs_names&lt;span style=&#34;color:#06287e&#34;&gt;[length&lt;/span&gt;(blogs_names)] &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(blogs_names&lt;span style=&#34;color:#06287e&#34;&gt;[length&lt;/span&gt;(blogs_address)],
                                                    &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\\n\\\t&amp;lt;\\/ul&amp;gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(blogs_names)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot; R stats&amp;quot;             &amp;quot; rstats&amp;quot;              &amp;quot;Jean Arreola&amp;quot;       
## [4] &amp;quot;R you ready?&amp;quot;        &amp;quot;(R)very Day&amp;quot;           &amp;quot;[citation needed] » R&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now I can build a &lt;code&gt;tibble&lt;/code&gt; of names and addresses of blogs!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;blogs_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;tibble&lt;/span&gt;(name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; blogs_names,
                     address &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; blogs_address)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are 746 blogs. The list also includes blogs that are no longer updated apparently, but that contributed content to R-bloggers at one point. My own blog isn&amp;rsquo;t in the list yet which is fine because &amp;ldquo;Maëlle&amp;rdquo; is a pretty unique blog name but neither funny nor witty, except if testing encoding issues is funny or witty.&lt;/p&gt;
&lt;p&gt;Before starting to have fun looking at blog names and addresses, I&amp;rsquo;ll extract the extension from the addresses.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;extract_extension &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;address, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;feed\\.r-bloggers\\.xml&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(x, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\.xml&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(x, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\.html&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace&lt;/span&gt;(x, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\.php&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(x, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\.&amp;#34;&lt;/span&gt;, simplify &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; x&lt;span style=&#34;color:#06287e&#34;&gt;[length&lt;/span&gt;(x)]
  x &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_replace_all&lt;/span&gt;(x, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;\\/.*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(x)
}

blogs_info &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;by_row&lt;/span&gt;(blogs_info,
                     extract_extension,
                     .to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;extension&amp;#34;&lt;/span&gt;,
                     .collate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols&amp;#34;&lt;/span&gt;)


knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(blogs_info, n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;address&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;extension&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;– R stats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://dmlc.ml&#34;&gt;http://dmlc.ml&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ml&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;– rstats&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://lionel-.github.io&#34;&gt;http://lionel-.github.io&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;io&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;–Jean Arreola–&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://jean9208.github.io/rss-R.xml&#34;&gt;https://jean9208.github.io/rss-R.xml&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;io&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;“R” you ready?&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://ryouready.wordpress.com&#34;&gt;http://ryouready.wordpress.com&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;(R)very Day&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;https://rveryday.wordpress.com/&#34;&gt;https://rveryday.wordpress.com/&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;[citation needed] » R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://www.talyarkoni.org/blog&#34;&gt;http://www.talyarkoni.org/blog&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;org&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;[R] tricks&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://rtricks.wordpress.com&#34;&gt;http://rtricks.wordpress.com&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;/mgritts_&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://mgritts.com/feed.r.xml&#34;&gt;http://mgritts.com/feed.r.xml&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;r&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;#untitled&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://blog.ambodi.com/&#34;&gt;http://blog.ambodi.com/&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;0xCAFEBABE&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://xcafebabe.blogspot.com/search/label/R&#34;&gt;http://xcafebabe.blogspot.com/search/label/R&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;4D Pie Charts » R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://4dpiecharts.com&#34;&gt;http://4dpiecharts.com&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;56north | Skræddersyet dataanalyse » Renglish&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://www.56n.dk&#34;&gt;http://www.56n.dk&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;dk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A blog from Sydney&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://a-blog-from-sydney.blogspot.com/search/label/R&#34;&gt;http://a-blog-from-sydney.blogspot.com/search/label/R&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A Blog On Data Analytics&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://aliarsalankazmi.github.io/blog_DA/&#34;&gt;http://aliarsalankazmi.github.io/blog_DA/&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;io&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A HopStat and Jump Away » Rbloggers&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://hopstat.wordpress.com/&#34;&gt;http://hopstat.wordpress.com/&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;a Physicist in Wall Street&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://aphysicistinwallstreet.blogspot.com/search/label/R&#34;&gt;http://aphysicistinwallstreet.blogspot.com/search/label/R&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A Pint of R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://rpint.wordpress.com&#34;&gt;http://rpint.wordpress.com&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;A Statistics Blog – R&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://statistics.rainandrhino.org/R.xml&#34;&gt;http://statistics.rainandrhino.org/R.xml&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;org&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Actuarially (Matt Malin)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://www.actuarially.co.uk/&#34;&gt;http://www.actuarially.co.uk/&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;uk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Adventures in Analytics and Visualization&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;a href=&#34;http://analyticsandvisualization.blogspot.com/search/label/R&#34;&gt;http://analyticsandvisualization.blogspot.com/search/label/R&lt;/a&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;analysing-blog-info&#34;&gt;Analysing blog info&lt;/h1&gt;
&lt;h2 id=&#34;how-and-where-do-people-blog&#34;&gt;How and where do people blog?&lt;/h2&gt;
&lt;p&gt;Out of the 746 blogs there are 156 &lt;code&gt;blogspot.com&lt;/code&gt; blogs, 181 &lt;code&gt;wordpress.com&lt;/code&gt; blogs and  53 &lt;code&gt;github.io&lt;/code&gt; blogs. I guess most &lt;code&gt;github.io&lt;/code&gt; blogs are &lt;a href=&#34;https://github.com/yihui/knitr-jekyll&#34;&gt;&lt;code&gt;knitr-jekyll&lt;/code&gt;&lt;/a&gt;-based like mine, or more modern &lt;a href=&#34;https://github.com/rstudio/blogdown&#34;&gt;&lt;code&gt;blogdown&lt;/code&gt;&lt;/a&gt; blogs. For blogs with a specific domain name, e.g. Julia Silge&amp;rsquo;s excellent &lt;a href=&#34;http://juliasilge.com&#34;&gt;&amp;ldquo;data science ish&amp;rdquo; blog&lt;/a&gt; who has &amp;ldquo;juliasilge&amp;rdquo; as domain name, it&amp;rsquo;s more difficult to know how people blog. Well I know Julia uses &lt;code&gt;knitr-jekyll&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What about extensions?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
blogs_info &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(extension) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;extension&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;com&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;533&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;io&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;53&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;org&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;net&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;de&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;info&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;me&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;uk&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;nl&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;co&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;eu&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;name&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ca&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;edu&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;es&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;fr&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I totally stopped at &amp;ldquo;fr&amp;rdquo; on purpose. Without surprise given the number of blogspot/wordpress blogs &amp;ldquo;.com&amp;rdquo; is a favourite, and then &amp;ldquo;.io&amp;rdquo;. I&amp;rsquo;m quite happy to see 4 fellow &amp;ldquo;.eu&amp;rdquo; bloggers. But I&amp;rsquo;ll admit regretting I didn&amp;rsquo;t choose &amp;ldquo;.guru&amp;rdquo; like &lt;a href=&#34;https://youranalytics.guru&#34;&gt;this blog&lt;/a&gt; because I&amp;rsquo;d have loved to become a R guru.&lt;/p&gt;
&lt;h2 id=&#34;so-whats-in-blog-names&#34;&gt;So, what&amp;rsquo;s in blog names?&lt;/h2&gt;
&lt;p&gt;The first thing I noticed when looking at the names of blogs was the high frequency of puns! There&amp;rsquo;s the &lt;a href=&#34;http://www.hallwaymathlete.com/search/label/rblogger&#34;&gt;&amp;ldquo;Hallway Mathlete&amp;rdquo;&lt;/a&gt;, &lt;a href=&#34;http://omaymaS.github.io/&#34;&gt;&amp;ldquo;Once Upon a Data&amp;rdquo;&lt;/a&gt;, &lt;a href=&#34;http://www.imachordata.com&#34;&gt;&amp;ldquo;i’m a chordata! urochordata! » R&amp;rdquo;&lt;/a&gt; (too bad this website doesn&amp;rsquo;t seem to exist any longer), etc. And well these were regular data / statistics puns&amp;hellip; then we have the R puns! &lt;a href=&#34;https://shiring.github.io/&#34;&gt;&amp;ldquo;Shirin’s playgRound&amp;rdquo;&lt;/a&gt;, &lt;a href=&#34;http://ryouready.wordpress.com&#34;&gt;&amp;quot;“R” you ready?&amp;quot;&lt;/a&gt;, &lt;a href=&#34;https://rveryday.wordpress.com/&#34;&gt;&amp;quot;(R)very Day&amp;rdquo;&lt;/a&gt;&amp;hellip; R Bloggers are a bit like hair dressers, said my husband when I told him about some names.&lt;/p&gt;
&lt;p&gt;Another not surprising feature of some blog names is to include something about statistics, like David Robinson&amp;rsquo;s &lt;a href=&#34;http://varianceexplained.org&#34;&gt;&amp;ldquo;Variance Explained&amp;rdquo;&lt;/a&gt;. Maybe we could resolve the Bayesians vs. frequentist feud by looking at blog names? Well 4 have a name including &amp;ldquo;Bayes&amp;rdquo;, 0 a &amp;ldquo;frequentist&amp;rdquo; name. That said, I can have missed a pun indicating the author&amp;rsquo;s position on the subject.&lt;/p&gt;
&lt;p&gt;Names of blogs can also indicate the field where the author applies R, e.g. 15 blogs include something &amp;ldquo;bio&amp;rdquo;-ish and 3 contain the word &amp;ldquo;finance&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Also, in case you want a bit of action in your life, there are 6 &amp;ldquo;adventures&amp;rdquo; blogs, and 3 &amp;ldquo;journey&amp;rdquo; blogs. By the way, my PhD advisor&amp;rsquo;s blog, &lt;a href=&#34;http://staff.math.su.se/hoehle/blog/&#34;&gt;&amp;ldquo;Theory meets practice…&amp;quot;&lt;/a&gt; can also help you in your daily adventures, from &lt;a href=&#34;http://staff.math.su.se/hoehle/blog/2016/06/12/optimalChoice.html&#34;&gt;choosing a Tinder profile&lt;/a&gt; to &lt;a href=&#34;http://staff.math.su.se/hoehle/blog/2016/12/23/surprise.html&#34;&gt;knowing which Kinder Surprise eggs contain a figure&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After this random exploration of blog names, I realized you&amp;rsquo;d all be waiting for a wordcloud. Or so I think. So let&amp;rsquo;s make a wordcloud of R blog names!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;wordcloud&amp;#34;&lt;/span&gt;)
words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;toString&lt;/span&gt;(blogs_info&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;name)
words &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;str_split&lt;/span&gt;(words, pattern &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;, simplify &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;wordcloud&lt;/span&gt;(words, colors &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; viridis&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;viridis_pal&lt;/span&gt;(end &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.8&lt;/span&gt;)(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;),
          min.freq &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;, random.color &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-01-29-rbloggersnames/unnamed-chunk-7-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-7&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;You might be disappointed that I don&amp;rsquo;t have any good advice for naming your blog. Sure, looking at existing names you can choose one for fitting in (including words like &amp;ldquo;data&amp;rdquo;, &amp;ldquo;rstats&amp;rdquo;, etc.) or a very original one, but does it predict success? I guess it&amp;rsquo;s better, however, to have a really cool blog name if you start printing t-shirts for your readers.&lt;/p&gt;
&lt;p&gt;Another thing you might need to name during your R journey/adventures is a package. If you&amp;rsquo;re interested in this issue, you might want to read Alex Whant&amp;rsquo;s post &lt;a href=&#34;http://alexwhan.com/2016-04-19-package-names&#34;&gt;&amp;ldquo;What&amp;rsquo;s in a [package] name?&amp;quot;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And last but not least, thanks again to Tal for creating and maintaining R-bloggers!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Cards on the table</title>
      <link>https://masalmon.eu/2017/01/27/catan/</link>
      <pubDate>Fri, 27 Jan 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/01/27/catan/</guid>
      <description>&lt;p&gt;After the &lt;a href=&#34;https://masalmon.eu/2017/01/26/morewater/&#34;&gt;last post&lt;/a&gt; building on feedback from readers, the blog is back to the regular program of recycling old Github repos. Today&amp;rsquo;s project was waiting for its turn &lt;a href=&#34;https://github.com/masalmon/catan_card_game&#34;&gt;here&lt;/a&gt; and will involve a Catan card game. Nearly a year ago, I played Catan with my husband who was kind enough to accept our monitoring all rounds. My goal? Producing a nice animated visualization of our game.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll first reckon I don&amp;rsquo;t even really like card games, board games, you name it. I don&amp;rsquo;t hate them, but there are thousands other things that I&amp;rsquo;d rather do even when socializing, like talking or listening. Well in any case we received a game of Catan cards as a present, and it&amp;rsquo;s actually not a bad game. If you&amp;rsquo;re curious you can read &lt;a href=&#34;https://en.wikipedia.org/wiki/Catan_Card_Game&#34;&gt;this page&lt;/a&gt;, for this article you only need to know that the game is about getting riches (lumber, grain, etc.) for your territory, which you gain by cards drawn from the market or exchanged with other players. The more riches your territory has, the bigger is your score. You stop playing when one of the players&amp;rsquo; score is higher than a limit, or after 20 rounds because you&amp;rsquo;re too tired to monitor any more round.&lt;/p&gt;
&lt;h1 id=&#34;collected-data&#34;&gt;Collected data&lt;/h1&gt;
&lt;p&gt;This is how the data we got looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;market &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-01-27-catan_market.csv&amp;#34;&lt;/span&gt;)
damien &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-01-27-catan_damien.csv&amp;#34;&lt;/span&gt;)
maelle &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-01-27-catan_maelle.csv&amp;#34;&lt;/span&gt;)

knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(damien))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;victory&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;round&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;lumber&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;brick&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;grain&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;wool&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;ore&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;settlement&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;city&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;knight&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;city_hall&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;development&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;road&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(maelle))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;victory&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;round&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;lumber&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;brick&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;grain&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;wool&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;ore&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;settlement&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;city&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;knight&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;city_hall&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;development&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;road&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For players for each turn one has a score which I called &lt;em&gt;victory&lt;/em&gt; and a number of cards for each type of riches.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(market))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;round&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;lumber&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;brick&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;grain&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;wool&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;ore&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The market has the same variables except &lt;em&gt;victory&lt;/em&gt;. I even entered the number of cards of each types in tables but chose not to check the total numbers of our collected data made sense because I didn&amp;rsquo;t have any desire to monitor again, since it makes playing a bit too serious. I promise that this is not how I deal with scientific data.&lt;/p&gt;
&lt;h1 id=&#34;design-of-the-visualization&#34;&gt;Design of the visualization&lt;/h1&gt;
&lt;p&gt;The title of this section sounds fancier than my actual creative process, and well even creative process sounds fancy&amp;hellip; Let&amp;rsquo;s say I had fun making decisions about my future viz. In my mind right from the beginning it was clear that I wanted to create a map of the territories where stuff would change over time to show the evolution of the scores.&lt;/p&gt;
&lt;h2 id=&#34;choosing-a-representation-of-riches&#34;&gt;Choosing a representation of riches&lt;/h2&gt;
&lt;p&gt;I am a big fan of the &lt;a href=&#34;https://github.com/GuangchuangYu/emojifont&#34;&gt;&lt;code&gt;emojifonts&lt;/code&gt; package&lt;/a&gt; so I decided to assign an emoji to each type of riches. It was not easy, sometimes emojis wouldn&amp;rsquo;t render, so I ended up with this list.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;emojis &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-01-27-catan_emojis.csv&amp;#34;&lt;/span&gt;)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(emojis)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;emoji&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;lumber&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;evergreen_tree&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;brick&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;construction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;grain&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;icecream&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;wool&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;sheep&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;ore&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lemon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;settlement&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;tent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;city&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;house&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;knight&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;horse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;city_hall&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;european_castle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;development&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;japanese_castle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;road&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;truck&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I&amp;rsquo;m in particular a bit ashamed of lemons as ore but I did not have a better idea. Lemons are not ore but they are a cool thing to own for your territory, okay?&lt;/p&gt;
&lt;h2 id=&#34;which-territories&#34;&gt;Which territories?&lt;/h2&gt;
&lt;p&gt;I wanted to draw locations for the riches on a map. I did not want to draw my own territories, so I decided to use existing countries, actually three countries where my husband and I lived together: France, Germany, Spain. I got a file with many cities in the world &lt;a href=&#34;http://www.opengeocode.org/download.php#cities&#34;&gt;from this website&lt;/a&gt; which I transformed using the following code.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
cities &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/worldcities1.csv&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(cities) &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;_&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(cities))
&lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(cities) &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gsub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(cities))
cities &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(language_script &lt;span style=&#34;color:#666&#34;&gt;%in%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;latin&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;english&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(ISO_31661_country_code,
         name,
         latitude, longitude) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;write_csv&lt;/span&gt;(path &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-01-27-catan_.csv&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this dataset for each city I get the country and longitudinal coordinates so it will be easy to get cities from the chosen countries.&lt;/p&gt;
&lt;h2 id=&#34;from-the-raw-data-to-ready-to-plot-data&#34;&gt;From the raw data to ready-to-plot data&lt;/h2&gt;
&lt;p&gt;Since I was going to transform three similar tables, I decided to write functions. Well at the time I first made the viz I copy-pasted code three times but I decided it&amp;rsquo;d be better not to make my clumsiness public. Instead, I even started using the &lt;code&gt;dplyr&lt;/code&gt; and &lt;code&gt;tidyr&lt;/code&gt; functions with &amp;ldquo;_&amp;rdquo;, which I think looks professional.&lt;/p&gt;
&lt;p&gt;The first step is to get from the wide to the long data, and to add emojis to each line. We thus have one line per round and riches type, with a number of cards for, say, lumber.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
add_emojis &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df, emojis){
  .dots &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(df)&lt;span style=&#34;color:#06287e&#34;&gt;[&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;which&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(df) &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;round&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ncol&lt;/span&gt;(df)]
  df &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;gather_&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;what&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;count&amp;#34;&lt;/span&gt;, 
                 .dots) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(emojis, by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;what&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter_&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; count &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The second step is to get one line per card of riches, because each of them will be plotted separately, and with an index number for cards of the same type in each round. Why? Well because if a territory had 1 card of lumber and then 2 cards of lumber, at the second round I want the card of lumber from the first round to stay at the same position.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;get_one_row_per_riches_unit &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; df&lt;span style=&#34;color:#06287e&#34;&gt;[rep&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;seq_len&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(df)), df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;count),]

  df &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;select_&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;quote&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; count)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;group_by_&lt;/span&gt;(.dots &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;lapply&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;round&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;what&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;emoji&amp;#34;&lt;/span&gt;), as.symbol)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(which &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;()

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then I draw cities from the territory for each card of lumber, card of ore, etc.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;cities &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; readr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read_csv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-01-27-catan_worldcities.csv&amp;#34;&lt;/span&gt;)
add_location &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df, country, cities){
  &lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;# get cities to put the things&lt;/span&gt;
  tobelocated &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; df &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;select_&lt;/span&gt;(.dots &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;what&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;emoji&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;which&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;()
  
  country &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter_&lt;/span&gt;(cities, &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;ISO_31661_country_code &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; country)
  &lt;span style=&#34;color:#06287e&#34;&gt;set.seed&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;)
  where &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sample_n&lt;/span&gt;(country, &lt;span style=&#34;color:#06287e&#34;&gt;nrow&lt;/span&gt;(tobelocated),
                            replace &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)
  
  tobelocated &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;cbind&lt;/span&gt;(where, tobelocated) 
  
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;left_join&lt;/span&gt;(df, tobelocated,
                  by &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;emoji&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;which&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;what&amp;#34;&lt;/span&gt;))
  df &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;select_&lt;/span&gt;(df, &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;round, &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;what, &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;emoji,
                &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;which, &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;latitude, &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;longitude) 
  
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(df)
  }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I also need to add the name of the participant.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;add_name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df, name){
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate_&lt;/span&gt;(df, who &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt;name)
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once we have defined the functions, we can write a pretty &lt;code&gt;purrr&lt;/code&gt; pipeline.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purrr&amp;#34;&lt;/span&gt;)
map_data &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(market, damien, maelle) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(add_emojis, emojis &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; emojis) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map&lt;/span&gt;(get_one_row_per_riches_unit) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map2&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;FR&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;DE&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ES&amp;#34;&lt;/span&gt;),
       add_location, cities &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; cities) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;map2&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;list&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Market&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Damien&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Maëlle&amp;#34;&lt;/span&gt;),
       add_name) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;bind_rows&lt;/span&gt;()

knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(map_data))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;right&#34;&gt;round&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;what&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;emoji&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;which&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;latitude&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;longitude&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;who&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lumber&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;evergreen_tree&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.77894&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.213335&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Market&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lumber&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;evergreen_tree&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.77894&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.213335&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Market&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lumber&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;evergreen_tree&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.61031&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.354705&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Market&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lumber&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;evergreen_tree&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.77894&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.213335&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Market&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lumber&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;evergreen_tree&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.61031&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.354705&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Market&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;lumber&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;evergreen_tree&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.77894&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.213335&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Market&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I won&amp;rsquo;t lie, getting until this point was not all easy. When I read the code from so many months ago I was surprised to still understand it and quite proud of myself if I may say so.&lt;/p&gt;
&lt;h1 id=&#34;draw-the-map&#34;&gt;Draw the map!&lt;/h1&gt;
&lt;p&gt;That&amp;rsquo;s where the &lt;code&gt;emojifont&lt;/code&gt; and &lt;code&gt;gganimate&lt;/code&gt; magic happen. I don&amp;rsquo;t only plot riches, but also a crown for each territory whose size depends on the score of the territory.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;emojifont&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;## load selected emoji font&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;load.emojifont&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;OpenSansEmoji.ttf&amp;#39;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggmap&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;gganimate&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(animation)
map &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;get_map&lt;/span&gt;(location &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;France&amp;#34;&lt;/span&gt;, maptype &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;watercolor&amp;#34;&lt;/span&gt;,
              zoom &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;)
p &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ggmap&lt;/span&gt;(map, extent &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;device&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_text&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;9&lt;/span&gt;, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;44&lt;/span&gt;,
             label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Maëlland&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_text&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;  &lt;span style=&#34;color:#40a070&#34;&gt;7&lt;/span&gt;, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;54&lt;/span&gt;,
            label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Damienland&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_text&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;50.5&lt;/span&gt;,
            label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Market&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_text&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; damien,
             &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;7&lt;/span&gt;, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;54.5&lt;/span&gt;,
                 size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; victory, frame &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; round),
            label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;emoji&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;crown&amp;#34;&lt;/span&gt;), family&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;OpenSansEmoji&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_text&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; maelle,
             &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;9&lt;/span&gt;, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;45&lt;/span&gt;,
                 size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; victory, frame &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; round),
            label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;emoji&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;crown&amp;#34;&lt;/span&gt;), family&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;OpenSansEmoji&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_text&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; map_data,
            &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; longitude,
                y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; latitude,
                label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;emoji&lt;/span&gt;(emoji), family&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#39;OpenSansEmoji&amp;#39;&lt;/span&gt;,
                col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; who,
                frame &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; round),
            size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(size&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;),
        legend.position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Round&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;ani.options&lt;/span&gt;(interval &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, ani.width &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;400&lt;/span&gt;, ani.height &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;400&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;gg_animate&lt;/span&gt;(p, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;catan.gif&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now, sit back and enjoy!&lt;/p&gt;
&lt;img src=&#34;https://masalmon.eu/figure/catan.gif&#34; alt=&#34;catan&#34;&gt;
&lt;p&gt;When I told &lt;a href=&#34;https://twitter.com/milesmcbain&#34;&gt;Miles McBain&lt;/a&gt; about this visualization he told me it would be useful for post-game debriefing. So you&amp;rsquo;ll have to excuse me, I&amp;rsquo;ll now ask my husband if he wants to debrief the game we played 10 months ago.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>More water, a bit more about saints</title>
      <link>https://masalmon.eu/2017/01/26/morewater/</link>
      <pubDate>Thu, 26 Jan 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/01/26/morewater/</guid>
      <description>&lt;p&gt;I was lucky enough to get some nice and interesting feedback on &lt;a href=&#34;https://masalmon.eu/2017/01/24/kervillebourg/&#34;&gt;my last post&lt;/a&gt;. One comment was really useful and pretty embarrassing: I had written &amp;ldquo;see&amp;rdquo; instead of &amp;ldquo;sea&amp;rdquo; in the whole post&amp;hellip; Thanks Steve Dempsey for the correction! I also got some questions which I decided to explore.&lt;/p&gt;
&lt;h1 id=&#34;more-water&#34;&gt;More water?&lt;/h1&gt;
&lt;p&gt;I had chosen to look specifically for a few rivers but one commenter, actually Steve Dempsey again, asked me how it would look like if I systematically retrieved all placenames with &amp;ldquo;sur-&amp;rdquo;, &amp;ldquo;upon&amp;rdquo;, because where he lived in France there were many &amp;ldquo;sur-Dronne&amp;rdquo; or &amp;ldquo;sur l&amp;rsquo;Isle&amp;rdquo;. He actually asked the question in French, &lt;em&gt;&amp;ldquo;Je me demande ce que ça donne avec tous les places avec un &amp;ldquo;-sur&amp;rdquo;. Là, où j&amp;rsquo;étais en France il y avait plein de &amp;ldquo;-sur-Dronne&amp;rdquo; ou &amp;ldquo;-sur-l&amp;rsquo;Isle&amp;rdquo;.&amp;quot;&lt;/em&gt; Let&amp;rsquo;s see! (or sea? just kidding)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;readr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;purrr&amp;#34;&lt;/span&gt;)
ville &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;read_tsv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-01-24-kervillebourg_FR.txt&amp;#34;&lt;/span&gt;, col_names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)[, &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;)]
&lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(ville) &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;placename&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;latitude&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;longitude&amp;#34;&lt;/span&gt;)
ville &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(ville)
upon &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(ville, &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sur-&amp;#34;&lt;/span&gt;, placename))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If truth be told, I thought I&amp;rsquo;d just need to filter the relevant placenames and then get nice rivers on my map&amp;hellip; nope. So I soon realized I should first find unique names of rivers, then group them by name and only draw the ones that have enough places for the map to be at least a bit pretty.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;upon &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;by_row&lt;/span&gt;(upon, &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
  &lt;span style=&#34;color:#06287e&#34;&gt;sub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.*sur-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;placename)
}, .to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;waterthing&amp;#34;&lt;/span&gt;, .collate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols&amp;#34;&lt;/span&gt;)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(upon))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;placename&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;latitude&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;longitude&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;waterthing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Domecy-sur-le-Vault&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47.49084&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.80953&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;le-Vault&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Yzeures-sur-Creuse&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46.78609&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.87166&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Creuse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Yville-sur-Seine&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.39938&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.87750&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Seine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Wingen-sur-Moder&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;48.91900&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.37955&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Moder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Willer-sur-Thur&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47.84392&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.07223&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Thur&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Wavrans-sur-Ternoise&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;50.41322&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.30002&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ternoise&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Let&amp;rsquo;s see what the more frequent &lt;em&gt;watherthings&lt;/em&gt; are:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(upon, waterthing) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;waterthing&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Mer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;214&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Loire&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;152&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Seine&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;148&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Marne&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;117&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Meuse&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;88&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Saône&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;70&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Sarthe&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Aube&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;44&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Cher&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;41&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Orne&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Seille&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;39&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Moselle&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;36&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Eure&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;34&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Yonne&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Oise&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Vienne&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Garonne&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Dordogne&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Aisne&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Allier&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;24&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;So I find &amp;ldquo;Sea&amp;rdquo; again, and the rivers I had chosen in the last post, and others, whose names I all knew so they must be quite important. I want to keep only the rivers with &amp;ldquo;enough&amp;rdquo;&amp;rdquo; places to make the map pretty, because at the scale of the country I prefer seeing a longer river.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;upon &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(upon, waterthing)
upon &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(upon, &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;25&lt;/span&gt;)
upon &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ungroup&lt;/span&gt;(upon)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggmap&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;viridis&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggthemes&amp;#34;&lt;/span&gt;)
map &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ggmap&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;get_map&lt;/span&gt;(location &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;France&amp;#34;&lt;/span&gt;, zoom &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;, maptype &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;watercolor&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This time the map will be really artsier than useful since I&amp;rsquo;ll have a color by river but no legend because of the higher numbers of rivers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;p &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ggmap&lt;/span&gt;(map) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; upon,
             &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; longitude, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; latitude,
                 col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; waterthing), size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1.3&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_map&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_colour_grey&lt;/span&gt;(end &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0.7&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;French placenames containing the word &amp;#39;sur&amp;#39;&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(plot.title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(lineheight&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, face&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bold&amp;#34;&lt;/span&gt;))&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(size&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;14&lt;/span&gt;),
        legend.position &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;)
p
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-01-26-morewater/unnamed-chunk-7-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-7&#34;&gt;&lt;/p&gt;
&lt;p&gt;I like this map because I could find the rivers again without having to enter their names, and it looks like drawing with a pencil on watercolor without making any effort. However, since I&amp;rsquo;m not very good in geography, I&amp;rsquo;d like to add labels to each river, let&amp;rsquo;s say somewhere in the middle of the river. I&amp;rsquo;ll use &lt;code&gt;ggrepel&lt;/code&gt; to avoid having overlapping labels. My definition of &amp;ldquo;somewhere in the middle&amp;rdquo; is sorting the places of a river by latitude and longitude and then choosing a place close to the middle.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggrepel&amp;#34;&lt;/span&gt;)
named_upon &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(upon, latitude, longitude)
named_upon &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(named_upon, waterthing)
named_upon &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(named_upon, index &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;())
named_upon &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(named_upon, name &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;ifelse&lt;/span&gt;(index &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;floor&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;),
                                   waterthing, &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;NA&lt;/span&gt;))
p &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;geom_label_repel&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; longitude,
                   y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; latitude, 
                   label &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; name,
                   max.iter &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;20000&lt;/span&gt;),
               data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; named_upon)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-01-26-morewater/unnamed-chunk-8-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;&lt;/p&gt;
&lt;p&gt;Okay, I&amp;rsquo;ll now look at the map and learn the names! I&amp;rsquo;ve lived near the Loire, near the Seine and near the Marne. It might be surprising not to see the Rhine on that map, but placenames in Alsace are often more Germanic, so that would be another story.&lt;/p&gt;
&lt;h1 id=&#34;which-saints&#34;&gt;Which saints?&lt;/h1&gt;
&lt;p&gt;I also got questions about saints, one &lt;a href=&#34;https://twitter.com/anboa4/status/824174331777478657&#34;&gt;on Twitter from Andrew Boa&lt;/a&gt; and a few ones from Andrew MacDonald.&lt;/p&gt;
&lt;p&gt;Andrew Boa&amp;rsquo;s question was the easiest one: how many unique names of saints are there? The questions of the other Andrew were &lt;em&gt;&amp;ldquo;I wonder, would it be possible to also obtain data on how old these towns are? It would be interesting to see if the gender of popular saints changes over time.
Or, more simply, which saints have the most towns? I imagine there are tons of &amp;ldquo;Saint Sernin&amp;quot;s in the South, and probably lots of &amp;ldquo;Jeanne-d&amp;rsquo;Arc&amp;quot;s all over&amp;rdquo;&lt;/em&gt;. Let me tell you I am thankful for the more simply part of the questions because I have no idea where one would find information about the age of the places. Nonetheless, this would be really interesting.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s answer the questions about the number of unique names and their frequencies. I am now in particular curious about &lt;em&gt;André&lt;/em&gt; since I got questions from two &lt;em&gt;Andrew&lt;/em&gt;&amp;rsquo;s.&lt;/p&gt;
&lt;p&gt;Note that for finding the name I remove the &amp;ldquo;Saint-&amp;rdquo; or &amp;ldquo;Sainte-&amp;rdquo; part but also everything that could come after another hyphen and a space, e.g. in &amp;ldquo;Alban-de-Varèze&amp;rdquo; which I want as &amp;ldquo;Alban&amp;rdquo;. Also note that in this analysis I ignore homonym saints, and that Jeanne d&amp;rsquo;Arc might be a saint, the places named after her don&amp;rsquo;t contain the word &amp;ldquo;sainte&amp;rdquo;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;saints &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ville &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(saint &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Saint-&amp;#34;&lt;/span&gt;, placename))  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(sainte &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Sainte-&amp;#34;&lt;/span&gt;, placename))  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;gather&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;gender&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;yes&amp;#34;&lt;/span&gt;, saint&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;sainte) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(yes &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; yes)
saints &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;by_row&lt;/span&gt;(saints, &lt;span style=&#34;color:#06287e&#34;&gt;function&lt;/span&gt;(df){
  &lt;span style=&#34;color:#06287e&#34;&gt;if&lt;/span&gt;(df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;gender &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;saint&amp;#34;&lt;/span&gt;){
    name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.*Saint-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;placename)
  }else{
    name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;sub&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;.*Sainte-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;, df&lt;span style=&#34;color:#666&#34;&gt;$&lt;/span&gt;placename)
  }
  name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;trimws&lt;/span&gt;(name)
  name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;)[[1]][1]
  name &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;strsplit&lt;/span&gt;(name, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;)[[1]][1]
  &lt;span style=&#34;color:#06287e&#34;&gt;return&lt;/span&gt;(name)
}, .to &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;saintname&amp;#34;&lt;/span&gt;, .collate &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;cols&amp;#34;&lt;/span&gt;)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(saints))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;placename&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;latitude&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;longitude&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;gender&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;saintname&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Ygos-Saint-Saturnin&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;43.97651&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.73780&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Saturnin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Canal de Vitry-le-François à Saint-Dizier&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;48.73333&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.60000&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Dizier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Vitrac-Saint-Vincent&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;45.79585&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.49356&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Vincent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Vineuil-Saint-Firmin&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.20024&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49567&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Firmin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Villotte-Saint-Seine&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47.42893&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.70571&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Seine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Villiers-Saint-Denis&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.00000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.26667&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Denis&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;How many unique names do we have?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(saints, gender) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(n_names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;length&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;unique&lt;/span&gt;(saintname)),
            n_places &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;()) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;gender&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n_names&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n_places&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1205&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;10310&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;157&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;971&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Let&amp;rsquo;s look at the distributions of number of places by saint name, separately for &lt;em&gt;saints&lt;/em&gt; then &lt;em&gt;saintes&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;saints_freq &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;group_by&lt;/span&gt;(saints, gender, saintname) 
saints_freq &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;summarize&lt;/span&gt;(saints_freq, n_places &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;n&lt;/span&gt;())

&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(saints_freq, gender &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;saint&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_histogram&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(n_places))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-01-26-morewater/unnamed-chunk-11-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-11&#34;&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(saints_freq, gender &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sainte&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
&lt;span style=&#34;color:#06287e&#34;&gt;ggplot&lt;/span&gt;() &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_histogram&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(n_places))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-01-26-morewater/unnamed-chunk-11-2.png&#34; alt=&#34;plot of chunk unnamed-chunk-11&#34;&gt;&lt;/p&gt;
&lt;p&gt;The information I get from looking at these ugly histograms is that there are some names that are very popular and a lot of them that are rarely used. Let&amp;rsquo;s look at the 11 more popular ones for &lt;em&gt;saints&lt;/em&gt; and &lt;em&gt;saintes&lt;/em&gt;. Don&amp;rsquo;t ask me why I chose 11!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(saints_freq, &lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n_places)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(gender &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;saint&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;11&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;gender&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;saintname&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n_places&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Martin&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;618&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Jean&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;416&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Pierre&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;391&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Germain&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;304&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Julien&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;219&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Laurent&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;215&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Georges&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;214&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Hilaire&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;181&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aubin&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;169&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Michel&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;168&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;André&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;164&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;So for &lt;em&gt;saints&lt;/em&gt; I see names that are still common in France. And &lt;em&gt;André&lt;/em&gt; as 11th one, which might explain why I chose the 11 most popular ones&amp;hellip;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(saints_freq, &lt;span style=&#34;color:#06287e&#34;&gt;desc&lt;/span&gt;(n_places)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(gender &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sainte&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;11&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;gender&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;saintname&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n_places&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Marie&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;122&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Croix&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;69&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Colombe&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;68&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Marguerite&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;52&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Anne&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Foy&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;36&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Eulalie&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Gemme&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Geneviève&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Catherine&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Radegonde&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I&amp;rsquo;m fascinated by some names like &lt;em&gt;Radegonde&lt;/em&gt; that are not common any longer.&lt;/p&gt;
&lt;p&gt;And since looking at rare names is so fun (isn&amp;rsquo;t it?), let&amp;rsquo;s look at the 11th of the least popular names.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(saints_freq, n_places) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(gender &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;saint&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;11&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;gender&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;saintname&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n_places&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Aaron&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Alexis&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Alvard&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Amas&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Amond&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Anastase&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Andre´&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Andrieu&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Andrieux&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Anne&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Apoll&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I think some rare names might be errors of accents, e.g. &lt;em&gt;Andre&lt;/em&gt; might be &lt;em&gt;André&lt;/em&gt; and seeing &lt;em&gt;Anne&lt;/em&gt; in the list of &lt;em&gt;saints&lt;/em&gt; I&amp;rsquo;m now wondering about the number of female names classified as &lt;em&gt;saints&lt;/em&gt; in the dataset. There are 10 &amp;ldquo;Saint Mary&amp;rdquo; in the dataset and 122 &amp;ldquo;Sainte Marie&amp;rdquo; so I think the gender inbalance would still exist when accounting for this, but it&amp;rsquo;s certainly a good point to keep in mind when using this Geonames dataset! If I were to really tackle the issue, I think I&amp;rsquo;d try using the &lt;a href=&#34;https://github.com/kalimu/genderizeR&#34;&gt;&lt;code&gt;genderizer&lt;/code&gt;&lt;/a&gt; package on names, although I&amp;rsquo;m not so sure it&amp;rsquo;d perform well for French old names and the &lt;a href=&#34;https://github.com/ropensci/gender&#34;&gt;rOpensci gender package&lt;/a&gt; doesn&amp;rsquo;t have an historical dataset for France (yet?). I could also simply look for a very French dataset of place names, and hope no name would be translated in it.&lt;/p&gt;
&lt;p&gt;Beside discovering this limitation of the dataset, I liked the names one can see by browsing the least popular saint names, like &lt;em&gt;Eusoge&lt;/em&gt; or &lt;em&gt;Exupère&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;arrange&lt;/span&gt;(saints_freq, n_places) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(gender &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sainte&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(n &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;11&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;gender&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;saintname&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;n_places&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Ame&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Assise&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Avoye&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Awawa&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Blaizine&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Clotilde&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Élisabeth&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Éturien&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Eugienne&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Eulard&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;sainte&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Genevieve&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This is similarly fascinating and also shows me it might be interesting to re-analyse the all dataset without diacritical accents (&lt;em&gt;Genevieve&lt;/em&gt; should be &lt;em&gt;Geneviève&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;And &lt;em&gt;Saint Maël&lt;/em&gt;, you might ask? Well &lt;em&gt;Maël&lt;/em&gt; or &lt;em&gt;Maëlle&lt;/em&gt; are Breton names so there&amp;rsquo;s no place called &lt;em&gt;Saint Maël&lt;/em&gt; in the dataset like my holy patron, but there is &lt;em&gt;Maël-Carhaix&lt;/em&gt; and &lt;em&gt;Maël-Pestivien&lt;/em&gt;. I can&amp;rsquo;t speak Breton, &lt;a href=&#34;https://fr.wikipedia.org/wiki/Ma%C3%ABl-Pestivien#Toponymie&#34;&gt;Wikipedia&lt;/a&gt; tells me that &lt;em&gt;Pestivien&lt;/em&gt; means &amp;ldquo;the end of the sources&amp;rdquo; and &lt;a href=&#34;https://fr.wikipedia.org/wiki/Carhaix-Plouguer#Toponymie&#34;&gt;for Carhaix&lt;/a&gt; it seems to be a long story. After looking at this dataset, I have the impression that the more toponomy questions one tries to answer, the more new questions one has. While this is awesome because of all the learning it implies, I&amp;rsquo;ll conclude this post (and probably my hobby career as a toponomist :)) by simply plotting the &lt;em&gt;Jeanne d&amp;rsquo;Arc&lt;/em&gt; places for Andrew MacDonald, and &lt;em&gt;Domrémy-la-Pucelle&lt;/em&gt; where she was born. There was no &lt;em&gt;Saint-Sermin&lt;/em&gt;!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;ville &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(ville, jeanne &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Jeanne [dD].[aA]rc&amp;#34;&lt;/span&gt;, placename))
ville &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(ville, domremy &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; (placename &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Domrémy-la-Pucelle&amp;#34;&lt;/span&gt;))
jeanne &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(ville, jeanne &lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt; domremy)
jeanne &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; tidyr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;gather&lt;/span&gt;(jeanne, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;word&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;, jeanne&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;domremy)
jeanne &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(jeanne, value)
&lt;span style=&#34;color:#06287e&#34;&gt;ggmap&lt;/span&gt;(map) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; jeanne,
             &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; longitude, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; latitude, col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; word), size &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_map&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt; 
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;French placenames containing &amp;#39;Jeanne d&amp;#39;Arc&amp;#39;&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(plot.title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(lineheight&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, face&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bold&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_color_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-01-26-morewater/unnamed-chunk-16-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-16&#34;&gt;&lt;/p&gt;
&lt;p&gt;So there are a few Jeanne d&amp;rsquo;Arc places all over as predicted by Andrew, none very close to &lt;em&gt;Domrémy-la-Pucelle&lt;/em&gt; but then this was called &lt;em&gt;Domrémy the virgin&lt;/em&gt; after her already.&lt;/p&gt;
&lt;p&gt;If you want to play with the dataset yourself, you&amp;rsquo;ll find it on Geonames, see &lt;a href=&#34;https://gist.github.com/hrbrmstr/0fd37cf3825fc8e3eddf042a4443d1dc&#34;&gt;this gist&lt;/a&gt; and in the data folder of &lt;a href=&#34;https://github.com/maelle/kervillebourg&#34;&gt;this Github repo&lt;/a&gt;. If you do, don&amp;rsquo;t hesitate to share your findings!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>French places and a sort of resolution</title>
      <link>https://masalmon.eu/2017/01/24/kervillebourg/</link>
      <pubDate>Tue, 24 Jan 2017 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2017/01/24/kervillebourg/</guid>
      <description>&lt;h1 id=&#34;sort-of-introduction-to-this-post-and-hopefully-the-next-ones&#34;&gt;Sort of introduction to this post and hopefully the next ones&lt;/h1&gt;
&lt;p&gt;I usually don&amp;rsquo;t have any New Year resolution. However, recent tweets about productivity &amp;ndash;  from people I actually find productive and inspiring &amp;ndash; made me ponder a bit on my unfinished side projects. My main 2016 side-project was submitting and defending &lt;a href=&#34;https://edoc.ub.uni-muenchen.de/19877/&#34;&gt;my PhD thesis&lt;/a&gt;, and I&amp;rsquo;ve written a few R packages, so I&amp;rsquo;m overall quite happy.&lt;/p&gt;
&lt;p&gt;But in 2016 I also started stuff without delivering. In particular, I prepared small data projects in Github repositories with a very precise README because I didn&amp;rsquo;t have a blog and planned to start one after my PhD thesis. Then I created my blog (thanks &lt;a href=&#34;http://www.njtierney.com/jekyll/2015/11/11/how-i-built-my-site/&#34;&gt;Nick&lt;/a&gt;!) and&amp;hellip; only re-posted &lt;a href=&#34;https://masalmon.eu/2016/10/02/first7jobs-repost/&#34;&gt;an analysis of mine&lt;/a&gt; from another blog. My nice repositories are still lying around and they represent quite a few of my &lt;a href=&#34;http://www.commitstrip.com/en/2014/11/25/west-side-project-story/&#34;&gt;West Side-project Story unfinished buildings&lt;/a&gt;. I&amp;rsquo;ve decided transforming some of my usable data projects into blog posts was a nice step towards being or at least feeling more productive.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start today with my visualizations of names of French places!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: the analysis was originally prepared &lt;a href=&#34;https://github.com/maelle/kervillebourg&#34;&gt;here&lt;/a&gt; and advertised on &lt;a href=&#34;https://twitter.com/ma_salmon/status/728660470798946304&#34;&gt;Twitter&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Inspired by &lt;a href=&#34;https://github.com/hrbrmstr/zellingenach&#34;&gt;this work about names of places in Germany&lt;/a&gt;, I wanted to have a look at the names of French places. I decided against looking at prefixes and suffixes because I got a more poetical idea: looking for water and saints in my home country.&lt;/p&gt;
&lt;p&gt;I got a file of all French places names and geolocation from &lt;a href=&#34;http://download.geonames.org/&#34;&gt;Geonames&lt;/a&gt;. Thanks to Bob Rudis for providing me with &lt;a href=&#34;https://gist.github.com/hrbrmstr/0fd37cf3825fc8e3eddf042a4443d1dc&#34;&gt;the link&lt;/a&gt;. The data is distributed under &lt;a href=&#34;http://creativecommons.org/licenses/by/3.0/&#34;&gt;this license&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;a-first-look-at-the-data&#34;&gt;A first look at the data&lt;/h1&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;dplyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;tidyr&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;readr&amp;#34;&lt;/span&gt;)
ville &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;read_tsv&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;data/2017-01-24-kervillebourg_FR.txt&amp;#34;&lt;/span&gt;, col_names &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;FALSE&lt;/span&gt;)[, &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;)]
&lt;span style=&#34;color:#06287e&#34;&gt;names&lt;/span&gt;(ville) &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;c&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;placename&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;latitude&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;longitude&amp;#34;&lt;/span&gt;)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(ville))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;placename&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;latitude&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;longitude&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Recon, Col de&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46.30352&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.82838&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Lucelle&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47.41667&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.50000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Les Cornettes de Bise&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46.33333&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.78333&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Ruisseau le Lertzbach&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47.58333&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.58333&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Le Cheval Blanc&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46.05132&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.87178&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Jougnena&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;46.71667&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6.40000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;names-of-rivers-and-sea&#34;&gt;Names of rivers and sea&lt;/h1&gt;
&lt;p&gt;Here I selected names of towns and places that include the names of a few rivers in France, or the word &amp;ldquo;sea&amp;rdquo; (&amp;ldquo;sur-Mer&amp;rdquo;). This is by no mean an exhaustive representation of such names since I only chose a few rivers and a single pattern of name.&lt;/p&gt;
&lt;p&gt;I created new variables that are Booleans by looking for given pattern in names, like &amp;ldquo;sur-Mer&amp;rdquo;, then I only filtered the lines where one of the pattern was found, and used &lt;code&gt;tidyr::gather&lt;/code&gt; function to end up with the long format you see below.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;water &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ville &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(mer &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sur-Mer&amp;#34;&lt;/span&gt;, placename))  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rhone &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sur-Rhône&amp;#34;&lt;/span&gt;, placename))  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(somme &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sur-Somme&amp;#34;&lt;/span&gt;, placename))  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(loire &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sur-Loire&amp;#34;&lt;/span&gt;, placename)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(seine &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sur-Seine&amp;#34;&lt;/span&gt;, placename)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(rhin &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sur-Rhin&amp;#34;&lt;/span&gt;, placename)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(garonne &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sur-Garonne&amp;#34;&lt;/span&gt;, placename)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(meuse &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;sur-Meuse&amp;#34;&lt;/span&gt;, placename)) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;gather&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;yes&amp;#34;&lt;/span&gt;, mer&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;meuse) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(yes &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; yes)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(water))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;placename&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;latitude&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;longitude&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Villers-sur-Mer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.32264&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.00027&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Villefranche-sur-Mer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;43.70470&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7.30776&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Vierville-sur-Mer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.37237&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.90709&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Veulettes-sur-Mer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.85162&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.59719&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Ver-sur-Mer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.32987&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.53118&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Vaux-sur-Mer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;45.64606&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-1.05841&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;mer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Then I made an artsy map thanks to the &lt;code&gt;&amp;quot;watercolor&amp;quot;&lt;/code&gt; &lt;code&gt;maptype&lt;/code&gt; of &lt;code&gt;ggmap&lt;/code&gt; and to my beloved &lt;code&gt;viridis&lt;/code&gt;. The zoom I chose makes the map only for the &lt;em&gt;métrople&lt;/em&gt;, I don&amp;rsquo;t even include Corsica.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggplot2&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggmap&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;viridis&amp;#34;&lt;/span&gt;)
&lt;span style=&#34;color:#06287e&#34;&gt;library&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;ggthemes&amp;#34;&lt;/span&gt;)
map &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ggmap&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;get_map&lt;/span&gt;(location &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;France&amp;#34;&lt;/span&gt;, zoom &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;, maptype &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;watercolor&amp;#34;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ggmap&lt;/span&gt;(map) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; water,
             &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; longitude, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; latitude, col &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; name)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;scale_color_viridis&lt;/span&gt;(discrete &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;, option &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;plasma&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_map&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;French placenames containing the name of a river or &amp;#39;sea&amp;#39;&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(plot.title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(lineheight&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, face&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bold&amp;#34;&lt;/span&gt;))&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(size&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;14&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-01-24-kervillebourg/unnamed-chunk-5-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-5&#34;&gt;&lt;/p&gt;
&lt;p&gt;It was also, I must say, a nice lesson in French geography for me.&lt;/p&gt;
&lt;h1 id=&#34;saint-et-saintes&#34;&gt;Saint et Saintes&lt;/h1&gt;
&lt;p&gt;In French, towns such as &amp;ldquo;Saint-Ouen&amp;rdquo; and &amp;ldquo;Sainte-Anne&amp;rdquo; can easily be partitioned into &lt;em&gt;cities named after a saint man&lt;/em&gt; (saint) and &lt;em&gt;cities named after a saint woman&lt;/em&gt; (sainte). Thinking of this prompted me to have a look at the distribution of such place names with a similar strategy than for rivers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;saints &lt;span style=&#34;color:#666&#34;&gt;&amp;lt;-&lt;/span&gt; ville &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(saint &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Saint-&amp;#34;&lt;/span&gt;, placename))  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;mutate&lt;/span&gt;(sainte &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;grepl&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Sainte-&amp;#34;&lt;/span&gt;, placename))  &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;gather&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;yes&amp;#34;&lt;/span&gt;, saint&lt;span style=&#34;color:#666&#34;&gt;:&lt;/span&gt;sainte) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;filter&lt;/span&gt;(yes &lt;span style=&#34;color:#666&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;TRUE&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;select&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt; yes)
knitr&lt;span style=&#34;color:#666&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;kable&lt;/span&gt;(&lt;span style=&#34;color:#06287e&#34;&gt;head&lt;/span&gt;(saints))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;placename&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;latitude&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;longitude&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;name&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Ygos-Saint-Saturnin&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;43.97651&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;-0.73780&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Canal de Vitry-le-François à Saint-Dizier&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;48.73333&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.60000&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Vitrac-Saint-Vincent&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;45.79585&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;0.49356&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Vineuil-Saint-Firmin&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.20024&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2.49567&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Villotte-Saint-Seine&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;47.42893&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4.70571&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Villiers-Saint-Denis&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;49.00000&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3.26667&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;saint&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Here is the result on a map.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span style=&#34;color:#06287e&#34;&gt;ggmap&lt;/span&gt;(map) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;geom_point&lt;/span&gt;(data &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; saints,
             &lt;span style=&#34;color:#06287e&#34;&gt;aes&lt;/span&gt;(x &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; longitude, y &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; latitude)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme_map&lt;/span&gt;()&lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;ggtitle&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Places named after a saint man or woman&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(plot.title &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(lineheight&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, face&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;bold&amp;#34;&lt;/span&gt;)) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;facet_grid&lt;/span&gt;(. &lt;span style=&#34;color:#666&#34;&gt;~&lt;/span&gt; name) &lt;span style=&#34;color:#666&#34;&gt;+&lt;/span&gt;
  &lt;span style=&#34;color:#06287e&#34;&gt;theme&lt;/span&gt;(text &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;element_text&lt;/span&gt;(size&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;20&lt;/span&gt;))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2017-01-24-kervillebourg/unnamed-chunk-7-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-7&#34;&gt;&lt;/p&gt;
&lt;p&gt;Well, I cannot say I&amp;rsquo;m surprised!&lt;/p&gt;
&lt;p&gt;Back when I published this small work only on Github and Twitter, I was pleasantly surprised to see a &lt;a href=&#34;https://github.com/ceresc/french-cities-names&#34;&gt;more elaborate analysis&lt;/a&gt; inspired by mine, so if this post made you curious about analysis of French placenames with R, head to Cérès Carton&amp;rsquo;s repository! And after this, I&amp;rsquo;ll just warn you to brace yourself for more old repos recycling from me.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Analyzing #first7jobs tweets with Monkeylearn and R</title>
      <link>https://masalmon.eu/2016/10/02/first7jobs-repost/</link>
      <pubDate>Sun, 02 Oct 2016 00:00:00 +0000</pubDate>
      
      <guid>https://masalmon.eu/2016/10/02/first7jobs-repost/</guid>
      <description>&lt;p&gt;Note that this is a repost of &lt;a href=&#34;https://blog.monkeylearn.com/analyzing-first7jobs-tweets-monkeylearn-r/&#34;&gt;my post on Monkeylearn&amp;rsquo;s blog&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Have you tweeted about your &amp;ldquo;#firstsevenjobs&amp;rdquo;? I did!&lt;/p&gt;
&lt;p&gt;&amp;ldquo;#firstsevenjobs&amp;rdquo; and &amp;ldquo;#first7jobs&amp;rdquo; tweets initial goal was to provide a short description of the 7 first activities they were paid for. It was quite fun to read them in my timeline! Of course the hashtag was also used by spammers, for making jokes, and for commenting the hashtag, so not all the tweets contain 7 job descriptions.&lt;/p&gt;
&lt;p&gt;However, I am confident quite a lot of &amp;ldquo;#firstsevenjobs&amp;rdquo; and &amp;ldquo;#first7jobs&amp;rdquo; actually describe first jobs, so I decided to use them as example of text analysis in R with Monkeylearn, starting from querying Twitter API with the rtweet package, then cleaning the tweets a bit, and then using the monkeylearn package to classify the jobs in a field of work&lt;/p&gt;
&lt;h1 id=&#34;getting-the-tweets&#34;&gt;Getting the tweets&lt;/h1&gt;
&lt;p&gt;I used the &lt;a href=&#34;https://github.com/mkearney/rtweet/&#34;&gt;&lt;code&gt;rtweet&lt;/code&gt; R package&lt;/a&gt; for getting tweets via the Twitter API, searching for both &amp;ldquo;#firstsevenjobs&amp;rdquo; and &amp;ldquo;#first7jobs&amp;rdquo; hashtags and then keeping only unique non-retweeted tweets in English. I got 4858 tweets, sent between the 2016-08-10 and the 2016-08-20. This does not mean there were only that few tweets produced with the hashtags, but the Twitter API does not output &lt;em&gt;all&lt;/em&gt; the tweets. You&amp;rsquo;d have to pay for it. But hey that&amp;rsquo;s a good number of tweets to start with, so I won&amp;rsquo;t complain. Here is part of the table I got:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;status_id&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;text&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;765226304073404416&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;What Were Your #FirstSevenJobs?: #firstsevenjobsphotography salespot washerbartenderurban plann&amp;hellip; https://t.co/wwGp8NCohG #Architectbiz&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;764629565431947264&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;The unexpected joys of #FirstSevenJobs https://t.co/wV8XeFVlv8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;764104419185229824&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;My piece on #firstsevenjobs https://t.co/Il3a2Wrm0I&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;765643154964025344&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#first7jobs: milkshake maker, national anthem singer, babysitter, phone bank caller, tutor, camp counselor, bartender (&amp;lt;- badly)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;765407468499374080&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;@BenSPLATT Oh, I thought you were posting your #firstsevenjobs!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;766334362447151104&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;13 Entrepreneurs and CEOs Share Their #First7Jobs #jobseekers #advice https://t.co/k1hhSFKznH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;764296241698238468&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Babysitter, educational video actor, Little League umpire, sales clerk, archery instructor, security guard, audiobook narrator. #first7jobs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763868874211078144&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#firstsevenjobs 1. Landscaper 2. passenger train car attendant 3. Mail sorter at Post office 4. pt Evenings/weekends/cruiser/prod 1090 CHEC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763922164655415296&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;#firstsevenjobs fashion intern, retail sales, rec coordinator,receptionist, teacher, school administrator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;766299512205811712&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;1. Golf course kitchen 2. Whole foods 3. Dean and Deluca 4. Hyatt 5. Gotts 6. Hillstone 7. Cheesecake Factory #firstsevenjobs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;parsing-the-tweets&#34;&gt;Parsing the tweets&lt;/h1&gt;
&lt;p&gt;So you see, part of them contains actual job descriptions, others don&amp;rsquo;t. I mean, even I polluted the hashtag for advertising my own analysis! Among those that do describe jobs, some use commas or new lines between descriptions, or number them, or simply use spaces&amp;hellip; Therefore, parsing tweets for getting 7 job descriptions per tweet was a little challenge.&lt;/p&gt;
&lt;p&gt;I counted the number of possible separators for finding which one I should probably use to cut the tweet into 7 parts. This yielded tweets cut in several parts &amp;ndash; sometimes less than 7, sometimes more. I could not parse tweets whose descriptions were separated only by spaces because words inside a description are separated by spaces too so I could not make the difference. Besides, some people have tweeted about less or more than 7 jobs. For instance one tweet says &lt;em&gt;I have not had seven jobs yet but so far&amp;hellip;\n- Accounts Assistant\n- Executive PA\n- Social Media Lead\n\nNext,yoga instructor?\n  #FirstSevenJobs&amp;rdquo;&lt;/em&gt;. I did my best to remove tweet parts that were something like &amp;ldquo;Here are my #firstsevenjobs&amp;rdquo;, in order to keep only the job descriptions. At the end I kept only the tweets that had exactly 7 parts.
Out of 4858 I got 1637 tweets, that is 11459 job descriptions. That is &lt;em&gt;a lot&lt;/em&gt;. Here is an excerpt of the table:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;status_id&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;wordsgroup&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;rank&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763505013675229193&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Shopping bag&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763505013675229193&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Shopping assistant&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763505013675229193&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Housekeeper&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763505013675229193&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Cashier at Empik&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763505013675229193&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Fast food worker&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763505013675229193&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Microsoft&amp;rsquo;s consultant&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763505013675229193&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Cashier at Sport shop&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763511170196135936&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Dish Pig&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763511170196135936&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Toy Packer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763511170196135936&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Asian Chef&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763511170196135936&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bike Fitter&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763511170196135936&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Bike Shop Dude&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763511170196135936&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Beard Grower&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763511170196135936&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Sports Therapist&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763512991731945472&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;babysitter&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763512991731945472&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;busperson&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763512991731945472&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;camp counselor&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763512991731945472&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;secretary/clerk&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763512991731945472&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;graduate assistant&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763512991731945472&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;college prof&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;763512991731945472&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;full time writer&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Rank is the rank of the jobs in the tweet, which should be the chronological rank too. For instance, for the first tweet, the first job is &amp;ldquo;shopping bag&amp;rdquo;, the second &amp;ldquo;shopping assistant&amp;rdquo;, etc.&lt;/p&gt;
&lt;h1 id=&#34;monkeylearn-magic-summarizing-the-information-by-assigning-a-field-to-each-job&#34;&gt;Monkeylearn magic: Summarizing the information by assigning a field to each job&lt;/h1&gt;
&lt;p&gt;It would take a long time to read them all the tweets, although I did end up reading a lot of tweets while preparing this post. I wanted to have a general idea of what people did in their life. I turned to machine learning to help me get some information out of the tweets. I&amp;rsquo;m the creator and maintainer of an &lt;a href=&#34;https://github.com/ropenscilabs/monkeylearn&#34;&gt;R package called monkeylearn&lt;/a&gt;, which is part of the &lt;a href=&#34;http://ropensci.org/&#34;&gt;rOpenSci project&lt;/a&gt;, that allows to use existing Monkeylearn classifiers and extractors, so I knew that Monkeylearn had a &lt;a href=&#34;https://app.monkeylearn.com/main/classifiers/cl_i7vMzUB7/&#34;&gt;cool job classifier&lt;/a&gt;. I sent all the 11459 job descriptions to Monkeylearn API.&lt;/p&gt;
&lt;p&gt;Monkeylearn&amp;rsquo;s job classifier assigns a field out of 31 possible fields (called &lt;em&gt;industries&lt;/em&gt;) and a probability to each job description. The algorithm uses a &lt;a href=&#34;https://en.wikipedia.org/wiki/Support_vector_machine&#34;&gt;supported vector machines (SVM) model&lt;/a&gt; for predicting the category of a job. It was originally developped by a client of Monkeylearn as a public module, and was then further developped by the Monkeylearn team, still as a public module &amp;ndash; I really like this collaborative effort. As a Monkeylearn user one could fork the classifier and play with catergories definitions, add or improve data for training the model, etc. With my package one can only use existing models, so that a possible workflow would be to develop modules outside of R and then to use them in R in production. If you wish to know more about classifiers, you can have a look at &lt;a href=&#34;http://docs.monkeylearn.com/knowledge-base/&#34;&gt;Monkeylearn knowledge base&lt;/a&gt; or even take a Machine learning MOOC such as &lt;a href=&#34;https://www.coursera.org/learn/machine-learning&#34;&gt;this one&lt;/a&gt;. But I disgress, I&amp;rsquo;ve been using the jobs classifier as it is, and it was quite fun and above all promising.&lt;/p&gt;
&lt;p&gt;I decided to keep only job descriptions for which the probability given by the classifier was higher than 50%. This corresponds to 6801 job descriptions out of the initial 11459 job descriptions.&lt;/p&gt;
&lt;h1 id=&#34;tweets-coverage-by-the-classifier&#34;&gt;Tweets coverage by the classifier&lt;/h1&gt;
&lt;p&gt;I then wondered how many jobs could be classified with a probability superior to 50% inside each tweet.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2016-10-02-first7jobs-repost/unnamed-chunk-5-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-5&#34;&gt;&lt;/p&gt;
&lt;p&gt;For each 11459 of the tweets I sent to the jobs classifier, I got a field with a probability higher to 0.5 for on average 4-5 job descriptions. We might want even more, and as I&amp;rsquo;ll point it out later, we could get more if we put some effort into it and take full advantage of Monkeylearn possibilities!&lt;/p&gt;
&lt;h1 id=&#34;what-are-jobs-by-field&#34;&gt;What are jobs by field?&lt;/h1&gt;
&lt;p&gt;In this work I used the classifier as it was without modifying it, but I was curious to know which jobs ended up in each category. I had a glance at descriptions by field but this can take a while given the number of jobs in some categories. Thanksfully &lt;a href=&#34;https://twitter.com/FedericoPascual&#34;&gt;Federico Pascual&lt;/a&gt; reminded me I could use &lt;a href=&#34;https://app.monkeylearn.com/main/extractors/ex_y7BPYzNG/&#34;&gt;Monkeylearn&amp;rsquo;s keyword extractor&lt;/a&gt; on all job descriptions of each category to find dominant patterns. Such a nice idea, and something my package supports. I chose to get 5 keywords by field. Here is the result:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;label&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;keyword&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Accounting / Finance&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Accounting clerk, financial analyst, account manager, Bookkeeper, Accountant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Administrative&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;office manager, front desk, office assistant, receptionist, assistant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Architecture / Drafting&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Land surveyor, surveyor, Job, applications, Landscaper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Art/Design / Entertainment&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;House painter, sandwich artist, web designer, Graphic Designer, designer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Banking / Loan / Insurance&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Private tutor, University, insurance, bank teller, teller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Beauty / Wellness&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;hot dog vendor, Physical Therapy Aide, dog sitter, Dog walker, Dog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Business Development / Consulting&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Business Owner, Mgmt consultant, strategist, analyst, consultant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Education&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;high school teacher, substitute teacher, library assistant, Math tutor, teacher&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Engineering (Non-Software)&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Audio Engineer, Engineer intern, network engineer, sales engineer, engineer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Facilities / General Labor&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;factory worker, Grocery Bagger, bagger, Janitor, Warehouse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Hospitality&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Gas station attendant, Gas Station, Kitchen porter, Stock boy, Hostess&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Human Resources&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;event coordinator, Recruitment Consultant, Manager, Recruiter, coordinator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Installation / Maintenance / Repair&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;golf course maintenance, ice cream shop, shop assistant, maintenance, shop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Legal&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Law Office Runner, corporate filth monkey, Law clerk, Paralegal, Law firm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Management&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;retail assistant manager, assistant manager, staff, manager, Director&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Manufacturing / Production / Construction / Logistics&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;park ride operator, Assembly line worker, construction laborer, construction worker, assembly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Marketing / Advertising / PR&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Market researcher, Social Media, Marketing Intern, intern, Marketing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Medical / Healthcare&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;ice cream scooper, Paperboy, Waiter, Waitress, Babysitter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Non-profit / Volunteering&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;student assistant, Orientation Leader, social worker, camp counselor, Camp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Product Management / Project Management&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Program manager, Programming Intern, Production Manager, project manager, manager&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Real Estate&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Real Estate Broker, mortgage broker, Actor Commercials, trainee, real estate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Restaurant / Food Services&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;fast food, Barista, Bartender, Dishwasher, clerk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Retail&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;grocery clerk, grocery store, retail sales, Grocery, cashier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Sales / Customer Care&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Customer Service Rep, Sales assistant, customer service, Sales Associate, sales&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Science / Research&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;tech support, lab tech, research assistant, Tech, research&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Security / Law Enforcement&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;office temp, Office admin, Security guard, Security, office&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Skilled Trade&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Computer Repair Tech, Manufacturer, repair, Carpenter, summer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Software Development / IT&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Software Engineer, Web Developer, data entry, Programmer, Developer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Sports / Fitness&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Gymnastics coach, Soccer Referee, Swim instructor, Lifeguard, instructor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Travel / Transportation&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;delivery driver, Bus Boy, Paper route, Newspaper delivery, Pizza delivery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Writing / Editing / Publishing&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;Freelance Writer, Copywriter, reporter, writer, intern&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For some categories, keywords seem natural to us, for some others we might be more surprised. For instance, the algorithm was trained with data wich included &amp;ldquo;&amp;lsquo;Pet Stylist&amp;rsquo;, &amp;lsquo;Dog Trainer&amp;rsquo;, &amp;lsquo;Pet Stylist (DOG GROOMER)&#39;&amp;rdquo; for the Wellness/Beauty category, and no &amp;ldquo;Dog sitter&amp;rdquo;, so that&amp;rsquo;s why here dog sitting is a wellness job. But wait having a dog is good for your health so people caring for your dog help your wellness, right?&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/assets/photos/2016-10-02-first7jobs-repost_mowgli.jpg&#34; alt=&#34;No comment, say hi to my sibling Mowgli. He&amp;rsquo;s quite a beauty.&#34;&gt;&lt;/p&gt;
&lt;p&gt;So, well, as any statistical or machine learning prediction&amp;hellip; the data you use for training your model is quite crucial. The jobs classifier could probably use even more data for improving classification. As any Monkeylearn public module, it can be built upon and improved, so who&amp;rsquo;s in for forking it? In the meanwhile, it still offers an interesting output to play with. I nearly want to add &amp;ldquo;Monkeylearn user&amp;rdquo; as an &amp;ldquo;Entertainment&amp;rdquo; job because our sample of classified job descriptions is a nice playground for looking at life trajectories.&lt;/p&gt;
&lt;h1 id=&#34;what-sorts-of-jobs-did-people-describe-in-their-tweets&#34;&gt;What sorts of jobs did people describe in their tweets?&lt;/h1&gt;
&lt;p&gt;The 6801 jobs for which we predicted a category with a probability higher than 0.5 are divided as follows among industries:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2016-10-02-first7jobs-repost/unnamed-chunk-7-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-7&#34;&gt;&lt;/p&gt;
&lt;p&gt;The most important categories are Restaurant/Food services and Retail. Usual first jobs?&lt;/p&gt;
&lt;h1 id=&#34;juniorness-of-the-jobs-in-each-field&#34;&gt;Juniorness of the jobs in each field&lt;/h1&gt;
&lt;p&gt;Since we know for each job whether it was the first, third or seventh job of the tweeter, we can explore whether some categories are rather first first jobs than late first jobs. For this, inside each field we can look if the field was mostly a label for first first jobs or for seventh first jobs. See it for yourself:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://masalmon.eu/figure/source/2016-10-02-first7jobs-repost/unnamed-chunk-8-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-8&#34;&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d tend to say that some industries such as Business Development / Consulting are not first-entry jobs (more yellow/green i.e. later jobs), while Non-Profit / Volunteering have a higher proportion of brand-new workers (more blue). Not a real surprise I guess?&lt;/p&gt;
&lt;h1 id=&#34;transitions-between-industries&#34;&gt;Transitions between industries&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve said I wanted to look at life trajectories. This dataset won&amp;rsquo;t give me any information about the level of the job of course, e.g. whether you start as a clerk and end up leading your company, but I can look at how people move from one category to another. &lt;a href=&#34;http://dacornu.github.io/&#34;&gt;My husband&lt;/a&gt; gave me a great idea of a circle graph he had seen in a newspaper. For this I used only job descriptions for which a field was predicted with a probability higher than 0.5. I kept only possible transitions where there were present more than 10 times in the data, otherwise we&amp;rsquo;ll end up looking at a &lt;a href=&#34;https://twitter.com/drob/status/768485328244056065&#34;&gt;hairball&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## Error in library(&amp;quot;circlize&amp;quot;): there is no package called &#39;circlize&#39;
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;## Error in circos.par(gap.degree = gap.degree): could not find function &amp;quot;circos.par&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;## Error in chordDiagram(df, order = names(category), grid.col = category_color, : could not find function &amp;quot;chordDiagram&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;## Error in highlight.sector(sector.index = category[b], track.index = 1, : could not find function &amp;quot;highlight.sector&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code&gt;## Error in circos.clear(): could not find function &amp;quot;circos.clear&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On this circle you see different industries, and the transition between them. The length of the circle occupied by each field depends on the number of jobs belonging to this category, so again the Food and Restauration category is the biggest one. One can see that people taking a position in the Hospitality field, below the circle, often come from the Restauration or the Retail field When they leave this field, they&amp;rsquo;ll often go work in the Restauration field &lt;a href=&#34;http://varianceexplained.org/&#34;&gt;David Robinson&lt;/a&gt; suggested I find the most common transitions and showed them in directed graphs but I&amp;rsquo;ll keep this idea for later, since this post is quite long already, ah!&lt;/p&gt;
&lt;p&gt;As a conclusion, I&amp;rsquo;m quite excited by the possibilities offered by Monkeylearn for text mining. I might be a grumpy and skeptical statistician so I&amp;rsquo;ll tend to look at all the shortcomings of predictions, but really I think that if ones takes the time to train a module well, they can then get pretty cool information from text written by humans. Now if you tweet about this article, I might go and look at &lt;a href=&#34;https://app.monkeylearn.com/main/classifiers/cl_qkjxv9Ly/&#34;&gt;Monkeylearn&amp;rsquo;s sentiment analysis for tweets module&lt;/a&gt; instead of reading them.&lt;/p&gt;
&lt;h1 id=&#34;acknowledgements&#34;&gt;Acknowledgements&lt;/h1&gt;
&lt;p&gt;Note that my whole code is &lt;a href=&#34;https://github.com/maelle/first_7_jobs&#34;&gt;in this Github repo&lt;/a&gt;. All analyses were performed in &lt;a href=&#34;https://www.R-project.org/&#34;&gt;R&lt;/a&gt;. I used those R packages: rtweet, dplyr, tidyr, ggplot2, stringr, purrr, readr, circlize and of course monkeylearn. Thanks a lot to their authors, and obviously thanks to people whose tweets I used&amp;hellip; I might be a &lt;em&gt;little bit&lt;/em&gt; more grateful to people who used separators and only posted 7 descriptions in their tweet. If you want to read another &amp;ldquo;#first7&amp;rdquo; analysis in R, I highly recommend &lt;a href=&#34;http://varianceexplained.org/r/seven-fav-packages/&#34;&gt;David Robinson&amp;rsquo;s post&lt;/a&gt; about the &amp;ldquo;7FavPackages&amp;rdquo; hashtag.&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>