Quantcast
Channel: as days pass by
Viewing all 158 articles
Browse latest View live

What I Did On My Holidays, or, Pouring Out A Forty

$
0
0
Before we begin, thank you. Thank you, all, thank you, thank you…
Dr Hook, The Millionaire

Bad Voltage on stage

This has been a busy few weeks. Culminating in me becoming forty years of age, of which more later.

I went to the US to see Jono and Erica. Watched The Martian on the plane on the way out. It is a very excellent film indeed, and if you have not seen it, go and see it. And I got to hang out in Walnut Creek for a few days; I can recommend Sasa, Ike’s Sandwiches1, and Library on Main2 if you find yourself in town. And see my friends, of course. Dr3 Matthew Garrett introduced me to Longitude, the best cocktail bar in Oakland. And I scored a new laptop.

Aside: amusing story about the laptop. A few months ago I mentioned to Jono that my dad’s phone (a Moto G) was dying, and he said, hey, I’ve got a Samsung Galaxy S5 you can have to give to him if you want. Cool, said I, and handed over fifty euros for it4. Sadly, on returning to the UK, I discovered that the phone was locked to its US T-Mobile SIM and so my dad couldn’t use it. So this trip saw its return to the US so Jono could get it unlocked. He rings up T-Mobile USA, and the conversation went something like this5:

Jono: I would like you to give me the unlock code for this here Galaxy S5 that I bought from you
Helpful T-Mobile USA person: No, sir, we can’t do that
J: This is ridiculous. You phone operators are all terrible and try to lock in your customers. I know that phones are unlockable, and you’re just keeping this secret in a further attempt to deny me my rights over my purchased hardware. I can’t believe you’d keep lying about this; give me the unlock code, which I’m technical enough to know exists.
TM: No, sir, we’re not refusing to unlock the phone because we’re oppressing your hardware rights. We’re refusing to unlock the phone because you haven’t finished paying for it yet.
J: Really?
TM: Yup. You still have twelve months to go on the contract.
J:… oh. (turns to me) Do you want that laptop you borrowed instead?

So, result. Every one’s a winner. And it meant I had a machine that didn’t have to be plugged in all the time; my poor Dell M1330 had finally given up the ghost. Nice one, Jono.6

The real purpose for being in the US7 was to travel to SCaLE 14x. Did a couple of talks about Ubuntu phone stuff at the colocated “Ubucon”; one on adding analytics and advertising to Ubuntu phone apps (SCaLE video8) and one with Alan Pope about Marvin, our cloud testing service for phone apps (SCaLE video) (footnote ditto). I was one of the panelists on The Weakest Geek, a “quiz show” where as far as I can tell the rules are that quizmaster extraordinaireGareth Greenaway asks various people increasingly hard questions about tech and sci-fi, and then Ruth Suehle wins. And there was the main purpose for my travel to SCaLE: Bad Voltage Live, our third live show and second at SCaLE. Video will be out tomorrow. It was a fun show to do, although rather dogged by problems with the AV. Still, we soldiered on, and at the after party a number of people said that they thought that our struggles with the audio and a Mac9 added to the comedy, so that’s OK. I’d like to say a special thank you to Linode for flying me out to LA10, the other sponsors for making the show possible, and to Tara for putting up with the dodgy software I wrote to run the Family Feud/Family Fortunes scoreboard for the show.

And the SCaLE team gave us some jerseys with our names on!

The four Bad Voltage presenters, being presented with branded SCaLE jerseys with names on the back

I feel a bit guilty about that. You see, we love SCaLE. The team try really hard to support Bad Voltage, and in return we use them shamelessly. We pressed Ilan into service as our audience fluffer, and made him wear lederhosen11, but we showed our gratitude with a decent bottle or bourbon in return for all his hard work. And we pressed Gareth into service as our Family Fortunes quizmaster, and made him wear a spangly gold quizmaster suit, and then showed our gratitude by getting him… a pink Hello Kitty stepstool so he can be even taller, and a pink Hello Kitty hat with movable ears. Sorry, Gareth. We love ya, buddy. And thank you both for everything.

But the real event for me was a bit at the end of the live show. You see, as of yesterday, as I post this, I am forty years old.

Forty. Cool, eh?

That makes all of this the 2016 iteration of thefamousonce-a-yearbirthdaypost (nowinits12thgreat year!), but my birthday this year was rather special. It appears to be what Cristian referred to as a “birthday week”, and I am perfectly happy with that. It started during the live show, where Jono had obviously done a whole bunch of behind the scenes hassling of lots of people to have them wish me happy birthday on video. I managed to resist the urge to actually cry on stage, but… not by much. Then a whole bunch of us went out on the Saturday night and drank yards of ale and then some sort of all night pie shop12. The day before my birthday13a whole bunch of us went out to Rub Smokehouse14 and then had celebratory beers15. Niamh and my parents and I went to Amantia for tapas16 and Niamh and I are going to Gordon Ramsay’s maze for sushi. I have a gorgeous new watch (a Roamer Ceraline Saphira, which I have not stopped constantly looking at since the moment it was strapped to my wrist, nor have I stopped telling people the time when they don’t want to know it). A copy of Watchmen which is signed by Dave Gibbons!17 A little model of Ron Weasley!18 A potato!

So I would like to say thank you. To all the people on Facebook, because once a year I get a million emails of people wishing me many happy returns. To Sam and Andrew. To the people on my birthday video: Rob McQueen, Matthew Walster, Jorge Castro, Rikki Endsley19, Ted Haeger, Adam Sweet20, Ron Wellsted, Bill21, Jono and Erica’s parents, Tarus Balog22, Ronnie Trommer, Jessi Hustace and the OpenNMS team, Erica Bacon23, Michael Hall24, Christian Heilmann, Cristian Parrino25, Alan Pope, Bruce Lawson, and Niamh. To the Bad Voltage team: Jono, Jeremy, and Bryan. To the Saturday night partiers26: Jono, Jeremy, Tara, IlanMaru, Hannah Anderson, Ian Santopietro, popey, mhall, Pete and Amber Graner. To the Birmingham crew: Dan, Ebz, Kev, Matt Somerville27, Matt Machell, Charles, and Rich. To Mike, who is skiing. To Andy and Tom, who I’m seeing next weekend.28 To Jono, for everything, including a rather lovely blog post. To mum and dad. And to Niamh.

I have the best friends. I really do.

Rather enjoying being forty.

It’s 11.27, by the way.

my gorgeous new watch showing the time

  1. stupid sandwich names, great actual sandwiches
  2. used to be Eleve
  3. this is important
  4. technically, I paid for half his lederhosen instead
  5. a certain amount of artistic licence is, I admit, taken here
  6. more on the ‘nice one Jono’ front later, too
  7. sandwiches and cocktails aside
  8. with rather dodgy sound; more on the AV issues later
  9. followed by brutal berating from aforementioned Dr Garrett during Wrong in 60 Seconds
  10. never did get to go to JPL in Pasadena. Or Buffalo Wild Wings
  11. we find lederhosen way funnier than I think we should
  12. where I may have left my hat
  13. we skip over here a week of me suffering from the most brutal jet lag I have every experienced. It was not a pretty sight.
  14. not actually recommended, unless you’re a professional stodge appreciator
  15. and Jura whisky. And Sambuca. And some other things
  16. also not actually recommended, it turns out. Go to La Tasca instead.
  17. nice one Charles!
  18. nice one Dan and Ebz!
  19. who, I am told, got stuck in that cemetery and couldn’t get out; cheers, Rikki
  20. I am now officially “the big ginger web lothario”
  21. sorry we haven’t managed to get together for beers, pal. It will happen. Promise. Plus, you’ve only got six months to go now…
  22. who is fifty! congrats!
  23. the “nearly crying on stage” thing? that was you, Erica
  24. I promise to look at the JS scopes stuff once I’m running 16.04
  25. I like the “decade of wisdom” thing. That sounds a lot like me, that
  26. hope you all enjoyed the gorilla joke
  27. who fixed traintimes.org.uk as a birthday present!
  28. as the birthday week turns into a birthday fortnight

Android apps and sensitive permissions

$
0
0

In the last two days, I’ve installed two Android apps (names redacted because it’s not their fault!) which, on install, have popped up a custom notification saying that the app “requests Sensitive Permissions”.

UPDATE: this is not these apps’s fault. It is ES File Explorer’s fault. Uninstall ES File Explorer. And everything below applies to the ES File Explorer people.

Tapping this notification pops up a thing named “Apps Analyze” which pretends to be analysing the stuff on your phone and then shows you a bunch of irrelevant information about your phone and weather and Facebook info, which have nothing whatsoever to do with the app you installed.

Let me be clear. This is bullshit. This is nothing more than malware. I wanted to dim my screen, or buy a sandwich. I did not want to have my phone “analysed”; I did not want “sensitive permissions”. I don’t think this thing needs permissions at all; at the very best it’s a completely unwanted bundled thing, like Oracle bundling adware with their Java installer. At worst, it’s some sort of unpleasant malware which harvests data from my phone and ships it off somewhere. I don’t know what it does; it’s certainly bloatware at the very least; there’s a Reddit thread about it.

I don’t know where this is coming from; since it’s shown up in two separate apps, it’s presumably some sort of third-party component, and presumably the authors of it pay app developers to include it. I do know where it’s coming from; it’s from ES File Explorer. If you are an Android app developer and you are using this thing, fucking pack it in. This is a hysterical betrayal of your users’ trust. I know it’s hard work to monetise software that you write. I know it’s tempting to scrape the barrel like this. But if you are using this, you are a terrible person and you should sit down and have a bloody word with yourself. Stop it. You’re pissing in the waterhole and ruining things for everyone. Do you really want to be part of this race to the bottom?

It’s possible that this is an official Android thing, since it’s also showing up in Google Sheets and so on. If so, Android people, what the hell are you thinking of?

Lost in the Maze

$
0
0

So, as part of my month-long birthday celebration, Niamh and I went to Gordon Ramsay’s Maze restaurant for sushi.

The Maze restaurant internal sushi bar, lit with purple neon

We were, honestly, a bit worried at first; we’d bought it as a “Red Letter Days” voucher, and when we got there and explained this, there was a certain amount of “er, we don’t know how to deal with that” and barely concealed snootiness at us having a voucher like the terrible commoners we are and so on. And that got combined with us saying that Niamh is both vegetarian (well, she eats fish, otherwise we wouldn’t have been in a sushi place, of course) and gluten-free, at which there was further barely-concealed snootiness at first. But, they got over it. And quite well, too; the remainder of the evening, the staff were the souls of courtesy, and that helped a lot; good one the Maze.

Niamh and I, getting ready to go out, full of smiles

We were having the seven-course tasting menu. I approve of this idea.

Of course, we did the shameful Instagram thing and took pictures of all the courses.

A glass of bubbly

Free glass of champagne! Actually, two free glasses; they seemed to think that Niamh was 18. However, she doesn’t like it, so that’s two free glasses for the birthday boy.

Kani snow crab

Kani snow crab, wakame, wasabi

Hiramasa

Hiramasa: kingfish, pecan nut, red onion vinaigrette. (I really liked the crunch of the pecans in this. Will steal this idea.)

Spicy tuna tartare

Spicy tuna tartare, chilli garlic, yuzu avocado, wonton crisps. (We have decided that it ought to be possible to do a whole meal with the courses served inside a fruit.)

