A two year success story

About two years ago, I began working at Psyon Games, a Finnish startup company making waves with its promise of games that could make a real difference in global healthcare and biology education. The product to do this was a bleeding edge combination of technology, psychology and biology in the form of Antidote, a casual strategy game where you defend the stem cell from bacteria and viruses.

When I saw the concept, a dream was immediately born: finally, an opportunity to order the production of a human sized cholera bacteria costume. This week, the hottest May on record in Finland since records began, the dream came true.

On a sunny day, the 16th of month, our budget rental van rounded the corner of an apartment block in an unsupposing suburb of fair Jyväskylä, our eyes fell upon a sight most beautiful. It’s glossy gym-ball sized eye reflecting then blazing sun, Ollie cholera sat nestled on the grass, jiggling gently with its flickering tongue.

This wonder was a gift that just kept giving. Without any warning, Ollie rose in an undignified squelching motion and walked toward me. The dream had come true: cholera was cuddleable.

With some difficulty, we assisted the hulking antihero in through the back doors of our van, and secured it inside. A tight fit, but we made it. The journey to SciFest 2018 would be Ollie’s maiden voyage.

If you want to read more, and witness a glorious video of the suit in action, check out the company blog post here.

Chocolate coated hazelnut toffee

I’ve been experimenting in candymaking, and this is the first “worth sharing”. It’s a fairly hard candy wrapped around hazelnuts and covered in delicious chocolate.

Ingredients

  1. 100g light/golden syrup
  2. A generous handful of hazelnuts (or other nuts)
  3. Chocolate. How much? How much do you like chocolate! I used a lot. I like chocolate.

Instructions

  1. Chop up hazelnuts (or whatever nuts you fancy). I got bored chopping and used a blender.
  2. Layer the hazelnuts on greaseproof/baking paper in a heatproof dish with cork pads or spare tea towels under it (to protect your surfaces). Spread the hazelnuts fairly evenly. The area of the dish will affect the thickness of the candy (big dish = thing candy)
  3. Put 100g of light/golden syrup and 200g of sugar in a pan (ideally a small radius pan with a thick base, and I don’t use non stick pans because sugar washes off easily if you don’t burn it)
  4. Use a sugar thermometer! Unless you’re already a candy master, getting consistent results is near impossible otherwise. Set it up in the pan (don’t let it touch the bottom, but make sure the bulb is immersed)
  5. Turn the heat on! KEEP IT LOW. I cannot overstate this. Do not rush. Burned sugar is not your friend. On a hob with 6 heat settings, 3 tends to work ok, but if you want to be safe, start with 2.
  6. Wait patiently for the temperature to reach 149C, meanwhile microwave the chocolate in a heatproof dish with a spout (use a low power setting, 10-20 second bursts with stirring in between). You want it to be -just- melted, not totally molten
  7. As soon as the sugar mix reaches 149C, pour it across the nuts. Wait for a little bit for it to get a bit cooler (I waited about 40 seconds) then slowly drizzle the molten chocolate all over it.
  8. Wait. And wait. And wait. This is torture, seriously. Oh, and while you wait, wash the pan.

Once it’s cool you might want to put it in the fridge to set the chocolate. Once it’s full set, you can do what you want with it! I strongly suggest eating it. As a side note, it’s actually better the following day – when the brittle candy has had a little time to soften and not shatter your teeth.

If you have any questions ask in the comments!

How to make enjoyable educational games?

For my masters thesis, I tackled the problem of educational games. Why are educational games a problem? Because the mass image of them is simply “quiz+rewards” – what has been referred to as “chocolate coated broccoli”. This analogy is particularly touching to me, because even though I like broccoli normally, the idea of coating it with chocolate repulses me. Similarly, the idea of smothering learning with patronizing encouragement and “rewards” makes the joy of learning less palatable.

In my thesis, I try to put into words some principles for producing games for learning, games that are enjoyable yet impart knowledge that is valued in the real world. Roughly, this ends up with me suggesting that games should be built by simulating a subject area, tightly coupled with structures to support both game driven and free playing experiences. In detail, I provide a list of stuff you can do to up your educational game, with a wide range of examples from mainstream games that you’ve no doubt heard of, and likely have played – summarized in the graphic below.

