Saturday, 4 October 2025

Hutspot

There are many hutspot recipies online, including one that I wrote decades ago  but that seems nothing like how I make it now.

This makes loads, but is great for left over meals and freezes well.

Equipment

One big pan
Sturdy masher

Ingredients

1 big brown onion (chopped)
1 tsp olive oil
vegetable stock (1 cube + enough water to almost cover everything that goes in the pan later)
400g tin of borlotti beans (for aesthetic reasons best not to replace with white beans)
1 tbsp mixed herbs
1 kg carrots (big chunky ones, chopped in not too small chunks)
1 kg potatoes (also chopped in not too small chunks)
sweet potatoes (I never measure this, but let's say 500g, also chopped in not too small chunks)

sausages (to serve along side)

Steps

  1. Chop the onion, heat the oil in an enormous pan, fry the onion until soft.
  2. Add the stock, liquid from the tin of beans, herbs and carrots, boil for five minutes.
  3. Add the potatoes and sweet potatoes and simmer for 20 - 25 minutes, until the potatoes seem mashable.
  4. In the meantime cook the sausages separately however you like them
  5. About 5 minutes before the potatoes are done, tip the beans on top to heat them through.
  6. Drain the liquid from the hutspot pan - I normally keep it to make a lentil soup for the next day.
  7. Mash - note this needs a sturdy masher to squash the carrots. Mash until everything is well mixed - it is not meant to be super smooth. The end result should be mostly orange but with some white marbling from the potatoes (and the beans will be visible too)

Thursday, 8 October 2020

Low-knead bread

Before the COVID-19 lockdown of early 2020 it had been a while since I had made bread. As I was suddenly home it seemed like a good time to get back to regularly making bread. Panic buying had depleted the local supermarkets' stock of flour, and while I managed to find some strong white flour and some wholemeal flour, it seemed impossible to find rye flour. This was a shame, as the bread recipe I used most required some rye flour. Somewhere on social media I read a suggestion to try making bread with some cooked oats, and this got me thinking if I could replace the rye flour with cooked oats.

A little bit of trial and error got me to this recipe. There are many steps, but not that much kneading. 

Ingredients

  • 310 ml water
  • 50 gr rolled oats
  • 15 gr unsalted butter
  • 1 tsp salt
  • 1 tbsp sugar (black treacle or honey)
  • 1 tsp yeast 
  • 275 gr strong white flour
  • 75 gr strong wholemeal flour

Needed

  • Oven
  • Loaf tin
  • Mixing bowl
  • Big spatula
  • Kettle
  • Measuring cup
  • Tsp and tbsp measures

Steps

  1. Boil the kettle.
  2. Pour 310 ml of boiling water into a large mixing bowl (I use the one from our Kenwood mixer)
  3. Add the oats, butter, salt and sugar.
  4. Leave for about twenty minutes until it has cooled enough (yeast apparently works hardest around 35℃ and dies somewhere around 60℃, so I just stick my finger in it to check that it is about body temperature).
  5. Once cool enough, sprinkle the yeast on top.
  6. Leave again for a few minutes until some foam has appeared, that's the yeast having been reactivated.
  7. Add the flours.
  8. Mix - I use the dough hook on our mixer and give it some wellie for only a few minutes - but am under the impression that just mixing well should be enough at this stage.
  9. Cover the bowl with a clean tea towel and leave to rest for 10 to 15 minutes. This should probably be "in a warm place," but I've just left it on the kitchen work surface so far.
  10. Uncover. Take a plastic spatula and lift the dough from one side and fold it over. Turn the bowl a quarter and do the same again. Repeat until you've turned the bowl around a few times.
  11. Repeat steps 9 and 10 three or four times (reuse the tea towel!)
  12. Grease and line your loaf tin. You'll want to stick the baking paper down quite well, as it will help with the next step.
  13. "Tip" the dough into the loaf tin. In reality this will mean scraping it out with the spatula.
  14. Stretch the dough a little so it sort of fills the loaf tin. It will rise to fill it, but if you push or pull it a little towards both ends the end result will be a more even loaf.
  15. Cover the loaf tin with a dome of kitchen foil, making sure that the kitchen foil does not touch the dough, and that the dough has room to rise. I make the dome small enough that the loaf tin plus dome will fit in the top oven of our double oven.
  16. Put the dough in a warm spot to rise. For this I use our top oven, which I will switch on for about a minute to 30℃. Don't want the oven to be warmer, as I don't want to kill the yeast at this point. 
  17. Wait for about half an hour. You might want to check on your dough to make sure it still has room under the kitchen foil dome. If it's not got room left, just take the foil off (but save it).
  18. Preheat your main oven to 230℃.
  19. When the oven is hot enough and you think your dough is ready to be baked (my estimate of this is "somewhere before it all spills over the edge of the loaf tin") move the loaf tin into the oven. Take the kitchen foil off if you haven't yet. Save the foil.
  20. After 10 minutes, turn the oven down to 200℃.
  21. Bake for another 25 minutes. It's probably wise to check the last 5 or 10 minutes to see if the bread needs protection from burning. If it does, stick the foil dome on top.
  22. Take bread out of the oven and tip it out on a wire rack.
  23. Tap the bottom. If it sounds hollow, it's probably done. If it does not sound hollow, stick it back in the oven for another 10 minutes (no need for the tin).
The timings might be a little off, not only because not all ovens are the same, but also because I actually use a tin that is 1.5 the size and have adjusted the ingredients accordingly, but am not entirely sure about adjusting the baking timings.

Now that I have found rye flour in the shops again I skip the oats steps, and add 50 gr rye flour along with the other flours.

Sunday, 13 March 2016

Rode kool met appeltjes en rozijnen

Today I made this vegetable side dish for some guests who asked for the recipe, and therefor you get to enjoy it too. The recipe that is.


  • 1 red cabbage
  • 2 apples
  • pinch of salt
  • pinch of powdered cloves
  • 1 tsp vinegar
  • handful of sultanas


  1. Cut the red cabbage into narrow strips.

  2. Peel and core the apples and cut into cubes.

  3. Place all ingredients in a pan with some boiling water. The water does not need to cover the cabbage, but there should be enough for the pan not to boil dry.

  4. Simmer for about 20 minutes.

  5. Drain and serve.

Monday, 11 May 2015

Britse Lagerhuisverkiezingen 2015

Sinds ik in Engeland woon heb ik de politiek matig gevolgd. Zowel de politiek in Nederland als die in het Verenigd Koninkrijk. Aangezien ik van de Nederlandse politiek weinig mee krijg en het stemmen vanuit het buitenland nogal een gedoe is, heb ik stemmen met de Tweede Kamerverkiezingen sinds de laatste keer opgegeven. Hier in het Verenigd Koninkrijk mag ik niet stemmen in het equivalent, de verkiezingen voor het Lagerhuis, omdat ik niet Brits ben.

Om hier te mogen stemmen zou ik me tot Brit moeten laten naturaliseren, met de kans dat ik dan mijn Nederlandse paspoort kwijt raak, en met op dit moment als enige voordeel dat ik mijn stem mag uitbrengen in deze verkiezing.

Dit zou me meer dan £1000 kosten en dat is het dankzij het gebruikte kiesstelsel niet waard. Stemmen is belangrijk en ik ben altijd van mening geweest dat als je niet stemt, dat je dan niet mag klagen. En stemmen vind ik nog steeds belangrijk, maar het blijkt in het Verenigd Koninkrijk niet altijd veel uit te maken. Het kiessysteem werkt hier heel anders dan in Nederland en er valt veel over te klagen.

Gedurende de jaren dat ik het kiesstelsel hier in actie heb gezien heb ik het altijd al vreemd gevonden, maar het is pas tijdens de verkiezingen van mei 2015 dat ik echt opgelet heb en zie dat het systeem knotsgek is.

Hoe het werkt

De verkiezingen voor het Lagerhuis in het Verenigd Koninkrijk worden gevoerd middels een districtenstelsel in combinatie met een meerderheidsstelsel. Er zijn 650 zetels in het Lagerhuis en het land is opgedeeld in 650 kiesdistricten. Een zetel hoort bij een kiesdistrict. Stemmers die in een kiesdistrict geregistreerd zijn kunnen alleen stemmen op kandidaten voor dat kiesdistrict. In ieder kiesdistrict is maximaal 1 kandidaat per partij, maar lang niet alle partijen hebben kandidaten in alle kiesdistricten.

Voor de verkiezingen van mei 2015 waren er meer dan 60 partijen, maar in het kiesdistrict waar ik woon waren er maar kandidaten van 6 van die partijen.

Veel districten worden gezien als "safe seats" wat betekent dat het onwaarschijnlijk is dat de zetel naar een andere partij gaat. Dit komt er op neer dat als je in zo'n district stemt, dat je stem eigenlijk nutteloos is. De winnaar van die zetel had ook gewonnen als je niet op hem/haar had gestemd, en de verliezer had ook verloren als je wel op hem/haar had gestemd (aannemende dat genoeg andere mensen nog wel stemmen).

Ik heb schattingen gezien dat van de 46 miljoen kiezers, de stemmen van slechts 100 duizend kiezers er toe doen.

Om een zetel te winnen hoef je alleen meer stemmen te krijgen dan de andere kandidaten. Als er bijvoorbeeld 1000 kiezers zijn en 5 kandidaten en 4 van die kandidaten krijgen 199 stemmen en 1 krijgt er 204 dan wint die laatste de zetel.

Op deze manier is het mogelijk om een meerderheid van de zetels in handen te krijgen met ruim minder dan de meerderheid van alle stemmen.

En dat is precies wat er nu is gebeurd. De Conservatives (Tories) hebben een "overgrote meerderheid" van 331 van de 650 zetels gewonnen met minder dan 37% van de stemmen. Dit verdient het om het nog een keer anders te zeggen: ze hebben 51% van de zetels gekregen voor 37% van de stemmen.

De resultaten

De resultaten van de verkiezingen zijn met veel detail beschikbaar, maar ik wil er een paar uitlichten om mijn punt duidelijker te maken.




Zetels 2015Verschil met 2010Aantal stemmenStemmen percentageVerschil met 2010
Conservative331+2411.334.52036,9%+0,8
Labour232-269.347.32630,4%+1,5
SNP56+501.454.4364,7%+3,1
LibDem8-492.415.8887,9%-15,2
DUP80184.2600,6%0
UKIP1+13.881.12912,6%+9,5
Green Party101.157.6133,8%+2,8

Om een overgrote meerderheid te behalen zijn minstens 326 zetels nodig. Dat is meer dan de helft van het Lagerhuis. De Conservatives hebben dat bereikt met slechts 36.9% van de stemmen.

Verder zijn er nog meer zetelverdelingen die duidelijk niet alleen op het aantal stemmen gebaseerd zijn:

  • SNP heeft minder stemmen dan de Liberal Democrats, maar 7 keer zoveel zetels;
  • Het verschil in aantal stemmen voor de SNP en de Green Party is niet erg groot, maar het verschil in de zetels wel - SNP heeft er 56 keer meer;
  • SNP en Liberal Democrats hebben samen minder stemmen dan UKIP, maar veel meer zetels;
  • UKIP en Green Party hebben evenveel zetels, maar UKIP kreeg ruim drie keer zoveel stemmen;
  • En nog duidelijker: Liberal Democrats en DUP hebben ook evenveel zetels, maar de Liberal Democrats hebben ruim 13 keer zoveel stemmen gekregen;
  • Tevens heeft Labour deze keer een groter percentage van de stemmen gekregen, maar minder zetels!

De stemmen voor de Green Party, UKIP en de Liberal Democrats zijn verspreid over het hele land, terwijl de stemmen voor de SNP en DUP in een beperkt geografisch gebied plaats vinden. Een partij heeft meer kans op een zetel als de stemmen geografisch dicht bij elkaar zijn.

Er gaan geruchten dat de Conservatives waarschijnlijk het aantal zetels naar beneden willen bijstellen door zetels van andere partijen samen te voegen, zodat ze er voor de volgende verkiezingen beter voor staan. Dit klinkt als een valse methode om aan de macht te blijven, en dat het een probleem met dit kiesstelsel is, blijkt wel uit het feit dat er een woord voor bestaat: gerrymandering.

Evenredige vertegenwoordiging

Er is weinig kans dat dit systeem zal veranderen, aangezien de grootste partijen geen belang bij verandering hebben - hun aandeel in het Lagerhuis zou waarschijnlijk omlaag gaan.

Lang niet iedereen is blij met het huidige systeem en er wordt uitgebreid geroepen dat het systeem moet veranderen. Het systeem is verouderd en werkt niet meer.

4 jaar geleden was er een referendum over Alternative Vote, een systeem dat voorgesteld werd omdat het niet een erg grote verandering zou zijn - en er vermoed werd dat echte evenredige vertegenwoordiging door het electoraat afgewezen zou worden omdat het te anders was.

Evenredige vertegenwoordiging wordt voor sommige verkiezingen wel gebruikt in het Verenigd Koninkrijk, maar niet voor die van het Lagerhuis - want dat zou de grote partijen geen goed doen.

Zetels 2015Zetels gebaseerd op stemmen percentage
Conservative331240
Labour232198
SNP5631
LibDem851
DUP84
UKIP182
Green Party125

Ik heb hier de simpele methode gebruikt om de stemmenpercentages te gebruiken, in werkelijkheid zou er waarschijnlijk een ingewikkeldere methode gebruikt worden die ongeveer op hetzelfde neer komt.

Aangezien veel mensen nu taktisch stemmen om te zorgen dat de partij die ze zeker niet in de regering wil ook werkelijk niet in de regering komt, is het waarschijnlijk dat minder mensen voor de twee grote partijen zouden stemmen. Ook is het waarschijnlijk dat meer mensen die nu niet stemmen, omdat hun stem er niet toe doet, alsnog zouden gaan stemmen wat de resultaten ook weer zou veranderen.

Friday, 30 November 2012

3D Printed Ice Structure

If you're local to me, you will have noticed it rained a lot earlier in the week. And that it was very cold last night.

Well. It appears somebody didn't cover up the sandpit.

While amusing, this is not what this post is about though.

This is:

This ice structure is poking out of another outdoor toy that wasn't covered up.

How did this happen?

It looks like a triangular shaped ice tube. It may not be too clear from the pictures, but the walls of the structure are made of ice and the inside is liquid water.

I imagine that due to the temperature the water under the ice needs space to expand and pushes up through what must have been the last small opening. Each time the water pushes a bit higher the edges freeze, constructing the walls layer by layer - a bit like a 3D printer might do it. Whether this is actually what happened I don't know.

To check that it was actually ice, I tapped against one of the walls and it came crumbling down, spilling some of the liquid it was holding back.



[UPDATE 30/11/2012 17:16 GMT]

Apparently, this is called an ice spike and they don't happen often in "non-distilled" water - making me feel all warm and fuzzy that I found one in our garden.

Sunday, 1 January 2012

Mincemeat Turnovers

Every New Year's Eve I crave oliebollen, but since these require deep frying and hence too much faff, I make appelflappen. Apple turnovers are the only traditional Dutch New Year's Eve food that isn't deep fried, but baked in the oven instead.



Last year I made the filling for the appelflappen from scratch. This year I used a jar of mincemeat instead. Far from traditional, but if the number of these minceflappen that my daughter ate is anything to go by then it was a success! Using a jar is definitely easier than making the filling from scratch, but I thought the mincemeat turned out a bit runny. I think I prefer the more traditional apple turnovers, but think that the ease of using a jar will probably win me over to make these again next New Year.

500gr puff pastry
400gr mincemeat
1 beaten egg
About 2 tsp sugar


Pre-heat fan oven to 200°C.

Roll out puff pastry thinly.

Cut pastry into twelve squares of about 12cm.

Place small heap of filling in centre of each square.



Fold each square over to form a triangle.



Brush with the beaten egg and sprinkle with sugar.



Bake in oven for about 10-15 minutes.


1 January 2017


I made two batches yesterday for a party, but because I only had one jar of mincemeat I made one version with a more traditional apple and sultana filling.

For the mincemeat version I heated the mincemeat in a pan and drained the liquid off through a sieve. This helped the consistency of the mincemeat turnovers, but not necessarily the flavour!

For the apple and sultana turnovers I used one cored and peeled and chopped apple and an inexact amount of sultanas and currants soaked in sherry with speculaas kruiden (cinnamon would do). Before folding the pastry over the filling I put a thin marzipan sausage on the filling.
This version was much tastier than the one with mincemeat and is the one I will be making in the future.


Sunday, 25 December 2011

Cheat's Trifle

For the last four years I have made a trifle for our Christmas dinner. You know you've been accepted when your family let's the foreigner make the trifle.

When I was looking for trifle recipes my wife initially suggested I would make Heston Blumenthal's version*. Hah, very funny, love, but no. I decided to go for Rick Stein's Traditional English Trifle.

Well, I looked at it.

And then I took every shortcut I could think of.

Bake my own madeira cake? Oh, look, cheap supermarket's madeira cake.
Make my own custard? Ooo, look, cheap supermarket's fresh custard...

I've never actually made Rick Stein's trifle and as a result I don't have a clue whether my shortcut version has any positive relation to his, but my family likes it, so who am I not to keep making it?

Since I'm not actually following Rick Stein's recipe I've always had to guess most of the quantities and have ended up buying too much. My main reason for writing this down is so next year I can finally stop buying too many ingredients.



While most celebrity chefs always seem to suggest getting the best ingredients money can buy, I suggest getting the "normal" range of fresh custard from your supermarket, and the cheapest madeira cake you can get.

2 * 500gr tubs fresh custard (I use Sainsbury's Fresh Custard, not the one from their Taste the Difference range)
1.5 jars raspberry conserve (I use Bon Maman)
4 * 265gr madeira cake (I use Sainsbury's Basics Madeira Cake)
200 gr milk chocolate
480 ml double cream
Oloroso sherry (about 20 spoonfuls, far less than a bottle)

This gives me about two medium sized serving bowls and a bit more worth of trifle. I tend to create little individual ones without the sherry for the kids and put all the sherry in the main bowls.

Day before serving (i.e. Christmas Eve):
Cut the cakes length ways into slices about 1cm thick, cut the "crusts" off.
Put one layer of cake on the bottom of your serving bowl.
Spread about two spoonfuls of jam on it.
Add another layer of cake + jam.
Depending on the height of your serving bowl, you might want to add another layer of cake + jam.
Drizzle over the sherry and give it a bit of time to sink in, you can help it by poking the cake layers with a knife to create a few holes.
Pour the custard on top, cover with cling film and put in the fridge.

Grate the chocolate (First time I bought a packed of grated chocolate, and since I haven't been able to find that cheat anymore I now grate the chocolate using a food processor). Cover and put in the fridge as well.

Just before serving (Christmas Day):
Whip cream, scoop and spread on top of the trifles, sprinkle over the grated chocolate.

There is no chocolate in Rick Stein's recipe, but I think the sprinkled chocolate looks and tastes good and the kids love doing the sprinkling.

Enjoy.

* I used to have a link to Heston Blumenthal's trifle recipe, but the recipe seems to have disappeared from the BBC Food website. I can't find the recipe online now, but it is the one that takes 6 hours to make and requires wonderful kitchen implements such as an electric drill and a blow dryer. [UPDATE: I found a simplified version of Blumenthal's trifle, which still seems like an awful lot of work.]

Friday, 3 June 2011

Shortened URL Expansion

Twitter provides me with a lot of value through the plenty of interesting and/or useful links that get tweeted by the selection of people that I follow.

Usually when I notice an interesting looking URL, I mark the tweet as favourite, so I can easily find it again later. The twitter.com's favourites interface isn't nearly easy enough for my liking, so I decided to create a webpage that would show me all my favourites links, so I could easily bookmark them on delicious or send them to instapaper.

However, I don't want to bookmark the shortened URL, to prevent link-rot I'm only interested in the actual link hidden behind one or more layers of URL shortening services. In fact I don't even want to see shortened URLs, I would much rather know where I'm going.

My initial attempt to solve this problem was to use the bit.ly api for expanding bit.ly URL-s, which works for a lot of shortened URL-s as many of them go to bit.ly under a different guise.

However, it doesn't work for all. Most importantly, it doesn't work for twitter's own t.co shortener. This also doesn't appear to have an easily discoverable API for expanding the url.

If I can't find a nice way to expand the URL, why not simply keep following the redirects until I hit the actual page I want to bookmark? The following few lines of code should expand any shortened URL, and indeed any redirected URL whether shortened or just hidden behind a redirect.

   protected string expandurl(string url) {
System.Net.HttpWebRequest hwr = (System.Net.HttpWebRequest) System.Net.WebRequest.Create(url);
hwr.Method = "HEAD";
hwr.AllowAutoRedirect = true;
hwr.MaximumAutomaticRedirections = 10;

System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)hwr.GetResponse ();

return response.ResponseUri.ToString();
}


The MaximumAutomaticRedirections setting will stop an endless redirection loop, but also means that you might still end up with a shortened URL if the one you've passed in hides even more lot of layers of redirection.

The HEAD HTTP method should only return the HTTP headers, not the actual content of the page, so using that should reduce network traffic.

Because I'm figuring out which URL is at the end of the redirect chain by following the chain, there is a rather high chance that every time this get's executed the intermediate URL shorteners will register our passing by as a "click" and update the stats for that particular shortened URL (if that service provides that service).

Friday, 17 December 2010

Creating a Moodle course selector

Moodle has a user selector base class that is used in a few places to select users using a select box, for instance with two side-by-side user selectors to assign users to a role - one with users assigned the role, and one with users who are not assigned the role.

For a project I'm working on I need a similar set up, but for courses, to use in a block. Initially I added the code for the course selector with my block, but have since moved it into a separate local plugin, so it should be easier to reuse.

To start adapting the user selector I copied the /user/selector directory to /local/course_selector, and changed the relative paths inside the three files in that folder.

Also added a version.php and lang/en/local_course_selector.php to make it a full fledged local plugin.

Lots of simple changes





  1. First up in lib.php get rid of everything after line 646:
    // User selectors for managing group members ==================================
    I don't need this for my course selector, and it just complicates the string replacements below.



  2. Global string replacements:








    from to
    "user selector" "course selector"
    "user_selector" "course_selector"
    "USER_SELECTOR" "COURSE_SELECTOR"
    "M.core_user" "M.block_abc"
    "userselector" "courseselector"
    "users" "courses"



  3. change the two calls to moodle_exception to include the module name parameter
    so instead of
    throw new moodle_exception('cannotcallusgetselecteduser');
    it becomes
    throw new moodle_exception('cannotcallusgetselectedcourse', 'local_course_selector');
    so that the appropriate error message can be found in the language file for the block.


  4. Add these two lines to the language file local_course_selector.php:
    $string['courseselectortoomany'] = 'course_selector got more than one selected course, even though multiselect is false.';
    $string['cannotcallusgetselectedcourse'] = 'You cannot call course_selector::get_selected_course if multi select is true.';



  5. All get_string calls need to get 'local_course_selector' as a second parameter as well (some have a blank one '', some have none, some have 'moodle', it's probably best to replace them all with 'local_course_selector').



  6. Then add these to the language file as well:
    $string['clear'] = 'Clear';
    $string['searchoptions'] = 'Search options';
    $string['courseselectorpreserveselected'] = 'Keep selected courses, even if they no longer match the search';
    $string['courseselectorautoselectunique'] = 'If only one course matches the search, select it automatically';
    $string['courseselectorsearchanywhere'] = 'Match the search text anywhere in the course's name';
    $string['toomanycoursesmatchsearch'] = 'Too many courses ({$a->count}) match \'{$a->search}\'';
    $string['pleasesearchmore'] = 'Please search some more';
    $string['toomanycoursestoshow'] = 'Too many courses ({$a}) to show';
    $string['pleaseusesearch'] = 'Please use the search';
    $string['nomatchingcourses'] = 'No courses match \'{$a}\'';
    $string['none'] = 'None';
    $string['previouslyselectedcourses'] = 'Previously selected courses not matching \'{$a}\'';
    $string['search'] = 'Search';




  7. Next up I replaced all occurences of "user" with "course", unless it was $USER or had anything to do with user_preferences.


  8. change output_course function (renamed from output_user in the near-global replace) to convert a course object to a string.
    so that instead of "fullname($user)" it now does "$course->fullname"



Slightly more complex changes



Then it would seem we are nearly there. We have a course selector.

Except that it doesn't quite work, because the search_sql function creates SQL based on the user table, not the course table. This is mainly to make sure the references to firstname/lastname are replaced with fullname similar to how it was done for the output_course function above, and the $tests array contains the 'visible = 1' instead of the 'deleted = 0', etc.
'firstname', 'lastname' in the required_fields_sql function also need to be replaced with 'fullname'.

module.js

In module.js there are references to some strings as M.str.moodle.nomatchingusers and M.str.moodle.previouslyselectedusers. These are made available to JavaScript via hte $jsmodule definition in lib.php (approx. at line 67).

Two lines to change there into:

array('previouslyselectedcourses', 'local_course_selector', '%%SEARCHTERM%%'),
array('nomatchingcourses', 'local_course_selector', '%%SEARCHTERM%%'),


Now note that these will be available to the JavaScript code as M.str.local_course_selector.previouslyselectedcourses and M.str.local_course_selector.nomatchingcourses, so the references in module.js need to be updated accordingly.

Now all that's left is to realize that the css class has been renamed from userselector to courseselector, so any css styling will need to be applied to that. I haven't done this yet, so I'll "leave that as an exercise for the reader."

Conclusion



I think I've been lucky that the user selector wasn't more bound to the user object. It only keeps track of users using the ids, which made it very easy to do a global replace from user to course.

It was a fairly easy adaptation.

I only had a small issue with the Ajax version of the search only partially working, but once I'd figured out how the M.str.moodle strings turned up in the JavaScript and that I had to change the JavaScript reference to the scripts it actually seemed to work.

If one of the requirements for this project wasn't to not change any core Moodle code, but only add using any of the plugins available, I would probably have changed the existing user_selector so that it and this course_selector could share a common ancestor object_selector, which would do the bulk of the work, while the user_selector and course_selector would only deal with their specific needs.

Tuesday, 7 December 2010

Developing on Windows, using Git, Dropbox and Ubuntu (and XAMPP)

I generally do my development work on Windows, mainly because a lot of it is .NET based. Occasionally I do non-.NET work (ruby/php), but since my main development pc is a Windows pc, I still usually use Windows.

Currently I have a client who uses Git for version control. Fair enough, I have TortoiseGit installed, so no problem, I thought. However we couldn't get the public/private key pair from my TortoiseGit/PuTTYgen to work with their Git server for authentication. I'm not sure why - something to do with the openssh keys being slightly different to the ones generated by PuTTYgen.

Since the client knows it works fine on Linux, it seemed to make sense to just go with Linux. But I still like to use my main development pc, which is a Windows pc.

Dropbox* to the rescue.

I have cloned the git repository into my Dropbox folder on my Linux pc. Dropbox syncs the files between my Linux and my Windows pc.

Now I can edit the files on my Windows pc and test them by running the Apache/MySQL/PHP based website on XAMPP. And while I'm doing the testing, Dropbox syncs my changes back to the cloned git repository on the Ubuntu pc.

It took a very long time to sync after the initial clone of the remote repository, and again after switching to the development branch, but after that it seems to work well.

TortoiseGit seems to be a bit confused with the synced git repository, so I'm not even going to try to actually use it for this project. Instead I'm using git on the command line on the Linux pc and that works fine.

A couple of points:


  • Sometimes there is a couple of seconds delay between saving files on Windows pc and appearing on the Linux pc, due to having to go through Dropbox, so it seems to be wise to wait a bit with git commands or at least check that the files have finished syncing.


  • Line endings. My editor saves with Windows style line endings by default, so I had to set it up to always save files with Unix style line endings (LF).


  • I have created symbolic links on Windows to link the git repository folder in the Dropbox folder into the htdocs folder in XAMPP (using mklink).
    mklink /D "moodle" "c:/users/me/my dropbox/git/moodle"
    The result is that I can now access the moodle site on http://localhost/moodle


  • I'm for now only working in one branch, and hope to keep it that way, as switching branches would possibly trigger another long sync time as it did the first time.



* If you don't have a Dropbox account, feel free to use this link to sign up and get a little bit of extra space. It will give me a bit of extra space as well.

Monday, 6 December 2010

Motion Detecting Bird Feeder Cam



It has been snowing quite a bit recently so despite never having had much success with the birds, I decided to put our bird feeder out. It is hanging from a washing line, well away from any structures that could hide predators. Well, once the snow lady has melted it will be.



Reading and watching Oli Wood's bird feeder webcam inspired me to dig out our "old" digital video camera as well. Our camera is a Canon MVX350i, which has 20x optical zoom, just what's needed to be able to zoom in on the bird feeder at this distance.

The camera is connected to the computer using a Firewire cable, and once I had figured out how to switch off the "auto power save" feature we were good to go.

The camera is directed at the bird feeder using this expensive hand optimized stand:




Because we always only get very few birds on our feeder, I wanted to use motion detection webcam software to take pictures of any birds coming to the feeder. I vaguely remembered a friend using software that took pictures when it detected motion and uploaded them to an ftp server. I don't remember what it was called and hence had no luck finding it.

I did however find open source surveillance software iSpy that appears to do the trick.
Whenever it detects motion it records a bit of video up to a certain length. It has a few settings to change the motion detection and its sensitivity.

The first day I had it running it took a nice bit of video of what I believe is a robin, but completely missed the pair of tits that appeared on the feeder a few minutes later.

Increasing the sensitivity - I think I was increasing it: the slider doesn't mention which we is up or down, so I presume left is down, right is up - only seemed to get me lots of video of the wind blowing the feeder about, so in the end I stuck to the default sensitivity.

It would probably be better to make sure the bird feeder is rigid by sticking a pole in the ground and up its bottom, and increase the sensitivity. The pole should stop the wind blowing the feeder about, while the increase in sensitivity should pick up even the most delecate of birds.

One nice touch is that iSpy buffers the frames, so that when it detects motion it can use a bit of buffered video so you get all of the action, and not just the bird disappearing. It would otherwise possibly have missed this coal tit flying in:



The video of the robin is unedited. I trimmed about a minute of feeder waving about off the end of the coal tit one.

Monday, 11 May 2009

The Big Agile Practices Survey

Last week Jurgen Appelo asked if anyone could help him create an online interactive table for the results from his Big Agile Practices Survey. Having just gone freelance I figured I could use the publicity and since I had a bit of time to spare, I volunteered.

The result: my sortable color coded table is on a separate page since it's a bit large and wouldn't work well on this blog.



Note the "ad" at the top, that's me available for some freelance work.

The table is an ordinary HTML table, manipulated using jQuery, the jQuery plugin tablesorter, and some JavaScript and CSS.

The page has been tested in IE7, Firefox 3, Google Chrome, Safari 4 beta for Windows, but if you find anything doesn't work, let me know, and I might fix it.

Thursday, 6 November 2008

Is disabled disabled?

In HTML boolean attributes can be set on elements without a value. For instance, an option of a select could be selected using <option value='1' selected>, a checkbox could be checked using <input type='checkbox' checked>.

In XHTML attributes are not allowed without a value, as that is not valid XML. Attributes are required to be 'unminimized.' E.g. selected becomes selected="selected", checked becomes checked="checked" and disabled becomes disabled="disabled".

Ah. Disabled is disabled? So surely that means the element is enabled? I know it makes perfect sense to keep the standard standard, but surely if you come to XHTML without the historical information and find out that disabled="disabled" means that the element is actually disabled, this just looks plain odd, weird and wrong?

Tuesday, 28 October 2008

Stupid design



Recently at my workplace the water coolers and the water boilers have been replaced by a machine which does both. It's very simple. It has a green light to indicate it is on. If you press the big button you'll get icy cold water. And if you press the small button on the left, the green light turns red to indicate there is enough hot water and that by (quickly!) pressing the big button before the light turns back to green you'll get hot water.

Great. Apart from the short time you're given to acquire the hot water when it is available, can you see something else that is flawed in this design?

A light that changes between red and green. Most colour blind people can't distinguish between the two. Great. Now how do they know whether there is hot water, other than by sticking their finger in the either freezing cold or scolding hot stream of water?

But it is even worse!

Because there are not two colours! There are three! Apparently the light turns yellow as well. I'm colour blind, but have no problem with red and green. Green and yellow on the other hand...

The above is how I thought the machine worked, but for people without my kind of colour blindness, it apparently works like this:

The light is yellow to say "there is no hot water", green to say "there is hot water" (or was that the other way around? I can't remember, and I can't check, because I can't tell the two apart!) and red to say "thanks for pressing the small button on the left and as a thank you I might just give you hot water if you press the big button. But only if you're quick enough."

Stupid design.

Monday, 23 June 2008

Star struck

John reminded me just now about the first time I saw a hummingbird in real life. Where I come from you only get them in nature programmes on the telly, not outside hovering near flowers. I don't think I ever realized where they do appear in the outside world, so when I saw one I was absolutely star struck: "Look, it's a hummingbird, off the telly!". I was in a suburb of Goleta trying to find the local supermarket on my first day there, and noticed a couple of really really big "bees" hovering above a tree, about three meters above the ground. Imagine my joy when I realized I was going to see them most mornings having their breakfast outside my kitchen window.

I had a similar experience years later (a couple of years ago now, blimey, I'm not getting any younger) when I visited the Grand Canyon and noticed a big vulture sitting below us. Someone uttering "condor" made me forget about the Grand Canyon ("just a big hole in the ground after all") and stare star struck at the condor. "Look, it's a condor, off the telly!". Apparently some California Condors I had seen going nearly extinct on the telly had been moved to the Grand Canyon to thrive.

Wednesday, 30 April 2008

Een fijne dag zonder nederlandse collega's!

Een van de vreemde ervaringen van het wonen in het buitenland is dat de dagen die je in je oude land als nationale feestdagen had in je nieuwe land niet altijd feestdagen zijn.

Kerst en nieuwjaar is vrij universeel in het westen - al is tweede kerstdag bijvoorbeeld een werkdag in de VS - maar hier in Engeland is tweede pinksterdag bijvoorbeeld geen vrije dag.

Mijn "probleemdag" is voornamelijk koninginnedag. Hemelsvaartsdag en tweede pinksterdag zijn ook geen vrije dagen, maar die vallen nog wel eens in de buurt van de twee vrije dagen die ze hier in mei hebben en omdat ze ieder jaar op een andere datum vallen weet ik nooit wanneer ze werkelijk zijn, dus merk ik ze niet echt meer op. De twee bank holidays in mei vervangen deze twee dagen met veel plezier.

Koninginnedag daarentegen valt altijd op 30 april en dat zie ik dan ook de hele maand april al aankomen. In Nederland vierde ik koninginnedag meestal niet meer dan "hoera vrije dag" dus nu ik hier in Engeland zit voel ik dan ook niet echt dat ik de festiviteiten mis, maar die vrije dag was best leuk geweest.

Ik mis koninginnedag duidelijk genoeg om er een blogpost over te schrijven, maar na een paar jaar is de pijn toch wel een stuk minder. Wellicht helpt het dat ik geen nederlandse collega's meer heb, die me aan hun vrije dagen helpen herinneren!

Monday, 28 January 2008

Fokke en Sukke filteren het nieuws

Mijn kijk op Nederlands nieuws is, sinds ik in Engeland woon, voornamelijk beperkt tot de cartoons van Fokke en Sukke. Er zijn genoeg andere sites via welke ik ook nieuws ontvang en ik zou makkelijk verder onderzoek kunnen doen, maar de cartoons fungeren als een prettig filter.

Soms heb ik geen enkel idee waar het over gaat, zoals in "Fokke en Sukke hebben niet ondertekend" en "Fokke en Sukke rehabiliteren Marinus van der Lubbe."

En soms herken ik dan wel de namen van de gedupeerden, zoals in "Fokke en Sukke zijn nog niet gevraagd," maar dan heb ik nog steeds geen idee waar het over gaat.

En wat belangrijker voor me is: ik heb ook niet altijd de behoefte om te weten welk nieuws er achter de cartoon schuil gaat. Ik vraag me af of Fokke en Sukke geschreven wordt in de hoop dat de grappen ook buiten de context werken. Het zou de verkoop van hun jaaroverzichten waarschijnlijk ten goede komen.

Wednesday, 5 December 2007

Telly

Yesterday, our daughter wanted to watch a bit of telly, or "teddy" as she calls it, and more particularly she wanted to watch Nijntje (Miffy). We thought we'd let her and popped in the DVD.

Somehow this made me think that when I was a kid my mum would probably have responded with "but it is not Wednesday afternoon, there is nothing on!"

I remember the tv test screen.

Wednesday, 19 September 2007

How to move your email to GMail using free tools

I've been using GMail for quite some time now, and have recently decided to import a lot of archived mail from my old mail accounts. Currently I have this mail stored in various formats, most notable Outlook PST-files. PST files are notorious for not being able to be read by anything but Outlook. Worse yet, I have an archive in Outlook 2003 format, which can't be read by the only (old) Outlook version that I have access too. I'll solve this situation one way or another, but that's not what this post is about.

I'm trying to find a good way to import my archiving email, using free tools. My first attempt some time ago, involved importing e-mail from an imminently closing POP account into Thunderbird and then redirecting/bouncing the e-mails using the MailRedirect plugin. [1] This worked fine, except that all mails showed up in my GMail inbox with the date of when I redirected them (apparently this can be fixed by importing them into a temporary GMail account, and then letting MailFetcher retrieve them all via POP, which fixes the date issue).

Using the Thunderbird MailRedirect plugin is not very user friendly when you have lots of emails to transfer: some will fail and it is a lot of work to pick out the ones that have failed and re-redirect them. Also, one reason why they might fail is that the smtp server you are using for the redirecting is refusing connections because you are sending too many e-mails in too short a time interval.

The best solution would be for all your archived mail to exist in a POP-accessible account and have GMail retrieve them. GMail will keep trying until it is done, which means that if it fails for some reason, it will just try again in an hour. If you have your e-mails in local files this doesn't work, unless you could somehow get your e-mails back into the mail server. Using IMAP you can. If you have an IMAP account available, then great. If not, you can still do it for free in a few steps, as long as your e-mail client understands IMAP and you have some time.

Firstly you need to install a free smtp server that supports both IMAP and POP. I used MailEnable Professional Evaluation Edition, which is fully usable for three months, for evaluation purposes. I set the mail server up inside a virtual machine (running an evaluation version of Windows) using the free VMWare Server. Using a virtual machine is good for security as it allows you to open a port on your firewall and forward it to just the virtual machine, which should leave your main machine protected. [2]

In MailEnable create a post office and add user accounts for each GMail label that you want to import mail to. If you have a lot of e-mail to import, this will make things easier to sort when it finally arrives in GMail, as the MailFetcher allows you to automatically assign a label to the imported mail. Using separate POP accounts means you can set the labels when they come in, rather then sorting through your mail manually after everything has been imported. For instance, if you want to add some mail to a label called Friends and some to a label called Family, add two accounts: "friends" and "family".

Open your e-mail client and connect to the accounts you have just created in MailEnable. You need to know the IP-address of your virtual machine. If you have called your post-office "mailenable" then the above accounts would have a login name of "friends@mailenable" and "family@mailenable" respectively. Now you're ready to start copying e-mails from your mailbox to your new IMAP accounts. Just drag them into the correct IMAP account's Inbox and they will be uploaded to the server.

Once you've got your e-mail in your IMAP server, it is time to open a port on your firewall and forward it to the IMAP server virtual machine. The default POP port is 110.

Add your accounts to the GMail MailFetcher (GMail settings / Accounts). You need to give them a real e-mail address, but that won't actually be used. Make sure the login name is the same as you have set up in your mail server (so friends@mailenable or family@mailenable in the above example). Set the mail/pop server address to your external IP address. Select the label you want GMail to use for the e-mails in this account (it will provide a reasonable default). Also select it to archive all the e-mails, so they don't clutter up your inbox. Don't select "leave a copy on the server", so you can easily tell when it is done by looking at the mail server. When you click "Add Account", GMail will start retrieving your e-mails!

GMail appears to retrieve e-mail from your pop3 account about once per hour, taking 200 e-mails at a time, so if you have more than 200 e-mails, you'll have to wait a while before all of them have been retrieved. 200 e-mails per hour = 4800 per day. If you have a lot of email, it can easily take a couple of days. Because you didn't select "leave a copy on the server", the e-mails will be deleted from the mail server when GMail retrieves them. This means that you can easily tell when it is done retrieving by looking at the user account list in the mail server (well, it was easy in MailEnable): It's done when the number of messages in the mailbox is 0.

When it is done retrieving all e-mails from all accounts you should close the port on your firewall. You can now stop your virtual machine and get rid of it if you want.

Don't remove the pop accounts yet from the GMail accounts settings, as GMail hasn't processed all the e-mails yet, and won't label/archive them if you remove the accounts, but dump them in your inbox instead. Leave it a while (I have no idea how long, one hour? two?), and the labelling should go on.

[1] I now wonder why I didn't just use GMail's MailFetcher for this particular case, but don't remember why. Perhaps MailFetcher wasn't available yet? Perhaps I wanted a local copy in Thunderbird? Perhaps I had other reasons? Or perhaps I just wasn't happy with handing my password for one service to another service.

[2] This of course assumes you're using a firewall (or router with built-in firewall) that supports port-forwarding. Note that I'm not a security expert. Don't forget to close the port when you're done.

Wednesday, 15 August 2007

Puter!

My wife and daughter are currently visiting Granny and Grandad. Apparently when asked where Grandad was, our 19-month old said "puter"...

I'm so proud! My little girl knows about computers! I think I'm more proud of this than of her saying "papa".

Another new word today is "key"... I wonder if she's considering a career in cryptography?