as days pass by: a weblog by Stuart Langridge//www.kryogenix.org/days/scratched tallies on the prison wallSun, 12 Nov 2017 11:31:00 +0000I wrote a Web Component//www.kryogenix.org/days/2017/11/12/i-wrote-a-web-component/<p>I’ve been meaning to play with Web Components for a little while now. After I saw <a href="https://twitter.com/BenNadel/status/929383549584789504">Ben Nadel create a Twitter tweet progress indicator with Angular</a> and <a href="https://github.com/LucasLeandro1204/vue-twitter-counter">Lucas Leandro did the same with Vue.js</a> I thought, here’s a chance to experiment.</p>
<p>Web Components involve a whole bunch of different dovetailing specs; <span class="caps">HTML</span> imports, custom elements, shadow <span class="caps">DOM</span>, <span class="caps">HTML</span> templates. I didn’t want to have to use the <span class="caps">HTML</span> template and import stuff if I could avoid it, and pleasantly you actually don’t need it. Essentially, you can create a custom element named <code>whatever-you-want</code> and then just add <code>&lt;whatever-you-want someattr="somevalue"&gt;content here&lt;/whatever-you-want&gt;</code> elements to your page, and it all works. This is good.</p>
<p>To define a new type of element, you use <code>window.customElements.define('your-element-name', YourClass)</code>.<sup id="sf-i-wrote-a-web-component-1-back"><a title="I relied for a lot of this understanding on Google’s web components documentation by Eric Bidelman." class="simple-footnote" href="#sf-i-wrote-a-web-component-1">1</a></sup> <code>YourClass</code> is an <span class="caps">ES2016</span> JavaScript class. <sup id="sf-i-wrote-a-web-component-2-back"><a title="All this stuff is present already in Chrome; for other browsers you may need polyfills, and I’ll get to that later." class="simple-footnote" href="#sf-i-wrote-a-web-component-2">2</a></sup> So, we start like this:</p>
<pre><code>
window.customElements.define('twitter-circle-count', class extends HTMLElement {
});
</code></pre>
<p>The class has a <code>constructor</code> method which sets everything up. In our case, we’re going to create an <span class="caps">SVG</span> with two circles: the “indicator” (which is the one that changes colour and fills in as you add characters), and the “track” (which is the one that’s always present and shows where the line of the circle goes). Then we shrink and grow the “indicator” circle by using <a href="https://jakearchibald.com/2013/animated-line-drawing-svg/">Jake Archibald’s dash-offset technique</a>. This is all perfectly expressed by Ben Nadel’s diagram, which I hope he doesn’t mind me borrowing because it’s great.</p>
<p><img src="https://kryogenix.org/images/twitter-progress-indicator-concept-angular5.png" alt=""></p>
<p>So, we need to dynamically create an <span class="caps">SVG</span>. The <span class="caps">SVG</span> we want will look basically like this:</p>
<pre><code>
&lt;svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"&gt;
&lt;circle cx="50" cy="50" r="45"
style="stroke: #9E9E9E"&gt;&lt;/circle&gt;
&lt;circle cx="50" cy="50" r="45"
style="stroke: #333333)"&gt;&lt;/circle&gt;
&lt;/svg&gt;
</code></pre>
<p>Let’s set that <span class="caps">SVG</span> up in our element’s constructor:</p>
<pre><code>
<span>window.customElements.define('twitter-circle-count', class extends HTMLElement {</span>
constructor() {
/* You must call super() first in the constructor. */
super();
/* Create the SVG. Note that we need createElementNS, not createElement */
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("viewBox", "0 0 100 100");
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
/* Create the track. Note createElementNS. Note also that "this" refers to
this element, so we've got a reference to it for later. */
this.track = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.track.setAttribute("cx", "50");
this.track.setAttribute("cy", "50");
this.track.setAttribute("r", "45");
/* And create the indicator, by duplicating the track */
this.indicator = this.track.cloneNode(true);
svg.appendChild(this.track);
svg.appendChild(this.indicator);
}
<span>});</span>
</code></pre>
<p>Now we need to actually add that created <span class="caps">SVG</span> to the document. For that, we create a <em>shadow root</em>. This is basically a little separate <span class="caps">HTML</span> document, inside your element, which is isolated from the rest of the page. Styles set in the main page won’t apply to stuff in your component; styles set in your component won’t leak out to the rest of the page.<sup id="sf-i-wrote-a-web-component-3-back"><a title="Pedant posse: yes, it’s a bit more complicated than this. One step at a time." class="simple-footnote" href="#sf-i-wrote-a-web-component-3">3</a></sup> This is easy with <code>attachShadow</code>, which returns you this shadow root, which you can then treat like a normal node:</p>
<pre><code>
<span>window.customElements.define('twitter-circle-count', class extends HTMLElement {
constructor() {
super();
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("viewBox", "0 0 100 100");
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
this.track = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.track.setAttribute("cx", "50");
this.track.setAttribute("cy", "50");
this.track.setAttribute("r", "45");
this.indicator = this.track.cloneNode(true);
svg.appendChild(this.track);
svg.appendChild(this.indicator);</span>
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(svg);
<span>}
});</span>
</code></pre>
<p>Now, we want to allow people to set the colours of our circles. The way to do this is with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/--*"><span class="caps">CSS</span> custom properties</a>. Basically, you can invent any new property name you like, as long as it’s prefixed with <code>--</code>. So we invent two: <code>--track-color</code> and <code>--circle-color</code>. We then set the two circles to be those colours by using <span class="caps">CSS</span>’s <code>var()</code> syntax; this lets us say “use this variable if it’s set, or use this default value if it isn’t”. So our user can style our element with <code>twitter-circle-count { --track-color: #eee; }</code> and it’ll work.</p>
<p>Annoyingly, it doesn’t seem to be easily possible to use <em>existing</em> <span class="caps">CSS</span> properties for this; there doesn’t seem to be a good way to have the standard property <code>color</code> set the circle colour.<sup id="sf-i-wrote-a-web-component-4-back"><a title="It would be possible to have color apply to our circle colour by monitoring changes to the element’s style, but that’s a nightmare." class="simple-footnote" href="#sf-i-wrote-a-web-component-4">4</a></sup> One has to use a custom variable even if there’s a “real” <span class="caps">CSS</span> property that would be appropriate. I’m hoping I’m wrong about this and there is a sensible way to do it that I just haven’t discovered.<sup id="sf-i-wrote-a-web-component-5-back"><a title="QML does this by setting “aliases”; in a component, you can say property alias foo: subelement.bar and setting foo on an instance of my component propagates through and sets bar on the subelement. This is a really good idea, and I wish Web Components did it somehow." class="simple-footnote" href="#sf-i-wrote-a-web-component-5">5</a></sup>
(Update: Matt Machell <a href="https://twitter.com/shuckle/status/929710831620820993">mentions <code>currentColor</code></a> which would work perfectly for this example, but it <em>only</em> works for <code>color</code>; there’s no way of setting other properties like, say, <code>font-size</code> on the component and having that explicitly propagate down to a particular element <em>in</em> the component; there’s no <code>currentFontSize</code>. I don’t know why <code>color</code> gets special treatment, even though the special treatment would solve my particular problem.)</p>
<pre><code>
<span>window.customElements.define('twitter-circle-count', class extends HTMLElement {
constructor() {
super();
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("viewBox", "0 0 100 100");
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
this.track = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.track.setAttribute("cx", "50");
this.track.setAttribute("cy", "50");
this.track.setAttribute("r", "45");
this.indicator = this.track.cloneNode(true);</span>
this.track.style.stroke = "var(--track-color, #9E9E9E)";
this.indicator.style.stroke = "var(--circle-color, #333333)";
<span>svg.appendChild(this.track);
svg.appendChild(this.indicator);
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(svg);
}
});</span>
</code></pre>
<p>We want our little element to be <code>inline-block</code>. To set properties on the element itself, from inside the element, there is a special <span class="caps">CSS</span> selector, <code>:host</code>.<sup id="sf-i-wrote-a-web-component-6-back"><a title="Firefox doesn’t seem to support this yet, either :host or scoping styles so they don’t leak out of the component, so I’ve also set display:inline-block and position:relative on the twitter-circle-count selector in my normal CSS. This should be fixed soon." class="simple-footnote" href="#sf-i-wrote-a-web-component-6">6</a></sup> Add a <code>&lt;style&gt;</code> element inside the component and it only applies to the component (this is special “scoped style” magic), and setting <code>:host</code> styles the root of your element:</p>
<pre><code>
<span>window.customElements.define('twitter-circle-count', class extends HTMLElement {
constructor() {
super();
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("viewBox", "0 0 100 100");
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
this.track = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.track.setAttribute("cx", "50");
this.track.setAttribute("cy", "50");
this.track.setAttribute("r", "45");
this.indicator = this.track.cloneNode(true);
this.track.style.stroke = "var(--track-color, #9E9E9E)";
this.indicator.style.stroke = "var(--circle-color, #333333)";
svg.appendChild(this.track);
svg.appendChild(this.indicator);
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(svg);</span>
var style = document.createElement("style");
style.innerHTML = ":host { display: inline-block; position: relative; contain: content; }";
shadowRoot.appendChild(style);
<span>}
});</span>
</code></pre>
<p>Next, we need to be able to set the properties which define the value of the counter — how much progress it should show. Having <code>value</code> and <code>max</code> properties similar to an <code>&lt;input type="range"&gt;</code> seems logical here. For this, we define a little function <code>setDashOffset</code> which sets the <code>stroke-dashoffset</code> style on our indicator. We then call that function in two places. One is in <code>connectedCallback</code>, a method which is called when our custom element is first inserted into the document. The second is whenever our <code>value</code> or <code>max</code> attributes change. That gets set up by defining <code>observedAttributes</code>, which returns a list of attributes that we want to watch; whenever one of those attributes changes, <code>attributeChangedCallback</code> is called.</p>
<pre><code>
<span>window.customElements.define('twitter-circle-count', class extends HTMLElement {</span>
static get observedAttributes() {
return ['value', 'max'];
}
attributeChangedCallback(name, oldValue, newValue) {
this.setDashOffset();
}
setDashOffset() {
var mx = parseInt(this.getAttribute("max"), 10);
if (isNaN(mx)) mx = 100;
var value = parseInt(this.getAttribute("value"), 10);
if (isNaN(value)) value = 0;
this.indicator.style.strokeDashoffset = this.circumference -
(value * this.circumference / mx);
}
<span>constructor() {
super();
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("viewBox", "0 0 100 100");
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
this.track = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.track.setAttribute("cx", "50");
this.track.setAttribute("cy", "50");
this.track.setAttribute("r", "45");
this.indicator = this.track.cloneNode(true);
this.track.style.stroke = "var(--track-color, #9E9E9E)";
this.indicator.style.stroke = "var(--circle-color, #333333)";</span>
/* We know what the circumference of our circle is. It doesn't matter
how big the element is, because the SVG is always 100x100 in its own
"internal coordinates": that's what the viewBox means. So the circle
always has a 45px radius, and so its circumference is always the same,
2πr. Store this for later. */
this.circumference = 3.14 * (45 * 2);
<span>svg.appendChild(this.track);
svg.appendChild(this.indicator);
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(svg);
var style = document.createElement("style");
style.innerHTML = ":host { display: inline-block; position: relative; contain: content; }";
shadowRoot.appendChild(style);
}</span>
connectedCallback() {
this.setDashOffset();
}
<span>});</span>
</code></pre>
<p>This works if the user of the component does <code>counter.setAttribute("value", "50")</code>, but it doesn’t make <code>counter.value = 50</code> work, and it’s nice to provide these direct JavaScript APIs as well. For that we need to define a getter and a setter for each.</p>
<pre><code>
<span>window.customElements.define('twitter-circle-count', class extends HTMLElement {
static get observedAttributes() {
return ['value', 'max'];
}
attributeChangedCallback(name, oldValue, newValue) {
this.setDashOffset();
}
setDashOffset() {
var mx = parseInt(this.getAttribute("max"), 10);
if (isNaN(mx)) mx = this.defaultMax;
var value = parseInt(this.getAttribute("value"), 10);
if (isNaN(value)) value = this.defaultValue;
this.indicator.style.strokeDashoffset = this.circumference - (
value * this.circumference / mx);
}</span>
get value() {
var value = this.getAttribute('value');
if (isNaN(value)) return this.defaultValue;
return value;
}
set value(value) { this.setAttribute("value", value); }
get max() {
var mx = this.getAttribute('max');
if (isNaN(mx)) return this.defaultMax;
return max;
}
set value(value) { this.setAttribute("value", value); }
<span>constructor() {
super();
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("viewBox", "0 0 100 100");
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
this.track = document.createElementNS("http://www.w3.org/2000/svg", "circle");
this.track.setAttribute("cx", "50");
this.track.setAttribute("cy", "50");
this.track.setAttribute("r", "45");
this.indicator = this.track.cloneNode(true);
this.track.style.stroke = "var(--track-color, #9E9E9E)";
this.indicator.style.stroke = "var(--circle-color, #333333)";
this.circumference = 3.14 * (45 * 2);
svg.appendChild(this.track);
svg.appendChild(this.indicator);
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(svg);
var style = document.createElement("style");
style.innerHTML = ":host { display: inline-block; position: relative; contain: content; }";
shadowRoot.appendChild(style);</span>
this.defaultValue = 50;
this.defaultMax = 100;
<span>}
connectedCallback() {
this.setDashOffset();
}
});</span>
</code></pre>
<p>And that’s all we need. We can now create our <code>twitter-circle-count</code> element and hook it up to a <code>textarea</code> like this:</p>
<div class="highlight"><pre><span class="nt">&lt;twitter</span><span class="na">-circle-count</span> <span class="na">value=</span><span class="s">"0"</span> <span class="na">max=</span><span class="s">"280"</span><span class="nt">&gt;</span><span class="err">&lt;</span>/twitter-circle-count&gt;
<span class="nt">&lt;p&gt;</span>Type in here<span class="nt">&lt;/p&gt;</span>
<span class="nt">&lt;textarea</span> <span class="na">rows=</span><span class="s">3</span> <span class="na">cols=</span><span class="s">40</span><span class="nt">&gt;&lt;/textarea&gt;</span>
</pre></div>
<div class="highlight"><pre><span class="nt">twitter-circle-count</span> <span class="p">{</span>
<span class="k">width</span><span class="o">:</span> <span class="m">30px</span><span class="p">;</span>
<span class="k">height</span><span class="o">:</span> <span class="m">30px</span><span class="p">;</span>
<span class="o">--</span><span class="n">track</span><span class="o">-</span><span class="k">color</span><span class="o">:</span> <span class="m">#ddd</span><span class="p">;</span>
<span class="o">--</span><span class="k">circle</span><span class="o">-</span><span class="k">color</span><span class="o">:</span> <span class="m">#333</span><span class="p">;</span>
<span class="o">--</span><span class="k">text</span><span class="o">-</span><span class="k">color</span><span class="o">:</span> <span class="m">#888</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<div class="highlight"><pre><span class="c1">// we use input, not keyup, because that fires when text is cut or pasted</span>
<span class="c1">// thank you Dave MN for that insight</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s2">"textarea"</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s2">"input"</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s2">"twitter-circle-count"</span><span class="p">).</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s2">"value"</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
<span class="p">},</span> <span class="kc">false</span><span class="p">);</span>
</pre></div>
<p>and it works! I also added a text counter and a couple of other nicenesses, such as making the indicator animate to its position, and included a <a href="https://www.webcomponents.org/polyfills">polyfill</a> to add support in browsers that don’t have it.<sup id="sf-i-wrote-a-web-component-7-back"><a title="Mikeal Rogers has a really nice technique here for bundling your web component with a polyfill which is also worth considering." class="simple-footnote" href="#sf-i-wrote-a-web-component-7">7</a></sup></p>
<script src="https://rawgit.com/webcomponents/webcomponentsjs/master/webcomponents-sd-ce.js"></script>
<p>Here’s the counter: <twitter-circle-count value="0" max="280"></twitter-circle-count></p>
<p>Type some text in here:</p>
<p><textarea cols="20" rows="3"></textarea>
<style>
twitter-circle-count {
width: 30px;
height: 30px;
--track-color: #ddd;
--circle-color: #333;
--text-color: #888;
text-indent: 0;
display: inline-block;
position: relative;
}
</style>
<script src="https://kryogenix.org/code/browser/twitter-circle-count.js">
</script>
<style>
pre code { font-size: 12px; }
pre code span { opacity: 0.25; }
</style></p><ol class="simple-footnotes"><li id="sf-i-wrote-a-web-component-1">I relied for a lot of this understanding on <a href="https://developers.google.com/web/fundamentals/web-components/customelements">Google’s web components documentation</a> by <a href="https://twitter.com/ebidel">Eric Bidelman</a>. <a class="simple-footnote-back" href="#sf-i-wrote-a-web-component-1-back">↩</a></li><li id="sf-i-wrote-a-web-component-2">All this stuff is present already in Chrome; for other browsers you may need polyfills, and I’ll get to that later. <a class="simple-footnote-back" href="#sf-i-wrote-a-web-component-2-back">↩</a></li><li id="sf-i-wrote-a-web-component-3">Pedant posse: yes, it’s a bit more complicated than this. One step at a time. <a class="simple-footnote-back" href="#sf-i-wrote-a-web-component-3-back">↩</a></li><li id="sf-i-wrote-a-web-component-4">It would be possible to have <code>color</code> apply to our circle colour by monitoring changes to the element’s style, but that’s a nightmare. <a class="simple-footnote-back" href="#sf-i-wrote-a-web-component-4-back">↩</a></li><li id="sf-i-wrote-a-web-component-5"><span class="caps">QML</span> does this by setting “aliases”; in a component, you can say <code>property alias foo: subelement.bar</code> and setting <code>foo</code> on an instance of my component propagates through and sets <code>bar</code> on the <code>subelement</code>. This is a really good idea, and I wish Web Components did it somehow. <a class="simple-footnote-back" href="#sf-i-wrote-a-web-component-5-back">↩</a></li><li id="sf-i-wrote-a-web-component-6">Firefox doesn’t seem to support this yet, either <code>:host</code> or scoping styles so they don’t leak out of the component, so I’ve also set <code>display:inline-block</code> and <code>position:relative</code> on the <code>twitter-circle-count</code> selector in my normal <span class="caps">CSS</span>. This should be fixed soon. <a class="simple-footnote-back" href="#sf-i-wrote-a-web-component-6-back">↩</a></li><li id="sf-i-wrote-a-web-component-7">Mikeal Rogers has a really nice technique here for <a href="https://medium.com/@mikeal/ive-seen-the-future-it-s-full-of-html-2577246f2210">bundling your web component with a polyfill</a> which is also worth considering. <a class="simple-footnote-back" href="#sf-i-wrote-a-web-component-7-back">↩</a></li></ol>silSun, 12 Nov 2017 11:31:00 +0000tag://www.kryogenix.org/days,2017-11-12:2017/11/12/i-wrote-a-web-component/Telegram notifications for Jenkins builds//www.kryogenix.org/days/2017/10/27/telegram-notifications-for-jenkins-builds/<p>It&#8217;s nice to get updates from your <span class="caps">CI</span> system when things build. It&#8217;s even nicer to do it without having to run any servers to do it. Here&#8217;s how I send build notifications to a Telegram bot from&nbsp;Jenkins.</p>
<p>Basically, Jenkins knows how to hit a webhook for every stage of the build, and <a href="https://integram.org">Integram</a> run a Telegram bot which knows how to respond to webhooks. All you need is a little bit of glue code to convert stuff Jenkins sends into stuff Integram receives, and you can put that glue code on any one of fifteen serverless systems. I used <a href="https://webtask.io">webtask.io</a>. </p>
<p><img src="/images/jenkins-webtask.png" alt="The Webtask.io editor"></p>
<p>Deploy the following code there, being sure to update the Integram <span class="caps">URL</span> in it to be&nbsp;yours:</p>
<div class="highlight"><pre><span class="kd">var</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;express&#39;</span><span class="p">)</span>
<span class="kd">var</span> <span class="nx">bodyParser</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;body-parser&#39;</span><span class="p">)</span>
<span class="kd">var</span> <span class="nx">request</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;request&#39;</span><span class="p">)</span>
<span class="kd">var</span> <span class="nx">Webtask</span><span class="p">;</span>
<span class="k">try</span> <span class="p">{</span>
<span class="nx">Webtask</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">&#39;webtask-tools&#39;</span><span class="p">);</span>
<span class="p">}</span> <span class="k">catch</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{}</span>
<span class="kd">var</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">()</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">bodyParser</span><span class="p">.</span><span class="nx">json</span><span class="p">())</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s1">&#39;*&#39;</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">body</span> <span class="o">&amp;&amp;</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">name</span> <span class="o">&amp;&amp;</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">build</span> <span class="o">&amp;&amp;</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">build</span><span class="p">.</span><span class="nx">url</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">status</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">build</span><span class="p">.</span><span class="nx">status</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">build</span><span class="p">.</span><span class="nx">phase</span> <span class="o">==</span> <span class="s2">&quot;STARTED&quot;</span><span class="p">)</span> <span class="p">{</span> <span class="nx">status</span> <span class="o">=</span> <span class="s2">&quot;STARTED&quot;</span><span class="p">;</span> <span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">build</span><span class="p">.</span><span class="nx">phase</span> <span class="o">==</span> <span class="s2">&quot;FINALIZED&quot;</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// don&#39;t care about FINALIZED because we get COMPLETED and that&#39;s enough</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s2">&quot;ok&quot;</span><span class="p">);</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;Received correct-looking JSON to webhook&quot;</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">output</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;text&quot;</span><span class="o">:</span> <span class="s2">&quot;Jenkins\nBuild of _&quot;</span> <span class="o">+</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span>
<span class="s2">&quot;_ status *&quot;</span> <span class="o">+</span> <span class="nx">status</span> <span class="o">+</span> <span class="s2">&quot;* &quot;</span> <span class="o">+</span>
<span class="s2">&quot;at http://YOUR-JENKINS-URL/&quot;</span> <span class="o">+</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">build</span><span class="p">.</span><span class="nx">url</span><span class="p">};</span>
<span class="nx">request</span><span class="p">({</span>
<span class="nx">uri</span><span class="o">:</span> <span class="s2">&quot;https://integram.org/YOUR-INTEGRAM-URL&quot;</span><span class="p">,</span>
<span class="nx">method</span><span class="o">:</span> <span class="s2">&quot;POST&quot;</span><span class="p">,</span>
<span class="nx">json</span><span class="o">:</span> <span class="nx">output</span>
<span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;Messaging Telegram bot failed&quot;</span><span class="p">,</span> <span class="nx">err</span><span class="p">);</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s2">&quot;failed&quot;</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;Messaging Telegram bot succeeded&quot;</span><span class="p">);</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s2">&quot;ok&quot;</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;Input to webhook was invalid&quot;</span><span class="p">,</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">);</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s2">&quot;Input was invalid: &quot;</span> <span class="o">+</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">Webtask</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="nx">Webtask</span><span class="p">.</span><span class="nx">fromExpress</span><span class="p">(</span><span class="nx">app</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">4569</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">&quot;Listening on port 4569&quot;</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>Then, put the webtask <span class="caps">URL</span> into Jenkins as a&nbsp;webhook:</p>
<p><img src="/images/jenkins-notifications.png" alt="Add a notifications endpoint in the configure section of your build job"></p>
<p>And invite the Integram bot to your Telegram channel (instructions at <a href="https://integram.org/">integram.org</a>).</p>
<p>And you&#8217;re done. Every time Jenkins does anything, it sends a web request to your webtask, the webtask sends a message to the Integram bot, the Integram bot repeats it to you, and you get a notification. No extra servers required. I love the&nbsp;internet.</p>
<p><img src="/images/jenkins-telegram-notifications.png" alt="The Telegram bot speaks the message it's given, and so Telegram notifies you"></p>silFri, 27 Oct 2017 10:53:00 +0100tag://www.kryogenix.org/days,2017-10-27:2017/10/27/telegram-notifications-for-jenkins-builds/Charles Paget Wade and the Underthing//www.kryogenix.org/days/2017/10/15/charles-paget-wade-and-the-underthing/<p>I got to spend a few days with <a href="https://twitter.com/rose0window">Andy</a> and his wife Gaby and their exciting new dog, Iwa. I don&#8217;t get to see them as often as I should, but since they&#8217;ve now moved rather closer to Castle Langridge we&#8217;re going to correct that. And since they&#8217;re in the Cotswolds I got to peer at a whole bunch of things. Mostly things built of yellow stone, admittedly. It is a source of never-ending pleasure that despite twenty-three years of conversation we still never run out of things to talk about. There is almost nothing more delightful than spending an afternoon over a pint arguing about what technological innovation you&#8217;d take back to Elizabethan England. (This is a harder question than you&#8217;d think. Sure, you can take your iPhone back and a solar charger, and it&#8217;d be an incredibly powerful computer, but what would they use it for? They can do all the maths that they need; it&#8217;s just slower. Maybe you&#8217;d build a dynamo and gift them electricity, but where would you get the magnets from? Imagine this interspersed with excellent beer from the <a href="http://www.thevolunteerinn.net/">Volunteer</a> and you have a flavour of&nbsp;it.)</p>
<p>There were also some <a href="http://www.rollrightstones.co.uk/">Rollright Stones</a>, as guided by Julian Cope&#8217;s finest-guidebook-ever <a href="http://www.themodernantiquarian.com/">The Modern Antiquarian</a>. But that&#8217;s not the&nbsp;thing.</p>
<p>The thing is <a href="https://www.nationaltrust.org.uk/snowshill-manor-and-garden">Snowshill Manor</a>. There was a bloke and his name was <a href="https://en.wikipedia.org/wiki/Charles_Paget_Wade">Charles Paget Wade</a>. Did some painting (at which he was not half bad), did some architecting (also not bad), wrote some poetry. And also inherited a dumper truck full of money by virtue of his family&#8217;s sugar plantations in the West Indies. This money he used to assemble an exceedingly diverse collection of Stuff, which you can now go and see by looking around Snowshill. What&#8217;s fascinating about this is that he didn&#8217;t just amass the Stuff into a big pile and then donate the house to the National Trust as a museum to hold it. Every room in the house was individually curated by him; this room for these objects, that room for those, what he called &#8220;an attractive set of rooms pictorially&#8221;. There&#8217;s some rhyme and some reason &#8212; one of the upstairs rooms is full of clanking, rigid, iron bicycles, and another full of suits of samurai armour &#8212; but mostly they&#8217;re things he just felt fitted together somehow. He&#8217;s like Auri from the Kingkiller Chronicles; this room cries out for this thing to be in it. (If you&#8217;ve read the first two Kingkiller books but haven&#8217;t read <em>The Slow Regard of Silent Things</em>, go and read it and know more of Auri than you currently do.) There&#8217;s a room with a few swords, and a clock that doesn&#8217;t work, and a folding table, and a box with an enormously ornate lock and a set of lawn bowls, and a cabinet containing a set of spectacles and a picture of his grandmother and a ball carved from ivory inside which is a second ball carved from the same piece of ivory inside which is yet another ball. The rhyme and the reason were all in his head, I think. I like to imagine that sometimes he&#8217;d wake up in his strange bedroom with its huge carved crucifix at four in the morning and scurry into the house to carefully carry a blue Japanese vase from the Meridian Room into Zenity and then sit back, quietly satisfied that the cosmic balance was somehow improved. Or to study a lacquered cabinet for an hour and a half and then tentatively shift it an inch to the left, so it sits there just so. So it&#8217;s <em>right</em>. I don&#8217;t know if the order, the placing, the detail of the collection actually speaks as loudly to anyone as it spoke to him, and it doesn&#8217;t matter. You could spend the rest of your life hearing the stories about everything there and never get off the ground&nbsp;floor.</p>
<p>Take that room of samurai armour, for example. One of the remarkable things about the collection (there are so many remarkable things about the collection) is that rather a lot of it is Oriental &#8212; Japanese or Chinese, mainly &#8212; but Wade never went to China or Japan. A good proportion of the objects came from other stately homes, selling off items after the First World War &#8212; whether because none of the family were left, or for financial reasons, or maybe just that the occupants came home and didn&#8217;t want it all any more. The armour is a case in point; Wade needed some plumbing done on the house and went off to chat to a plumber&#8217;s merchant about it, where he found a box of scrap metal. Since the bloke was the Lord High Emperor of looking for objects that caught his fancy, he had a look through this discarded pile and found in it&#8230; about fifteen suits of samurai armour. (A large box, to be sure.) So he asked the merchant what the score was, and was told: oh, those, yeah, take them if you want&nbsp;them.</p>
<p>This sort of thing doesn&#8217;t happen to me all that&nbsp;much.</p>
<p>Outside that room, just hanging on the wall, is the door from a carriage; one of the ones with the large wheels, all pulled by horses. Like the cabs that Sherlock Holmes rode in, or that the Queen takes to coronations. It was monogrammed <span class="caps">ECC</span>, and had one of those coats of arms where you just know that the family have been around for a while because two different shields have been quartered in it and then it&#8217;s been quartered again. After some entirely baseless speculation we discovered that it was owned by <a href="https://en.wikipedia.org/wiki/Emily_Temple,_Viscountess_Palmerston">Countess Cowper</a>. She married Lord Palmerston; her brother was <a href="https://en.wikipedia.org/wiki/William_Lamb,_2nd_Viscount_Melbourne">William Lamb</a>, Lord Melbourne, who was another Prime Minister and had the Australian city named after him; his wife was <a href="https://en.wikipedia.org/wiki/Lady_Caroline_Lamb">Lady Caroline Lamb</a>, who infamously described Byron as &#8220;mad, bad, and dangerous to know&#8221;. History is all intertwined around&nbsp;itself.</p>
<p>None of the clocks in the house work. Apparently at one point Wade had a guest over who glanced at a clock and assumed she had plenty of time to catch her train. Of course, she missed it, and on hearing from him that of course the clocks don&#8217;t tell the right time, she was not best pleased. Not sure who it was. Virginia Woolf, or someone like&nbsp;that.</p>
<p>There is too much stuff. He can&#8217;t possibly have kept it all in his head. You can&#8217;t possibly keep it all in, walking around. Visitors ought to be banned from going into more than three or four rooms; by the time you&#8217;ve got halfway through it&#8217;s just impossible to give each place the attention it deserves. There are hardly any paintings; Wade liked actual things, not drawings or representations. It&#8217;s not an art gallery. It&#8217;s a craftsmanship gallery; Wade sought out things that were made, that showed beauty or artistry or ingenuity in their construction. Objects, not drawings; stuff that demonstrates human creation at work. The house is like walking around inside his head, I think. (&#8220;Sometimes I think the asylum is a head. We&#8217;re inside a huge head that dreams us all into being. Perhaps it&#8217;s your head,&nbsp;Batman.&#8221;)</p>
<p>Next time you&#8217;re near Evesham, go&nbsp;visit.</p>silSun, 15 Oct 2017 23:49:00 +0100tag://www.kryogenix.org/days,2017-10-15:2017/10/15/charles-paget-wade-and-the-underthing/The Niamh prime//www.kryogenix.org/days/2017/09/10/the-niamh-prime/<p>A bit of maths-y fiddling around on a Sunday&nbsp;afternoon.</p>
<p>Fascinating video on <a href="https://www.youtube.com/watch?v=fQQ8IiTWHhg">the Trinity Hall prime</a> at&nbsp;Numberphile:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/fQQ8IiTWHhg?rel=0" frameborder="0" allowfullscreen></iframe>
<p>Apparently, Professor James McKee found a prime number which, when written out as <span class="caps">ASCII</span> art, looks like the crest of Trinity Hall college. Jack Hodkinson at Cambridge then searched for and found <a href="https://friendlyfieldsandopenmaps.com/2017/09/08/the-corpus-christi-prime/">a prime which looks like a picture of Corpus Christi college</a> (via <a href="https://www.futilitycloset.com/">Futility Closet</a>). That seems like a cool idea. So, with a bit of help from <a href="http://mir3z.github.io/aalib.js/">aalib in JavaScript</a> and the <a href="https://rosettacode.org/wiki/Miller%E2%80%93Rabin_primality_test">Miller-Rabin primality test</a>, plus a bit of scaling images up and down in Gimp, I found this 2,850-digit&nbsp;prime:</p>
<p>777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,577,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;752,385,356,&shy;867,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;775,352,235,&shy;666,688,668,&shy;667,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,776,765,&shy;555,556,666,&shy;856,868,667,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;222,335,666,&shy;666,866,686,&shy;666,665,777,&shy;777,777,777,&shy;777,777,777,&shy;777,355,336,&shy;358,866,556,&shy;666,655,665,&shy;655,777,777,&shy;777,777,777,&shy;777,777,733,&shy;552,236,666,&shy;666,655,665,&shy;665,666,555,&shy;777,777,777,&shy;777,777,777,&shy;777,276,265,&shy;666,666,656,&shy;655,555,555,&shy;555,533,777,&shy;777,777,777,&shy;777,777,253,&shy;252,566,666,&shy;665,555,556,&shy;555,555,565,&shy;557,777,777,&shy;777,777,777,&shy;725,222,236,&shy;666,565,555,&shy;555,556,555,&shy;535,355,237,&shy;777,777,777,&shy;777,772,266,&shy;725,366,535,&shy;555,355,555,&shy;555,553,553,&shy;533,577,777,&shy;777,777,777,&shy;272,637,356,&shy;655,555,555,&shy;353,535,556,&shy;655,355,332,&shy;277,777,777,&shy;777,772,235,&shy;775,355,665,&shy;553,355,353,&shy;535,533,555,&shy;555,223,777,&shy;777,777,777,&shy;322,222,255,&shy;555,556,353,&shy;555,355,336,&shy;355,653,533,&shy;537,777,777,&shy;777,772,222,&shy;225,555,565,&shy;555,355,335,&shy;355,356,555,&shy;655,353,237,&shy;777,777,777,&shy;772,272,355,&shy;553,553,355,&shy;535,353,365,&shy;355,355,553,&shy;523,577,777,&shy;777,777,332,&shy;333,566,333,&shy;553,555,533,&shy;355,355,555,&shy;555,353,555,&shy;677,777,777,&shy;777,332,355,&shy;555,555,555,&shy;555,555,553,&shy;555,535,555,&shy;666,556,777,&shy;777,777,775,&shy;533,355,535,&shy;355,553,565,&shy;535,353,655,&shy;655,555,565,&shy;557,777,777,&shy;777,756,533,&shy;555,533,335,&shy;353,566,655,&shy;353,566,535,&shy;656,655,577,&shy;777,777,777,&shy;565,353,535,&shy;535,553,335,&shy;566,666,555,&shy;666,568,566,&shy;665,777,777,&shy;777,775,633,&shy;535,555,555,&shy;555,535,565,&shy;556,555,666,&shy;566,666,677,&shy;777,777,777,&shy;758,333,333,&shy;355,555,656,&shy;556,565,866,&shy;666,866,658,&shy;667,777,777,&shy;777,777,582,&shy;233,333,333,&shy;355,565,555,&shy;566,666,666,&shy;868,666,677,&shy;777,777,777,&shy;775,822,333,&shy;333,333,535,&shy;555,556,666,&shy;666,668,688,&shy;586,777,777,&shy;777,777,736,&shy;355,333,333,&shy;355,556,555,&shy;636,666,686,&shy;688,888,557,&shy;777,777,777,&shy;777,565,555,&shy;555,333,555,&shy;566,666,565,&shy;686,666,886,&shy;886,777,777,&shy;777,777,776,&shy;656,888,853,&shy;335,556,686,&shy;556,666,666,&shy;868,886,887,&shy;777,777,777,&shy;777,775,356,&shy;368,532,355,&shy;555,688,666,&shy;866,666,668,&shy;668,877,777,&shy;777,777,777,&shy;732,233,553,&shy;223,323,335,&shy;533,556,666,&shy;686,686,686,&shy;777,777,777,&shy;777,777,323,&shy;333,332,222,&shy;233,332,233,&shy;568,665,666,&shy;656,337,777,&shy;777,777,777,&shy;773,233,333,&shy;322,222,223,&shy;222,223,566,&shy;556,655,533,&shy;777,777,777,&shy;777,777,722,&shy;333,232,222,&shy;222,233,222,&shy;225,665,555,&shy;632,277,777,&shy;777,777,777,&shy;777,323,333,&shy;322,222,223,&shy;222,222,236,&shy;553,553,222,&shy;777,777,777,&shy;777,777,777,&shy;233,232,222,&shy;223,232,222,&shy;223,355,533,&shy;552,277,777,&shy;777,777,777,&shy;777,772,333,&shy;333,222,233,&shy;322,222,223,&shy;353,233,355,&shy;777,777,777,&shy;777,777,777,&shy;723,333,355,&shy;665,533,233,&shy;333,333,322,&shy;335,677,777,&shy;777,777,777,&shy;777,777,735,&shy;533,333,222,&shy;233,333,333,&shy;332,223,356,&shy;777,777,777,&shy;777,777,777,&shy;777,555,333,&shy;232,222,333,&shy;333,333,222,&shy;233,677,777,&shy;777,777,777,&shy;777,777,772,&shy;533,332,222,&shy;222,333,333,&shy;322,222,255,&shy;777,777,777,&shy;777,777,777,&shy;777,775,356,&shy;566,665,553,&shy;333,333,222,&shy;223,557,777,&shy;777,777,777,&shy;777,777,777,&shy;733,335,333,&shy;332,223,333,&shy;332,222,233,&shy;577,777,777,&shy;777,777,777,&shy;777,777,233,&shy;335,332,222,&shy;223,332,322,&shy;222,233,777,&shy;777,777,777,&shy;777,777,777,&shy;777,333,232,&shy;222,222,223,&shy;332,222,222,&shy;237,777,777,&shy;777,777,777,&shy;777,777,773,&shy;222,222,222,&shy;222,223,222,&shy;322,222,377,&shy;777,777,777,&shy;777,777,777,&shy;777,777,222,&shy;222,222,222,&shy;323,332,222,&shy;223,777,777,&shy;777,777,777,&shy;777,777,777,&shy;773,232,222,&shy;222,333,353,&shy;222,222,227,&shy;777,777,777,&shy;777,777,777,&shy;777,777,733,&shy;332,222,223,&shy;355,322,222,&shy;222,277,777,&shy;777,777,777,&shy;777,777,777,&shy;777,755,333,&shy;333,555,533,&shy;222,222,222,&shy;277,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,775,555,&shy;555,322,222,&shy;222,222,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;755,555,533,&shy;222,222,222,&shy;227,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,755,&shy;553,332,222,&shy;222,222,227,&shy;777,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,555,533,&shy;322,222,222,&shy;222,227,777,&shy;777,777,777,&shy;777,777,777,&shy;777,777,773,&shy;553,332,222,&shy;222,222,222,&shy;277,777,777,&shy;777,777,777,&shy;777,777,777,&shy;777,735,533,&shy;322,222,222,&shy;222,222,277,&shy;779,769</p>
<p>although it looks rather better when properly&nbsp;formatted.</p>
<pre style="font-size: 6px; line-height: 3px; letter-spacing: -1px; text-align: center">77777777777777777777777777777777777777777777777777
77777777777777777777777777777777777777777777777777
77777777777777777777777577777777777777777777777777
77777777777777777777775238535686777777777777777777
77777777777777777753522356666886686677777777777777
77777777777777776765555556666856868667777777777777
77777777777777722233566666686668666666577777777777
77777777777773553363588665566666556656557777777777
77777777777733552236666666655665665666555777777777
77777777777727626566666665665555555555553377777777
77777777772532525666666655555565555555655577777777
77777777725222236666565555555556555535355237777777
77777777226672536653555535555555555355353357777777
77777772726373566555555553535355566553553322777777
77777772235775355665553355353535533555555223777777
77777732222225555555635355535533635565353353777777
77777722222255555655553553353553565556553532377777
77777772272355553553355535353365355355553523577777
77777733233356633355355553335535555555535355567777
77777773323555555555555555555535555355556665567777
77777775533355535355553565535353655655555565557777
77777775653355553333535356665535356653565665557777
77777775653535355355533355666665556665685666657777
77777775633535555555555535565556555666566666677777
77777775833333335555565655656586666686665866777777
77777775822333333333555655555666666668686666777777
77777775822333333333535555556666666668688586777777
77777773635533333335555655563666668668888855777777
77777775655555553335555666665656866668868867777777
77777776656888853335556686556666666868886887777777
77777777535636853235555568866686666666866887777777
77777777322335532233233355335566666866866867777777
77777777323333332222233332233568665666656337777777
77777777323333332222222322222356655665553377777777
77777777223332322222222332222256655556322777777777
77777777323333322222223222222236553553222777777777
77777777723323222222323222222335553355227777777777
77777777723333332222333222222233532333557777777777
77777777723333355665533233333333322335677777777777
77777777773553333322223333333333222335677777777777
77777777775553332322223333333332222336777777777777
77777777772533332222222333333322222255777777777777
77777777777535656666555333333322222355777777777777
77777777777333353333322233333322222335777777777777
77777777777233335332222223332322222233777777777777
77777777777733323222222222333222222223777777777777
77777777777732222222222222232223222223777777777777
77777777777777222222222222323332222223777777777777
77777777777777323222222233335322222222777777777777
77777777777777333322222233553222222222777777777777
77777777777777755333333555533222222222277777777777
77777777777777777777555555532222222222277777777777
77777777777777777777555555332222222222277777777777
77777777777777777777755553332222222222227777777777
77777777777777777777755553332222222222222777777777
77777777777777777777735533322222222222222777777777
77777777777777777777735533322222222222222277779769</pre>
<p>I think I&#8217;ll call it the Niamh&nbsp;Prime.</p>silSun, 10 Sep 2017 20:32:00 +0100tag://www.kryogenix.org/days,2017-09-10:2017/09/10/the-niamh-prime/Double Oh Seven//www.kryogenix.org/days/2017/08/24/double-oh-seven/<p>A long time ago, when I was young and you were even younger, gentle reader, we had <a href="https://en.wikipedia.org/wiki/Acorn_Archimedes">Acorn Archimedes</a> computers at school. Back when there was more than one kind of computer. The Arc was great. There will be those who liked the Amiga, or the Atari <span class="caps">ST</span>, but those were basically small toy computers for children. Yes. Long live the&nbsp;Archimedes.</p>
<p>Anyway, for no reason I can discern, this evening I remembered a thing on the Arc; a &#8220;sound demo&#8221;. It was just a looping sample, presented as an app; you ran the app and it played the sample, over and over. It was a short little composition &#8212; a few seconds, only &#8212; made up of different snippets taken from Bond films over a bit of music. This may not seem exciting to you, with your instantly streamable 4K video and stuff, but it was pretty goshdarn exciting back then. Get off my&nbsp;lawn.</p>
<p>I thought to myself: I wonder if that&#8217;s still around? A bit of googling led me to <a href="http://ftp.uni-stuttgart.de/pub/systems/acorn/riscos/CONTENTS">an old archive of <span class="caps">RISC</span> <span class="caps">OS</span> software</a> and there it was: <code>"<a href="http://ftp.uni-stuttgart.de/pub/systems/acorn/riscos/demos/007.spk">007.spk</a>: Sound-demo"</code>. A download later, and then&#8230; what format is it in? <code>file 007.spk</code> says it&#8217;s &#8220;data&#8221;, which is not helpful, because that&#8217;s <code>libmagic</code><span class="quo">&#8216;</span>s codename for &#8220;no idea what this is, dude&#8221;. What&#8217;s an spk file? More googling &#8212; no, it&#8217;s not an installation package for Synology NASes, no it&#8217;s not a design for an electronics board, and then someone mentioned SparkPlug. In those days there were many, many, many compression formats. It&#8217;s not like now where there are basically <span class="caps">ZIP</span> files and occasionally <span class="caps">RAR</span> and tar.gz and that&#8217;s it. There was <span class="caps">ZOO</span>, <span class="caps">LHA</span>, <span class="caps">ARC</span>, loads of them. Zip files were the thing that <span class="caps">PKZIP</span> produced, and that was shareware. Loads of them. And on the Archimedes, everyone used SparkPlug. Actually, it was <a href="https://www.davidpilling.com/spark.html">SparkFS</a>, by David Pilling; you needed that (which cost money) to make Spark archives. But SparkPlug was free, and just did decompression. Unsurprisingly, that never got ported to other platforms, and I was mildly disappointed to discover that my desktop didn&#8217;t know how to open it without being told. But some more googling around led to <a href="https://github.com/mjwoodcock/nspark">nspark</a>, a &#8220;dearchiver for <span class="caps">RISC</span> <span class="caps">OS</span> archives&#8221;. You have to compile it, but by this time I had the bit between my teeth &#8212; digital preservation is <em>everybody&#8217;s</em> responsibility! &#8212; and the <code>COMPILING</code> file says that that&#8217;s literally one command, <code>make -f makefile.gcc</code>. Run that and you get an <code>nspark</code> binary, and <code>nspark 007.spk</code> unpacks it! I have a folder named <code>!James</code>.</p>
<div class="highlight"><pre><span class="gp">$</span> ls !James
<span class="go">MemAlloc !Run !RUNIMAGE !RunImage2 !Sprites</span>
</pre></div>
<p>Arc software came in a folder; if that folder was called <code>!something</code>, then it got treated like a single file you could drag around and run. This is the idea that the Mac used, later, for its application bundles (and I wish Linux software worked that way, but that ship&#8217;s sailed). Anyway, you could click the app and it would actually execute a file named <code>!Run</code>, inside the bundle. That file was a sort of tiny script which would set things up and then normally execute <code>!RunImage</code>, which was your actual compiled program, and indeed that&#8217;s what this one does too. So, <code>!RunImage</code> was the binary&#8230; and <code>!RunImage2</code> was 200K, by far the largest file in the bundle, so the sound sample had to be in there. But&#8230; what format is it? <code>file</code> again claimed that it was &#8220;data&#8221;, but I thought: it&#8217;s a sound sample, right? I bet it&#8217;s just raw sound data. Can it be&nbsp;played?</p>
<p><code>aplay !James/!RunImage2</code> gives a burst of meaningless noise. Hrm. Are there formats for these things? Read the help&#8230; ah, yes, there are. And <code>aplay -f S16_LE</code> plays it understandably, hooray! But that just plays&#8230; how do I make this into an actual modern&nbsp;file?</p>
<p>Aha, again. <a href="http://www.audacityteam.org/">Audacity</a> allows importing raw audio. So, we import it, as a 16-bit set of samples, at sample rate 7600 (8000 sounded a tiny bit fast) and&#8230; success! Save as an mp3, and that works&nbsp;fine.</p>
<p>Not a hugely critical piece of software archaeology, but nice nonetheless. And I know of no better way of backing stuff like this up than to write a blog post about it so that a decade from now when I think of it again, it&#8217;s still here. (We made this mistake with the sound samples from Armadeus; after some serious digging around, <a href="https://whizzy.org">Bill</a> found the one that said &#8220;The mask; the ray-traced picture; and finally, the wireframe city&#8221;, and then we bloody lost it and now I don&#8217;t have it again.) So we&#8217;ll call this one a birthday present for Bill and I&#8217;ll try not to lose it this&nbsp;time.</p>
<p>The <code>!Run</code> file for <code>!007</code> credits a Toby Cole on 25/2/90 and says: <code>well here it is!!</code>. Nice one Toby. From 27 years into your future, here it is&nbsp;again.</p>
<p><audio controls loop>
<source src="https://kryogenix.org/random/007-sound-demo-archimedes.mp3" type="audio/mpeg" />
<source src="https://kryogenix.org/random/007-sound-demo-archimedes.ogg" type="audio/ogg" />
</audio></p>silThu, 24 Aug 2017 23:22:00 +0100tag://www.kryogenix.org/days,2017-08-24:2017/08/24/double-oh-seven/Birmingham tech events in the Alexa Flash Briefing//www.kryogenix.org/days/2017/07/05/birmingham-tech-events-in-the-alexa-flash-briefing/<p>I&#8217;ve got <a href="https://www.kryogenix.org/days/2017/05/28/the-internet-of-unreliable-and-broken-things/">an Amazon Echo Dot</a>, as previously mentioned. One of the things it does is the &#8220;Flash Briefing&#8221;: basically, a personalised news report. You choose &#8220;feeds&#8221; &#8212; places for it to get news &#8212; and then &#8220;Alexa, what&#8217;s new?&#8221; will read them out. I&#8217;ve got the <span class="caps">BBC</span> and the Birmingham weather report enabled. But I&#8217;d also like to know what&#8217;s going on in town; specifically, the <a href="https://calendar.birmingham.io">Birmingham.<span class="caps">IO</span> calendar</a> lists the tech events in the city and I wanted my Flash Briefing to tell me about&nbsp;them.</p>
<p>Well, now it does,&nbsp;handily. </p>
<p><audio controls>
<source src="https://raw.githubusercontent.com/stuartlangridge/bio-calendar-flashbriefing/master/bio-alexa.mp3">
<source src="https://raw.githubusercontent.com/stuartlangridge/bio-calendar-flashbriefing/master/bio-alexa.ogg">
<a href="https://raw.githubusercontent.com/stuartlangridge/bio-calendar-flashbriefing/master/bio-alexa.mp3">play mp3</a>
</audio></p>
<p>To add these to <em>your</em> Flash Briefing, search for &#8220;Birmingham.<span class="caps">IO</span>&#8221; in the Skills section of the Alexa app, or enable this skill in the <a href="https://www.amazon.co.uk/dp/B073PF3RKK/ref=sr_1_1?s=digital-skills&amp;ie=UTF8&amp;qid=1499242293&amp;sr=1-1&amp;keywords=birmingham.io">online Alexa Skills Store</a>.</p>
<p>That was actually quite fun to do! There are some details of how it works in the <a href="https://github.com/stuartlangridge/bio-calendar-flashbriefing">source</a>. Thank you to <a href="https://surge.sh">surge.sh</a> for giving me a place to deploy it which is <span class="caps">HTTPS</span> (as Alexa requires) and not Let&#8217;s Encrypt (which, moronically, <a href="https://forums.developer.amazon.com/questions/64875/german-flash-briefing-not-workign-with-lets-encryp.html#comment-67966">Alexa doesn&#8217;t like</a>). Questions and suggestions for improvement should be directed to <a href="https://talk.birmingham.io/t/alexa-whats-new-from-the-birmingham-io-calendar-upcoming-tech-events-are/3401/1">the birmingham.io forum post</a>. I submitted the skill and it was reviewed and accepted 24 hours later, which is nice. And there&#8217;s a promotion going on right now in the <span class="caps">UK</span> where if you submit a new skill during July 2017 then <a href="https://developer.amazon.com/en-gb/alexa-skills-kit/alexa-developer-skill-promotion">you get an Echo Dot</a>, so maybe I&#8217;ll have two! Which is also pretty cool. So, what&#8217;s on tonight,&nbsp;Alexa?</p>silWed, 05 Jul 2017 09:31:00 +0100tag://www.kryogenix.org/days,2017-07-05:2017/07/05/birmingham-tech-events-in-the-alexa-flash-briefing/The Fleb 100K Special//www.kryogenix.org/days/2017/06/12/the-fleb-100k-special/<p><a href="http://flebpuzzles.com">Fleb</a> reviews mechanical puzzles on YouTube. I subscribe to his <a href="https://www.youtube.com/channel/UCTlGuNR-3QM0PMPNCAcAX2w/">puzzle review channel</a> and it’s jolly interesting. Today, in celebration of his hitting 100,000 subscribers<sup id="sf-the-fleb-100k-special-1-back"><a title="nice one Fleb; a hundred thousand! sweet!" class="simple-footnote" href="#sf-the-fleb-100k-special-1">1</a></sup>, he published <a href="https://www.youtube.com/watch?v=3yLavi3-dy4">a video</a> reviewing the <a href="https://www.artofplay.com/collections/puzzles/products/small-puzzle-box-3">Mini Puzzle Box</a> (sold out, as I write this) and, more intriguingly, a link to a “100k special”, a puzzle produced by Fleb for viewers to look at. It’s at <a href="http://www.flebpuzzles.com/100kspecial">www.flebpuzzles.com/100kspecial</a><sup id="sf-the-fleb-100k-special-2-back"><a title="since the website was down when I started writing this, I pinged Fleb and said: install WP Super Cache and talk to your hosting provider, and I added a mirror of puzzle 1’s text in a youtube comment" class="simple-footnote" href="#sf-the-fleb-100k-special-2">2</a></sup> and it presents the first in a series of four puzzles, for channel viewers.</p>
<p>These are “Puzzle Hunt”-style puzzles; that is, the answer to the puzzle is a word or phrase. Here, I’ll show you how I solved each. Be warned: if you’re looking to solve these yourself, stop reading now. Really.</p>
<h2>The Opening</h2>
<p>Puzzle 1, at <a href="http://www.flebpuzzles.com/100kspecial">www.flebpuzzles.com/100kspecial</a>, is entitled “The Opening” and consists of a number of clues about puzzles. Each of these clues indicates a puzzle which has been reviewed on <a href="https://www.youtube.com/channel/UCTlGuNR-3QM0PMPNCAcAX2w/">Fleb’s channel</a>, but with a single letter alteration. The bracketed letters indicate the length of the puzzle name. So, to make a start on solving this, list all the puzzles reviewed on the channel with the length of the puzzle names, and that’ll help. For example, “This puzzle was about the pigs owned by one of the United States’ greatest presidents. I think it was called the (7 4) puzzle!” suggests <a href="https://www.youtube.com/watch?v=9xpi1f9t6nY">The Lincoln Logs Puzzle</a> because its name is of length 7 and 4 (“Lincoln Logs”).</p>
<p>But the clue mentions pigs, and there are no pigs involved? What gives? Well, this is the next step; each puzzle name has a letter changed in it to better match the clue. So <span class="caps">LINCOLN</span> <span class="caps">LOGS</span> becomes <span class="caps">LINCOLN</span> <span class="caps">HOGS</span>, and now it’s about the pigs owned by an American President… and the changed letter is “H”. That’s important. The clues in order have these answers:</p>
<table>
<tbody><tr><td>…the last moment of a punch (4 3)</td><td><del><span class="caps">CAST</span> <span class="caps">BOX</span></del> <ins><span class="caps">WIT</span>’S <span class="caps">END</span></ins></td><td><del><span class="caps">CAS</span><strong>H</strong> <span class="caps">BOX</span></del><sup id="sf-the-fleb-100k-special-3-back"><a title="" class="simple-footnote" href="#sf-the-fleb-100k-special-3">3</a></sup> <ins><strong>H</strong><span class="caps">IT</span>’S <span class="caps">END</span></ins><sup id="sf-the-fleb-100k-special-4-back"><a title="Thank you to JDiMase8 for the correction!" class="simple-footnote" href="#sf-the-fleb-100k-special-4">4</a></sup></td></tr>
<tr><td>…a small chirping insect which is located directly to the right of the solver (4 7)</td><td><span class="caps">CAST</span> <span class="caps">CRICKET</span></td><td><strong>E</strong><span class="caps">AST</span> <span class="caps">CRICKET</span></td></tr>
<tr><td>…the strange hybrid of a young man and a buzzing insect (3 3)</td><td><span class="caps">BEE</span> <span class="caps">BOX</span></td><td><span class="caps">BEE</span> <span class="caps">BO</span><strong>Y</strong></td></tr>
<tr><td>…a four sided geometric shape embedded in something found on a piece of clothing or a mattress (6 2 3 3)</td><td><span class="caps">SQUARE</span> <span class="caps">IN</span> <span class="caps">THE</span> <span class="caps">BAG</span></td><td><span class="caps">SQUARE</span> <span class="caps">IN</span> <span class="caps">THE</span> <strong>T</strong><span class="caps">AG</span></td></tr>
<tr><td>…the pigs owned by one of the United States’ greatest presidents (7 4)</td><td><span class="caps">LINCOLN</span> <span class="caps">LOGS</span></td><td><span class="caps">LINCOLN</span> <strong>H</strong><span class="caps">OGS</span></td></tr>
<tr><td>…a rectangular tile and something that connects two points (5 <span class="amp">&amp;</span> 4)</td><td><span class="caps">PANEL</span> <span class="amp">&amp;</span> <span class="caps">LING</span></td><td><span class="caps">PANEL</span> <span class="amp">&amp;</span> <span class="caps">LIN</span><strong>E</strong></td></tr>
<tr><td>…a score of payments for monthly living accommodations (2 4 9)</td><td>20 <span class="caps">CENT</span> <span class="caps">PUZZLEBOX</span></td><td>20 <strong>R</strong><span class="caps">ENT</span> <span class="caps">PUZZLEBOX</span></td></tr>
<tr><td>…a spiral (4)</td><td><span class="caps">GYRO</span></td><td><span class="caps">GYR</span><strong>E</strong></td></tr>
<tr><td>…a brave machine that tells you how long you have until you have to move your car. It was near the sea (4 5 7 5)</td><td><span class="caps">GOLD</span> <span class="caps">COAST</span> <span class="caps">PARKING</span> <span class="caps">METER</span></td><td><strong>B</strong><span class="caps">OLD</span> <span class="caps">COAST</span> <span class="caps">PARKING</span> <span class="caps">METER</span></td></tr>
<tr><td>…the final, cute, regular three dimensional figure with all edges the same side (4 4)</td><td><span class="caps">CAST</span> <span class="caps">CUBY</span></td><td><strong>L</strong><span class="caps">AST</span> <span class="caps">CUBY</span></td></tr>
<tr><td>…a light source that was run on a black rock (4 2 4)</td><td><span class="caps">LUMP</span> <span class="caps">OF</span> <span class="caps">COAL</span></td><td>L<strong>A</strong><span class="caps">MP</span> <span class="caps">OF</span> <span class="caps">COAL</span></td></tr>
<tr><td>…a man who checks gas gauges (9) </td><td><span class="caps">METERMASS</span></td><td>??<sup id="sf-the-fleb-100k-special-5-back"><a title="from context, this is obviously an N, but how does it match the clue? METERMANS? But that’d be more than one man. A “gas gauge” is presumably a METER, so is a man who checks them a METERNASS? Maybe a METERMASN? Another one I don’t fully understand." class="simple-footnote" href="#sf-the-fleb-100k-special-5">5</a></sup> (<strong>N</strong>)</td></tr>
<tr><td>…small breads designed for small cats (6 8)</td><td><span class="caps">BITTEN</span> <span class="caps">BISCUITS</span></td><td><strong>K</strong><span class="caps">ITTEN</span> <span class="caps">BISCUITS</span></td></tr>
</tbody></table>
<p>Take all the changed letters in order and you get <strong><span class="caps">HEY</span> <span class="caps">THERE</span> <span class="caps">BLANK</span></strong><sup id="sf-the-fleb-100k-special-6-back"><a title="well, you get _EY THERE BLA_K, and then you ping Fleb for help because you don’t get it" class="simple-footnote" href="#sf-the-fleb-100k-special-6">6</a></sup>. And the puzzle’s named “The Opening”, and how does Fleb open every video? With “Hey there, puzzlers!”. So <span class="caps">BLANK</span> is <span class="caps">PUZZLERS</span>, and our link to the second puzzle of the 100K special must therefore be <a href="http://www.flebpuzzles.com/PUZZLERS">www.flebpuzzles.com/<span class="caps">PUZZLERS</span></a>.</p>
<h2>The Spoiler Break</h2>
<p>This second puzzle has a bunch of pictures where each picture has an associated phrase, and then separately a list of clues for “spoilers” from film and <span class="caps">TV</span> history. Our job is to match up the phrases with the spoilers, and that will give us the pictures in order.</p>
<p>Each picture is a 7×2 grid in which one or more coloured squares is placed: one example (the first example) looks roughly like this:</p>
<p><img src="https://kryogenix.org/images/fleb100k/d1.svg" alt="" class="fleb-smaller"></p>
<p>So first, the list of spoiler clues and their answers<sup id="sf-the-fleb-100k-special-7-back"><a title="warning! spoilers" class="simple-footnote" href="#sf-the-fleb-100k-special-7">7</a></sup>:</p>
<ul>
<li>He killed Dumbledore: <strong><span class="caps">SNAPE</span></strong> (from the Harry Potter series)</li>
<li>He was dead the whole time: <strong><span class="caps">BRUCE</span></strong> (Willis from The Sixth Sense)</li>
<li>He never existed and was a figment of the imagination: <strong><span class="caps">TYLER</span></strong> (Durden from Fight Club)</li>
<li>It was his sled’s name: <strong><span class="caps">ROSEBUD</span></strong> (from Citizen Kane)</li>
<li>It was this planet the whole time: <strong><span class="caps">EARTH</span></strong> (from Planet of the Apes)</li>
<li>He was Keyser Soze: <strong><span class="caps">VERBAL</span></strong><sup id="sf-the-fleb-100k-special-8-back"><a title="Láttam a Keyser Söze-t! Te nem értesz?! Keyser Söze!! " class="simple-footnote" href="#sf-the-fleb-100k-special-8">8</a></sup> (from the Usual Suspects)</li>
<li>She shot <span class="caps">JR</span>: <strong><span class="caps">KRISTEN</span></strong><sup id="sf-the-fleb-100k-special-9-back"><a title="not Sue Ellen, which is who I thought it was until I looked it up" class="simple-footnote" href="#sf-the-fleb-100k-special-9">9</a></sup> (from Dallas)</li>
<li>He is the one: <strong><span class="caps">NEO</span></strong> (from The Matrix)</li>
</ul>
<p>Now we pair those answers with the picture clues:</p>
<ul>
<li><span class="caps">BGREED</span> <span class="caps">BAUSE</span> <span class="caps">BN</span> <span class="caps">BIGHTING</span>: <span class="caps">BRUCE</span> (the phrase “Agreed pause in fighting → Truce” with initial letters all replaced by B)</li>
<li><span class="caps">FLOWERBUD</span> <span class="caps">WITBID</span> <span class="caps">THORNBUD</span>: <span class="caps">ROSEBUD</span> (the phrase “Flowers with thorns → Roses” with final S replaced by <span class="caps">BUD</span> in each word)</li>
<li><span class="caps">DOUGHNTIN</span> <span class="caps">SHTIN</span> ______ <span class="caps">KRETIN</span>: <span class="caps">KRISTIN</span> (the phrase “Doughnut shop Krispy Kreme” with the final two letters of each word replaced by <span class="caps">TIN</span>)</li>
<li><span class="caps">LETTEREO</span> <span class="caps">AFTEREO</span> <span class="caps">MEO</span>: <span class="caps">NEO</span> (letter+eo after+eo m+eo → letter after m + eo → n+eo → neo)</li>
<li><span class="caps">NOMPKOP</span> <span class="caps">REBPUN</span> <span class="caps">YTNPWT</span> <span class="caps">EERPT</span>: <del>(don’t know)</del><ins>reverse to give <span class="caps">POKEMON</span> <span class="caps">NUMBER</span> <span class="caps">TWENTY</span> <span class="caps">THREE</span> with letters replaced by P; Pokemon 23 is <span class="caps">EKANS</span>, so reverse and replace one letter by P to give <span class="caps">SNAPE</span></ins></li>
<li><span class="caps">LOOR</span> <span class="caps">ROUND</span> <span class="caps">IREPLACE</span>: <span class="caps">EARTH</span> (the phrase “floor around fireplace: hearth” with initial letters all removed)</li>
<li><span class="caps">LYLGE</span> <span class="caps">SYLIPED</span> <span class="caps">CYL</span>: <del>(don’t know)</del><ins><span class="caps">LARGE</span> <span class="caps">STRIPED</span> <span class="caps">CAT</span> with pairs replaced by <span class="caps">YL</span>; replace “ig” with “yl” in <span class="caps">TIGER</span> to give <span class="caps">TYLER</span></ins></li>
<li><span class="caps">VYPE</span> <span class="caps">VF</span> <span class="caps">VEA</span>: <span class="caps">VERBAL</span> (the phrase “type of tea: herbal” with initial letters all replaced by V)</li>
</ul>
<p>This gives us an ordering of (<span class="caps">SNAPE</span>/<span class="caps">TYLER</span>) <span class="caps">BRUCE</span> (<span class="caps">SNAPE</span>/<span class="caps">TYLER</span>) <span class="caps">ROSEBUD</span> <span class="caps">EARTH</span> <span class="caps">VERBAL</span> <span class="caps">KRISTIN</span> <span class="caps">NEO</span>. <del>It’s not clear to me which clues the <span class="caps">SNAPE</span> and <span class="caps">TYLER</span> answers match with and why.</del><sup id="sf-the-fleb-100k-special-10-back"><a title="One of the nice things about Puzzle-Hunt-style puzzles is that you don’t necessarily have to have worked out every step in order to get the answer; you’ll see that in both this puzzle and the first one I deduced some parts of the answer from context without actually having a proper solution for the clue which gives that part of the answer" class="simple-footnote" href="#sf-the-fleb-100k-special-10">10</a></sup> We’ll go with <span class="caps">SNAPE</span> first and <span class="caps">TYLER</span> third, because that makes the below answer work.<sup id="sf-the-fleb-100k-special-11-back"><a title="" class="simple-footnote" href="#sf-the-fleb-100k-special-11">11</a></sup> So we can take the pictures in that order:</p>
<style>
p > img.fleb-smaller:first-child:last-child:not([style]) { max-width: 60%; box-shadow: none }
</style>
<p><img src="https://kryogenix.org/images/fleb100k/d5.svg" alt="" class="fleb-smaller"></p>
<p><img src="https://kryogenix.org/images/fleb100k/d1.svg" alt="" class="fleb-smaller"></p>
<p><img src="https://kryogenix.org/images/fleb100k/d7.svg" alt="" class="fleb-smaller"></p>
<p><img src="https://kryogenix.org/images/fleb100k/d2.svg" alt="" class="fleb-smaller"></p>
<p><img src="https://kryogenix.org/images/fleb100k/d6.svg" alt="" class="fleb-smaller"></p>
<p><img src="https://kryogenix.org/images/fleb100k/d8.svg" alt="" class="fleb-smaller"></p>
<p><img src="https://kryogenix.org/images/fleb100k/d3.svg" alt="" class="fleb-smaller"></p>
<p><img src="https://kryogenix.org/images/fleb100k/d4.svg" alt="" class="fleb-smaller"></p>
<p>and if we plot the lines drawn by the different colours then we get the following four coloured tracks:</p>
<p><img src="https://kryogenix.org/images/fleb100k/dl.svg" alt="" class="fleb-smaller"></p>
<p><img src="https://kryogenix.org/images/fleb100k/do1.svg" alt="" class="fleb-smaller"></p>
<p><img src="https://kryogenix.org/images/fleb100k/do2.svg" alt="" class="fleb-smaller"></p>
<p><img src="https://kryogenix.org/images/fleb100k/dt.svg" alt="" class="fleb-smaller"></p>
<p>or, slightly fancifully:</p>
<p><img src="https://kryogenix.org/images/fleb100k/dloot.svg" alt=""></p>
<p>the word <span class="caps">LOOT</span>, leading us to puzzle 3 at <a href="http://www.flebpuzzles.com/LOOT/">flebpuzzles.com/<span class="caps">LOOT</span></a>.</p>
<h2>The Solution</h2>
<p><span class="caps">OK</span>, it’s becoming apparent that these puzzles are named after the stages of a Fleb puzzle review: the first puzzle was named <em>the opening</em>, the second <em>the spoiler break</em>, and now <em>the solution</em>. This third puzzle has a series of letter grids, each of which apparently matches with a clue. The letter grids are:</p>
<style>
table.fleb-wordgrid {
width: auto;
margin: 0 auto 1em;
}
table.fleb-wordgrid td {
border: 2px solid black;
width: 2em;
max-width: 18%;
height: 2em;
text-align: center;
line-height: 2em;
padding: 0;
}
</style>
<table class="fleb-wordgrid">
<tbody><tr><td>G</td><td>N</td><td><span class="caps">ME</span></td><td><span class="caps">AT</span></td><td>Y</td></tr>
<tr><td><span class="caps">PL</span></td><td><span class="caps">AT</span></td><td>G</td><td>R</td><td>O</td></tr>
<tr><td>S</td><td>A</td><td>E</td><td><span class="caps">BO</span></td><td><span class="caps">ION</span></td></tr>
<tr><td><span class="caps">GE</span></td><td><span class="caps">AY</span></td><td>U</td><td><span class="caps">SI</span></td><td>N</td></tr>
<tr><td>N</td><td><span class="caps">EO</span></td><td><span class="caps">ST</span></td><td>E</td><td>S</td></tr>
</tbody></table>
<table class="fleb-wordgrid">
<tbody><tr><td>G</td><td><span class="caps">OL</span></td><td><span class="caps">HN</span></td><td><span class="caps">TE</span></td><td><span class="caps">LT</span></td></tr>
<tr><td>R</td><td>O</td><td><span class="caps">SE</span></td><td>N</td><td>R</td></tr>
<tr><td>C</td><td><span class="caps">OO</span></td><td>R</td><td>D</td><td>T</td></tr>
<tr><td><span class="caps">CO</span></td><td>R</td><td>I</td><td><span class="caps">VE</span></td><td>N</td></tr>
<tr><td>J</td><td>A</td><td>A</td><td><span class="caps">SO</span></td><td><span class="caps">GE</span></td></tr>
</tbody></table>
<table class="fleb-wordgrid">
<tbody><tr><td><span class="caps">LA</span></td><td><span class="caps">AR</span></td><td>I</td><td><span class="caps">TI</span></td><td>Y</td></tr>
<tr><td>D</td><td>R</td><td><span class="caps">IG</span></td><td><span class="caps">ND</span></td><td>D</td></tr>
<tr><td>M</td><td>V</td><td>E</td><td>I</td><td><span class="caps">ON</span></td></tr>
<tr><td>O</td><td><span class="caps">RN</span></td><td>A</td><td>S</td><td><span class="caps">LD</span></td></tr>
<tr><td><span class="caps">CA</span></td><td>A</td><td><span class="caps">CH</span></td><td>O</td><td><span class="caps">ER</span></td></tr>
</tbody></table>
<table class="fleb-wordgrid">
<tbody><tr><td>S</td><td>C</td><td>I</td><td><span class="caps">NI</span></td><td><span class="caps">LL</span></td></tr>
<tr><td><span class="caps">BA</span></td><td>E</td><td>K</td><td>N</td><td><span class="caps">ER</span></td></tr>
<tr><td>T</td><td>S</td><td>C</td><td>E</td><td>G</td></tr>
<tr><td><span class="caps">HO</span></td><td>X</td><td>E</td><td>C</td><td>S</td></tr>
<tr><td><span class="caps">BO</span></td><td>O</td><td>N</td><td><span class="caps">BA</span></td><td>Y</td></tr>
</tbody></table>
<p>and the clues (of which more later) make it fairly obvious that we’re supposed to extract multiple words from each grid and then use that to work out which clue applies to each grid. Well, I stared at this for a long, long time, trying to find words in the grids, see what the deal was, and so on. The implication from the clues is that we should be extracting at least five words from each grid (one clue refers to “the fourth word”, and then “the final word”, so “final” is more than four) and it’s hard to see how one could consistently remove six or more words from a 5×5 grid, so I figured I was looking for five words. I got nowhere with this for quite some time until it occurred to me that I could brute-force it and see if that gave me an answer. Slightly off the pure puzzler mindset, but, hey, computers are handy. So I wrote <a href="https://gist.github.com/stuartlangridge/2ba6666cf665b575754669c6970039a8">a little program</a> that tried every combination of letters from the grids, in this way: we assume that each word takes its first letter(s) from column 1, its second letter(s) from column 2, and so on. So in the fourth grid, above, a word might be S-C-I-<span class="caps">NI</span>-<span class="caps">LL</span> or S-E-K-N-<span class="caps">ER</span> or S-X-N-N-Y or something else… and was it possible to decompose a grid this way into five separate words which used up all the letters?</p>
<p>Well, yes it is. My little script printed out this:</p>
<ul>
<li>For grid 2: <span class="caps">CARTER</span>, <span class="caps">COOLIDGE</span>, <span class="caps">GRANT</span>, <span class="caps">JOHNSON</span>, <span class="caps">ROOSEVELT</span></li>
<li>For grid 3: <span class="caps">CARNATION</span>, <span class="caps">DAISY</span>, <span class="caps">LAVENDER</span>, <span class="caps">MARIGOLD</span>, <span class="caps">ORCHID</span></li>
<li>For grid 4: <span class="caps">BASEBALL</span>, <span class="caps">BOXING</span>, <span class="caps">HOCKEY</span>, <span class="caps">SOCCER</span>, <span class="caps">TENNIS</span></li>
</ul>
<p><img src="https://kryogenix.org/images/fleb100k/fleb3words.png" alt=""></p>
<p>Nothing for grid 1, but that’s probably down to its dictionary. So this helps a lot! I was honestly surprised at how successful that was. The clues look like this:</p>
<ul>
<li><span class="caps">LOTUS</span>: Take the 1st letter of the 4th answer and the second to last letter of the final answer.</li>
<li><span class="caps">CAST</span> <span class="caps">CRICKET</span>: Take the 3rd letter of the 2nd answer and the 1st letter of the final answer.</li>
<li><span class="caps">XBOX</span>: Take the 4th and 5th letters of the last answer.</li>
<li><span class="caps">LINCOLN</span> <span class="caps">LOGS</span>: Take the 5th letter of the 1st answer and the 4th letter of the last answer.</li>
</ul>
<p>and they pretty clearly match up:</p>
<ul>
<li><span class="caps">LOTUS</span> matches grid 3 (flowers, like a lotus), so <strong>M</strong>arigold + orch<strong>I</strong>d</li>
<li><span class="caps">CAST</span> <span class="caps">CRICKET</span> matches grid 4 (sports), so bo<strong>X</strong>ing + <strong>T</strong>ennis</li>
<li><span class="caps">XBOX</span>… we’ll come back to</li>
<li>and <span class="caps">LINCOLN</span> <span class="caps">LOGS</span> matches grid 2 (<span class="caps">US</span> president names), so cart<strong>E</strong>r + roo<strong>S</strong>evelt</li>
</ul>
<p>But what of grid 1, matching <span class="caps">XBOX</span>? Well, knowing now that it’s <em>about</em> the XBox it’s pretty quick to decompose the square by hand into <span class="caps">GAMEBOY</span>, <span class="caps">GENESIS</span><sup id="sf-the-fleb-100k-special-12-back"><a title="Americans, eh? Tch. It’s called a Sega Megadrive, yes it is" class="simple-footnote" href="#sf-the-fleb-100k-special-12">12</a></sup>, <span class="caps">NEOGEO</span>, <span class="caps">PLAYSTATION</span>, <span class="caps">SATURN</span><sup id="sf-the-fleb-100k-special-13-back"><a title="and now you see why my script didn’t get it; not many dictionaries have “neogeo” as a word" class="simple-footnote" href="#sf-the-fleb-100k-special-13">13</a></sup> and so its letters are sat<strong><span class="caps">UR</span></strong>n. And so our whole word for this puzzle is <span class="caps">MI</span>+<span class="caps">XT</span>+<span class="caps">UR</span>+<span class="caps">ES</span>, leading us to puzzle 4 at <a href="http://www.flebpuzzles.com/MIXTURES/">flebpuzzles.com/<span class="caps">MIXTURES</span></a>.</p>
<h2>The Comment Section</h2>
<p>So, for this fourth puzzle, we’re confronted with a set of eight images. Since I’m now pretty familiar with Fleb’s selection of puzzle reviews, these images look like they’re each portraying a word I recognise; they are <span class="caps">DEVIL</span>, some knots which I think clues <span class="caps">FIGURE</span> <span class="caps">EIGHT</span>, <span class="caps">COAL</span>, <span class="caps">LOTUS</span>, <span class="caps">HORSESHOE</span>, <span class="caps">GYRO</span>, <span class="caps">SQUARE</span>, and <span class="caps">BEE</span>, each of which is relevant to a reviewed puzzle. Fleb also says at the top of this puzzle: “Don’t forget to respond to comments on old videos! It’ll help to pin the best ones!”, hinting that the comments section for these puzzles may have some extra hints. And indeed it does; Fleb has pinned a comment on each of these videos, reading as follows:</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=WKX3VVB8lGw"><span class="caps">DEVIL</span></a>: “-[opposite of good]﻿”</li>
<li><a href="https://www.youtube.com/watch?v=FZqYxmbjvKc"><span class="caps">FIGURE</span> <span class="caps">EIGHT</span></a>: “-[black ball number] -[small carpet] -[chemical symbol for iron]﻿”</li>
<li><a href="https://www.youtube.com/watch?v=8cVJCaye1ns"><span class="caps">COAL</span></a>: “-[centilitre, for short] -[universal donor blood type]﻿”</li>
<li><a href="https://www.youtube.com/watch?v=ofse2Y8MB4s"><span class="caps">LOTUS</span></a>: “-[remove from power]﻿”</li>
<li><a href="https://www.youtube.com/watch?v=D-hKTGl2kys"><span class="caps">HORSESHOE</span></a>: “-[Kentucky Derby racer] -[female pronoun]﻿”</li>
<li><a href="https://www.youtube.com/watch?v=VcCyWLMYw18&amp;t=11s"><span class="caps">GYRO</span></a>: “-[cowboy Rogers]﻿”</li>
<li><a href="https://www.youtube.com/watch?v=hTWIokjzeH0"><span class="caps">SQUARE</span></a>: “-[they might be burning] -[17th letter]﻿”</li>
<li><a href="https://www.youtube.com/watch?v=35WhEcCTbdU"><span class="caps">BEE</span></a>: “-[exist]﻿”</li>
</ul>
<p>And, obviously, each comment is a clue to remove some letters from each of the puzzle clues. So <span class="caps">DEVIL</span> - <span class="caps">EVIL</span> (the opposite of good) gives <strong>D</strong>. The others:</p>
<ul>
<li><span class="caps">FIGURE</span> <span class="caps">EIGHT</span> - <span class="caps">EIGHT</span> - <span class="caps">RUG</span> - <span class="caps">FE</span> → <strong>I</strong></li>
<li><span class="caps">COAL</span> - <span class="caps">CL</span> - O → <strong>A</strong></li>
<li><span class="caps">LOTUS</span> - <span class="caps">OUST</span> → <strong>L</strong></li>
<li><span class="caps">HORSESHOE</span> - <span class="caps">HORSE</span> - <span class="caps">SHE</span> → <strong>O</strong></li>
<li><span class="caps">GYRO</span> - <span class="caps">ROY</span> → <strong>G</strong></li>
<li><span class="caps">SQUARE</span> - <span class="caps">EARS</span> - Q → <strong>U</strong></li>
<li><span class="caps">BEE</span> - <span class="caps">BE</span> → <strong>E</strong></li>
</ul>
<p>and so our final puzzle word and the link to the solution is <a href="http://www.flebpuzzles.com/DIALOGUE"><span class="caps">DIALOGUE</span></a>.</p>
<p>If you’ve got thoughts or responses to all this, or answers to the couple of clues I didn’t understand, or want to chat more, best to reply to <a href="https://www.youtube.com/watch?v=3yLavi3-dy4&amp;lc=z12usvbzlkbgefgvt22qudshituzyxg5e04">my YouTube comment</a> linking to these solutions on Fleb’s announcement video, <a href="https://www.youtube.com/watch?v=3yLavi3-dy4&amp;lc=z12usvbzlkbgefgvt22qudshituzyxg5e04">here</a>!</p>
<p>Thank you to Fleb for this fun set of puzzles, and congrats on the milestone. What’s next?</p><ol class="simple-footnotes"><li id="sf-the-fleb-100k-special-1">nice one Fleb; a hundred thousand! sweet! <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-1-back">↩</a></li><li id="sf-the-fleb-100k-special-2">since the website was down when I started writing this, I pinged Fleb and said: install <span class="caps">WP</span> Super Cache and talk to your hosting provider, and I added a mirror of puzzle 1’s text in <a href="https://www.youtube.com/watch?v=3yLavi3-dy4&amp;lc=z12zhvoqplj4ef4ok04cevdb1pvbfzvpkpc0k">a youtube comment</a> <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-2-back">↩</a></li><li id="sf-the-fleb-100k-special-3"><del>the letter is definitely H, but I’m pretty dubious about my solution; “a punch” is obviously <span class="caps">BOX</span>, but is “the last moment” <span class="caps">CASH</span>? Should it be <span class="caps">HAST</span>? <span class="caps">CHST</span>? <span class="caps">CASH</span> is the best I can come up with, but I’m not really sure why it’s the answer</del> <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-3-back">↩</a></li><li id="sf-the-fleb-100k-special-4">Thank you to <a href="https://www.youtube.com/watch?v=3yLavi3-dy4&amp;lc=z13yuvyaymqtsndp404cdfj5xujfghhrmts0k.1497495200095540">JDiMase8</a> for the correction! <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-4-back">↩</a></li><li id="sf-the-fleb-100k-special-5">from context, this is obviously an N, but how does it match the clue? <span class="caps">METERMANS</span>? But that’d be more than one man. A “gas gauge” is presumably a <span class="caps">METER</span>, so is a man who checks them a <span class="caps">METERNASS</span>? Maybe a <span class="caps">METERMASN</span>? Another one I don’t fully understand. <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-5-back">↩</a></li><li id="sf-the-fleb-100k-special-6">well, you get _EY <span class="caps">THERE</span> BLA_K, and then you ping Fleb for help because you don’t get it <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-6-back">↩</a></li><li id="sf-the-fleb-100k-special-7">warning! spoilers <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-7-back">↩</a></li><li id="sf-the-fleb-100k-special-8">Láttam a Keyser Söze-t! Te nem értesz?! Keyser Söze!! <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-8-back">↩</a></li><li id="sf-the-fleb-100k-special-9">not Sue Ellen, which is who I thought it was until I looked it up <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-9-back">↩</a></li><li id="sf-the-fleb-100k-special-10">One of the nice things about Puzzle-Hunt-style puzzles is that you don’t necessarily have to have worked out every step in order to get the answer; you’ll see that in both this puzzle and the first one I deduced some parts of the answer from context without actually having a proper solution for the clue which <em>gives</em> that part of the answer <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-10-back">↩</a></li><li id="sf-the-fleb-100k-special-11"><del>Suggestions as to <em>why</em> <span class="caps">LYLGE</span> <span class="caps">SYLIPED</span> <span class="caps">CYL</span> clues <span class="caps">TYLER</span> (lots of Ys in there), or <span class="caps">NOMPKOP</span> <span class="caps">REBPUN</span> <span class="caps">YTNPWT</span> <span class="caps">EERPT</span> clues <span class="caps">SNAPE</span>, are invited</del><ins>Suggestions and hints were received from <a href="https://www.youtube.com/watch?v=3yLavi3-dy4&amp;lc=z13yuvyaymqtsndp404cdfj5xujfghhrmts0k.1497614572708385">Angus Mills</a>, <a href="https://www.youtube.com/watch?v=3yLavi3-dy4&amp;lc=z13yuvyaymqtsndp404cdfj5xujfghhrmts0k.1497650784074770">Robertlavigne1</a>, and <a href="https://www.youtube.com/watch?v=3yLavi3-dy4&amp;lc=z13yuvyaymqtsndp404cdfj5xujfghhrmts0k.1497670720621937"><span class="caps">PANICFAN1227</span></a>, for which many thanks!</ins> <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-11-back">↩</a></li><li id="sf-the-fleb-100k-special-12">Americans, eh? Tch. It’s called a Sega Megadrive, yes it is <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-12-back">↩</a></li><li id="sf-the-fleb-100k-special-13">and now you see why my script didn’t get it; not many dictionaries have “neogeo” as a word <a class="simple-footnote-back" href="#sf-the-fleb-100k-special-13-back">↩</a></li></ol>silMon, 12 Jun 2017 00:53:00 +0100tag://www.kryogenix.org/days,2017-06-12:2017/06/12/the-fleb-100k-special/The internet of unreliable and broken things//www.kryogenix.org/days/2017/05/28/the-internet-of-unreliable-and-broken-things/<p>or, 24 hours with Alexa.</p>
<p>So I got myself an Amazon Echo Dot. Because I got an Amazon voucher<sup id="sf-the-internet-of-unreliable-and-broken-things-1-back"><a title="from Crunch, my accountants, after I referred someone who signed up; that someone got an Amazon voucher too! So if you are looking for an accountant, do so by following this shameless referral link and I can buy more stuff!)" class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-1">1</a></sup> and then asked The <a href="http://popey.com">High</a> <a href="http://whizzy.org">Council</a> On Interesting Electronic Stuff what I should get with it and they said: get an Echo Dot, come on in, the water’s lovely.</p>
<p>I have had reservations about this sort of thing in the past, I must admit.<sup id="sf-the-internet-of-unreliable-and-broken-things-2-back"><a title="People who listen to Bad Voltage will know what I’m talking about here." class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-2">2</a></sup> But I’m semi-convinced by the idea that nothing gets sent out without the wake word being heard. I’m interested in chat interfaces; that’s why I wrote <a href="https://www.kryogenix.org/days/2015/11/19/no-ui-is-some-ui/">No <span class="caps">UI</span> is Some <span class="caps">UI</span></a>, and why I’ve delivered <a href="https://kryogenix.org/code/the-ux-of-text-fusion/">The <span class="caps">UX</span> of Text</a> talk at a <a href="https://www.fusionmeetup.com/">couple</a> of <a href="http://hydrahack.co.uk/">conferences</a>.<sup id="sf-the-internet-of-unreliable-and-broken-things-3-back"><a title="if you’d like me to deliver this talk at your conference, let me know" class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-3">3</a></sup> And I’m sick of waiting for my <a href="https://mycroft.ai/">Mycroft</a> and also not very convinced that it’ll actually be good; maybe it will, fingers crossed, &amp;c.</p>
<p>So, the little box that could arrived. Went through setup, which was terribly confusing. It shouldn’t have been: you plug in the Dot and it glows for a bit and then says, in a calm and unhurried voice, “now use the Amazon Alexa app to set up your Dot”. And you open the Alexa app and… the Dot is already in there. I think this is Amazon trying to be <em>terribly</em> clever and inserting the Dot I bought into my account before it actually arrives in the post. Sadly for them this turns out to be a spectacularly confusing idea, because… what do I do now? Do I say “set up a new device”? Or do I go into the existing device that’s listed in the app and then… what? There’s no obvious setup button in the app for this Dot that I already own. (There is “set up wifi”… is that what I’m meant to do?) I think the Alexa app was originally written so you’d use it to “set up a new device”, and then some Amazon bright spark said “haha with our ultimate control over shipping and stuff we can record <em>which</em> Echo a punter has bought and put it in the app!” without stopping to consider that this completely breaks the first user experience. Well done, Amazon bright spark (golf clap).</p>
<p>Anyway, once I’d worked that out, I couldn’t get it to set up. Tch, eh? The way setup seems to happen is, the Dot broadcasts its own wifi access point named Amazon-<span class="caps">1AB</span> or something; the app disconnects you from your normal wifi and then connects you to that network, and does whatever handoff is required to teach the Dot about your house wifi. Except that this wasn’t working; my phone would connect to the Amazon-<span class="caps">9YZ</span> network and then… spinner, forever. After a good twenty minutes of faffing around with this, I installed the Alexa app on my iPhone instead and used that and it worked first time. No love, Amazon. Especially since most people don’t have two phones.<sup id="sf-the-internet-of-unreliable-and-broken-things-4-back"><a title="technically I haven’t got two phones either, I’ve got ten phones, but that’s not the point." class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-4">4</a></sup></p>
<p><span class="caps">OK</span>. Now it’s set up. <code>Alexa, what's the weather</code> correctly says “Currently in Birmingham it’s 24 degrees and sunny”<sup id="sf-the-internet-of-unreliable-and-broken-things-5-back"><a title="yes! really! nobody is as surprised as I am" class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-5">5</a></sup>, so things work. So I try the next thing: <code>Alexa, play the latest Madness album</code><sup id="sf-the-internet-of-unreliable-and-broken-things-6-back"><a title="which is great. I particularly like Mr Apples and Blackbird, and it’s on YouTube" class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-6">6</a></sup>, and Alexa, in her calm, unhurried voice, offers to play me <em>samples</em> of the songs and then shills “Amazon Music Unlimited” at me. Haven’t I already got Prime? Oh, I have, but Prime Music it turns out doesn’t actually have much music in it. You gotta pay extra for that. Bah humbug, etc. Fine, let’s do something generic. <code>Alexa, play some jazz</code>. Nope: “I can’t find any tracks matching ‘jazz’”, she says, calmly and unhurriedly. What? None? The little pamphlet even <em>suggests</em> that I say this! Grrrr!</p>
<p>Off to <a href="http://music.amazon.co.uk">music.amazon.co.uk</a>, which redirects me to <a href="http://music.amazon.com">music.amazon.com</a> and then pops up a big whiny banner saying “your music account thinks you’re in the <span class="caps">US</span>! But your Amazon account thinks you’re in the <span class="caps">UK</span>! That can’t be right! Click on this big button to fix it!” and then clicking on the button prints an error. So, y’know, cheers for that. I suspect that maybe this cross-cultural confusion — perhaps I’m somewhere midway between the two? In the Azores maybe? — is why I can’t search for music (there is not much jazz in the Azores) and is also why the Alexa app just throws up its hands in a sort of fit when I look at the music menu. God, do I have to ring them up? Like mediaeval times?</p>
<p>Amazon helpline. (By the way, the way you get help from Amazon (and thank you to <a href="https://twitter.com/popey">popey</a> for this) is that you go to <a href="https://www.amazon.co.uk/gp/help/contact-us/general-questions.html?skip=true">the Amazon contact-us page</a> and then choose the thing you want help with, and then scroll down and choose “Chat” if it’s there or “Phone” if it isn’t, and then you get to talk to an actual person, and the actual people are pretty much always helpful.) I explain the problem and the bloke says, yeah, that’s because your Amazon Music account thinks you’re in the <span class="caps">US</span>. I (calmly and unhurriedly) say: I know this, that’s why I’m on the phone, I want you to fix it. He talks me through navigating to a completely different screen<sup id="sf-the-internet-of-unreliable-and-broken-things-7-back"><a title="Amazon > Your Account > Digital content and devices > Music settings > Your country settings > " class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-7">7</a></sup> where I get asked the same question again but this time, remarkably, clicking the button works. Now Amazon Music works. The Alexa app works. Alexa works. Nice one, Amazon bloke.</p>
<p>Still gotta pay for Unlimited, though, which I’m not doing. New wheeze: rack my brains for bands I like who aren’t all that new (so their music isn’t under terrible money embargo) but only had one album (so if I say <code>Alexa, play Band X</code> it’s only got that one album to shuffle, hahaha). This works excellently, and now I’ve also refreshed my memory on <a href="https://en.wikipedia.org/wiki/Maxinquaye">Maxinquaye</a> by Tricky, so that’s <span class="caps">OK</span>.</p>
<p>A bit of diving around in the settings leads me to turning on <sup id="sf-the-internet-of-unreliable-and-broken-things-8-back"><a title="Settings > “your device name” > sounds" class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-8">8</a></sup> <em>Request Sounds</em> &gt; <em>Start of Request</em>, which means that now I can say <code>Alexa</code> and I get a little bleep meaning “I am listening”, just like Picard saying “Computer” and getting the little sound squiggle meaning the same thing.<sup id="sf-the-internet-of-unreliable-and-broken-things-9-back"><a title="I can even make the wake word be “Computer”, but that’s a crap idea" class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-9">9</a></sup> This is as it should be.</p>
<p>Cor, there are games on this thing? <a href="https://www.amazon.com/Warner-Bros-The-Wayne-Investigation/dp/B01C9AX5VY">The Wayne Investigation</a> is a voice-driven game by <span class="caps">DC</span> where you gotta find who killed Bruce Wayne’s parents. Well, I think it is. I can’t tell. Because it’s not available in the <span class="caps">UK</span>. Alexa seems to have this rather quixotic relationship with territories: a whole bunch of stuff is only in the <span class="caps">US</span> and then travels out across the Atlantic (and apparently even further out to Germany) in dribs and drabs over time. This isn’t just the stuff you’d expect, such as services (there’s no Pandora integration in the <span class="caps">UK</span>, but there’s no Pandora in the <span class="caps">UK</span> to integrate <em>with</em> unless you buy a lot of charm bracelets, so I’m not worried about that) but also some fairly core infrastructure bits. If you write “skills”, Amazon’s name for third-party plugins/apps on Alexa, then how they <em>work</em> is different in subtle ways between <span class="caps">UK</span> and <span class="caps">US</span>. This is weird and surprising and I can’t see how it will do anything other than trip people up and they should jolly well stop it.</p>
<p>More hilarious adventures with <a href="https://www.wunderlist.com/">Wunderlist</a>, which is where Niamh and I keep our shared grocery shopping.<sup id="sf-the-internet-of-unreliable-and-broken-things-10-back"><a title="because it has background sync, an Android client, an iOS client, a web client, and allows multiple people to share a list. Yes, we’ve tried others as well. This is harder to find than you’d think, especially since I need to copy and paste the content of the list to actually buy it from Tesco, and Google Keep inexplicably doesn’t allow copy and paste" class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-10">10</a></sup> Wunderlist haven’t done Alexa integration<sup id="sf-the-internet-of-unreliable-and-broken-things-11-back"><a title="although they’ve been begged to do so by loads of their users it seems)" class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-11">11</a></sup>, but <span class="caps">IFTTT</span> have support for both Alexa and Wunderlist, and there’s even an <span class="caps">IFTTT</span> “applet”<sup id="sf-the-internet-of-unreliable-and-broken-things-12-back"><a title="applet? what are they, java? what was wrong with “recipe” exactly? grr" class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-12">12</a></sup> named <a href="https://ifttt.com/applets/54883911d-add-amazon-echo-shopping-list-items-to-wunderlist">Add Amazon Echo shopping list items to Wunderlist</a>, so that’s good. Of course, my <span class="caps">IFTTT</span> gmail setup was broken so I had to delete it and recreate it, and Wunderlist wasn’t <a href="https://www.wunderlist.com/account/mailtowunderlist">set up to receive emails from me and add them to my list</a>, and then you have to set it up to receive emails from <code>you@gmail.com</code>, <em>not</em> whatever actual real email address you have mapped to gmail from your real domain, and then Wunderlist’s “send emails to this particular list” screen <a href="https://support.wunderlist.com/customer/portal/questions/16772141-mail-to-wunderlist-can-t-select-lists-for-each-send-from-account">is broken</a> and has been since last year<sup id="sf-the-internet-of-unreliable-and-broken-things-13-back"><a title='which I got around by manually editing the HTML in the devtools and writing custom <option value="mylistid">mylist1</option><option value="mylistid">mylist2</option> entries into the empty <select>; I freely admit that this is not an option (ha!) that is open to most people' class="simple-footnote" href="#sf-the-internet-of-unreliable-and-broken-things-13">13</a></sup>, but after all that nightmare of fiddling around and divining of underlying technology which would have defeated almost everyone, I can now say <code>Alexa, add squash to my shopping list</code> and it shows up in my actual shopping list that I care about. And it only took an hour of faffing around and it wouldn’t at all have been quicker to just walk to the damn shop, shut up, I don’t know what you’re talking about and your face is stupid.</p>
<p>So. Personal home assistants, eh? Are they the future?</p>
<p>Yeah. They are. Music was playing and I needed to concentrate, so I just snapped <code>Alexa, shut up</code> without thinking and it <em>worked</em>. This is how to make your electronic devices come alive, folks. Assimilated into my life in the space of a few hours without thinking about it; I just reacted to it like I would to a real person. This extends to the point where I felt a tiny bit guilty about saying that; the mark of a gentleman is how he behaves to his valet, after all. I shall try to be less peremptory.</p>
<p>Fine, the current process is rocky. Some of that is that it’s not matured yet (<code>Alexa, when did Vincent Price die?</code> No, not “play vincent price die”, not “christ die”, not “do you speak some price dead”, you stupid pile of undocumented microchips!) Some of it is that basically every large company underestimates how much people’s accounts are set up incorrectly or incompletely; after all, <em>employees</em> have everything set up right, because they know what they’re doing, and so this never comes up in testing. Some of it is because I’m joining dots on three or four very different puzzles: I’m sure if I were to get a Google Home and use Google Mail to send my shopping list to Google Keep and then buy things from Google Shopping, or if I were to get some theoretical Home Siri device and play music from my Apple account and put things in my Apple iCloud account… then all this would be a lot more seamless. But you should beware people who proclaim that technology would be easy if all us heathens were just to renounce our diverse needs and join their true faith. Mastery goes to the designer who can cope with us real people, in all our glittering and varied patterns and colours and desires. Not just the ones who take the easy way out and block you if you haven’t already bought all the rest of your stuff from them too.</p>
<p>Alexa, welcome to Castle Langridge.</p><ol class="simple-footnotes"><li id="sf-the-internet-of-unreliable-and-broken-things-1">from Crunch, my accountants, after I referred someone who signed up; that someone got an Amazon voucher too! So if you are looking for an accountant, do so by following <a href="http://www.crunch.co.uk/referrals/?c2c=sl14342l">this shameless referral link</a> and I can buy more stuff!) <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-1-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-2">People who listen to Bad Voltage will know what I’m talking about here. <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-2-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-3">if you’d like me to deliver this talk at your conference, let me know <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-3-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-4">technically I haven’t got two phones either, I’ve got <em>ten</em> phones, but that’s not the point. <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-4-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-5">yes! really! nobody is as surprised as I am <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-5-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-6">which is great. I particularly like Mr Apples and Blackbird, and it’s <a href="https://www.youtube.com/watch?v=0NKNGKNBYs0&amp;list=PLiF0kTVfCbi953MAEMh5ClMYhGJGbhooz">on YouTube</a> <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-6-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-7"><em>Amazon</em> &gt; <em>Your Account</em> &gt; <em>Digital content and devices</em> &gt; <em>Music settings</em> &gt; <em>Your country settings</em> &gt; <a href="https://www.amazon.co.uk/gp/dmusic/account/settings"><em>View music library country settings</em></a> <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-7-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-8"><em>Settings</em> &gt; <em>“your device name”</em> &gt; <em>sounds</em> <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-8-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-9">I can even make the wake word <em>be</em> “Computer”, but that’s a crap idea <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-9-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-10">because it has background sync, an Android client, an iOS client, a web client, and allows multiple people to share a list. Yes, we’ve tried others as well. This is harder to find than you’d think, especially since I need to copy and paste the content of the list to actually <em>buy</em> it from Tesco, and Google Keep inexplicably doesn’t allow copy and paste <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-10-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-11">although they’ve been <a href="https://support.wunderlist.com/customer/portal/questions/16946016-amazon-echo-new-api">begged to do so</a> by loads of their users it seems) <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-11-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-12">applet? what are they, java? what was wrong with “recipe” exactly? grr <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-12-back">↩</a></li><li id="sf-the-internet-of-unreliable-and-broken-things-13">which I got around by manually editing the <span class="caps">HTML</span> in the devtools and writing custom <code>&lt;option value="mylistid"&gt;mylist1&lt;/option&gt;&lt;option value="mylistid"&gt;mylist2&lt;/option&gt;</code> entries into the empty <code>&lt;select&gt;</code>; I freely admit that this is not an option (ha!) that is open to most people <a class="simple-footnote-back" href="#sf-the-internet-of-unreliable-and-broken-things-13-back">↩</a></li></ol>silSun, 28 May 2017 13:49:00 +0100tag://www.kryogenix.org/days,2017-05-28:2017/05/28/the-internet-of-unreliable-and-broken-things/Public wall murals//www.kryogenix.org/days/2017/05/10/public-wall-murals/<p>Across from the window of my flat there is this big&nbsp;wall.</p>
<p><a href="https://kryogenix.org/images/wallbyflat.jpg"><img src="https://kryogenix.org/images/wallbyflatsmaller.jpg" alt=""></a></p>
<p>It is not very pretty. It would be nice if it were pretty. Say, by having some kind of excellent massive mural painted on it. I haven&#8217;t looked into this whatsoever, and presumably the people who own the building that this wall is part of are entitled to some sort of opinion on this, but&#8230; what&#8217;s involved in getting a big mural there? Are there, like, <em>rules</em> about this sort of thing? Or can you just paint what you like on outside walls? Also, who out there can pay for this? I&#8217;d like it to be me, but unless my six lottery numbers come up that isn&#8217;t happening, so&#8230; are there grants or something? I feel like there ought to be grants for public art and that sort of thing. And how much money would be needed? I have no idea what sort of community arts projects there are around or how they get paid or whether this sort of thing costs ten quid or ten thousand. Your thoughts <a href="https://twitter.com/sil/status/862234394085470210">invited</a>.</p>silWed, 10 May 2017 10:03:00 +0100tag://www.kryogenix.org/days,2017-05-10:2017/05/10/public-wall-murals/Making Gnome Shell feel like Unity//www.kryogenix.org/days/2017/04/05/making-gnome-shell-feel-like-unity/<p>I like the way the Ubuntu Unity desktop works. However, a while ago I switched over to Gnome Shell to see what it was like, and it seemed good so I stuck around. But I&#8217;ve added a few extensions to it so it <em>feels</em> a bit more like the parts of the Unity experience that I liked. In light of <a href="https://insights.ubuntu.com/2017/04/05/growing-ubuntu-for-cloud-and-iot-rather-than-phone-and-convergence/">the news</a> from Canonical that they&#8217;ll be shipping the Gnome desktop in the next <span class="caps">LTS</span> in 2018, and in light of much hand-wringing from people who like Unity as much as I do about how they don&#8217;t want to lose the desktop they prefer, I thought I&#8217;d write down what I did, so others can try it&nbsp;too.</p>
<p><a href="https://www.kryogenix.org/images/gnome-shell-unity.png"><img src="https://www.kryogenix.org/images/gnome-shell-unity.png" alt="Gnome shell, customised to look like the Unity desktop"></a></p>
<p>As you can see, that looks like Unity. It feels like Unity&nbsp;too.</p>
<p>The main bit of customisation here is extensions. From the <a href="https://extensions.gnome.org">Gnome shell extensions web app</a>, install <a href="https://extensions.gnome.org/extension/759/better-volume-indicator/">Better Volume Indicator</a>, <a href="https://extensions.gnome.org/extension/307/dash-to-dock/">Dash to Dock</a>, <a href="https://extensions.gnome.org/extension/118/no-topleft-hot-corner/">No Topleft Hot Corner</a>, and <a href="https://extensions.gnome.org/extension/1031/topicons/">TopIcons Plus</a>. That gives you the Launcher on the left, indicators in the top right, and a volume indicator that you can roll the mouse wheel on. Choose a theme; I use the stock Gnome theme, &#8220;Adwaita&#8221;, but I turned it to &#8220;dark mode&#8221; (in &#8220;Tweak Tool&#8221;, turn on &#8220;Global Dark Theme&#8221;), and set icons to &#8220;Ubuntu-mono-dark&#8221; in the same&nbsp;place.</p>
<p>Most of the stuff you&#8217;re familiar with in Unity actually carries through to Gnome Shell pretty much unchanged &#8212; they&#8217;re actually very similar, especially with the excellent Dash to Dock extension! One neat trick is that the window spread and the search have been combined; if you hit the Super key (the &#8220;Windows&#8221; key), it opens up the window spread <em>and</em> lets you search, so the normal way of launching an app by name (hit Super, type the name, hit Enter) is completely unchanged. Similarly, you can launch apps from the Launcher on the left with Super+1 or Super+2 and so on, just like&nbsp;Unity.</p>
<p>There are a whole bunch of other extensions to customise bits of how Gnome Shell works; if there are some that make it more like a Unity feature you like and I haven&#8217;t listed, I&#8217;d be happy to hear about them. Meanwhile, I&#8217;ve still got the feel I like, on the desktop I&#8217;ll be using. Hooray for&nbsp;that.</p>silWed, 05 Apr 2017 19:10:00 +0100tag://www.kryogenix.org/days,2017-04-05:2017/04/05/making-gnome-shell-feel-like-unity/