Graphisme ou l’apprentissage enfin moderne de l’écriture

Behold, voici une application Android unique en son genre, qui ne manquera pas d’intéresser petits, grands, et grands petits. Comme l’écrivait déjà en son temps Werni le Sage :

Un adulte qui naît, c’est un enfant qui grandit.

Graphisme donc, car tel est son nom, est à l’apprentissage de l’écriture, ce que le fer est au chemin. Une véritable perle qui ne mérite pas d’être encensée, mais installée et utilisée autant que possible pour reprendre espoir dans les nouvelles générations. La τεχνολογία au service de l’éradication des pattes de mouches, pour retrouver la beauté oubliée de la calligraphie, c’est sans aucun doute la huitième Merveille du Monde, et l’on ne doutera pas que Steve Jobs lui-même en serait tombé amoureux, au point d’échanger son iPad contre n’importe quel appareil Android et pouvoir enfin connecter the dots.

Trève de dactylographie, place à la découverte et au plaisir d’écrire : sur le vénérable Play Store, une version gratuite est disponible ici (lite) et complète là.

How to find all Gmail unlabelled messages: finally an official operator

I am happy to discover that a native way to filter unlabelled messages in Gmail was recently made available by the Gmail team, though it does not seem to be widely known yet.

The operators has:userlabels and has:nouserlabels achieve what previously required the concatenation of negative label conditions for all labels in your account (such as “-label:Stuff -label:OtherStuff”). The greasemonkey extension gmailUnlabelled certainly existed to automate the process. But it had to be potentially updated with each alteration of the Gmail UI and did not work well with non US locales.

As per the official documentation:

has:userlabels, has:nouserlabels: Finds all messages without any of your own labels (excludes automatic labels like inbox, spam, and trash). Since Gmail applies labels to individual messages, you might see results that appear to have labels; in this case, another message in the same conversation thread has had a label applied to it.

The simplest search expression to obtain all unlabelled emails in gmail (and exclude system labels as well) is henceforth the following:

has:nouserlabels -label:inbox -label:sent -label:chats -label:draft -label:spam -label:trash

For regular use, this dynamic search result can be saved using the “Quick links” feature available in the Gmail Labs.

Mono 3.0.0 Windows installer download link

Update: a Windows installer package for version 3.0.1 (including a hotfix) is now available here on Mono’s official website. The below information is no longer relevant.

Mono 3.0.0 has been released on the 18th of October but as of today no combined installer for Windows has been made available on the official website.

I managed to compile the master repository from GitHub on Cygwin following the official instructions, but the binary files I generated were somehow not good enough for use in MonoDevelop. So, I went on trying to generate a Windows installer using scripts from the mono/release repository. I had a limited success due to the lack of documentation and maybe the fact that I was using Windows instead of Linux.

Xamarin and all the project contributors are doing a great job. Those who are knowledgeable about the build process should document it better (and if possible simplify it) to as to share the love even more and encourage people to contribute. It is really motivating (and necessary for debugging purposes) to be able to see how code modifications can improve a compilable/installable/working version of the program.

Anyway, I tried to locate with Google a theoretical installer file name that would be consistent with the Mono 2.11 version: “mono-3.0.0-gtksharp-2.12.11-win32-0.exe”, and happily found a link in a publicly visible workfile. It seems to work well and come from the continuous build system MonkeyWrench.

I have mirrored it here: mono-3.0.0-gtksharp-2.12.11-win32-0.exe.

Enjoy and long live Mono (and .NET).

Say hello to MySQL

Why does software so often fail to understand basic social conventions?

MySQL - Hello

Call and send SMS/MMS from your ZTE 3G modem

I recently wanted to use my cell phone sim card inside my 3G USB stick (a ZTE 3565-Z bought in Croatia), without losing the ability to receive (or make, though I generally use VoIP software for this) calls.

Given what these 3G modems were designed for (i.e. modem use), and a previous unsuccessful experience trying to make a landline call with my laptop internal 56K modem, I was not sure whether this would be at all technically feasible. Yet digging the web revealed that it did could work with specific hardward and software. I preferred to challenge rather than change my hardware, and therefore set myself up for a new quest, in the hope of finding the holy missing piece of software, if there was any.

And I eventually found an uncluttered dashboard (equivalent to Vodafone Mobile Connect or Gestionnaire de Connexion SFR), which worked perfectly both to access the Internet (at least with all the 3G service providers around the world I tried) and to receive/make calls.