Niamh tucking in

The chef's sushi platter

Chef’s sushi platter: from left, wasabi, pickled ginger (which I again ate a bunch of in one go after Niamh lied and told me it was chilli garlic, which it was not), salmon, kingfish, sea bass, tuna, crab, tuna. The crab was the nicest; Niamh’s is pictured with puffed rice and mine had little wheat strips.

Pork belly

Suckling pig belly, crackling, mandarin salad, pork jus. Of course, Niamh didn’t have this, and instead had:

fish and radish salad

Fish (of some kind, we can’t remember) with radish salad and cream sauce

No man goes like a mango goes

Mango with lime and shichimi pepper is what the menu says, but I’m not sure that’s what this was. It was a sort of mango foam as a palate cleanser, and was delicious.

Dry ice clouds boiling all over our table

Then a cool thing happened. They brought out a dish of lemons, and then poured water into it; it turned out it was a dish of lemons and solid carbon dioxide pellets, meaning that we had boiling clouds of dry ice flowing all over the table, and we were massively impressed. Also took the opportunity to revise what “sublimation” is in preparation for Niamh’s chemistry GCSE in a couple of months.

Lemon pie

Lemon pie with Italian meringue and passionfruit sorbet.

Passionfruit meringue

Niamh’s passionfruit meringue with lemon and lime curd (since lemon pie has pastry in)

Niamh and I, at the Maze

We like the Maze. Nice work, restaurant team. More sushi for us.

Mothering

$
0
0

So, my fortieth Mothering Sunday. Although I don’t remember the first few. We don’t always agree, my mum and I. We might argue about politics (she’s quite a lot more right wing than me, mainly from reading the Daily Mail). But, honestly, these days, we mostly do. It’s nice, that. I like that I have parents, both mum and dad, who I can ring up and tell them about how work is going and who I’m hoping to get as clients and which flats I want to buy.

If you’re currently avoiding talking to your parents, because they’re just annoying or something… you should think about rebuilding that bridge. It’s worth hearing from them.

Really. I’m glad I hear from mine. Happy Mother’s Day, mum.

Reasons to not like ads

$
0
0

Bruce linked to Kagan MacTane’s list of “reasons to use ad-blockers”, and I thought it was pretty good. I’ve been describing people who want to use an ad-blocker really as falling into four categories; these obviously cross over a lot, and most people will have aspects of each.

Ads are bad for privacy

Primary concern here, ads that track you around the internet. Advertising itself isn’t so bad; it’s when the ad networks build up a list of sites you look at by dropping tracking cookies on you, and then create a profile of you and what you do and what you care about. There are potential benefits here — if you’re going to see adverts, then they might as well be for stuff you’re interested in, right? — but in a post-Snowden world, having this sort of profile of you available to a company who may not have your best interests at heart and may hand it over to whoever asks for it when compelled or paid isn’t necessarily a good thing. People who feel this way find that worrying. You can see your Google ads profile from your Google account, and get a sense of the sort of demographic information that has been built up about you, and you can change your list of interests or opt out entirely; most ad networks don’t have this level of control. The EFF’s Privacy Badger browser extension is primarily designed to alleviate this sort of worry, by permitting ads but removing any tracking cookies, or blocking ads and script requests that attempt to do tracking.

Ads are bad for performance

Primary concern: that a page full of adverts loads much more slowly, because the script in the ads holds up the page, and because the ads themselves take a lot of time to download. Les Orchard did a great job analysing The Verge and showed that an article with 57K of HTML also included nearly 10MB of ads and took thirty seconds to download. (The Vox Media team are working on it.) It’s quite startling how much faster a page is when it’s not downloading 200 times its own weight in extra advert code; this is what’s behind the AMPHTML initiative, although it’s not clear whether that serves the needs of people solely or whether it’s a bit of a landgrab by a few big companies. But it’s nonetheless a response to this performance issue, and I suspect that the only reason more people do not identify themselves with this concern over performance is that they don’t realise how much faster the web ought to be when done right. (Also, here, see Progressive Web Apps.)

Ads are visually disruptive

A fair few people don’t necessarily mind adverts as a concept but dislike the actual ads we’ve got, because they animate or flash colours or move around or play a video when you inadvertently mouse over them; that is, they’re distracting and terrible. People who feel like this tend not to mind, for example, text ads on the side of a set of search results, but don’t like awful flashing things. It makes it difficult to see what you’re actually reading. One of the larger offences in this particular category are ads which make a page’s content jump around; the ad appears after page load and pushes everything below it down, leading to immense annoyance on the part of someone reading the pushed-around thing (and screwing up the scroll position if you’ve just hit Back).

I shouldn’t have to see any ads at all

And then there are those who feel that they ought to not see any ads whatsoever, and if publishers have a problem with that, then the publishers need to solve it.

Here’s the important point. In general, complaints about ad blocking (from publishers, from adtech companies, from ad networks, and the like) tend to assume that everyone’s solely and completely in the last category. That is: the argument that ad blockers are bad goes “you just don’t care about how we fund the stuff that you read for free”. This is, I suggest, not the case for everyone. Yes, there are some people — plenty of people — who just don’t want any ads, and take a brutal and blasé attitude (“it’s not my problem you’re relying on a crappy business model”), and ignore the very tragedy-of-the-commons outcome of this (if everyone does it, we break everything). But, I think (and I’d love to see data on this, beyond the anecdata I have from talking to people) that some if not most people don’t dislike ads qua ads, they dislike the ads we get. Because the ads we get are visually distracting, privacy-invasive, and slow down the web to the point of ridiculousness. Maybe if adverts didn’t track us around the internet, didn’t screw up reading a page, and didn’t take thirty seconds to load, everyone wouldn’t be so quick to blame “ads” and could instead blame “bad ads”.

But… maybe it’s too late, now. I suspect it’s quite possible that the ad industry has pissed so comprehensively in this waterhole that there’s no way to come back from this and offer ads that can fund producers and aren’t dreadful.

I hope I’m wrong.

The wisest words spoken

$
0
0
If all the world’s a stage
Then light my way
Because out, out your brief candle is not
Four centuries past, yet I still cannot grasp
That undiscovered country that makes words immortal
If the good that men do is interred with their bones
Then this precious stone is a beauty too rich
Methinks it’s a jewel in the ear of us all
As the wisest words spoken are spoken by fools

from This Gives Life To Thee, performed by Akala, Nitin Sawhney, and Dane Hurst, as part of the BBC’s Shakespeare Live! From the RSC, 23rd April 2016.

LOWREZJAM reviews

$
0
0

A few weeks ago, the LOWREZJAM kicked off on itch.io. It’s a game jam; the idea is to build a computer game. This one had an interesting restriction: the game had to be 64x64 pixels. So, we’re going old-school.

I thought I’d enter. So did about four hundred other people. It turns out that a jolly good way to get people to rate your game is for you to rate theirs and comment on it; then, your comment gets decorated with a link saying “see their submission” and they tend to follow it and rate you in turn. So, I wrote a bunch of short reviews. There doesn’t seem to be a way to link to all my reviews in a given jam on itch.io (although it would be good if there were!), so I’ve collected them here for posterity. Note that these make no attempt to be comprehensive or fair or balanced; they’re basically comments on what I thought of the games I played and why I didn’t like them, if indeed I didn’t.

A few games got a rating but not a comment; those aren’t included. I also haven’t included the actual ratings I gave, because those don’t matter as much. The comments are mainly designed to be helpful to the game’s developer, if anything.

I only played in-browser games, because they’re easiest to play, and I don’t have the Unity web player so those games which require it didn’t get played. It’s good to see that a pretty high proportion of “Unity” games are using the Unity WebGL export so they can be played without the plugin! I also didn’t play everything; with 188 games just in-browser, I was never going to get through them all. Pro-tip: this is one good reason to give your game nice imagery, so it looks interesting in a big list.

In essence, this was a lot of fun. There were an awful lot of things which were clearly only part-finished (didn’t have sound, didn’t have a way to win, didn’t have title screens, and so on), but there were some really accomplished entries in here; things that I can absolutely imagine being a released game that one could play and have fun with. Nice work, indie game dev community.

You can also watch Jupiter Hadley play all the games on her YouTube channel; at time of writing mine isn’t done yet, but it should be over the next few days.

So! Reviews!


MatchMerchant

The extra challenge provided by trying to match 4 (to get a potion) while not matching 3 (so the things disappear) adds an interesting extra wrinkle to this. The scene — a potion seller, wizards — adds some meaning to the game mechanic, and the graphics are good. Dragging is a little awkward, and unlike most match-3 games you can drag to swap any two pieces, which I didn’t at first realise.


Time Scale

I appreciate the idea of slowing down time. But I’m not sure why I wouldn’t play just with my finger on the shift key the whole entire time, thus turning the game into Bullet Time All The Time? Some puzzles which require performing them with time at normal speed would be nice, although maybe there are plenty and I just didn’t get that far….

(also, the sound made by the “fire dots into the air” triangles is not perfectly synchronised with actually firing dots into the air, which makes jumping over them considerably harder; this may have been a deliberate thing, but it’s over the line between “maliciously confusing” and “just annoying”, for me at least)


r

Ouch, the ponderous music is quite painful to endure.


Kulten

Great graphics — the text is a little hard to read at times, especially distinguishing D and O, or similar — but the feel of the game is marvellous. It really misses sound!


micro-society

Interesting concept, although the 64px limitation maybe makes the representation a bit too abstract! Having new children get born just by walking into other players feels a bit weird, too. But there are some quite complex game mechanics underlying this!


Star Shield

Obviously simple graphics, but easy to play. The white UFOs are terribly hard to kill! I’m not sure what “shield” does; it certainly doesn’t stop you being killed by bullets or collisions :-)


Castle Storm

Really nicely put together; a complete and well-implemented fun game. The font is, as noted, a little hard to read, and it’s sometimes hard to know why you’re not allowed to buy a thing — is it because you haven’t bought one of the pre-requisites, or because you don’t have enough money, or because you’ve bought it already — and that does break the immersion somewhat. Watching a Lord attacking the enemy castle is highly amusing. Nice work!


Fast Escape LowRez

Maze gameplay boiled down to its simplest possible form. :) Agreed with bonus1up that some framing device and music and sounds would help it feel more like a game rather than a demo of the technique. The maze generator seems to generate some pretty tangled messes at times, and I roamed pretty aimlessly until I discovered the green exit block. A score or some method of assessing progress would be nice, perhaps.


Gummy Turbo Tunnel

I see the idea, but I assume that the deadline landed before gameplay could be added. Nice start on an idea, though!


FRSTFIRE

Sadly, the game crashed with an error (screenshot at imgur) when I tried to increase the growth rate; I think I may have pressed “right” and Z at the same time. I love the concept; it would be nice to see a version of this which wasn’t constrained to 64x64 and the Pico, as an art piece and less clunky to fiddle with the parameters!


Dungeon Shifter

Interesting concept, and the graphics are nice (blocky, but nice). I don’t think I understood what most of the “control panel” is actually for, though, and needing to control that by clicking while simultaneously either clicking arrows or using the arrow keys to go up and down means that the challenge is not “playing the game” but “managing the controls”, which I don’t think is meant to be the challenging part :)


64s Resistance

