Des sources de motivations

Voici quelques liens qui permettent de ne pas se laisser entraîner par la facilité technique de la routine.

Challenge algorithmique :
Nos neurones ont souvent l’envie de paresser et de croire que les algorithmes maîtrisés lors de nos études, le reste par la suite.
Rien de tel que des petits challenges pour relancer notre gymnastique intellectuel :

CodinGame Des concours, des puzzles, des challenges .. il y a toujours moyen de se divertir en enrichissant son agilité algorithmique.

Project Euler Dans le même esprit, mais précurseur, le côté mathématique est beaucoup plus mis en avant.

Histoire de côtoyer les challenges entrepreneurial, voici une triptyque à suivre :
humancoders, pragmaticentrepreneurs, voir codeur

Car nous avons toujours quelques choses à apprendre :
Mooc fun : un Mooc intéressant et de qualité dans la langue de molière.
Safari Une source semblant inépuisable de documentations, vidéos et tutoriels.

Tips référentiel géographique

En passant

C’est connu et reconnu mais avec la libéralisation des données, avoir un référentiel géographique prêt à l’emploi et actualisé est maintenant très rapide.

Le site de l’INSEE met les données dispositions l’ensemble de ces référentiels en libre accès sous forme de fichier dbf ou txt. Le travail d’actualisation des données est pré-mâché (puisqu’une liste de données d’actualisation est disponible).
Il n’y a donc plus aucune excuse à fournir un outil ne permettant pas de faire des statistiques fines sur le positionnement de ces utilisateurs.


Lien sur les référentiels : http://www.insee.fr/fr/methodes/nomenclatures/cog/telechargement.asp

Bonne intégration

Oracle : Update or Insert = MERGE

J’ai du répondre à une question simple de prime abord, comment mettre un jour un référentiel, non prévu pour être versionné, et ayant pu évoluer de manière différente sur chacun des différents sites de manière indépendante.

Après quelques recherches, le principal mot clé qui pouvait revenir était : MERGE

Un merge pour un développeur, c’est quelque chose de connu et ce n’est pas souvent envisager comme quelque chose de simple et de généralisable.
En théorie si, mais en pratique, c’est souvent durant cette étape que la livraison de son code prend un retard inattendu.

Alors avant d’envisager une telle pratique quand on utilise traditionnellement le SQL pour faire de simple CRUD … on cherche du simple … on envisage de se mettre au PL …. voir de faire une mini application faisant ce que l’on veut.

Et pourtant, le merge cela peut aussi être simple dans certain cas et cela peut rapidement être mis en place.

Comme dit en introduction, mon contexte était le suivant :
– Mise à jour de référentiel
– Pas d’assurance sur l’état du référentiel avant travaux
– Pas nécessairement le temps de s’assurer de la cohérence des données pour chacun des sites.

A priori, il existe plusieurs techniques, plus ou moins simple pouvant arriver à ce résultat.
Dans mon cas, il fallait que le génération du script se fasse dans un temps relativement court … et en ne demandant pas de devenir DBA au passage.

Le processus choisit pour l’actualisation de la table fut le suivant :

– Mise en place d’une date de fin pour l’ensemble des champs du référentiel utilisé en production (assurance de conserver les champs pour les données déjà saisies).
– Injection de la nouvelle table de référentiel
– merge proprement dit entre l’ancienne table et la nouvelle afin d’actualiser les champs utiles, quelques soit l’état de la table initialement.

En SQL, cela donne cela :


-- Généralisation de la date de fin à l'ensemble des occurrences de la table
update SOC_TYPE_DOMICILE set datefin= '01/11/14';

-- Injection de la table référentiel nouvelle version
CREATE TABLE "SOC_TYPE_DOMICILE_REF"
( "CODE" VARCHAR2(10 BYTE),
"CODEREGROUPEMENT" VARCHAR2(10 BYTE),
"DATEDEBUT" DATE,
"DATEFIN" DATE,
"LIBELLE" VARCHAR2(100 BYTE),
"RANGAFFICHAGE" NUMBER(3,0),
"ANCIENCODECSD" VARCHAR2(10 BYTE),
"CODEREGROUPEMENTTYPE" VARCHAR2(10 BYTE),
"ID_LIBELLE" NUMBER(7,0)
);