The existence of this simple yet world changing software (for me) was somehow unveiled here on d-c unlocker forums (then also mentionned on this German website and here), with a link to download it. For those who have not heard of it yet, d-c unlocker is a brilliant piece of software that can unlock 3G data cards (and that works!).

Surprisingly, this state-of-the-art piece of software was released under Metfone’s brand, a Khmer (Cambodian) mobile and residential Internet provider. This must be why most of the countries in the area are considered as “emerging” or “pre-emerging”…

I now have the best smartphone one could ever dream of: a laptop connected to the Internet :).

Metfone UI

A tip to improve the performance of your Bloomberg API application

If you make a request for data which results in a lot of events generated by Bloomberg API (such as long historical intraday data request, or possibly real time subscriptions), do not use the pattern specified in the API documentation, as it may end up making your application very slow to retrieve all events. Basically, do not call NextEvent() on a Session object, use a dedicated EventQueue instead.

Instead of doing this:

var cID = new CorrelationID(1);
session.SendRequest(request, cID);
do {
   Event eventObj = session.NextEvent();
   ...
}

Do this:

var cID = new CorrelationID(1);
var eventQueue = new EventQueue();
session.SendRequest(request, eventQueue, cID);
do {
   Event eventObj = eventQueue.NextEvent();
   ...
}

This simple change may yield performance improvements by an order of magnitude (or not, as the API is known to not be particularly deterministic…).

Recursive algorithm to generate all combinations of elements in successive enumerables

If you need to flatten ordered enumerables, that is taking one element of each enumerable, in order, to flatten a combination, here is a quick solution in C# and VB.NET, accompanied with an example:

Code in VB.NET:

Private Shared Sub GetCombinationsRec(Of T)(sources As IList(Of IEnumerable(Of T)), chain As T(), index As Integer, combinations As ICollection(Of T()))
	For Each element As var In sources(index)
		chain(index) = element
		If index Is sources.Count - 1 Then
			Dim finalChain = New T(chain.Length - 1) {}
			chain.CopyTo(finalChain, 0)
			combinations.Add(finalChain)
		Else
			GetCombinationsRec(sources := sources, chain := chain, index := index + 1, combinations := combinations)
		End If
	Next
End Sub

Public Shared Function GetCombinations(Of T)(ParamArray enumerables As IEnumerable(Of T)()) As List(Of T())
	Dim combinations = New List(Of T())(enumerables.Length)
	If enumerables.Length > 0 Then
		Dim chain = New T(enumerables.Length - 1) {}
		GetCombinationsRec(sources := enumerables, chain := chain, index := 0, combinations := combinations)
	End If
	Return combinations
End Function

Code in C#.NET:

private static void GetCombinationsRec<T>(IList<IEnumerable<T>> sources, T[] chain, int index, ICollection<T[]> combinations) {
	foreach (var element in sources[index]) {
		chain[index] = element;
		if (index == sources.Count - 1) {
			var finalChain = new T[chain.Length];
			chain.CopyTo(finalChain, 0);
			combinations.Add(finalChain);
		}
		else {
			GetCombinationsRec(sources: sources, chain: chain, index: index + 1, combinations: combinations);
		}
	}
}

public static List<T[]> GetCombinations<T>(params IEnumerable<T>[] enumerables) {
	var combinations = new List<T[]>(enumerables.Length);
	if (enumerables.Length > 0) {
		var chain = new T[enumerables.Length];
		GetCombinationsRec(sources: enumerables, chain: chain, index: 0, combinations: combinations);
	}
	return combinations;
}

Usage is simple:

Dim list1 = New String() {"hello", "bonjour", "hallo", "hola"}
Dim list2 = New String() {"Erwin", "Larry", "Bill", "Steve"}
Dim list3 = New String() {"!", ".."}
Dim result = Utils.GetCombinations(list1, list2, list3)
For Each r In result
    Debug.Print(String.Join(" "c, r))
Next

or in C#:

var list1 = new[] { "Hello", "Bonjour", "Hallo", "Hola" };
var list2 = new[] { "Erwin", "Larry", "Bill", "Steve" };
var list3 = new[] { "!", "..." };
var result = Utils.GetCombinations(list1, list2, list3);
foreach (r in result) {
    Debug.Print(string.Join(" ", r));
}