I don’t think I understand what the score is actually scoring, here. Button-mashing, once I started being “attacked” from all sides, got me up to 70 or so, but I didn’t really have much of an idea what I was doing, and then my score reset to 0 and I didn’t know what I’d done wrong. It feels like there might be a good idea in here for twitch gameplayers and people who like Super Hexagon, but I think more feedback as to what’s going on and why is needed.


LZRS

The try-and-die-iest of try-and-die games :) Fun! The controls feel a little bit wonky; sometimes I wouldn’t be able to jump and it wasn’t clear why. Fun, though, and I won after only forty (!) deaths.


Ghost

Seems fun — it’s a tiny 64x64 Gunpoint, sorta! Really short, though; maybe more levels would be good.


Duck Quest

As you say, an in-progress demo rather than a complete game, but what’s there is pretty good. I like the single-colour palette; I can imagine this being a working game (once completed) on something like a watch or a single-use handheld game.


Marble Incline Redux

I don’t think the text display fits the 64px grid, does it? Also, it would be useful if continuing to the next level and starting that level were controlled with a keypress you’re already using, such as up arrow, as well as restarting after death, rather than having to wait or press R.


Wall Defender

Simple, and basic graphics, but easy to play and understand, and the two offset guns provide a modicum of strategy when trying to shoot two different attackers at once. I won first time out, so the difficulty curve probably needs a bit of tweaking :)


The Forest

Smooth movement, and I like that running into a shadow is not an instakill. Attempting to find the key is very frustrating!


In’Out

Elegantly done graphics. I didn’t realise for quite some time that you can jump :) Sound effects would be good to go along with the music, perhaps?


Hyper Racing

The car handles excellently — the first level is so easy to pass that I was already thinking of recommending more realistic movement (rather than being able to turn instantly), and then the second level (which is just the same idea, with a larger oval) is much much harder to pass in the time! So I think the difficulty curve is just about right, and the graphics are good; nice work!


Memoblox

The skull and its laugh makes me laugh in turn. I didn’t really realise that I was supposed to be remembering the colours until after the first playthrough; maybe some minimal instructions, or a slide saying “REMEMBER” before the colours start?


Postal Panic

Oh goodness me the voice commentary is so annoying. My game went out of its way to mock failure and have annoying voices and it’s not a patch on this; I kept missing parcels because I wanted to punch the screen. Excellently done. Also, nice graphics, good sound work, and slick; a complete game. Only a weakling such as myself would rate it down because it’s just too hard :)


Monty Norman’s James Bond Theme

I didn’t realise that I was meant to shoot without being able to see Bond! Once I worked that out, and that the “gunsight” was actually moving even though it doesn’t appear to be because the background is all white, I was able to shoot at and hit 007. I like the music loudness approach (reminiscent of Find the Invisible Cow).


Sk8Skull

A good start; nice pixel art. The game obviously needs work, as you know; as far as I can tell it’s not possible to jump over two sets of spikes next to one another. You’ll also not want to make the “restart the game” keypress also count as a “jump” keypress. But this could grow to be something good with more work!


Terracell

I suspect this is a demo that never got finished? The graphics are surprisingly impressive — I particularly liked the realism of the rain — but there doesn’t seem to be a purpose to the game (nor any sound), and walking through an elephant means that the elephant sticks right with you and flickers on and off, weirdly. Could be the nucleus of something impressive with lots more development, though; a good start.


The Sheriff

Sadly, the game doesn’t cancel keypresses when they’re not used, which means that every time I’m walking downwards and I walk into something, the down arrow is ignored by the game and passes on to the web page and the page scrolls downwards, taking the game out of vision! This made it really hard to play, I’m afraid! Opening the frame in its own tab helps, though.


BuggyBall

Nice art, and the car is surprisingly controllable. The low resolution meant that I didn’t realise for quite a while that my car could be turned upside down and that’s why I couldn’t drive anywhere, though, and if you leave the AI alone for three seconds it scores a goal :-)


Useless Clicker

Impeccably implemented simple joke. It gets a smirk, which I’m sure is all its little heart desires :)


Mogee

I think I got trapped in a corner and couldn’t get out, even after I died and the game restarted. Simple mechanic, and it’d benefit from some sound, but playable!


Cat Herder 9000

The cats slide around not on the 64x64 grid, which makes them look smooth but breaks the rules :) As noted, there’s not much of a sense of agency here; I don’t feel like I have much control over the cats (arguably, because they’re cats), but that does mean that the game feels like making a succession of random moves until you win by accident, rather than by superior play. I can’t see how anyone could become an expert at this game rather than merely winning by luck…


Circle Pong

Quite a clever mechanic — that I get confused when I’m atop the circle and the “left” button is actually going to the right is not the game’s fault :) It’s very easy to overshoot or undershoot, though, which is frustrating; it might be nice if this were made less punishing, although maybe the idea of having to get it dead on right is a deliberate part of gameplay!


Intents: Man to Man (v1.01a)

The description calls this “weird”, which I don’t think is fair, but it is detailed. As noted, paying attention to the manual is pretty important to work out what’s going on. Choosing the squares to move to feels unusually clumsy, by comparison with the rest of the UI which actually flows pretty well once you’ve got the hang of what you’re doing. This feels like the video equivalent of what “proper” wargames (measure the hexes, spend time with books of tables calculating precise angles and damage for mortars, etc) are to Risk, and there’s definitely an audience for that.

(also, as @phantomax says… it’s not meant to be called “intense”, is it? :))


Cat’s Trophy!

Cute but rather bare graphics. The game’s actually surprisingly hard. Instadeath for going off screen seems a bit harsh, rather than just locking the player to the screen.


Dexno

I found it useful to apply a changed style to the canvas in the game: canvas { height: 60vh; } makes it much bigger and easier to see, which may help with the issue you were having with the HTML viewport.


SQUARESQUARE

Interesting idea. It’s really, really difficult though; maybe start slower and speed up over time? Otherwise it leads less to attempts to do better and more to just table-flipping annoyance and a move on to another game :)


Mini Prix

Ninth out of nine, but this was good fun!


Zerwol the Wizard

I don’t have any very clear idea of what I’m meant to do — just wander around and kill everything?


FusionSpace

The music kept making me think it was going to be the Game of Thrones theme :)


Of A Forgotten Earth

Hard to see what’s going on when most of the screen is obscured (although maybe that’s the point). The cutscene at the beginning is interesting the first time through the game but has to be manually skipped through every time you die, which is rather frustrating.


Air War 64x64

Looks really good! but it’s sometimes hard to see exactly where the Red Baron is when he’s just three or four red pixels :) Also, it’s a little hard to tell whether I won or lost when we end up flying directly at one another firing. (Perhaps it’s just that I’ve never won and so I’ve never seen a win screen!)


Cave 64

Basic graphics, but has potential to be developed into something!


Battle Box (LowRezJam)

I’m not sure I wholly understand what I’m doing, here. I can roll around, shoot white blocks (which moves them), and shoot the enemy (which moves them but doesn’t kill them, to my surprise), but… then what? I like the conceit of the rolling cube which fires in a particular direction, much like a bunch of single-player puzzles of this kind. The time limit on a move makes it all feel rather rushed, which is a little unfortunate because it makes the game feel like a very low rez arena deathmatch, rather than like a carefully thought-out chess game.


Endless Burger

I wish there were some sound in this. That the merest touch of a burger bap on my mostly-complete burger counts as instadeath means that I end up playing the game by merely fleeing from burger tops like a gluten-free lunatic with a flour phobia, but that’s perhaps part of the skill of the game.But without sound, it feels half-finished. This wouldn’t take much to be turned into a really challenging game, I think!


GhostShi

Sadly, the “up” and “down” abilities didn’t seem to work for me, so all I could seem to do is walk off the edge into the first water pool and die. Maybe there’s something I missed, but a little tutorial level might have helped if there’s an action I didn’t know to do. Nice graphics and feel.


Total Devotion

This is alarmingly creepy. It also shamelessly violates the 64x64 pixel grid :)


Forms II : Hero Of the Office

An interesting concept. After the first day, the screen went red and I didn’t seem to be able to do anything else, sadly. I like the graphical approach and the idea behind it, though!


Gravimine

Took me some time to realise that collisions with (a) the rocks you’re trying to mine and (b) the bottom of the tractor beam (?) are fatal and I’m supposed to avoid that. Once I’d got it, there is potential here; it’s Thrust, but with the added attraction that the rock follows you around and you mustn’t collide with it. Obviously it’s just a prototype and therefore doesn’t have music or backstory or anything, but I think this could be quite entertaining once it becomes a game!


Big Sword

Nice feel, especially the squelch on hitting something. It does lend itself a bit to button mashing, but that’s part of the old-school fun :)


babelburger

I don’t think I’d eat a burger which had a burger bun, a slice of lettuce, another slice of lettuce, and two more burger buns. Might be a bit bland :) That aside, the game takes real advantage of its low resolution and is rather fun! The logo’s delightful, too. It’s a little hard in initial play, perhaps; softening the difficulty curve just a tiny bit might be useful, so people can get beyond about two burgers without having to be the Flash. I suspect this might be easier with a touchscreen…


Bring Your Wedge

Yay! 64 points! I still don’t think I’ve quite grasped what the perfect tempo is, but I like the game a lot; quite a compelling challenge, and getting a hole in one is lovely :)


Snakoban

Surprisingly difficult for such a simple game mechanic! It would be worth cancelling the keypresses after you’ve trapped them, so that up/down arrows don’t navigate up and down the page.


Looping Zip

Simple gameplay and easy to grasp, but rather hard to master! It may be worth prohibiting space bar presses from changing direction if they’re pressed after the game has “started” but before the ship has actually started moving, because a few times I hit space to start when I thought my previous press hadn’t been registered, only to discover that it had been registered but the ship is slow to get started.


QWER

Needs, I think, a little tutorial bit or similar to explain the mechanics? I managed to have two of my shapes completely disappear but I don’t know whether that was a good thing or a bad…


A Leader

Hard to work out what to do to pick up people and avoid losing them; it feels like this might be a good twitch game, or a good puzzle game, but trying to solve the puzzle of how to bypass each impediment and pick up each person while also trying to manage the twitch element of doing it all at the right time is overwhelming my poor brain…


Lament

The controls are… a bit difficult to get one’s head around, but once mastered they’re OK. That you can’t stop on a wall (you can either climb or slide, but not stay still) is a touch weird, but getting to grips with that is the required skill, perhaps. The music is a cool track but maybe a bit overdramatic for the actual gameplay. This is the kernel of a good idea, I think; could be good with work.


1985

Nicely done. Feels very old-school, in a good way; I can absolutely imagine this being a released game back in the day.


bitbout

Was driven nuts by the lack of friction on the platforms, at which I’m sure the author was cackling and rubbing their hands in glee because that’s the point. Having a computer enemy would be good for practice, although I fell off enough all by myself…


PRTs

Delightful graphics; the limited palette really helps! Sailing around does feel a bit aimless, especially since I don’t seem to be able to re-visit an island where I died (does it sink back into the sea when the crabs make a kill or something?). Once I’d worked out that the combat relied on me hitting the arrow keys in time with those on screen rather than just as fast as possible, I never lost another battle, so that was nice :)


Dual Wielded

Flinging myself around by firing guns is interesting; reminds me of the XKCD What If article about flying by building a platform of AK-47s! Nice low-res graphics, too, and choice of protagonist.


H4LFL1F3

