Static Jekyll Comments

Those of you paying very close attention will have noticed that posts now have a comment section at the bottom. It's currently reading the comments reading in from specially named YAML files in the _data directory of the site, which I have to put in manually.

You can find my comment HTML and YAML on GitHub, hopefully it's pretty straight self-explanatory.

To do it, I had to get a filename-friendly page identifier from the, which I did by replacing slashes with dashes and capturing it in a comment id.

{% capture commentid %}comments{{ page.id | replace: '/','-'}}{% endcapture %}

From here, I read the data from site.data[commentid] and display it on the page. I wanted to allow some formatting in comments, so I pass the content through the | markdownify filter. The comment contents in the YAML have to be multi line as well, ending up with a YAML file with a bunch of entries like so:

- author: Steve
  date: 2014-04-02 10:00 +1000
  contents: |
    I've added comment support to the site now! See [my post](/2014/04/static-jekyll-comments) to see how I went about it.

    You'll note that it has *markdown* support too! I'll moderating it though, so don't try any dirty hacks...

The plan now is to make use of the GitHub API to allow comment submission by creating issues. I think this means that the commenter requires GitHub account, but that's ok. I don't think I'll get enough comments to need more automation than that - I will want to moderate them to ensure there's nothing malicious in the comment anyway, so I don't mind having to copy-paste the markdown from the GitHub issue into a YAML file.

For now, you'll have to create the GitHub issue yourself!

Jekyll Me This

So, I've moved the blog over to Jekyll, a static site generator that's pretty well suited to doing blogs, if you're a tech person, like myself. No, this is not an April fool's joke!

Moving over was a little arduous, not least of all because all the Jekyll tooling (including Ruby) really targets Linux or Mac users more than Windows users.

So, if you're thinking of doing the same, here's a few tips:

  1. Use the guide by juthilo on GitHub on how to run Jekyll on Windows
  2. Pay attention to the version numbers in the article above, as they are written for a reason. When I set mine up, it was Jekyll v1.4.2, but it looks like he's now recommending 1.5.1.
  3. Consider using Javascript code prettifier instead of Pygments if you don't want to install Python.
  4. GitHub pages does NOT support most plugins, only the ones found in the master repository. So either avoid using them, or generate the HTML locally and commit that
  5. While there are a tonne of themes at Jekyll Themes, it's very hard to find a good one - with no search or rating system, it's really a list of the latest submitted ones. A lot of them have hardcoded site names and categories. Avoid the hassle and style it yourself.

I have a GitHub repository for this blog if you want a fairly simple setup or template to base it off. I'm not using Jekyll Bootstrap, so it shows how easy it is to make a very functional blog with vanilla Jekyll.

I still don't know what I want to do with comments, I may simply avoid using them, as I'd have to hand them over to a 3rd party (like Disqus), something I'd rather not do.

If you have any helpful comments or find any problems, let me know by raising an issue or submitting a pull request.

"Mejh" Dev Log - Part 3

I decided it was time to start getting the Mejh to look around and guess their positions. That got messy pretty fast - I want to be able to swap out the "find the closest stuff to you" part very quickly, which meant creating a World class for the Mejh to live in, and a "Finder" interface, which has a "findNearbyMejh" method. If I need to optimise to a quad tree or something, it should be rather simple, success!

Unfortunately, this is where the success starts to run out. Because the next feature I wanted was to be able to hover over a Mejh, and have nearby Mejh glow. As much as I trust my tests, I do like to see this progress on the screen, and this is a stepping stone to having an interactive sort of game. So I go in and start writing tests for the renderer to have interactivity.

When a circle is clicked it appears selected

And I've already hit a wall, which is d3.js. I either haven't found out how to test it easily yet, or it's a difficult API to write tests for. Or both. See, d3.js works by selecting a bunch of elements, binding them to data, and specifying behaviour for the nodes, with special cases for entering nodes and exiting nodes. So the rendering code of last week was:

Renderer.prototype = {
    render: function() {
        var allMejh = this._world.allMejh();
        var selection = d3.select(this._canvas)
            .selectAll('circle')
            .data(allMejh, function(m) { return m.id; });

        selection.enter().append('circle');
        selection.exit().remove();

        this._formatter.format(selection);
    }
};