As with any recursive function, memory usage can be exponential so make sure you know the number of target combinations is reasonable. Speed-wise, parallelizing this function is not worth it as we are just iterating over the elements.

How to replace Drupal core’s tracker module using views

This can be pretty handy, especially if you would like to customize it a bit more and add other tabs. Here is a simple step-by-step tutorial:

  1. Disable Drupal’s original core tracker module.
  2. Install views.
  3. Go to Site Building > Views and enable the tracker view.
  4. In the tracker view, go to the Page item, and rename it for example as “Recent posts” in Basic settings > Name and Basic settings > Title.  Make sure you click on override before saving, so that you keep the original configuration in Defaults.
  5. In the Page settings fieldset, set Path to tracker/all and the type to Default menu tab. Set Title to Recent posts and Weight to -10. Click on update and when asked for the Parent menu item, select Normal menu item, and once again type Recent posts as Title. Click on update. We are done with this page type that will display the latest nodes modifications by all users. You can now enjoy the power of views and tweak the display to precisely show what you have in mind.
  6. In the left drop-down list, select Page and click Add display. Rename it for example as “My recent posts” in Basic settings > Name and Basic settings > Title.  Make sure you click on override before saving, so that you keep a version of the original values.
  7. In the Page settings fieldset, set Path to tracker/my and the type to Menu tab. Set Title to My recent posts and Weight to 1. Click on update.
  8. In the Arguments fieldset, click on Node: User posted or commented (if it doesn’t exist, add it), and as the Action to take if argument is not present, select Provide default argumentUser ID from logged in user.
  9. That’s it! The link to your new tracker view is mysite.com/tracker; two tabs will be displayed just like in the original core module. You may for example create a menu item that links to this page.

Cloning objects with events in Visual Basic .NET

The easiest way to clone an object (deep copy) in .NET is to use the serialization functions available:

    Public Shared Function CloneObject(ByVal obj As Object) As Object
        If Not obj Is Nothing Then
            Dim bf = New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
            Dim fs = New System.IO.MemoryStream()
            bf.Serialize(fs, obj)
            fs.Seek(0, System.IO.SeekOrigin.Begin)
            Dim copy = CType(bf.Deserialize(fs), Object)
            fs.Close()
            Return copy
        Else
            Return Nothing
        End If
    End Function

Though the performance is not very good, for occasional operations it will do the job perfectly. However, I was confronted to the following problem: what if there are events inside the class, to which other objects have subscribed? I found several methods (and functions :-)) on various places over the Internet; they basically were:

  • Implement ISerializable yourself (meaning you have to update it each time you modify the class);
  • Disconnect from events (retrieved using Reflection), serialize the object, and then reconnect the events (I could not make this working properly);
  • Implement a serialization surrogate;
  • Implement your events in a separate class that is not serialized;
  • Implement your events in a C# base class.

Plenty of potential solutions, but none of them was good enough for me. So I played around with Reflection and found something that nobody else might have done so far. For a cloning interface that does just a shallow copy, like what MemberwiseClone does, but without event, I wrote this:

    Public Function Clone() As Object Implements System.ICloneable.Clone
        Dim cl = New MyClassName(Me)
        'Here we don't capture events, only normal fields, including non public ones (private, protected...)
        Dim FldInfos() As Reflection.FieldInfo = Me.GetType.GetFields(Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.NonPublic)
        For Each FldInfo As Reflection.FieldInfo In FldInfos
            FldInfo.SetValue(cl, FldInfo.GetValue(Me)) 'For serialization purpose we just need not to have events, so no need to perform a deep copy of the fields.
        Next
        Return cl
    End Function

Now if one of your class member is an object with events (or if you want to perform a deep copy), you should call its clone method (to be implemented the same way) when performing the FldInfo.SetValue, like this:

        For Each FldInfo As Reflection.FieldInfo In FldInfos
            If FldInfo.Name <> "MyObjectWithEvents" Then
                FldInfo.SetValue(cl, FldInfo.GetValue(Me)) 'It is not really necessary to clone a possible reference class member here for serialization purpose, we just need not to have events in the clone
            Else
                FldInfo.SetValue(cl, Me.MyObjectWithEvents.Clone())
            End If
        Next