A summary of my pragmatic thesis findings
Simulations, a system for goals and hints, coaching and enjoyable difficulty all contribute to enjoyable, educational games

Whether you’re curious or horrified, I encourage you to read the full thesis! I hope that it sparks topics for discussion, and leads to more awesome games with a serious experience at heart.

Quiet YouTube when steam “donks”?

I’ve been noticing steam messages seem to seriously reduce the audio of my music player and youtube videos and what not. It was a bit frustrating, so I searched for it and found a typical tech thread here. This didn’t help at all, so I carried on hunting and found the answer burief in steam’s forums, it’s a Windows setting which makes other things quiet when you’re “in a voice call” (which.. well, steam messages don’t really fall into that category). Anyway, file a bug report with steam if this irritates you, and find a workaround/fix here:

http://makingwindowseasy.com/2011/04/30/change-windows-volume-during-phone-calls/

It fixes the issue, and I’m pretty happy to mute my music when I skype or whatnot…

How can we evaluate the quality of learning experiences?

Among other things, Bloom’s taxonomy allows us to categorize learning experiences. Bloom’s work was revised somewhat by Anderson a bit later, and it’s that revised edition I’ll describe here.

A taxonomy is a way of arranging things, and the revised Bloom’s taxonomy has two dimensions for categorization, the knowledge dimension and the cognitive dimension. Here they are in tables with examples.

Knowledge Dimension

Level Example
Factual knowledge Crude oil can be made into gasoline
Conceptual knowledge Crude oil is a mixture of many different hydrocarbons including gasoline.
Procedural knowledge Mixtures of chemicals in general can be separated through distillation, including gasoline from crude oil.
Metacognitive knowledge Determining if a chemical mixture can be separated with distillation is possible through internet searches or experimentation with different temperatures.

Cognitive Dimension

Level Example
Remember Crude oil can be made into gasoline
Understand Draw diagram showing how gasoline is extracted from gasoline
Apply Set up alcohol distillation in test tubes
Analyze Given a set of 20 liquids, determine which are mixtures separable by distillation
Evaluate Compare your methods to those of your classmates
Create Try to make brandy by distilling wine (not quite kid friendly.. :D)

 

International government spending on education

I was playing around with statistics from UNESCO to see if there were any trends in education spending over the past few years. Here’s a box plot showing the average international % of GDP spent on education in the last 14 or so years. The 2013 data seemed a bit sparse, so it might be wise to ignore it. Seems like there is a trend of decreasing spending in the past 4 years, but not a huge change over the past 10 years. Enjoy!

graph
% of GDP spent on education

Cafeteria Nipponica Recipes – A progression tree

Cateria, my second restaurant

I’ve been playing Cafeteria Nipponica on my phone recently, and found myself regularly checking Happy Enna’s Recipe Reference to work out how to do the things I “remember” from last playthrough in the best order. The information there is invaluable but spreadsheets hurt my eyes. So, I created these flow charts!

All dishes come from a “root” dish, you can find out how to get them here.

Colors indicate the max * ranking, keys on each image. I wonder why rice and soba are so lame?

Rice

Rice recipes
So much recipes. But whole team is babies! Also how does rice become french fries, or pizza, or salad? Mysterious.

Udon

Udon recipes
Udon! This all seems pretty logical.

Ice cream

Ice cream recipes
Ice creaaaaaaaaam.

Sauteed Chicken

Sauteed chicken recipes
Sauteed chicken obviously develops into steak!

Grilled Fish

Grilled Fish Recipes
Grilled fish sucks at first, but makes great end products!

Soba

Soba Recipes
Soba seems pretty lame :<

Introduction to AI for game programming students

I was recently invited to give a talk on “AI in games” to Jyväskylä’s AMK game programming students. The lecture could have gone better if I had prepared more material for it, but the catch was that I didn’t know what to prepare. These notes act as a guide for “next time”. I won’t go into any depth on the subjects here.

  1. Briefly introduce scientific AI, point out useful libraries [A*, speech recognition, opencv] then waft it away
  2. Focus on architecture of players, representation of game state and move logic
  3. Establish the simplest AI player for tic-tac-toe, then develop it to a perfect player [“smart as possible AI”]
  4. Make the tic tac toe player more fun to play against
  5. Consider expanding it to more complex games (chess, civilization) and optimizations
  6. Human behavior simulation – know the limits of senses, program them in. FPS/Stealth AI is a good example. [“dumb as a human AI”]
  7. Planning and decision making architecture
  8. Techniques for more realistic behavior