Formatter.prototype = {
    format: function(selection) {
        selection
            .attr('r', 3)
            .attr('cx', function(m) { return m.position().x; })
            .attr('cy', function(m) { return m.position().y; });
    }
};

Pretty simple code. Pain in the butt to test though, because you have to consider the case where a node is entering, where one is exiting, and that each one is formatting. While the implementation is about 15 lines of code, the tests take up 55 or so. Of course, lines of code aren't a good way of measuring quality or anything, but it just felt *wrong*.

Updating for hover code was simple, but writing tests for it first proved even more difficult, as the mouse events are bound to the d3 selection, and it's all very d3-selectiony, not DOM elementy, and gets confusing fast.

So I thought to myself, let's try out something that's NOT d3.js. I hit up http://angularjs.org/

Angular JS

In brief AngularJS provides a way of specifying views using markup, and having it bind to a model (ish), with a controller floating around there to give it all some behaviour. It's fairly impressive I have to admit. egghead has some fantastic video tutorials on it.

So I watched a few videos, did some dodgy demo apps with ridiculously simple models and repeat sections and thought "yes, let's go!". I had trouble doing it in SVG, so I just used divs with text displaying the model position - I figured I could switch out the rendering easy enough. And that WAS easy enough - it just worked. Well, as long as I made sure my application attached the world onto some global scope because angular didn't play nice with InjectJS. I figured I could work on DI integration later, global scope was fine while researching this stuff. And it's just the world, not a big deal, right?

Next was the hover behaviour, and I realised I also had to expose my finder - since what I wanted to do is find the Mejh that are close to the clicked node, and add them to a list of 'nearby' Mejh (or mark them as nearby some other way). That's 2 in the global scope, but it worked well enough. I didn't attempt testing just now - still just researching and seeing if it's worth pursuing)

Time to work on SVG support. I wire up the same repeat infrastructure, but with circles instead of divs, and run it. Woo! There they are, a circle for each Mejh. Just for posterity, I put in 2 more repeats - one for the highlighted one, another for the 'nearby' ones. Bam, they show, the click events work, too easy!

But, I don't want 3 repeats. I want 1 list of Mejh, and the format of it dependant on whether it's selected, nearby, or neither. Which means a directive - <mejh-circle>. Test it in HTML, all good, do it in SVG. Nothing. I inspect the DOM using Chrome's dev tools, all the circle elements are there with perfect markup, why isn't it showing?

Fast forward half an hour or so, turns out my directive makes HtmlUnknownElement instead of SvgCircleElement. Because that's what happens when you use strings to build SVG - something that Angular wasn't really designed for (understandably). So I have to throw Angular out for this project, too painful.

Ahh well, live and learn. I think what I'll do is make a view model for the world, test the view model, and not test the bit that actually makes DOM elements out of the view model. Stay tuned!

"Mejh" Dev Log - Part 2

I've done my first chunk of code, and TDD has blown me away yet again.

So I created a class for my Mejh dudes, a "placer" to just randomly put them all over the bounding area for now, a renderer to create SVG elements for each of them, and a formatter to give the SVG elements what they need (radius, position, etc.). And an application to tie it all together.

Once the application was finished, and I had 100% code coverage and DI everywhere, I created an index.html, set up the DI container how I wanted it, and it worked (well, not quite - I forgot to set cx and cy attributes of the circles, so they all appeared at 0,0). What's more, the container setup only required 3 manual registrations - everything else was automatic.

It may not seem like much - a handful of classes which, when put together, do nothing more than display a bunch of random dots on the screen - but having any app "Just Work" feels damn good.

Here's the libraries I'm using to do the bits:

  • InjectJS: DI Container for Javascript. Written just last week by a coworker, it's brilliant. Highly recommended.
  • d3js: Library to bind data to DOM elements. Chose this one because I knew it, and it works well.
  • Basil, ChaiJS, SinonJS: Trinity of Javascript testing, I talk about these enough so I'll leave it at that

And to finish it off, some things I've learnt

Dependencies

When everything is tested, the list of scripts in test.html match exactly to the list in index.html. The only difference in the real version is the instantiation and starting of the Application. Maybe I should be testing my container setup/initial resolve?

Testing the DOM is very fiddly