If you have an object that is for example a dictionary of objects with events, you can call this:

        For Each FldInfo As Reflection.FieldInfo In FldInfos
            If FldInfo.Name <> "MyObjectsWithEventsDictionary" Then
                FldInfo.SetValue(cl, MyLib.CloneObject(FldInfo.GetValue(Me))) 
            Else
                FldInfo.SetValue(cl, Me.MyObjectsWithEventsDictionary.ToDictionary(Of String, MyObjectWithEvent)(Function(entry) entry.Key, Function(entry) CType(entry.Value.Clone(), MyObjectWithEvent)))
            End If
        Next

Finally, if you intend to use the Clone interface to serialize objects, you should make sure you don’t include class members marked as NonSerialized():

        For Each FldInfo As Reflection.FieldInfo In FldInfos
            If Not FldInfo.IsNotSerialized Then
                FldInfo.SetValue(cl, FldInfo.GetValue(Me))
            End If
        Next

I hope this will give you an insight to build something more tailored to your needs. There are other optimizations I can already think of, such as implementing a recursive Clone function where you would just put your original object and a virgin instance of it as a reference, and get a perfect serializable deep copy, whatever the class members and sub class members are! This could become a universal Clone method…

How to sort WordPress posts by modified date instead of published date?

Here is the simple solution. Simply use this:

<?php query_posts($query_string . '&orderby=modified&order=desc'); ?>

before where the Loop checks for posts:

<?php /* If there are any posts: */ 
if (have_posts()) ...
?>

It basically adds a condition to the Loop. Enjoy!

WPF or not WPF?

I would not say it is a new paradigm, but the least we have to recognize is that Windows Presentation Foundation helps building more good-looking applications than our beloved Winforms

Le primat du software

Walter Mossberg and Kara Swisher interview Steve Jobs and Bill Gates at ‘D5: All Things Digital’ conference in Silicon Valley in 2007. Quotes made during the time of the photograph.

Kara: “What you think each has contributed to the computer and technology industry, starting with you, Steve, for Bill, and vice versa.”

Steve: “Bill built the first software company in the industry and I think he built the first software company before anybody really in our industry knew what a software company was, except for these guys. And that was huge. That was really huge. And the business model that they ended up pursuing turned out to be the one that worked really well, you know, for the industry. I think the biggest thing was, Bill was really focused on software before almost anybody else had a clue that it was really the software.”

Walt: “Bill, how about the contribution of Steve and Apple?”

Bill: “Well, first, I want to clarify: I’m not Fake Steve Jobs. [Peals of laughter.] What Steve’s done is quite phenomenal, and if you look back to 1977, that Apple II computer, the idea that it would be a mass-market machine, you know, the bet that was made there by Apple uniquely—there were other people with products, but the idea that this could be an incredible empowering phenomenon, Apple pursued that dream. Then one of the most fun things we did was the Macintosh and that was so risky. People may not remember that Apple really bet the company. Lisa hadn’t done that well, and some people were saying that general approach wasn’t good, but the team that Steve built even within the company to pursue that, even some days it felt a little ahead of its time—I don’t know if you remember that Twiggy disk drive and…”

Bill Gates and Steve Jobs at D5: all things digital

Aujourd’hui encore, le software n’a pas perdu de sa superbe et de son importance. Plusieurs exemples sont là pour nous le rappeler.

Synaptics est le principal équipementier en pavés tactiles (touchpads) pour ordinateurs portables. Regardez dans la liste des drivers de votre machine, il y a de bonnes chances pour que ce nom apparaisse quelque part.
En septembre dernier, ils ont sorti en grande pompe plusieurs nouvelles gestures rappelant celles utilisables sur des écrans multitouch. On aurait pu saluer l’innovation et s’en arrêter là. Oui mais voilà, ces fonctionnalités auraient pu être implémentées depuis plus de 5 ans ! Le hardware, et même le firmware peuvent depuis bien longtemps différencier les doigts, capter leurs coordonnées absolues (comme une tablette graphique), et ce avec une résolution d’environ 640×480 ! Pourtant, seuls trois misérables logiciels de démonstration étaient jusqu’alors disponibles sur le site de Synaptics. Quant au SDK, il n’a pas été mis à jour depuis 2004. Si aujourd’hui le nouveau driver offre quelques gestures supplémentaires (et encore pas disponibles sur tous les firmware malgré la compatibilité matérielle), Il faut donc toujours passer par la pseudo API en C++ pour accéder à la matrice générée par le touchpad et créer un gestionnaire de fonctionnalités supplémentaires.