Additionally…

  • Examples of AI in video games: planner in fear, neural networks aren’t used much in industry (notable exception, Supreme Commander 2) and only for decisions, Quake 3 doesn’t have neural net bots
  • Data structures and algorithms are ever useful
  • Observe nature and mimic behaviour

Troubleshooting the Database

A customer sent me a short email about formatting in their new system. Simple enough, I created a sample in the system and sent them a specification for formatting, and told them “just delete the sample when you’re done”.

Alas. Ten minutes later, an email arrives “I deleted the sample… everything is gone and I can’t log in?!”

Shock.

Shock fades into denial – it must be the platform. Right? A database failure, or a virus. Glancing at the database, it appears to have rolled back 3 months. I sent off a support request to Heroku and they pulled a friendly face of “that’s very odd, our databases don’t do that kind of thing on their own”.

So, I took a closer look, and sure enough there are suggestions it isn’t just a rolled-back database – a few missing things were created before a few present things, so it isn’t just a plain rollback, more like a systematic deletion. And the automated database backup hasn’t run since last night, so the most recent work by the customer is lost.

Despite it apparently being a bug in the delete method, no matter how hard I tried, I wasn’t able to reproduce it in the CMS locally or on production. I created almost exact replicas of the structure prior to the error, and couldn’t get a repeat of the bug – maybe there was something malicious at play?

I played around for hours, loading up content, deleting it, renaming it, trying to be malicious, and nothing came up. I pored over the logs from the client working on the CMS,  and as I got further back in time noticed that they were testing content in the “client” side application as they added it.

I connected the client side application and worked through some exercises, deleted a few from the CMS. Nothing. Edited a few more things, completed a few more exercises, hit delete.

Long pause… “Signed out of CMS”. Ok… How odd. I couldn’t sign back in, either – user not found. I’m a system administrator, how can I be not found! This sounds exactly like the reported problem. There’s a lot to be said for examining the logs carefully – not just the immediate problem, but the surrounding context. Get a feel for what the user was doing when they encountered the problem!

Another database dump, and sure enough, my user account is deleted, along with quite a few (but not all) of the slides. Mixed feelings at this point – on one hand, I’ve reproduced the bug and am making some headway. On the other hand, the bug and subsequent data loss must be my fault – depressing.

At this point I wrote down the facts as I knew them

  • The user needs to use the application as well as the CMS for the bug to occur
  • A few User(s) are deleted
  • Many Exercises are deleted

Not much links users to exercises in the system. Just one little table called “UserProgress” which has a many-1 relationship with users and exercises, which entries are created in as the user progresses through exercises. A quick check of the database, and indeed all UserProgress rows are deleted as well. A lot of fingers now point at this relation.

Opening up the rails models, the UserProgress model has dependent => destroy set on it’s relations to User and Slide. On the other end, that’s also set – so if one end is destroyed, so is the other, regardless of which end is destroyed. This is not good. If a slide is destroyed here, it cascades – all the Exercise’s Progress relations are deleted, then all the Progress’s Users, then all the User’s Progresses, then all the Progress’s Exercises. We have come full circle – and it doesn’t have to end here… This explains why almost all users, and absolutely all slides vanished from the production database.

I created a simple test case and deleted a slide the user has marked progress on. The Bug is reproduced! This is a vital step in any troubleshooting. Another two unrelated deletion-of-progress bugs raise their heads – unrelated in the sense they don’t help fix the initial bug, but they take an hour to fix (they get in the way of running test cases for the show-stopper bug).

A quick removal of the offending dependent => destroy association from the UserProgress model (http://guides.rubyonrails.org/association_basics.html – deleting a customer deletes orders, which is sensible. Not the other way round!) and I am ready to re-run my test case.

Fixed! Hurray – off to the autobuild it goes.

Lessons learned:

  • Bugs usually clump together around bad code
  • Bad code is usually the less tested code
  • “System” level bugs that don’t occur until everything comes together require more complex tests
  • Be humble, expect the mistake to be in your code, not others
  • Don’t just throw answers together until they work. (i.e. putting the association property on both sides “just to be sure”)