Insert into SOC_TYPE_DOMICILE_REF (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE) values ('SIFO','SIT_LOC',to_date('01/01/07','DD/MM/RR'),to_date('01/11/14','DD/MM/RR'),'Sans information','1','0',null,null);
Insert into SOC_TYPE_DOMICILE_REF (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE) values ('HEBST','SIT_LOC',to_date('01/01/07','DD/MM/RR'),to_date('01/11/14','DD/MM/RR'),'Hébergement stable','2','2',null,null);
Insert into SOC_TYPE_DOMICILE_REF (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE) values ('HEBPR','SIT_LOC',to_date('01/01/07','DD/MM/RR'),to_date('01/11/14','DD/MM/RR'),'Hébergement précaire ou de durée incertaine','3','A',null,null);
Insert into SOC_TYPE_DOMICILE_REF (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE) values ('HOP','SIT_LOC',to_date('01/01/07','DD/MM/RR'),to_date('01/11/14','DD/MM/RR'),'Hôpital sans perspective de logement à la sortie','4','B',null,null);
Insert into SOC_TYPE_DOMICILE_REF (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE) values ('SAB','SIT_LOC',to_date('01/01/07','DD/MM/RR'),to_date('01/11/14','DD/MM/RR'),'Sans abri, absence totale d hébergement','5','1',null,null);

-- Merge
-- deux cas : la ligne existe : dans ce cas on modifie le libellé pour qu'il corresponde exactement avec le résultat attendu (les valeurs, même modifiées, ne changent pas de sens)
-- La ligne n'existe pas, on l'insère
MERGE INTO SOC_TYPE_DOMICILE S
USING SOC_TYPE_DOMICILE_REF R
ON ( S.CODE = R.CODE )
WHEN matched
THEN UPDATE SET S.DATEFIN = null, S.LIBELLE = R.LIBELLE, S.RANGAFFICHAGE = R.RANGAFFICHAGE, S.ANCIENCODECSD = R.ANCIENCODECSD
WHEN not MATCHED
THEN INSERT (CODE,CODEREGROUPEMENT,DATEDEBUT,DATEFIN,LIBELLE,RANGAFFICHAGE,ANCIENCODECSD,CODEREGROUPEMENTTYPE,ID_LIBELLE)
VALUES (R.CODE,R.CODEREGROUPEMENT,R.DATEDEBUT,R.DATEFIN,R.LIBELLE,R.RANGAFFICHAGE,R.ANCIENCODECSD,R.CODEREGROUPEMENTTYPE,R.ID_LIBELLE);

-- et c'est fini ...

Duplication de clé USB

des fois on se fait plaisir avec peu de ligne de commande ..

Duplication de la clé
dd if=/dev/sdc of=/dev/sdd bs=4096 conv=notrunc,noerror

Hors avec des clés de tailles différentes, on obtient :

fsck /dev/sde1
fsck from util-linux 2.20.1
e2fsck 1.42.8 (20-Jun-2013)
La taille du système de fichiers (selon le superbloc) est de 7793408 blocs
La taille physique du périphérique est de 7674624 blocs
Le superbloc ou la table des partitions est peut-être corrompue !

Un simple : resize2fs -f /dev/sde1 7674624

et tout est de nouveau opérationnel :

fsck /dev/sde1
fsck from util-linux 2.20.1
e2fsck 1.42.8 (20-Jun-2013)
/dev/sde1 : propre, 25468/1925120 fichiers, 303289/7674624 blocs

Je vais de nouveau mettre ma sd card classique dans le Eeepc et la microSD dans une nouvelle go-pro ^^

Java versus C++ (2nd round)

j’avais mis en ligne un premier résultat de test montrant que Java pouvait concurrence C++ dans le registre de la performance.

Afin de compléter ce premier résultat, j’ai poursuivi ma comparaison en accroissant le volume de calcul à réaliser ( volume des données et précision de calcul). Ce 2nd résultat confirme le premier test et encore une fois, la version Java de mon programme est autant performante (ou aussi peu pour les mauvaises langues) que ma version C++.

Voici les résultats :

C++/MPI

nb Dec Tps moyen Tps tot Prec moy Prec U
1 693,49 693,49 -5,39E-004 8,51E-004
2 689,225 1378,45 1,50E-005 7,65E-004
4 496,445 1985,78 -5,48E-005 5,12E-005
8 212,62 1700,96 2,54E-005 1,43E-005
16 89,039375 1424,63 3,14E-005 8,89E-006