Théorie du complot ou non sur les raisons de ce bridage, on peut surtout retenir que le fabricant du hardware ne verse pas beaucoup dans le software, et c’est donc une inefficience qu’il faut combler ! On peut imaginer bon nombre d’applications qui pourraient profiter à plusieurs centaines de millions d’utilisateurs instantanément.

On ne se rend pas non plus compte à quel point les connectiques comme le bluetooth ou le Wifi ne sont utilisées que partiellement par le software qui les accompagne. Une start-up a d’ailleurs développé des drivers Wifi voués à faire au moins aussi bien que le Bluetooth en termes de débit de données et consommation électrique pour des applications identiques (casque, clavier…). Voilà qui risque de faire un peu d’ombre au consortium Bluetooth.
Je cherchais moi-même à faire quelque chose a priori très simple : lire simultanément de la musique sur mon ordinateur et celui de mon frère, lorsqu’on est physiquement peu éloigné. Les solutions trouvées ont été les suivantes :
Développer un script AutoIT qui synchronise la lecture des morceaux via le réseau (avec une parfaite synchronisation d’horloge),
Mettre en place un serveur de streaming temps réel (contrairement à Youtube ou à toutes les webradios, il s’agit de pouvoir écouter avec seulement quelques millisecondes d’écart le son qui est joué sur le serveur, il n’est donc pas possible d’avoir extensivement recours à la mémoire tampon),
Utiliser un bon vieux câble audio reliant la prise casque d’un ordi à la prise line in de l’autre.

Chaque solution présente des inconvénients : la première suppose que les bibliothèques des deux ordis soient identiques ou très proches, la deuxième n’offre pas une qualité d’écoute suffisamment stable (distortions comme en VoIP), et la troisième vous fait réaliser qu’il n’est même pas possible sur un ordi portable de choisir de ne pas désactiver les hauts-parleurs lorsque quelque chose est branché sur la prise line out (seul mon ordinateur, un Asus F3JA, et la version courante de mon driver son, présente un dysfonctionnement qui permet d’avoir les 2 simultanément au sortir d’une mise en veille :-), cela suppose donc d’utiliser un jack et des hauts parleurs externes au moins sur l’ordinateur émetteur.

Ne devrait-on pas pouvoir envoyer de l’analogique ou quasi analogique (pour éviter toute décompression complexe ou gestion des pertes) avec un protocole approprié sur un câble RJ45 ? Ce câble n’a pas moins de fonctionnalité qu’un câble audio classique. Mais soit, plutôt que d’inventer un nouveau protocole from scratch, pourquoi ne peut-on pas tout simplement activer le profil standardisé “Headset” ou “Generic Audio Video Distribution Profile” sur le PC de destination du signal ? Aujourd’hui, on ne peut pas par défaut utiliser un PC comme extension sonore d’un autre PC, sans raison valable vu que tout le hardware nécessaire est pourtant là. En allant plus loin, pourquoi est-il impossible d’utiliser les profils bluetooth standards sur des réseaux Ethernet Wifi ou RJ45 ?

Si le hardware a atteint une certaine maturité, on voit donc que le software en est encore à ses balbutiements en terme de mise en valeur des périphériques sous-jacents. Espérons que les interfaces utilisateurs à venir basées sur le multitouch et les caméras 3D s’accompagneront également d’une révolution en termes de software. On peut bien sûr compter sur les fabricants de hardware, mais je ne saurais que trop nous conseiller à nous tous, utilisateurs et développeurs, d’être à l’origine de cette refondation du rapport de l’homme à la machine. C’est ni plus ni moins ce qu’ont su faire en leur temps, dans une perspective business appropriée, Apple et Microsoft.

Du software, toujours du software !

ASIN to EAN converter

Désolé, cet article est seulement disponible en Anglais Américain. Pour le confort de l’utilisateur, le contenu est affiché ci-dessous dans une autre langue. Vous pouvez cliquer le lien pour changer de langue active.

Since I was needing an EAN to ASIN converter and ASIN to EAN converter (UPC/barcode and Amazon code), but could not find any on the web, I decided to write one myself. It is always fun to learn a new API (here I used Amazon Web Services). And when it works exactly as you expect, you are definitely API!