Nice effects on the title screen. Game seems smooth but occasionally the framerate drops. I killed a monster but then wasn’t sure what to do; shooting the “cells” seems to make them react, but they don’t die, and shooting the big “cell” in the middle makes the screen flash and we get a “gasp!” sound effect but that doesn’t die either.


The Legend of Fangury

Classic, indeed, but well implemented. I particularly appreciate that inadvertently touching an enemy is not instadeath! I do occasionally find myself leaping a bit into the unknown because it’s hard to see what’s coming up, but perhaps that’s a feature rather than a bug.


Swarm

I think this is hurt by the 64x64 limitation; it feels like I’m frantically moving my tiny letterbox around the map searching for a flower under attack as pointed to by the indicators. Of course, that’s part of the game, but it’s probably a bit far over the frustrating-vs-fun line for me. I also spent almost the whole first playthrough thinking that the little darker green “grass” things were flowers and failing to understand why nothing worked :) The swarming effect is really nice!


OR-BIT

Avoiding things is really, really hard. Not, like, “I must get expertise” hard, but “solid wall of unavoidable rocks” hard. I like the slightly drifty slow uncontrollable nature of the astronaut, which fits with the low-gravity backstory, but combining that with the sheer volume of rocks makes survival pretty much impossible…


Potion Guesser

It’s very hard to know which ingredient is currently selected, and it’s possible to select the “right arrow” even when you’re at the end of the list, meaning that I spent half the time baffled that mouse clicks weren’t doing anything. Other than that, the UI seems quite smooth and nice. The game’s a lot harder because you can’t use the same ingredient twice! I expected the “troll’s eye” to do something special because I was especially given it in the opening cutscene, but maybe that’s just misinterpretation.


Pixel Eater

Obviously very minimal in graphics (and no sound at all), but the idea is reasonable. Interestingly, I expected red berries to be an instakill and was pleased to see that they drop you a size category instead. The game is very easy, though; I won on the second and all subsequent tries :-)


BNOD

