16 décembre 2014

Javscript arkanoid

Searching Google for "Javascript arkanoid" got me to these interesting pages:

27 mars 2013

Chloé veut des dessins animés

Monsieur Apache est un vieil archiviste qui vit sur une ile deserte au milieu du Pacifique. Il est responsable de miliers de fiches information qu'ils ne comprends pas. Chaque fiche a un titre. Quand on veut obtenir une information on envoie un SMS à M. Apache avec le titre de la fiche, et l'archiviste vous renvoie un SMS avec le contenu de la fiche.

M. LeFox vit à Achetey-Hémelle et comme tout Hémellois il ne sait parler que le HTML. Quand le contenu d'une fiche d'information lui est transmise il est responsable de dessiner une représentation graphique des fiches de M. Apache. Malheureusement un triste accident de la vie à fait perdre ses deux bras à M. Lefox et il ne peut plus dessiner. Son apprenti Dominique, plus communément appelé Dom, est chargé de dessiner ce qui est écrit en HTML sur la fiche. Mais M. LeFox est vieux jeu, et il ne laisserait pour rien au monde Dom toucher au téléphone.

Un jour Mlle Chloé arrive chez M. LeFox et demande une copie de la fiche "index.html". M. LeFox envoie un SMS à M. Apache lui demandant la fiche "index.html" M. Apache s'en va dans ses archives, cherche la fiche "index.html" et envoie une copie de son contenu à M. LeFox. M. LeFox recoit le SMS avec le contenu de la fiche, et explique à Dom comment le dessiner: "Tu dois dessiner un titre, met les caractères en gras pour qu'on les voie correctement, voilà c'est bien. Maintenant dessine un paragraphe, en rouge s'il te plait." Quand Dom a fini son dessin il le donne à Chloé.

Le lendemain Mlle Chloé arrive chez LeFox et lui demande la fiche "index.php". Comme le jour précédent M. LeFox demande le contenu de la fiche à M. Apache. Il commence à expliquer à Dom comment dessiner: met un titre, puis un paragraphe. Mais soudain il tombe sur une partie de la fiche qui commence par < ? php ... ? > et qu'il ne comprend pas. Il demande donc à Dom de reproduire à l'exact cette partie de la fiche. Quand Chloé recoit sont dessin elle se demande bien ce que peut bien être ce truc étrange au milieu de son dessin, mais personne à Achetey-Hémelle ne comprend cette langue bizarre.

Suite à une longue série de plaintes, provenant de tous les habitants de Achetey-Hémelle, M. Apache décide d'engager un consultant, M. Pépé Achpé, qui comprend le PHP. Maintenant quand M. Apache recoit le titre d'une fiche, avant de renvoier son contenu, il demande à M. Achepé de traduire les parties PHP en HTML. Une fois que c'est fait il achemine le résultat vers M. LeFox.

Le salaire de M. Achepé est peut être élevé, d'autant plus que réaliser ses traductions lui prend un certain temps, mais il est très flexible et parle plusieurs langues dont un dialecte du vieux continent: le SQL. On peut demander à M. Achepé de réaliser différentes tâches pendant qu'il traduit. Par exemple lui demander d'appeler Mme Ada Base qui vit à Essequelle, pour lui poser des questions. Ce qu'il y a de bien avec Mme Base c'est qu'elle connait une gigantesque quantité d'informations. Elle connait entre autre la liste de tous les articles vendus par le Mégastore du Coin. Par contre Mme Base ne sait parler que le SQL c'est pourquoi M. Apache ne l'appele jamais. Mais M. Achepé lui sait, et ne se prive pas de la contacter. Et une fois sa conversation avec Mme Base terminée, Pépé peut en insérer une partie dans la fiche traduite.

Chloé est bien contente de cette restructuration chez M. Apache, les dessins qu'elle recoit contiennent maintenant les informations concernant les articles dont elle à envie au Mégastore du Coin et plus de charabia incompréhensible.

Mais comme on se lasse vite des bonnes choses, Chloé devient plus exigeante, elle en a marre des dessins statiques elle veut voir des desins qui bougent, des dessins annimés. Seulement ca, M. LeFox et Dom ne savent pas le faire. Tout ce qu'il peuvent c'est dessiner ce qu'ils recoivent dans les SMS de M. Apache.