You can input several codes (batch mode) by separating them with “;” (semicolon). The output will be one column with the original code and another with the converted code.

So, long story short, here comes the beauty, and the beast (also available here on a dedicated page/window):

This converter can easily be embedded on your own website using the following code:

<iframe style="border: solid 1px #ccc;" src="https://erwinmayer.com/labs/asin2ean/index.php" width="490" height="630"></iframe>

Latest features:
30/12/2014: Tab in URL and locale persistence.
19/12/2014: Responsive/Mobile-friendly version.
09/12/2014: Much faster batch operations & UI rewritten for easier readability.
09/06/2014: UI improvements for batch operations.
30/04/2014: Added support for BR (Brazil) and IN (India) locales.
02/10/2011: Added support for ES (Spain) locale.
27/08/2011: Added support for IT (Italy) and CN (China) locales.

Please feel free to report any bug you might encounter, or suggest improvements.

I may be available for consulting work on a case by case basis. Just drop me a note if needed.

Comment financer Wikipédia ?

Depuis plusieurs jours, je ne sais pas trop quoi penser de la manie de Wikipédia à bannir toute publicité, mais à occuper grassement l’espace normalement dédié aux articles pour afficher un bandeau “publicitaire” en vue de sa campagne de dons. Celui-ci restera au moins 1 mois d’après mes estimations. Voici à quoi cela ressemble :

Dons sur Wikipédia

Maintenant, que se passe-t-il si l’on utilise le même espace de manière plus productive ? Si l’on choisit par exemple Google Adwords pour financer Wikipédia durant le même intervalle de temps ? Cela donnerait à peu près ça :

Dons sur Wikipédia

Faisons un rapide calcul sur les bénéfices générés. D’après Tux-planet, en date du 10 octobre 2008, Wikipédia générait 10 milliards de pages vues par mois. Si on prend un CTR (click through rate, c’est à dire le nombre de clics pour 1000 impressions) de 1% (hypothèse pessimiste, vu que la fourchette va généralement jusqu’à 15%), et une moyenne de 5 cts par clic, la recette en un mois est donc de 10^10*0.01*0.05 = 5 millions de dollars (et un peu moins pour Google, qui serait certainement prêt à faire preuve d’une générosité en la matière :-)). Voilà de quoi faire supporter le coût de Wikipédia à des annonceurs tout contents de toucher cette audience.

Et ça serait même l’occasion de supprimer cet horrible bandeau en haut de page pour plutôt mettre à la fin des articles une section “Liens commerciaux”, que je cherche d’ailleurs souvent quand je lis certains articles. Discrétion et performance, encore une fois pour une durée pouvant rester identique à celle des campagnes de dons actuelles.

Ajoutons ma recommandation de longue date, de permettre aux détenteurs de compte de Wikipédia de choisir d’afficher ou non de la pub (pour ceux notamment qui n’ont pas les moyens de faire un don significatif), et la fondation Wikimedia deviendra bientôt aussi riche que sa consoeur de Mozilla…

A vos marques, prêts ? Cliquez !

Do you really know Tetris and the like?



De l’applicatif pour le multitouch, vite !

Pas besoin de réinventer la roue pour innover.

Cependant, on peut déplorer qu’ils n’aient toujours pas plus d’imagination que le redimensionnement de photos. Si ça n’avance pas du côté de l’applicatif, je vois mal le multitouch s’imposer. Inventeurs, à nos claviers !

Les claviers : goulots d’étranglement de la sécurité ?

Des chercheurs du laboratoire de sécurité et cryptographie de Lausanne ont mis en évidence la vulnérabilité de nos chers claviers à de “simples” détecteurs de radiations électromagnétiques.
Cela fait froid dans le dos. J’avais lu il y a quelques années un article sur les récepteurs à ondes courtes qui si je me souviens bien permettaient notamment de récupérer à distance l’affichage d’écrans cathodiques (pour regarder la télévision de vos voisins par exemple :-), là cela va un peu plus loin puisque les claviers sont notablement utilisés pour saisir nombre d’informations sensibles. Bien évidemment, la prouesse ici est qu’il s’agit de claviers filaires (c’est tout de suite plus facile pour les claviers sans-fils).

Je crois que la solution est de trouver un domaine de 40 hectares sympa où vous pourrez construire une cage de Faraday où vous calfreutrer.