Agreed with other comments; I don’t get the rules. I don’t see what FRIENDS? or SPACE actually mean. Possibly the whole game is to work that out, but the hurdle makes me turn away rather than puzzle to figure it out :(


Oort

(no sound, though?) Obviously unfinished, as mentioned in the description. That said, I like that the jumps are absurdly high by comparison with other platforms (and in addition to this absurdly high jump we have a double jump which is doubly absurdly high); it changse the way I think about the game a surprising amount for such a nominally small change. Being followed about by the nasty things with red eyes and being unable to shake them off is also an interesting mechanic, and I like their hammers. As noted, the space-to-“attack” thing doesn’t actually do anything other than draw a dotted circle around me and freeze the game, so i suspect that’s not yet implemented. But there’s the core of a good thing here; interesting graphics, interesting divergence from standard platforming rules with the high jump, and I’d like to see more.

And the game I thought was best…

Slumber Knight

Great fun game; graphics are well done, sound matched, good feel to the game. Nice one! Full marks.

I really liked Slumber Knight. Delightful graphics and feel. I confessed to the developer on Twitter that I ended up hacking the game a bit so I could see how it ended, by making myself immune to collisions, but that’s not a bad thing about the game, it’s a bad thing about my impatience. It’s excellent work.

And… what I did

I did, of course, enter a game myself. It’s called “Have You Seen This Image?“, and you can play it. It was deliberately simple — I didn’t want to devote much time to writing it — but I really enjoyed the experience of building a complete game, releasing it, and seeing people rate it. A pretty common theme in the comments was that it doesn’t _quite_ explain exactly what you need to do, but I think everybody gets it after one playthrough, and playthroughs are very quick indeed. (I put some effort into making sure that you can start again without having to wait as soon as you die.) The juxtaposition of the abusive failure messages with the marvellously jaunty music still makes me laugh every time I play it. (The music is Pixelland from the incomparable Kevin MacLeod.) Images were from Wikipedia; after some help from the #wikimedia-tech IRC channel, I discovered Quarry which allows you to run arbitrary SQL queries against the Wikimedia databases from inside the browser, and is a very excellent thing indeed. So I wrote a query to return all 64x64 images from Wikimedia Commons and then picked a bunch of them. In order to make the game more difficult, I then made three copies of each image, tinted blue, red, and green respectively, so you’d see images that you might have seen before but in different colours. And that was that. There’s a bug in there somewhere which causes two success sounds to play at once (so you get the game saying “Awesome!” _and_ “Fantastic!” when you get it right sometimes), but after trying and failing to work out why, I’ve reclassified it as a feature because it amuses me to hear the sounds anyway. So, conclusion: writing a game is fun; hanging out with the game jam community is fun; thank you to popey for nudging me into doing it; and I came 72nd for game feel, which I am perfectly happy with. Must do this again at some point.

CSS colour words in hex

$
0
0

One of the nice little fillips about writing CSS is that occasionally you use a colour code which turns out to be a word; the most famous here is probably #DECADE. I ran across bada55.io which has made a whole site from this and was quite pleased, but the terrible old grammarian in me just can’t deal with the l33tsp34k nature of most of the suggestions. You’re obviously allowed A to F, and I’m prepared to allow 0 as O and 1 as I, but using 5 as an S or 3 as E is dubious, using 1 as an L is exceptionally dubious (especially when it’s already being an I in the same word!), and 7 for T or 4 for A or 6/G or (incomprehensibly) 9/P are right out. The fun nature of the game goes away when you have to puzzle out the meaning of the word like it’s a crossword clue or one of those horrid personalised number plates.

So, if we excise these crimes against spelling, all the colours that make what I consider to be proper words are below. There are obviously rather a lot of pastel shades, since each of the red, green, and blue channels will almost certainly be A0 or larger, but that’s not necessarily a problem (and there are a couple of decent highly-saturated colours in there too; I’m particularly fond of #AC1D1C and plan to use it more often). If we admit white and black into the palette, it’d almost certainly be possible to build a site while drawing solely from this list for your colour choices. Something to bear in mind for a future project, maybe.

  • abided
  • acacia
  • accede
  • acidic
  • babied
  • baobab
  • beaded
  • bedded
  • beefed
  • bobbed
  • bodice
  • boobed
  • cabbed
  • cabbie
  • caddie
  • cicada
  • codded
  • coffee
  • coifed
  • dabbed
  • decade
  • decide
  • decode
  • deeded
  • deface
  • defied
  • deiced
  • doffed
  • doodad
  • eddied
  • efface
  • facade
  • fibbed
  • fobbed
  • office

Addendum: I forgot about three-character hex colour codes! Of which there are also quite a few, and we do a lot better at the saturated ones this time because a whole channel is quite often 0 or 1. Although it’s less lexicographically elegant to use a three-character word.

  • ace
  • add
  • ado
  • aid
  • baa
  • bad
  • bed
  • bee
  • bib
  • bid
  • boa
  • bob
  • boo
  • cab
  • cad
  • cob
  • cod
  • coo
  • dab
  • dad
  • deb
  • did
  • die
  • doc
  • doe
  • ebb
  • fad
  • fed
  • fee
  • fib
  • fie
  • fob
  • foe
  • ice
  • oaf
  • odd
  • ode
  • oof
  • off

Addendum addendum: Matthew Somerville points out a few more words, of varying acceptability in formal conversation :) I can only plead that /usr/share/dict/words didn’t contain the better ones in here (IODIDE and BODIED), and reiterate that I’m not including BAE anywhere and I don’t care if you think it’s a word. Also, the CSS Colour Module Level 4 spec dangles the tantalising possibility of eight-hex-digit codes which can include an alpha channel (#rrggbbaa) which would bring the excellent CODIFIED and ACIDIFIC into the list, as well as the increasingly Latinate FABACEAE, IBIDIDAE, and COCCIDAE.

  • BABBIE
  • BODIED
  • DOBBED
  • IDEAED
  • IODIDE
  • FAB
  • DIB
  • BOD

The importance of URLs

$
0
0
“You don’t control Xykon! He controls you!”
“Like I said: subtle.”

Redcloak, The Order of the Stick

Lots of discussion about progressive web apps recently, with a general consensus among forward-thinking web people that this is the way we should be building things for the web from now on. Websites that work offline, that deal well with lie-fi1, that are responsive, that are progressive, that work everywhere but are better on devices that can cope with the glory. Alex Russell, who originally coined the term, talks about PWAs being responsive, connectivity independent, fresh, safe, discoverable, re-engageable, installable, linkable, and having app-like interactions.

We could discuss every part of that description, every word in that definition, for hours and hours, and if someone wants to nominate a pub with decent beer then I’m more than happy to have that discussion and a pint while doing it. But today, we’re talking about the word linkable.

Linkability

Jeremy tweeted:

Strongly disagree with Lighthouse wanting “Manifest’s display property set to standalone/fullscreen to allow launching without address bar.”

Jeremy Keith

A little background

First, a little background. Google Chrome attempts to detect whether the website you’re looking at “qualifies” as a Progressive Web App, because if it does then they will show an “install to home screen” banner on your second visit. This is a major improvement over the previous state of a user having to manually install a site they like to their home screen by fishing through the menus2 or using the “add to home screen” button in iOS Safari3. The Chrome team have then created Lighthouse, a tool which invokes a Chrome browser, checks whether a site passes their checks for “this looks like a PWA”, and returns a result.

So Jeremy’s point is this: Lighthouse is declaring that to be a valid PWA, you have to insist that when you’re added to the home screen, you stop showing the URL bar. And he doesn’t agree, because

I want people to be able to copy URLs. I want people to be able to hack URLs. I’m not ashamed of my URLs …I’m downright proud.

Jeremy Keith

This is inspirational stuff, and it’s true. URLs are important. Individual addressability of parts on the web is important.

However. (You knew there was a “however” coming.) Whether your web app shows a URL bar is not actually a thing about that web app.

A little more background

A bit more background. In order to qualify as a progressive web app, you have to provide a manifest.4 That manifest lists various properties about this web app which are useful to operating systems: what its human-readable name is, what a human-readable short name for it is, what its icon should be, a theme colour for it, and so on. This is all good.

But the manifest also lists a display_mode, defined in the spec as “how the web application is being presented within the context of an OS (e.g., in fullscreen, etc.)” Essentially, the options for the display mode are fullscreen (the app will take all the screen; hardware keys and the status bar will not be shown), standalone (no browser UI is shown, but the hardware keys and status bar will be displayed), and browser (the app will be shown with normal browser UI, ie. as a normal website).

Now we see Jeremy’s point. Chrome propose that you only qualify as a “real” PWA if you request “fullscreen” or “standalone” mode: that is, that you hide the URL bar. Jeremy says that URLs are important; they’re not a thing to hide away or to pretend that don’t exist. And he has a point. The hackability of URLs is surprisingly important, and unsurprisingly dismissed by app developers who want to lock down the user experience.

But, and this is the important point, whether a web app shows its URLs is not a property of that app. It’s a property of how that app’s developer thinks about the web.

Property versus preference

If Jeremy and I were both to work on a website, and then discuss what should be in the manifest, we’d agree on what the app’s name was, what a shortened name was, what the icon is. But we might disagree on whether the app should show a URL bar when launched. That disagreement isn’t about the app itself; it’s about whether you, the developer, think it’s OK to hide that an app is actually on the web, or whether you should proudly declare that it’s on the web. That doesn’t differ from app to app; it differs from developer to developer. The app manifest declares properties of the app, but the display property isn’t about the app; it’s about how the app’s developer wants it to be shown. Do they want to proudly declare that this app is on the web and of the web? Then they’ll add the URL bar. Do they want to conceal that this is actually a web app in order to look more like “native” apps? Then they’ll hide the URL bar. The display property feels rather less like it’s actually tied to the app, and rather more like it should be chosen at “add-to-home-screen” time by the user; do you, the bookmarking user, prefer to think of this as a web thing? Include the URL bar. Do you want to think of it as an app which doesn’t involve the web? Hide the URL bar. It’s a preference. It’s not a property.

On the desktop

The above argument stands alone. But there are additional issues with having a URL bar showing on an added-to-home-screen web app. We should discuss these separately, but here I have them in the same essay because it’s all relevant.

The additional issue is, essentially, this. On my desktop — not my phone — I add an app to my “home screen”. This might add it to my desktop as a shortcut icon, or to my Start Menu, or in the Applications list, or all of the above, depending on which OS I’m on.5 If that PWA declares itself as being standalone then how to handle it is obvious: open it in a new window, with no URL bar showing. Similarly, fullscreen web apps launched from an icon should be full screen. But what do we do when launching a browser display-mode web app on a desktop?

Since we’re launching something indistinguishable from just another browser tab, it should launch a browser tab, right? I mean, we’re opening something which is essentially a bookmark. But… wouldn’t it feel strange to you to pick something from your app menu or an icon from your desktop and have it just open a browser tab? It would for me, at least. So maybe we should launch a new browser window, with URL bar intact, as though you’d clicked “open in new window” on a link. But then I’d have a whole new browser window for something which doesn’t really deserve a whole new window; it’s just one more web page, so why does it get a window by itself? I manage my browser windows according to project; window A has tabs relevant to project A, window B has tabs relevant to project B, and so on. I don’t want a whole new window, and indeed I have extensions installed so that links which think they deserve a new window actually get a new tab instead.

It’s not very clear what should happen here. The whole idea of launching a website from an OS-level icon doesn’t actually mesh very well at all with the idea of tabbed browser windows. It does mesh well with the 2002-era idea of a-new-browser-window-for-every-URL, but that idea has gone away. We have tabbed browsing, and people like it.6

The Chrome team’s idea, that basically you can’t add an “OS-level bookmark” for a website which wants to be treated as a website, avoids these problems.

Jeremy’s got a point, though. Hiding away URLs, pretending that this thing you’re looking at is a “native” app, does indeed sacrifice one of the key strengths of the web — that everything’s individually addressable. You can’t bookmark the “account” page in Steam, or the “settings” window in Keynote or Word or LibreOffice. With the web, you can. That’s a good thing. We shouldn’t give it up lightly. But you already can’t do that for apps which use web technologies but pretend to be native. If Word or iTunes used a WebView to render its preferences dialog, would it be good if you could link directly to it with a URL like itunes://settings? Yes it would. Would it be good if the iTunes user interface had a URL bar at the top showing that URL all the time? Not really, no.

There is a paternalism discussion, here. URLs are a good thing about the web; the addressability of parts is a good thing about the web. People don’t necessarily appreciate that. How much effort should we put into making this stuff available even though people don’t want it, because they’re wrong to not want it? Do we actually know better than they do? I think: yes we do.7 But I don’t know how important that is, when we can also win people over to the web by pretending that it’s native apps, which is what people wrongly want.

Conclusions

On balance, therefore, I approve of the Lighthouse team’s idea that you don’t qualify as an add-to-home-screen-able app if you want a URL bar. I can see the argument against this, and I do agree that we’re giving up something important, something fundamental to the web by hiding away URLs. But I think that wanting to see the URL is not a property of an app; it’s a property of how you personally want to deal with apps. So browsers should, when adding things to the home screen, pretend that display:browser actually said display:standalone, but give people who care the ability to override that if they want. And if we want more people to care, then that’s what evangelism is for; having individual app developers decide how they want their app to be displayed just leads to fragmentation. Let’s educate people on why URLs are important, and then they can flip a switch and see the URLs for everything they use… but until we’ve convinced them, let’s not force them to see the URLs when what they want is a native-like experience.

  1. Jake Archibald eloquently names lie-fi as that situation where your phone claims to have a connection but actually it doesn’t, the lying sack of dingo’s entrails that it is, and just spins forever when you tell it to connect to a website. If you’ve ever toggled a device into airplane mode and back out again, you know what we’re talking about
  2. although the Chrome approach is not without its problems
  3. which is obscure enough that Matteo Spinelli made a library to show a pointer to the add-to-home-screen button; the library is wonderful, don’t get me wrong, but it ought to not need to exist
  4. If you don’t know how to create one, see the manifest generator that Bruce and I created
  5. and it should be noted that basically nobody actually handles PWAs properly on desktop yet; it’s all about mobile. But desktop is coming, and we’ll need to solve this.
  6. Whether tabbed browsing actually makes conceptual sense is not up for discussion, here; we’ve collectively decided to use it, much as we’ve collectively decided that one-file-manager-window-per-folder isn’t the way we want to go either.
  7. Hubris is a great idea. The Greeks taught us that.

Programmatic Progressiveness

$
0
0

The Chrome team have put together a thing called Lighthouse, a programmatic checker for whether a website is a progressive web app. It’s a nice structure; it goes through a big list of checks on whether you’ve got a manifest, whether performance is good, if the site’s HTTPS, if you’ve got icons defined, so on and so forth, and it’s possible to add more (many more!) checks to the list. You can think of it as the list of criteria that a browser should use to tell whether it should put up the “add to home screen” button.

However, as has been previously mentioned by me and others, there is a bit of a worry that we’re missing out on the Progressive part of Progressive Web Apps; that in the rush to check that you support exciting new features such as manifests and service workers, we’re not also checking that your web site provides content to everyone, that it progressively uses those new features where they’re available rather than requiring them to be present, that you’re available to everyone and not just to the hippest.

A brief diversion, here: I have occasionally probably strayed over the line from “why aren’t we doing better at this” (which I do think) into “why don’t the Chrome team care about this”, and that’s not fair. Sorry, Chrome people. Accusation not justified.

Anyway, what I’d like to see is Lighthouse actually checking that your app is progressive as well as featureful. This is harder than it looks; progressive enhancement, like accessibility, is difficult to check programmatically. It’s easy for a human to confirm that this site can still perform its basic actions if its scripts are blocked; it’s a lot more difficult for a computer to do so. I don’t think we’ll ever be able to say “yes, you have definitely done everything right”, here, much like we can’t with accessibility. But we can flag that you’ve done things wrong.

So, I’ve now got some code in Lighthouse which is a place we can build programmatic checks for progressiveness. At the moment it literally only checks whether there is any content at all if your scripts don’t load, and complains if you do not. That will catch sites which just serve <body></body> and create their whole entire UI in JavaScript; such sites are (thankfully) rare now, after a spate of them existing a few years ago. But we can do better than this. Yes, it’s difficult to adequately create such tests, but if we can land a man on the moon we can come up with checks here, too. So, I’d like to start a discussion around how we can programmatically check for signs that a website isn’t doing progressive enhancement. What should we look for to show you’re doing it right; what should we look for to show you’re doing it wrong? If you have ideas, a good place to discuss them may be by filing issues against Lighthouse; there, we can hash out details of whether a check makes sense, whether it’s a good idea, how it can be made better. And then someone can build that check; if you’re a developer, you can add an “audit” to Lighthouse which has access to the page text and HTML and checks for warning signs or good signs and adds them to the report that Lighthouse creates. This is our chance to help stamp out sites that don’t do things right, and help define that a progressive web app should actually be progressive. I’d love you to help.

Making a better Ubuntu app scope (not very successfully)

$
0
0

I was rather excited to discover the idea that one could change the icons used on an Android phone’s home screen. (As Sam Hewitt put it, I have “become a themer”.) I didn’t know this was doable, and I went from not knowing this to having it done in the space of about half an hour. It is rare that something just works this nicely; I’ve been living my life a long time and I know how it works. So far, the other shoe hasn’t dropped, which is encouraging.

At first, there was Android

Anyway, my Android home screen now looks like this:

I’m pretty pleased with that. (The lock screen is even more minimal and pretty, but we’re not talking about lock screens today: see the G+ post for what that looks like.)

There is a UI concern here — in general, I don’t like using icons without text to indicate a thing, because it means you’re spending cognitive time remembering what an icon stands for rather than what it’s similar to. That is: icons are quite good for, say, files where you want to see that all of these are .txt files, but they’re not good for actions where you have to remember what a “heart” or some obscure little symbol means. I’ve lost count of the number of times when I’ve used a new app which only has icons and not text labels on its buttons and I have no idea what half the icons do; a few things are enshrined by everyone using them (a Share icon, a Save icon, an Open icon, etc) but most of the time using an icon alone to indicate an action or an app is a bad idea. However, this is an exception to that rule. I am very familiar with my home screen; the set of apps on it do not change very much at all. So there’s minimal cognitive load in remembering that this icon is for Twitter and that one is for Moon Reader. I do a reasonable proportion of that by spatial arrangement; the icons don’t move around, and I am familiar and trained in where they are. You wouldn’t want to ship a phone which looks like this to a new user, but it’s a perfectly good experience for me, with my own personal home screen that I know well.

How is this beautiful miracle achieved? Well. The default Android home screen doesn’t let you change the icons used for apps. So when I discovered the (free!) Lines icon set in the Play store my immediate thought was, cor, how does that work? And the answer is: use a different home screen app (in Android parlance, they’re called launchers). So I installed Nova Launcher. (This also had the rather nice benefit of allowing me to remove the hated Google search bar; I never, ever, ever used that because it shows results in some Google app rather than the web, meaning that you can’t long-press on images to save them or on links to open in a new tab. Pack it in, Google. Open in the browser. It’s good at that.) A little bit of setup with Nova Launcher and Lines and, lo, I had the nice minimal icons and pretty dark wallpaper (which came with Lines). Nova Launcher doesn’t let you resize the icons, and by default they’re a bit small, but you can buy the Nova Launcher Prime add-on to enable that, and it was fifty pence so that’s a no-brainer. The Lines icon set is both worryingly comprehensive (they claim to have over two thousand icons!) and equally worryingly incomplete (with a million apps in the Play store they’re never going to carry them all, but not having Telegram? Seriously?) and so I added two more similar-looking icon sets (Min and Glyphsy) to give me a wider choice. A bunch of tweaking of icon sizes, icon choices, margin sizes, and so on later and I have the screen above, and every time I look at it I like it a little more. Ultra-happy with it.

And then there was Ubuntu

I thought to myself, hang on, it ought to be possible to do the same thing with Ubuntu phone, right? One can write a custom scope which looks like that and shows all one’s apps, and add it to the Dash as the only scope, and then you’ve got a cool-looking app-launcher home screen. Sweet. That’s what I want. And it’ll give me an excuse to play with all the new scopes stuff and learn something about it.

Not so fast, grasshopper.

Here’s my basic idea. The existing apps scope is annoyingly slow; I’m sure it does a whole bunch of stuff and that’s why, but it’s slow to load, slow to scroll, and slow to react to things changing. This is obviously being worked on by the Canonical team and I’m sure it’ll get better, but currently it’s pretty frustrating. So I thought: what I’ll do is this. I’ll add a click hook so when apps get installed and removed I can update a sqlite database, and then my scope will just hit that database rather than inspecting the filesystem and loading loads of files. That database can also hold the locations of icons in my custom “wireframe” icon theme, and it’ll use those icons for the apps. So it’ll be fast and have custom icons, and tapping an icon will launch that app via an application:/// url. Job’s a good’un, etc. Off down the pub.

It was not as easy as I had hoped.

There are a few things that made the task difficult and which are basically my fault and for which no blame attaches to the Ubuntu team. Firstly, I’m still running Ubuntu 14.04. This is because it’s an long-term-support release, and LTSes don’t offer to upgrade to the next LTS release (16.04, which came out in April) until the first point release (16.04.1, which isn’t out at time of writing). This is so the new LTS gets a bit of testing before it hits all the people who desire stability, and is a good idea, and I am entirely happy with it. Secondly, I wanted to write the scope in JavaScript; one can write Unity 8 scopes in C++ (which I can’t do), Go (which I can’t do), and JS via node (which I am completely comfortable with). But the JS scopes stuff is new, and so doesn’t exist in 14.04. This meant that I had to do a great deal of faffing around in lxc containers to get a working version of a JS scope. However, that faffery did actually work out in the end, and it’s hard to see the need for it as due to anything more than my own desire to not upgrade away from the latest stable release LTS. So, no blame there, as mentioned. After a bit of poking, I managed to get a JavaScript scope, and some discussions with Brian Douglass and one tiny bash deploy script later (which basically does click build . and then adb pushes the .click file to my Bq E4.5 and pkcon install-locals it), I had a scope that I’d written running on the phone. Hooray! Now to make that scope actually do and look as I want it to.

This is where we run into problems. The JavaScript scopes stuff is, admittedly, new, but it had two major issues that caused me a great deal of grief. The first is that making async fs.readdir calls early in a scope search() handler were making my scope crash, and sometimes crashing all of Unity. (LP#1598967) Oops. That took some time debugging before I eventually went for the synchronous fs.readdirSync, cursing all the while. Worse, though, is the activate problem. You see, a scope, by default, when a thing is tapped shows you the preview page for that thing. However, you can change things so that a tap on a thing does something directly; in this case, of course, I wanted a tap on one of my app icons to launch that app via the URL dispatcher. To do that, you call set_intercept_activation() on a scope icon when you create it, and then Unity will call your scope’s runtime_config.activate() method with the details when that icon is tapped; you can then handle it in whatever way you want, or return an ActivationNotHandled type of ActivationResponse to let Unity handle it for you, which in this case means “open the app with the url you provided”. (You can see a good example of how this works in Go in Brian Douglass’s Falcon alternative app scope.) However! If you do that in JavaScript, your scope ignores the tap and throws an error about how you returned nullptr from activate(). (LP#1598969.) As the bug says, “this, in practice, means it’s impossible to write a JS scope which allows tapping on a result item to do anything other than show the preview (for example, launching an app).”

(The observant will notice that the JS scopes documentation doesn’t actually mentionActivationResponse or even that activate() handlers are possible in scope.initialize(), which will hopefully get better as the docs get written.)

Now, that’s just a bug, and I’m sure it’ll get fixed (I’m sure they’ll all be fixed). It is frustrating (has nobody writing the JS scopes stuff ever triedset_intercept_activation()? Isn’t there lots of QA built into the Ubuntu process now?) But it’s a temporary thing, I’m sure, and in the same class of “frustrating and show-stopping but will be fixed eventually” things as how unity-js-scopes-tool doesn’t build node-pre-gyp packages (LP#1598971) or that unity-js-scopes-tool seems to actually be the node binary itself but that’s carefully kept secret for some reason, or that you have to remove and reinstall an app if you change the apparmor stuff otherwise the changes aren’t picked up (LP#1549369) which cost me an hour of banging my head against the desk (thanks mzanetti for helping). They’ll get fixed. Move on.

The things which actually stopped me building the scope I wanted weren’t these sorts of incidental bugs; they’re design decisions saying that what I want should not be possible. I’m hoping that the detail I’m going into here helps to explain why I want these things, and perhaps makes its way back to the team deciding on this stuff and helps to inform their decisions.

For example. You see how my Android screen above has four columns of app icons? Like the Ubuntu apps scope has? Well… my replacement scope can’t. Scopes are only allowed three columns of icons. The apps scope has been magically hardcoded into Unity to be allowed four columns; nobody else can do that. That’s pretty annoying.

Similarly, customisation of the look of a scope is superficially good but actually rather limited. A scope header can have a custom background image, but a scope itself can’t; you can pick a colour, but you can’t set an image as the background for your scope. (LP#1598973) Scopes put the “Ubuntu shape” around all your scope icons, but you can turn that off by settings ShapeImages=false in your scope ini file. Except… that doesn’t work; it’s ignored, and you always get the Ubuntu shape border on every image, whether you want it or not. (LP#1598933) I understand the idea behind shaping imagery, but it looks heart-stoppingly ugly when done to icons with transparent backgrounds, such as all the “wireframe” icons I planned to use in this project. You can have settings for your scope, but they can’t change the appearance, because that stuff’s not programmatic; it’s in the scope.ini file and can’t be changed by code. So I can’t allow people to have a dark scope with white icons (as above) or choose a light scope with black icons. Also, making a replacement apps scope is essentially fruitless because the default apps scope cannot be removed. You can’t turn it off; it must be present in your Dash. This to me seems strange; I’m fine with you not being able to delete it, but it will always be present in the bottom-edge menu. Fine, maybe making replacement apps scopes is an edge case, but it’s hard to get the feeling that my phone is mine when I’m obliged to keep the default apps scope around even if I’ve got a replacement.

Oh, and the idea of making the scope fast by populating a database? You can’t have that, either. Yes, there are click hooks. But you can’t install one. They must be stored in /usr/share/click/hooks, and that’s part of the system image, which is read-only. What this means is that there’s no way that a third-party app will ever be able to be informed of app installs and removals, sadly. I can put an app which requires extra permissions into the Open Store, but even such an app can’t install a click hook; I’d have to make it a deb, and even then a deb won’t install either unless you mark your image as read-write, which requires plugging it into a computer. Talking someone through that process is close to impossible unless they’re the hardest of the hardcore Ubuntu touch hackers. Perhaps click might look in some other folder as well, which is accessible to apps, and have a new apparmor permission protect that folder? Then it would be possible for an application to request that permission and keep a database of installed and removed apps up to date, which would allow us to compete on making a better app launching experience.

So all this means that the best I can do on Ubuntu is this. Ubuntu shapes around the transparent icons, no background imagery, three columns. And that’s just not pretty, I’m sad to say.

(I freely admit that some of this is down to the icons, which I drew quickly, and some more is down to the E4.5 having much worse screen resolution than my OnePlus X. But those aren’t the only things.)

Anyway. I still have my beautiful Android home screen. But I’ve reluctantly decided that I just can’t do that on Ubuntu. Maybe it’ll be possible later; maybe these bugs will be fixed and the design decisions revisited. I hope the above explains why I think that’s important and what app developers could maybe do if those restrictions are slightly relaxed. Fingers crossed.

Feeling old, depending on how old you are

$
0
0

I recently discovered Martin O’Leary‘s Feeling Old twitter bot,1 which has a big list of “things that have happened” and then constructs comparisons such as “Y2K was as close to the release of Return of the Jedi as to now”, to make you do that weird “wow, I am old!” double-take. As Martin says, it occasionally throws out a gem. But, looking through the list, I think that they’re probably all gems, but whether they hit home for you depends on how old you are.

Basically, the form of the sentence is: thing is closer to old thing than to today. Ideally, you want thing to be something that you think is recent, and old thing to be something that you think is ancient, and therefore you’ll be surprised that thing really isn’t actually recent and that’s because you’re a decrepit old codger.

My theory is this: old thing ought to be before you were born. By definition, anything that happens before you were born feels like a long time ago to you. And the gap between thing and old thing is the same as the gap between thing and now (because that’s what constructs the sentences). So thing has to happen in the first half of your life. Stuff that happens while you’re a young child also feels like a long time ago — you were a kid when it happened! — so we want something that happened once you started to feel like you in your head. Say, around 12 or so years of age. Thus, we take a big list of pop culture things, find an event which happened between the ages of 12 and half your current age, find a corresponding old event, display them to you, and have you be surprised and displeased. It’s a living.

Give it a try.

I was born

  1. because I was reading his excellent work on how to create accurate looking fantasy maps

My nominations for the Silicon Canal Tech Awards 2016

$
0
0

The Silicon Canal tech awards are coming up here in Birmingham, so I thought I’d write down who I’ve nominated and why! Along with a few categories where I had difficulty deciding, in which an honourable mention or two may be awarded, although such things do not get submitted to the actual award ceremony :-)

Best Tech Start-Up

ImpactHub Birmingham

As ImpactHub say, “We want to empower a collective movement to bring about change in our city, embracing a diverse range of people and organisations with a whole host of experiences and skills.” ImpactHub is a place enabling the tech scene in Birmingham, which is the most important part of it all; that’s what makes Birmingham great and more than just some half-baked clone of London or San Francisco. Bringing tech companies together with the rest of the city also hugely increases the number of connections made and opportunities created right here in Birmingham itself, and helps tech entrepreneurs meet other communities and unify everyone’s goals.

Most Influential Female in Technology

Jessica Rose

Jess tirelessly advocates technology and Birmingham, both inside and outside the city. She’s great at connecting dots, showing people who they can work with to get things done, and advising on how best to grow a community or a company into areas you might not have otherwise pursued. And she’s helpful and engaging and good to work with, and knows basically everyone. That’s influence, and she’s using it to better the Brum tech scene as a whole, and that deserves reward.

Runner up:Immy Kaur for setting up ImpactHub :-)

Small Tech Company of the Year

Technical Team Solutions

TTS are heavily invested in the tech life of Birmingham itself. They sponsor events, they’ve partnered with Silicon Canal as exclusive recruitment agents, and most importantly they’re behind Fusion, a regular and vibrant quarterly tech conference drawn from the city and supporting both local tech and local street food vendors. This isn’t like some other conferences which basically are in Birmingham by coincidence; Fusion is intimately involved with the Brum tech scene, as are TTS themselves, and that should be massively encouraged.

Runner up:Jump 24, web design and development studio getting good stuff done and run by a very smart and very short Welshman1 :-)

Large Tech Company of the Year (revenue over £10 million)

Talis

Talis are strong supporters of the Birmingham tech scene, a successful large scaleup here in the city, and willing to work openly with others in pursuit of those goals. They regularly sponsor tech events with money or by providing space to host meetups, hold hack days and write about them afterwards, donate time and money to helping others in the city including events for entrepreneurs as well as developers, and run their own events (such as Codelicious) to add more to the growing vibrancy of Brum. It’s great to see a company of this size be cognisant of the city and their life within it, and this certainly deserves to be recognised.

Most Influential Male in Technology

Roy Meredith

A jolly good way to make connections in the city is through Roy, who is connected to all sorts of people via being responsible for the tech sectors in Marketing Birmingham. I’m not sure the government marketing agency are always perfect, but I am sure that Roy is a person to know. He’s an engaging public speaker, he’s got a background in industry (with a list of AAA games he’s worked on that’d blow your mind), and he’s approachable and smart and everyone listens to him. If that’s not influence, I don’t know what is.

Outstanding Technology Individual of the Year

Mary Matthews from Memrica

Mary describes herself as “passionate about using technology to make a difference to people’s lives” and, unlike quite a few people who might say that, I think she actually means it. It was marvellous to see Memrica get recognised as part of the UberPITCH consultancy earlier this year, and her trip out to meet Travis Kalanick not only will have helped her continue her long history of doing good tech things but also helped elevate Birmingham’s profile as a place for internationally recognised startups. That’s pretty outstanding, in my opinion.

Runner up:Jess Rose

Others

Best Angel or Seed Investor of the Year: no nomination here because I have no idea! I know a couple, but haven’t worked with them.

Graduate Developer of the Year: no nomination here because I don’t know enough graduates. I’d have nominated @jackweirdy if he hadn’t left us :)

Developer of the Year: no nomination here because, well, too contentious. I don’t know who I’d pick as the best, and I do know that everyone I don’t pick will never buy me a pint again, so I’m not sure who to say here. Maybe I should have just picked myself :-)