Réunion de crise, on reflechit, et on arrive à la conclusion qu'il faut engager un nouveau consultant mais cette fois chez M. LeFox. Malheureusement les seuls consultants capables de faire bouger des dessins sont ceux de Ecmaland, qui ne parlent que le Javascript, une langue ancienne et cryptique (d'ou son nom) qui s'aparente au sanscrit. Tant pis, aux grands maux les grands moyens, on engage M. Jah Vashcri, un vieux Ecmalandien, le seul disponible sur le marché. M. Vashcri peut découper des morceaux des dessins de Dom et les faire bouger. Mais pour ca il faut que M. LeFox lui dise quels morceaux prendre, et comment les déplacer. Mais ni Dom, ni M. LeFox ne savent parler le Javascript. Il faut que les fiches qu'ils recoivent contiennent déjà les instructions de mouvement. Ce sur quoi LeFox les transmettra à Vashcri.

Pour chaque fiche des archives que l'on veut voir animée, des concepteurs créent une nouvelle fiche en Javascript avec les instructions, puis ils l'envoient à M. Apache en lui disant bien que ce sont les instructions pour la fiche XYZ.

Maintenant quand Chloé demande sa fiche index.php, un branle-bas de combat se met en place:

M. LeFox envoie un SMS à M. Apache, qui va chercher la fiche, qui la passe à M. Achepé, qui la traduit. Mais avant de renvoier la fiche, M. Apache regarde s'il y a des instructions de mouvement Javascript associées et le cas échéant les renvoie également. Quand M. LeFox recoit sa réponse, il demande à Dom de dessiner le contenu, puis donne les instructions Javascript à M. Vashcri pour qu'il fasse bouger le dessin.

Chloé est très contente de ses nouveaux dessins qui bougent. Elle en veut toujours plus.

Mais M. Vashcri se fait vieux, il est à moitié sourd. Le concepteurs des instructions de mouvement pour les dessins ont de plus en plus de mal à communiquer avec lui. Il ne parle pas le Javascript 'djeuns. A force de perdre du temps à expliquer, il décident d'engager un Ecmalandien plus jeune du nom de Jay Quiri. Il est beaucoup plus simple de communiquer avec Jay il comprend le Javascript de la rue, le language des jeunes..

Malheureusement M. Vashcri, sentant son poste mis en danger, met les pieds au mur et décide qu'il sera le seul autorisé à decouper les dessins de Dom. Depuis le temps qu'ils collaborent, une certaine promiscuité s'est installée entre Vashcri et LeFox, ce qui pousse ce dernier à accepter ce compromis. Les instructions pourront être écrites en language 'djeunes, mais seulement si M. Apache envoie le consultant Quiri avec ces instructions. Le salaire de Jay devra bien sûr être payé par M. Apache, et donc par les concepteurs des mouvements.

C'est dans un sacrée bouhaha que Chloé va maintenant récupérer ses dessins: LeFox occupé à donner des instructions à Dom et à Vashcri, Quiri débarquant et expliquant ce que signifient tous ces termes Javascript argotiques, Dominique dessinant, Vashcri decoupant...

Chloé se dit que ca fait beaucoup trop de bruit pour un "simple" dessin qui bouge. Elle decide d'enfermer tout ce joli beau monde dans une boîte sur laquelle elle écrit au feutre rouge: BROWSER.

21 mars 2013

Create an entity repository as a Symfony service

In the bundle MyVendor\MyBundle, to instantiate the entity repository MyRepository for the entity MyEntity, you can use the following service definition.

    MyVendor\MyBundle\Entity\MyClass

Source: http://blog.code4hire.com/2011/08/custom-repository-with-dic-in-symfony2/

14 janvier 2012

ClassGrapher



I have developped a small utility command line application able to generate simple class diagrams out of any set of namespaced PHP files. The goal being to have a quick way to figure out how some PHP classes were structured without browsing too much code. This is not very accurate but give you a quick big picture of the code structure.

The code can be found on github:
https://github.com/sixty-nine/ClassGrapher

The PHP parser

The class grapher does not use PHP reflection to gather inheritance information about the classes. Indeed, in order to work, PHP reflection needs to be able to instanciate the classes it loads. This is not possible if you have missing dependencies in your project.
The goal of the grapher was to draw the structure of any PHP files.
Thus I implemented a simple recursive parser for only the parts of the PHP language that were needed for the grapher (basically any "use", "namespace", "class" and "interface" statement).