Via l’électron libre.

Forfait ordinateur et Internet à 40 € par mois : une si bonne affaire ?

Une nouvelle formule a été concoctée par l’Etat et divers opérateurs pour aller plus loin dans l’opération “micro-portable étudiant”, qui semble avoir rencontré un franc succès ces 4 dernières années, si l’on en croit Le Parisien.

Saluant les bonnes intentions, je suis néanmoins depuis le départ sceptique quant à la pertinence réelle de ces offres à destination des étudiants, à la fois d’un point de vue des performances techniques et du financement.

En 2005, j’avais conseillé à une amie de s’équiper d’un portable Fujitsu-Siemens bundlé dans une offre spéciale pour étudiants. Par rapport aux prix de marché pour le même type d’appareil, l’avantage consistait principalement en une garantie étendue à deux ans au lieu d’un, avec prise en charge à domicile (en Europe). Soit une réduction de facto d’environ 120€. Voilà, c’était bien (je ne parle pas des divers problèmes techniques rencontrés par la suite, qui ne sont pas spécifiques aux “micro-portables étudiants” mais hélas une constante sur ce marché au turnover si élevé). Mais 6 mois plus tard, voire 1 an plus tard après la sortie du modèle, ça l’est déjà moins. Non seulement parce que dans ce laps de temps les gammes ont évolué, permettant pour le même prix de disposer de performances supérieures (ou pour moins cher de performances identiques), mais parce que cela revient à proposer des machines ayant déjà 6 mois/1 an d’existence (ce qui je présume affecte d’une manière ou d’une autre la durée de vie des composants).

Dans le même genre, le BDE de mon Ecole en France avait aussi négocié des prix avec HP, et j’étais pour le moins surpris de ne voir aucun avantage réel par rapport aux prix publics sur RueDuCommerce ou autres sites d’achat en ligne d’électronique. A croire que les commerciaux d’HP étaient partis sur des bases différentes des prix publics (ou que le BDE n’avait pas de grands talents de négociateur).

Concernant l’aspect financier, analysons l’offre à 40€ par mois. Un micro-portable (cette fois c’est l’occasion de le dire) moyen de gamme coûte entre 200€ et 400€. Prenons 300€ comme référence. Prenons 15€ pour l’abonnement 3G (illimité ? Je ne serais pas surpris de découvrir les mêmes clauses de quotas ridicules présentes dans les forfaits actels). Sur 2 ans, cela fait un coût de 27,5€/mois… Où vont donc les 300€ de différence ?
S’il s’agit d’un forfait vraiment débridé, l’offre vaut le coup, rien que pour Internet (50€/mois séparément). Si la machine vaut 300€ de plus, on reste dans les prix du marché, rien de sensationnel. Il faudrait enfin évaluer le SAV fourni pour juger avec tous les éléments s’il s’agit ou non d’une bonne affaire.

Reste la question du financement, tout le monde ne peut pas payer cash. Sans faire de calcul de TEG précis, les 300€ potentiellement payés en trop correspondrait à un taux global d’environ 30%…

Même si des éléments m’ont sans doute échappé, je pense qu’il y a un vrai travail à faire pour que l’entreprise fournissant le matériel et le service fasse des économies d’échelles et permette vraiment de proposer une fourchette de prix attractive. Faute de quoi, l’Etat n’a pas intérêt à mettre la main à la pâte avec quelque subvention (car alors autant créer une bourse spéciale “achat d’ordinateur” pour tous les étudiants, qui laisserait le choix du matériel).

They Rule, une application de la puissance du FoaF

Le “web sémantique” est souvent une appelation pompeuse pour un domaine qui n’a pas encore émergé. Cependant, quelques initiatives isolées mettent en avant la puissance de l’organisation sémantique du contenu. Parmi celles-ci, TheyRule propose de visualiser le graphe “social” des membres des boards des plus grandes sociétés et institutions américaines.

Vous pouvez consulter ici une map que j’ai créée avec les principales firmes high tech du NASADQ et d’autres entreprises importantes. Je m’attendais à un peu plus de connections, notamment entre des firmes du même secteur. Mais j’ai déjà observé cet effet à moindre échelle sur Facebook. Une chose est sûre, vu la quantité de “grands” au pouvoir, et les faibles interactions entre eux, on se demande bien comment une théorie du complot pourrait avoir lieu.