Now, your turn

Maybe you agree, maybe you don’t. That’s what I think. You will notice that I primarily care about the tech life of the city; if you do a bunch of good stuff here in Birmingham and you’re proud of that, I like what you do. If you do interesting things but never talk about them here in the city, I’m less interested in your things. Perhaps you have different criteria: you should now go and say what you think. Go and add your nominations, Birmingham people; let’s get everyone’s voices heard.

  1. sorry, Dan; Fusion just tips it for TTS, but maybe you should run a conference as well to lobby for the vote :)

OnePlus are great at customer service

$
0
0

Around a year ago, I bought a OnePlus X phone. I was given a whole bunch of warnings by a whole bunch of people that their customer support was terrible and if the phone broke, I stood no chance of getting it repaired.

Well, it broke. Specifically, it stopped charging. I had to wiggle the connector, charge it by holding the lead at different angles, the works. That was really annoying. So I thought: they should fix this. Here’s what happened.

Tuesday evening, at eleven pm, I used the “Live Chat” thing on OnePlus’s website, and was put in touch with a service engineer named “Irish”. I explained the problem. Irish said: OK, we’ll fix that; if it turns out you broke it you’ll be charged, if not we’ll fix it. A pleasant conversation, in which he talked me through setting up an RMA request on their support site. Shortly thereafter, I received by email a DHL dispatch note, which I printed out and glued on the outside of a jiffy bag with my phone in it. DHL rang me up the next morning to arrange pickup; I arranged that for this Monday. A chap arrived and picked up the phone. Today, four days later, I’ve just got the phone back, delivered back to me by DHL again, and it works.