Using composer to download vendors libraries

Composer is a PHP utility used to manage project dependencies.
See composer website.

The idea is simple.

You download the composer.phar binary to the root of your project, then create a composer.json file describing the dependencies of the project and finally run the command:

./composer.phar install

This will automatically download the dependencies as well as create an autoload file for your project.

Example of composer.json file

The grapher project uses the smyfony/console component from the Symfony2 framework. Additionnaly we would like to autoload the files of the project.

The corresponding composer.json file looks as follow:

{
    "require": {
     "symfony/console": "2.0.7"
    },

    "autoload": {
        "psr-0": {
            "LazyGuy\\ClassGrapher": "src"
        }
    }
}

This file will indicate to composer that the library "symfony/console" version "2.0.7" must be downloaded to the project directory. Furthermore any class in the namespace "LazyGuy\ClassGrapher" will be searched in the "src" directory.

Be carefull, this is JSON, you cannot add extra coma at the end of a list if there is no successor in the list (in PHP you can).

Using travis for continuous integration

Travis is a free, lovely continuous integration online service that provides seamless integration with github.

All you need to do is:
  1. Register to travis
  2. Go to github and enable the travis hook
  3. Create a .travis.yml file to indicate to travis how to run the tests of your app
This will cause any github commit in your project to trigger a build on the travis continuous integration server. Travis will run your tests in two PHP environments:
  • PHP 5.3
  • PHP 5.4

The .travis.yml file

This file must indicate to the travis server how to build your project.

In our case, travis must download the dependencies with composer and then run the tests

language: php
php:
  - 5.3
  - 5.4

before_script:
  - wget http://getcomposer.org/composer.phar
  - chmod +x composer.phar
  - ./composer.phar install

script: phpunit -c src/LazyGuy/ClassGrapher/Tests/

The language section indicates which is the language of the project. The "php" key lists the PHP versions to run the tests against. The section "before_script" tells to travis what to do before running the tests (here it will download composer and then run the install command). Finally the "script" section indicates the command to run the tests.

Once you configured travis, any commit to github will cause travis to build the project, run the tests, and report success or failure.

Isn't that lovely?

8 décembre 2011

Experiments with the Arduino - Multiplexed leds

Introduction

In a previous experiment I was controlling 5 leds using 5 outputs of the Arduino. With the help of a 4051 multiplexer it is possible to control up to 8 leds using only 3 outputs.

Basically a multiplexer is an electronic device that can send it's single input to one of it's height outputs. The active output is selected by sending a binary number from 000 to 111 to the three control pins of the multiplexer.

Wikipedia will tell you everything you ever wanted to know about multiplexers.

The schematic

This image was generated with the awesome Fritzing application.

The code

int pinA1 = 8;
int pinA2 = 9;
int pinA3 = 10;

void setup() {                

  for(int i = 1; i <= 10; i++) {
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  }

  digitalWrite(2, LOW);  // Ground
  digitalWrite(3, HIGH); // Power
  digitalWrite(4, HIGH); // Mux input to send to the leds
}

void ledOn(int nr)
{
  int r0 = nr & 0x01;
  int r1 = (nr >> 1) & 0x01;
  int r2 = (nr >> 2) & 0x01;

  digitalWrite(pinA1, r0);
  digitalWrite(pinA2, r1);
  digitalWrite(pinA3, r2);
}

void loop() {
  for (int j = 0; j < 8; j++) {
    ledOn(j);
    delay(50);
  }
  for (int j = 7; j >= 0; j--) {
    ledOn(j);
    delay(50);
  }
}


Demo

1 novembre 2011

Website screenshots with PhantomJS

Introduction

PhantomJS is an headless (i.e. without frontend) web browser based on Webkit with a Javascript API. It is mainly used for headless testing of webpages. It also allows the capture of a webpage into PNG, JPEG, and PDF files.

Compiling PhantomJS

Please follow the instructions here.

sudo apt-get install libqt4-dev libqtwebkit-dev qt4-qmake
  git clone git://github.com/ariya/phantomjs.git && cd phantomjs
  git checkout 1.3
  qmake-qt4 && make