Pour ceux qui veulent en savoir plus sur le pourquoi du comment, ils peuvent commencer à se documenter sur l’article relatif au FoaF (Friend of a Friend) de Wikipedia.

Créer une FAQ facile à mettre à jour en Javascript

Souhaitant implémenter une FAQ basique mais fonctionnelle sur un site, et n’ayant pas envie de réinventer la roue, j’ai cherché rapidement des codes tout faits, sans grand succès. Ce tutoriel (qui ne marchait pas chez moi) m’a donc inspiré et j’ai tout repris à zéro. Le résultat est relativement light (pas de librairie Ajax externe), malgré le workaround que j’ai dû trouver pour pallier la méthode setAttribute(“onclick”,”…”) qui ne marche pas sur IE7.

Le principe est simple, à chaque balise h4 correspond un seul et unique paragraphe p (pour sauter des lignes, utiliser <br />). Il suffit d’ajouter des couples (h4,p) à la balise “faqs” pour que le javascript s’occupe du côté dynamique. L’intérêt est de ne pas avoir à recourir à une base de données pour ajouter des entrées (peu pratique lorsque les personnes chargées de la maintenance ne savent pas en gérer une), ni à surcharger chaque entrée de la faq de balises spécifiques. Ajoutons enfin que c’est navigateurement correct puisque ça permet un affichage même si javascript est désactivé.

Une application du code suivant est visible ici ou .

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body><div style="margin: 5px 15px 0px 5px; text-align: justify;" id="faqs">
<h1 align="center">Questions fréquemment posées (FAQ)</h1>

<h3>Courage</h3>
<h4>&amp;#9658; Pourquoi ne faut-il pas avoir peur ?</h4>
<p>La peur est l'ennemie du Bien.<br /><br />
Pour que le Bien vous accompagne dans votre vie, <a href="http://erwinmayer.com/kamashanti">faites un don</a>.
</p>
<br />

<h4>&amp;#9658; Comment puis-je obtenir la rédemption ?</h4>
<p><a href="http://erwinmayer.com/kamashanti">Faites un don</a>. Remercier le Bien est la source de tout salut.</p>
<br />

<h4>&amp;#9658; J'ai déjà donné, mais je n'ai pas l'impression que le Bien est avec moi, que puis-je faire ?</h4>
<p>Il ne faut pas perdre la foi ! Peut-être votre générosité n'est pas à la hauteur du Bien que vous attendez. <a href="http://erwinmayer.com/kamashanti">Ouvrez votre coeur</a>.</p>
<br />

<h4>&amp;#9658; Je ne trouve pas réponse à ma question, que faire ?</h4>
<p><a href="http://erwinmayer.com/kamashanti">Donner !</a>. Les réponses sont transcendantes lorsque l'on est allégé des fardeaux de la vie.</p>

</div>
<br />
<br />

<center><a href="#" onClick="faq_toggle_all('block')"><small>Tout afficher</small></a> | <a href="#" onClick="faq_toggle_all('none')"><small>Tout masquer</small></a> </center>

</body>
<script type="text/javascript">
function faq_toggle(pdiv) {
var action = (pdiv.style.display == "block") ? "none" : "block";
pdiv.style.display = action;
}
function faq_toggle_all(action) {
var faqs = document.getElementById('faqs');
var pfaqs = faqs.getElementsByTagName('p');
for(i=0;i<pfaqs.length;i++) {
pfaqs[i].style.display=action;
}
}

var faqs = document.getElementById('faqs');
var pfaqs = faqs.getElementsByTagName('p');
var hfaqs = faqs.getElementsByTagName('h4');
for(i=0;i<pfaqs.length;i++) {
//hfaqs[i].setAttribute("onclick","faq_toggle(pfaqs["+i+"])"); // Does not work in IE.
hfaqs[i].onclick = function(){
var faqs = document.getElementById('faqs');
var pfaqs = faqs.getElementsByTagName('p');
var hfaqs = faqs.getElementsByTagName('h4');
for(j=0;j<hfaqs.length;j++) {
if(hfaqs[j] === this) {
faq_toggle(pfaqs[j]);
}
}
}
hfaqs[i].style.fontStyle="italic";
hfaqs[i].style.cursor="pointer";
hfaqs[i].style.color="#006699";
pfaqs[i].style.display="none";
}
</script>
</html>

Page suivante »