It is hard to imagine how customer service could be any better than this. My thing broke, they picked it up from my flat, repaired it, and delivered it back to my flat at their expense, with no complaints, in four days. This is excellent. Thank you OnePlus, thank you Regenersis the OnePlus service centre, thank you Irish. Maybe I’m unusual; maybe OnePlus have upped their game in the last year; maybe this is just luck. But this is a sterling example of how interaction with a company should go. OnePlus: exemplars of customer service. I am impressed.

None Of Us Are Free

$
0
0

Well you better listen my sisters and brothers,
‘Cause if you do you can hear
There are voices still calling across the years.
And they’re all crying across the ocean,
And they’re cryin’ across the land,
And they will till we all come to understand.

None of us are free
None of us are free
None of us are free, if one of us is chained
None of us are free

And there are people still in darkness,
And they just can’t see the light.
If you don’t say it’s wrong then that says it right.
We got try to feel for each other, let our brothers know that we care.
Got to get the message, send it out loud and clear

None of us are free
None of us are free
None of us are free, if one of us is chained
None of us are free

Now I swear your salvation isn’t too hard too find,
None of us can find it on our own
We’ve got to join together in spirit, heart and mind
So that every soul who’s suffering will know that they’re not alone

None of us are free
None of us are free
None of us are free, if one of us is chained
None of us are free

If you just look around you,
You’re gonna see what I say.
‘Cause the world is getting smaller each passing day
Now it’s time to start making changes,
And it’s time for us all to realize,
That the truth is shining real bright right before our eyes

None of us are free
None of us are free
None of us are free, if one of us is chained
None of us are free.

Application of this to the year 2016, how you should deal with everything that’s happened this year, and how you should stand with your friends and the people around you… is left as an exercise for the reader.


The Niamh prime

$
0
0

A bit of maths-y fiddling around on a Sunday afternoon.

Fascinating video on the Trinity Hall prime at Numberphile:

Apparently, Professor James McKee found a prime number which, when written out as ASCII art, looks like the crest of Trinity Hall college. Jack Hodkinson at Cambridge then searched for and found a prime which looks like a picture of Corpus Christi college (via Futility Closet). That seems like a cool idea. So, with a bit of help from aalib in JavaScript and the Miller-Rabin primality test, plus a bit of scaling images up and down in Gimp, I found this 2,850-digit prime:

777,777,777,­777,777,777,­777,777,777,­777,777,777,­777,777,777,­777,777,777,­777,777,777,­777,777,777,­777,777,777,­777,777,777,­777,777,777,­777,777,777,­777,777,777,­777,777,577,­777,777,777,­777,777,777,­777,777,777,­777,777,777,­777,777,777,­752,385,356,­867,777,777,­777,777,777,­777,777,777,­777,777,777,­775,352,235,­666,688,668,­667,777,777,­777,777,777,­777,777,777,­777,776,765,­555,556,666,­856,868,667,­777,777,777,­777,777,777,­777,777,777,­222,335,666,­666,866,686,­666,665,777,­777,777,777,­777,777,777,­777,355,336,­358,866,556,­666,655,665,­655,777,777,­777,777,777,­777,777,733,­552,236,666,­666,655,665,­665,666,555,­777,777,777,­777,777,777,­777,276,265,­666,666,656,­655,555,555,­555,533,777,­777,777,777,­777,777,253,­252,566,666,­665,555,556,­555,555,565,­557,777,777,­777,777,777,­725,222,236,­666,565,555,­555,556,555,­535,355,237,­777,777,777,­777,772,266,­725,366,535,­555,355,555,­555,553,553,­533,577,777,­777,777,777,­272,637,356,­655,555,555,­353,535,556,­655,355,332,­277,777,777,­777,772,235,­775,355,665,­553,355,353,­535,533,555,­555,223,777,­777,777,777,­322,222,255,­555,556,353,­555,355,336,­355,653,533,­537,777,777,­777,772,222,­225,555,565,­555,355,335,­355,356,555,­655,353,237,­777,777,777,­772,272,355,­553,553,355,­535,353,365,­355,355,553,­523,577,777,­777,777,332,­333,566,333,­553,555,533,­355,355,555,­555,353,555,­677,777,777,­777,332,355,­555,555,555,­555,555,553,­555,535,555,­666,556,777,­777,777,775,­533,355,535,­355,553,565,­535,353,655,­655,555,565,­557,777,777,­777,756,533,­555,533,335,­353,566,655,­353,566,535,­656,655,577,­777,777,777,­565,353,535,­535,553,335,­566,666,555,­666,568,566,­665,777,777,­777,775,633,­535,555,555,­555,535,565,­556,555,666,­566,666,677,­777,777,777,­758,333,333,­355,555,656,­556,565,866,­666,866,658,­667,777,777,­777,777,582,­233,333,333,­355,565,555,­566,666,666,­868,666,677,­777,777,777,­775,822,333,­333,333,535,­555,556,666,­666,668,688,­586,777,777,­777,777,736,­355,333,333,­355,556,555,­636,666,686,­688,888,557,­777,777,777,­777,565,555,­555,333,555,­566,666,565,­686,666,886,­886,777,777,­777,777,776,­656,888,853,­335,556,686,­556,666,666,­868,886,887,­777,777,777,­777,775,356,­368,532,355,­555,688,666,­866,666,668,­668,877,777,­777,777,777,­732,233,553,­223,323,335,­533,556,666,­686,686,686,­777,777,777,­777,777,323,­333,332,222,­233,332,233,­568,665,666,­656,337,777,­777,777,777,­773,233,333,­322,222,223,­222,223,566,­556,655,533,­777,777,777,­777,777,722,­333,232,222,­222,233,222,­225,665,555,­632,277,777,­777,777,777,­777,323,333,­322,222,223,­222,222,236,­553,553,222,­777,777,777,­777,777,777,­233,232,222,­223,232,222,­223,355,533,­552,277,777,­777,777,777,­777,772,333,­333,222,233,­322,222,223,­353,233,355,­777,777,777,­777,777,777,­723,333,355,­665,533,233,­333,333,322,­335,677,777,­777,777,777,­777,777,735,­533,333,222,­233,333,333,­332,223,356,­777,777,777,­777,777,777,­777,555,333,­232,222,333,­333,333,222,­233,677,777,­777,777,777,­777,777,772,­533,332,222,­222,333,333,­322,222,255,­777,777,777,­777,777,777,­777,775,356,­566,665,553,­333,333,222,­223,557,777,­777,777,777,­777,777,777,­733,335,333,­332,223,333,­332,222,233,­577,777,777,­777,777,777,­777,777,233,­335,332,222,­223,332,322,­222,233,777,­777,777,777,­777,777,777,­777,333,232,­222,222,223,­332,222,222,­237,777,777,­777,777,777,­777,777,773,­222,222,222,­222,223,222,­322,222,377,­777,777,777,­777,777,777,­777,777,222,­222,222,222,­323,332,222,­223,777,777,­777,777,777,­777,777,777,­773,232,222,­222,333,353,­222,222,227,­777,777,777,­777,777,777,­777,777,733,­332,222,223,­355,322,222,­222,277,777,­777,777,777,­777,777,777,­777,755,333,­333,555,533,­222,222,222,­277,777,777,­777,777,777,­777,777,777,­777,775,555,­555,322,222,­222,222,777,­777,777,777,­777,777,777,­777,777,777,­755,555,533,­222,222,222,­227,777,777,­777,777,777,­777,777,777,­777,777,755,­553,332,222,­222,222,227,­777,777,777,­777,777,777,­777,777,777,­777,555,533,­322,222,222,­222,227,777,­777,777,777,­777,777,777,­777,777,773,­553,332,222,­222,222,222,­277,777,777,­777,777,777,­777,777,777,­777,735,533,­322,222,222,­222,222,277,­779,769

although it looks rather better when properly formatted.

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

I think I’ll call it the Niamh Prime.

Charles Paget Wade and the Underthing

$
0
0

I got to spend a few days with Andy and his wife Gaby and their exciting new dog, Iwa. I don’t get to see them as often as I should, but since they’ve now moved rather closer to Castle Langridge we’re going to correct that. And since they’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’d take back to Elizabethan England. (This is a harder question than you’d think. Sure, you can take your iPhone back and a solar charger, and it’d be an incredibly powerful computer, but what would they use it for? They can do all the maths that they need; it’s just slower. Maybe you’d build a dynamo and gift them electricity, but where would you get the magnets from? Imagine this interspersed with excellent beer from the Volunteer and you have a flavour of it.)

There were also some Rollright Stones, as guided by Julian Cope’s finest-guidebook-ever The Modern Antiquarian. But that’s not the thing.