I'm using d3 to render the svg circles, and so all my rendering tests have to be integration tests - I can't feasibly mock that thing. It makes it quite painful to test, especially since pulling attributes out of Svg elements return animated strings, so the easiest way to assert on them is with d3.select(el).attr("r").should.equal("3"). Of course, .attr always returns strings, not numbers... I'm glad I won't have much render code!

Slowdowns

My environment is slowing me down a lot. Manually making class methods instead of just pressing alt+enter takes time. Not having the tests Autorun takes time (I really need to update that chrome extension...). Not being terribly familiar with WebStorm's keyboard shortcuts takes time. Heck, even not knowing d3/sinon/chai/injectjs off the top of my head slows me down plenty (not to mention the bits and bobs of missing functionality, like array matchers in chai - .deep isn't the answer)! Hopefully I'll get faster, and nut a lot of this down, but right now, it's annoying.

So what's next? I think I'll get the Mejh guessing their positions now. This will mean adding neighbour discovery, and what I think will be a visitor pattern for the Mejh to add different guessing behaviours, not certain yet. Going mejh.Visit(this._positionGuesser) just seems sensible, and sets me up for adding movement later.

I'll also spend some time on configuring the IDE to do more stuff for me.

Until next time!

"Mejh" Dev Log - Part 1

I was talking with a coworker the other day, and we lamenting about how bad GPS is in the city - what with all the buildings and reflections messing everything up. We came to the realization that there are a tonne of phones all around, each with a pretty-good-but-not-perfect idea of where it's located. So we got all excited about the idea of creating an app which uses all the clients to build mesh-based location service for phones with that app. It's like bittorrent, for GPS!

We figured it would only take a few 'seed' nodes (that is, nodes with 100% certainty of their location) to stabilize a large mesh of nodes with fairly-certain distances to neighbouring nodes, and low certainty of its own location.

Of course, it will be damn difficult to get the distances to neighbouring nodes. Bluetooth is too low range, wifi signal strength is not very accurate, tone measuring will be ridiculously annoying and GPS cannot be considered - or we wouldn't need a mesh at all!

Which makes me want to test the idea in a game. The idea will be a community of "Mejh" (the jh being pronounced as the 'g' in 'genre'), where each member:

  1. Does not know their own location
  2. Can make a guess at their location, with a certainty level (or error margin)
  3. Knows the rough distance and (maybe) direction of nearby Mejh friends
  4. Can communicate with nearby Mejh to get their calculated positions

There will also be some sort of oracle-Mejh, which has 100% certainty of location, but must remain stationary.

The goal of the game will be to expand your colony as large as possible. Find resources, have the Mejh workers mine them and take them back home, in order to build more Mejh (and oracles), to find more resources, ad infinitum.

I think it's a fairly innovative idea, so we'll see how it turns out! The main thing I like about this idea is it isn't dependent on a highly skilled graphics or sound person - I can really get away with some nicely themed dev art for it - think Darwinia.

Not yet sure if I'll throw the code on GitHub, or keep it all to myself, but I'll certainly be keeping this up to date with how development is going. I'm leaning towards having it open, though.

As for development, here's a bunch of details about my approach, and some rules I'm setting myself:

  • 100% browser based. No server component at all (at least, until I want multiplayer or high score tracking)
  • Frequent releases, possibly continuous deployment when I figure out how
  • 100% DI. In my 80ish lines of JS at the moment, I have a single 'new' statement. I plan to keep it that low
  • 100% TDD. No code unless I have first written a test for it. This excludes DI container setup. But this includes DOM manipulation
  • Maximum of 4 args per constructor. No logic beyond assigning instance variables in the constructor
  • No jQuery. I shouldn't need it, and I want to use js without it for once
  • A blog post per night of coding. Two for tonight, because it's my first go :)

I'm setting pretty stringent rules for DI and testing for a few reasons. There really isn't that much of either in browser-based Javascript going on in the world. Heck, I doubt there's even that much of it going on in Node.js land. I'm hoping to show how it can be done successfully for a non-trivial project, and perhaps give reference to those who want it (contingent on me opening up the code, of course). I've had a lot of success with DI and TDD in my professional career thus far (DI primarily in C#, TDD in both personal and work projects), but I often get lazy and thing "not a big deal this time..." and regret it later. Especially with constructor parameter counts. I want to push myself further, and this will provider a great opportunity to.

Stay tuned!