Rasterize a website

The script to render a website to a file is provided as an example of PhantomJS. The code and explanations can be found here.

var page = new WebPage(),
    address, output, size;

if (phantom.args.length < 2 || phantom.args.length > 3) {
    console.log('Usage: rasterize.js URL filename');
    phantom.exit();
} else {
    address = phantom.args[0];
    output = phantom.args[1];
    page.viewportSize = { width: 600, height: 600 };
    page.open(address, function (status) {
        if (status !== 'success') {
            console.log('Unable to load the address!');
        } else {
            window.setTimeout(function () {
                page.render(output);
                phantom.exit();
            }, 200);
        }
    });
}

Now run:

bin/phantomjs rasterize.js http://aventures-logicielles.blogspot.com test.png

And magically you will see the file test.png appear on your disk.

This is absolutely awesome, we just created a screen capture of the website. However this will capture the whole page, and that means for a blog, a very long image. The above will produce an image of 1000 pixels per 15'000+ pixels (2.3Mb).

Getting only the head of the page

With a small modification to the script we can render only the first part of the page. This is possible by setting the clip rectangle before rendering the page. Let's use the page.clipRect function just before calling render as explained on StackOverflow.

var page = new WebPage(),
    address, output, size;

if (phantom.args.length < 2 || phantom.args.length > 3) {
    console.log('Usage: rasterize.js URL filename');
    phantom.exit();
} else {
    address = phantom.args[0];
    output = phantom.args[1];
    page.viewportSize = { width: 800, height: 600 };
    page.open(address, function (status) {
        if (status !== 'success') {
            console.log('Unable to load the address!');
        } else {
            window.setTimeout(function () {
  // ----- CHANGE HERE -------------------------------------------
  page.clipRect = { top: 0, left: 0, width: 800, height: 600 };
  // -------------------------------------------------------------
                page.render(output);
                phantom.exit();
            }, 200);
        }
    });
}

This will produce images of 800 x 600 pixels with an acceptable size (here 360Kb).

Here we go

Let's try the script on my three blogs.







First observation, the third screenshot contains a big grey area where there was originally a youtube video. Apparently the rasterize script is not able to grab it.

Create a screenshot from Apache


The next step is to try to grab a screenshot from within a php script running in Apache. The following snippet searches for the PhantomJS binary and the rasterize script on the same path as the PHP file.

$phantomjs = __DIR__.'/phantomjs';
$script = __DIR__.'/rasterize.js';
$url = 'http://http://aventures-logicielles.blogspot.com';
$outfile = 'webss_' . uniqid() . '.png';

$command = "$phantomjs $script $url $outfile 2>&1";
$output = shell_exec($command);
header('Content-Type: image/png');
echo file_get_contents($outfile);

If you try to run the above script you will not get any result. To understand what's going on you have to var_dump the $output of the shell_exec command. You will get the following error message: "phantomjs: cannot connect to X server".

Strange, isn't PhantomJS supposed to be a headless web browser? The reply can be easily found by googleing the error string. There is an open issue with PhantomJS on *nix systems, Ariya Hidayat, the creator of PhantomJS says: "PhantomJS is not 'pure headless' yet. On Unix, it still needs X Server for font stuff, etc.".

Fortunately there is a quite simple workaround using XVFB. See here for the full explanation.

Once you have set XVFB up following the above explanations, you can modify the PHP script to use XVFB as X server.

$phantomjs = __DIR__.'/phantomjs';
$script = __DIR__.'/rasterize.js';
$url = 'http://http://aventures-logicielles.blogspot.com';
$outfile = 'webss_' . uniqid() . '.png';

$command = "DISPLAY=:0 $phantomjs $script $url $outfile 2>&1";
$output = shell_exec($command);
header('Content-Type: image/png');
echo file_get_contents($outfile);


The sequel


I wanted to play a bit more with PhantomJS and the rasterize script so I created a small Symfony2 bundle using it to create web pages screenshots on the fly. You will find the sources on github.

Take a look here !


Portability


The above code works well on my Ubuntu workstation but a friend of mine just reported the following facts:

  • The rasterize script causes a segmentation fault on my mac
  • On Debian 5 (lenny) the QT libraries are too old to use the rasterize script
  • On Debian 6 (squeeze) everything runs fine

Links