The thing is Snowshill Manor. There was a bloke and his name was Charles Paget Wade. 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’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’s fascinating about this is that he didn’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 “an attractive set of rooms pictorially”. There’s some rhyme and some reason — one of the upstairs rooms is full of clanking, rigid, iron bicycles, and another full of suits of samurai armour — but mostly they’re things he just felt fitted together somehow. He’s like Auri from the Kingkiller Chronicles; this room cries out for this thing to be in it. (If you’ve read the first two Kingkiller books but haven’t read The Slow Regard of Silent Things, go and read it and know more of Auri than you currently do.) There’s a room with a few swords, and a clock that doesn’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’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’s right. I don’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’t matter. You could spend the rest of your life hearing the stories about everything there and never get off the ground floor.

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 — Japanese or Chinese, mainly — 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 — whether because none of the family were left, or for financial reasons, or maybe just that the occupants came home and didn’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’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… 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 them.

This sort of thing doesn’t happen to me all that much.

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 ECC, 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’s been quartered again. After some entirely baseless speculation we discovered that it was owned by Countess Cowper. She married Lord Palmerston; her brother was William Lamb, Lord Melbourne, who was another Prime Minister and had the Australian city named after him; his wife was Lady Caroline Lamb, who infamously described Byron as “mad, bad, and dangerous to know”. History is all intertwined around itself.

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’t tell the right time, she was not best pleased. Not sure who it was. Virginia Woolf, or someone like that.

There is too much stuff. He can’t possibly have kept it all in his head. You can’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’ve got halfway through it’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’s not an art gallery. It’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. (“Sometimes I think the asylum is a head. We’re inside a huge head that dreams us all into being. Perhaps it’s your head, Batman.”)

Next time you’re near Evesham, go visit.

Telegram notifications for Jenkins builds

$
0
0

It’s nice to get updates from your CI system when things build. It’s even nicer to do it without having to run any servers to do it. Here’s how I send build notifications to a Telegram bot from Jenkins.

Basically, Jenkins knows how to hit a webhook for every stage of the build, and Integram 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 webtask.io.

The Webtask.io editor

Deploy the following code there, being sure to update the Integram URL in it to be yours:

varexpress=require('express')varbodyParser=require('body-parser')varrequest=require('request')varWebtask;try{Webtask=require('webtask-tools');}catch(e){}varapp=express()app.use(bodyParser.json())app.post('*',function(req,res){if(req.body&&req.body.name&&req.body.build&&req.body.build.url){varstatus=req.body.build.status;if(req.body.build.phase=="STARTED"){status="STARTED";}if(req.body.build.phase=="FINALIZED"){// don't care about FINALIZED because we get COMPLETED and that's enoughres.send("ok");return;}console.log("Received correct-looking JSON to webhook");varoutput={"text":"Jenkins\nBuild of _"+req.body.name+"_ status *"+status+"* "+"at http://YOUR-JENKINS-URL/"+req.body.build.url};request({uri:"https://integram.org/YOUR-INTEGRAM-URL",method:"POST",json:output},function(err){if(err){console.log("Messaging Telegram bot failed",err);res.send("failed");}else{console.log("Messaging Telegram bot succeeded");res.send("ok");}})}else{console.log("Input to webhook was invalid",req.body);res.send("Input was invalid: "+req.body.toString());}})if(Webtask){module.exports=Webtask.fromExpress(app);}else{app.listen(4569);console.log("Listening on port 4569");}

Then, put the webtask URL into Jenkins as a webhook:

Add a notifications endpoint in the configure section of your build job

And invite the Integram bot to your Telegram channel (instructions at integram.org).

And you’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 internet.

The Telegram bot speaks the message it's given, and so Telegram notifies you

I wrote a Web Component

$
0
0

I’ve been meaning to play with Web Components for a little while now. After I saw Ben Nadel create a Twitter tweet progress indicator with Angular and Lucas Leandro did the same with Vue.js I thought, here’s a chance to experiment.

Web Components involve a whole bunch of different dovetailing specs; HTML imports, custom elements, shadow DOM, HTML templates. I didn’t want to have to use the HTML 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 whatever-you-want and then just add <whatever-you-want someattr="somevalue">content here</whatever-you-want> elements to your page, and it all works. This is good.

To define a new type of element, you use window.customElements.define('your-element-name', YourClass).1YourClass is an ES2016 JavaScript class. 2 So, we start like this:


window.customElements.define('twitter-circle-count', class extends HTMLElement {
});

The class has a constructor method which sets everything up. In our case, we’re going to create an SVG 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 Jake Archibald’s dash-offset technique. This is all perfectly expressed by Ben Nadel’s diagram, which I hope he doesn’t mind me borrowing because it’s great.

So, we need to dynamically create an SVG. The SVG we want will look basically like this:

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="45" 
  style="stroke: #9E9E9E"></circle>
  <circle cx="50" cy="50" r="45" 
  style="stroke: #333333)"></circle>
</svg>

Let’s set that SVG up in our element’s constructor:

window.customElements.define('twitter-circle-count', class extends HTMLElement {
  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);
  }
});

Now we need to actually add that created SVG to the document. For that, we create a shadow root. This is basically a little separate HTML 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.3 This is easy with attachShadow, which returns you this shadow root, which you can then treat like a normal node:

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);
    let shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.appendChild(svg);
  }
});

Now, we want to allow people to set the colours of our circles. The way to do this is with CSS custom properties. Basically, you can invent any new property name you like, as long as it’s prefixed with --. So we invent two: --track-color and --circle-color. We then set the two circles to be those colours by using CSS’s var() 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 twitter-circle-count { --track-color: #eee; } and it’ll work.

Annoyingly, it doesn’t seem to be easily possible to use existingCSS properties for this; there doesn’t seem to be a good way to have the standard property color set the circle colour.4 One has to use a custom variable even if there’s a “real” CSS 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.5 (Update: Matt Machell mentions currentColor which would work perfectly for this example, but it only works for color; there’s no way of setting other properties like, say, font-size on the component and having that explicitly propagate down to a particular element in the component; there’s no currentFontSize. I don’t know why color gets special treatment, even though the special treatment would solve my particular problem.)

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);
  }
});

We want our little element to be inline-block. To set properties on the element itself, from inside the element, there is a special CSS selector, :host.6 Add a <style> element inside the component and it only applies to the component (this is special “scoped style” magic), and setting :host styles the root of your element:

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);
    var style = document.createElement("style");
    style.innerHTML = ":host { display: inline-block; position: relative; contain: content; }";
    shadowRoot.appendChild(style);
  }
});

Next, we need to be able to set the properties which define the value of the counter — how much progress it should show. Having value and max properties similar to an <input type="range"> seems logical here. For this, we define a little function setDashOffset which sets the stroke-dashoffset style on our indicator. We then call that function in two places. One is in connectedCallback, a method which is called when our custom element is first inserted into the document. The second is whenever our value or max attributes change. That gets set up by defining observedAttributes, which returns a list of attributes that we want to watch; whenever one of those attributes changes, attributeChangedCallback is called.

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 = 100;
    var value = parseInt(this.getAttribute("value"), 10);
    if (isNaN(value)) value = 0;
    this.indicator.style.strokeDashoffset = this.circumference - 
        (value * this.circumference / mx);
  }
  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)";
    /* 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);

    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);
  }
  connectedCallback() {
    this.setDashOffset();
  }
});

This works if the user of the component does counter.setAttribute("value", "50"), but it doesn’t make counter.value = 50 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.

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);
  }
  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); }
  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);
    this.defaultValue = 50;
    this.defaultMax = 100;
  }
  connectedCallback() {
    this.setDashOffset();
  }
});

And that’s all we need. We can now create our twitter-circle-count element and hook it up to a textarea like this:

<twitter-circle-countvalue="0"max="280"></twitter-circle-count>
<p>Type in here</p><textarearows=3cols=40></textarea>
twitter-circle-count{width:30px;height:30px;--track-color:#ddd;--circle-color:#333;--text-color:#888;}
// we use input, not keyup, because that fires when text is cut or pasted// thank you Dave MN for that insightdocument.querySelector("textarea").addEventListener("input",function(){document.querySelector("twitter-circle-count").setAttribute("value",this.value.length);},false);

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 polyfill to add support in browsers that don’t have it.7

Here’s the counter:

Type some text in here:

  1. I relied for a lot of this understanding on Google’s web components documentation by Eric Bidelman.
  2. All this stuff is present already in Chrome; for other browsers you may need polyfills, and I’ll get to that later.
  3. Pedant posse: yes, it’s a bit more complicated than this. One step at a time.
  4. 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.
  5. 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.
  6. 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.
  7. Mikeal Rogers has a really nice technique here for bundling your web component with a polyfill which is also worth considering.

OwnTracks and a map

$
0
0

Every year we do a bit of a pub crawl in Birmingham between Christmas and New Year; a chance to get away from the turkey risotto, and hang out with people and talk about techie things after a few days away with family and so on. It’s all rather loosely organised — I tried putting exact times on every pub once and it didn’t work out very well. So this year, 2017, I wanted a map which showed where we were so people can come and find us — it’s a twelve-hour all-day-and-evening thing but nobody does the whole thing1 so the idea is that you can drop in at some point, have a couple of drinks, and then head off again. For that, you need to know where we all are.

Clearly, the solution here is technology; I carry a device in my pocket2 which knows where I am and can display that on a map. There are a few services that do this, or used to — Google Latitude, FB messenger does it, Apple find-my-friends — but they’re all “only people with the Magic Software can see this”, and “you have to use our servers”, and that’s not very web-ish, is it? What I wanted was a thing which sat there in the background on my phone and reported my location to my server when I moved around, and didn’t eat battery. That wouldn’t be tricky to write but I bet there’s a load of annoying corner cases, which is why I was very glad to discover that OwnTracks have done it for me.

You install their mobile app (for Android or iOS) and then configure it with the URL of your server and every now and again it reports your location by posting JSON to that URL saying what your location is. Only one word for that: magic darts. Exactly what I wanted.

It’s a little tricky because of that “don’t use lots of battery” requirement. Apple heavily restrict background location sniffing, for lots of good reasons. If your app is the active app and the screen’s unlocked, it can read your location as often as it wants, but that’s impractical. If you want to get notified of location changes in the background on iOS then you only get told if you’ve moved more than 500 metres in less than five minutes3 which is fine if you’re on the motorway but less fine if you’re walking around town and won’t move that far. However, you can nominate certain locations as “waypoints” and then the app gets notified whenever it enters or leaves a waypoint, even if it’s in the background and set to “manual mode”. So, I added all the pubs we’re planning on going to as waypoints, which is a bit annoying to do manually but works fine.

OwnTracks then posts my location to a tiny PHP file which just dumps it in a big JSON list. The #brumtechxmas 2017 map then reads that JSON file and plots the walk on the map (or it will do once we’re doing it; as I write this, the event isn’t until tomorrow, Friday 29th December, but I have tested it out).

The map is an SVG, embedded in the page. This has the nice property that I can change it with CSS. In particular, the page looks at the list of locations we’ve been in and works out whether any of them were close enough to a pub on the map that we probably went in there… and then uses CSS to colour the pub we’re in green, and ones we’ve been in grey. So it’s dynamic! Nice and easy to find us wherever we are. If it works, which is a bit handwavy at this point.

If you’re coming, see you tomorrow. If you’re not coming: you should come. :-)

A static version of the map: you'll want the website for the real dynamic clever one

  1. well, except me. And hero of the revolution Andy Yates.
  2. and you do too
  3. the OwnTracks docs explain this in more detail
Viewing all 158 articles
Browse latest View live