Java/Jace

nb Dec Tps moyen Tps tot Prec moy Prec U
1 608,1793823242 608,1793823242 4,87E-007 1,53E-003
2 596,3627929688 1192,7255859375 -1,43E-004 7,35E-004
4 492,4767684937 1969,9070739746 -4,16E-010 4,22E-004
8 197,4866099358 1579,8928794861 -1,61E-005 8,70E-005
16 88,004909873 1408,0785579681 6,35E-006 1,15E-005

Voici les conditions de test :

Java utilisée :
java version « 1.6.0_16 »
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) 64-Bit Server VM (build 14.2-b01, mixed mode)

C++ : (Configuration du mésocentre)
Option d’optimisation -O2 (à vérifier la compatibilité de cette option
avec ICC)
Compilateur : ICC
MPI : openMPI (Intel)

L’ensemble des tests ont été réalisé sur mésoshared un jour de calme ^^

DoseViewer, interface graphique pour Neurad

Quelques petites informations sur le projet Neurad.

Bien que le site de Neurad soit maintenant fermé depuis quelques mois, son développement est toujours en cours. Ces derniers temps, le travail a surtout porté sur l’interfaçage du logiciel.

Le choix du Toolkit graphique reste QT et je vous propose un premier aperçu d’écan :

C’est du basique et il reste encore du travail, mais maintenant que les premières briques sont placées, le reste devrait avancer plus rapidement. Tout est une question de priorité.

Si vous avez des remarques ou des demandes particulières, n’hésitez pas.

Toujours lire les warnings … ils peuvent être plus génants que des erreurs …

3 sessions de travail, 3 sessions à me battre avec Eclipse, Hibernate et Tomcat pour comprendre pourquoi aucune de mes configurations ne marchait.

3 Sessions à tricher, à rechercher où coller mes fichiers de configuration pour qu’ils soient pris en compte …

3 sessions à avancer pas à pas, sans comprendre pourquoi tout ne marchait pas comme prévu, à ne pas comprendre le pourquoi des problèmes …

Jusqu’à ce moment où j’ai pensé à lire les warnings, tous les warnings …
———————————————-
Description Resource Path Location TypeClasspath entry WebContent/WEB-INF/classes will not be exported or published. Runtime ClassNotFoundExceptions may result.
———————————————-

Et voilà, j’avais oublié de cocher une case pour la construction de mon ClassPath, et le répertoire local de mon application n’était pas pris en compte … et donc Hibernate ne retrouvait pas ses fichiers … La case cochée, tout est rentré dans l’ordre …

Un warning qu’il faudrait peut être passer en erreur …

Astuces systèmes

1 Manipulation de fichier.

Travaillant actuellement sous plusieurs système, je me suis retrouvé à avoir des fichiers mal encodés … résultat, dans un même projet, j’avais des fichiers en ISO-XxX et d’autre en UTF-8. Donc pour homogénéiser le tout, le plus simple est d’utiliser la commande Linux suivante :

file nom_du_fichier > Permet de connaître l’encodage utilisé

iconv -f type_initial -t type_voulu nomFichier > nouveauFichier

Et le problème est résolu.

Astuce de prog

Cet article/section n’est pas un. Il va simplement me permettre de lister une petite série d’astuces ou de techniques qui peuvent être utiles … et que l’on met souvent un temps fou à retrouver.

Astuce 1 : Spécifier le nombre de digits d’un nombre (Très utile quand le lecteur associé aux programmes demande un format strict)

Utilisation de la STL

std::ostringstream oss;
oss <

la fonction fill va permettre de présenter le nombre rg avec obligatoirement 3 digits (120 -> 120 mais 1 -> 001)

Astuce 2 : Faire un tri rapide sur une liste.

Si vous avez besoin de QT dans votre développement, et que à certains moment, vous devez faire appel à des techniques de tri … Le plus simple est de laisser à l’environnement QT faire le tri à votre place.

Pour ce faire, il suffit d’utiliser des QList et, son tri se limitera à l’appel à la fonction suivante :

qSort(listeMat.begin(), listeMat.end(), qGreater());

Dans ce context, listeMat correspond à une liste d’entier, mais si vous travaillez sur des listes d’objets, il suffit de ré-implementer les méthodes qGreater pour votre objet.