aprendomatico: l'automatisation de l'apprentissage des trucs chiants.

C'est marrant, internet: tu testes des trucs avec tes élèves, ça marche bien, t'en fais mention sur mastodon et PAF ! ça intéresse des gens... (comme quoi, on n'est pas à l'abri ! )

rhopitin

Donc, il y a eu des questions, des demandes etc.

Tout d'abord, je précise que le bouzin n'était prévu que pour mon usage personnel ce qui implique plusieurs conséquences:

  1. l'ergonomie et le design sont sans doute perfectibles.

    sansdec

  2. de la gestion des caractères à la gestion des erreurs, tout a été prévu pour l'espagnol: non pas qu'il soit impossible de l'adapter, mais il faudra quand même y réfléchir.
  3. pas de page de config pour éditer les banques de verbes etc...
  4. une stratégie de programmation pas forcément adaptée à d'autres matières

1 : De quoi-t-est-ce que ça s'agit ?

C'est tout con: je pars du principe que la conjugaison (et les autres trucs ne dépendant que d'un apprentissage par coeur) doivent être révisés régulièrement pour devenir automatiques et minimiser la charge mentale de l'élève au moment de la création de sa phrase. En effet, quand on fait une phrase, il y a beaucoup de processus qui interviennent, de l'ordre des mots et la priorité des informations (qui varient d'une langue à l'autre), aux accords (sujet/verbe, article/nom, nom/adjectif etc) en passant par le vocabulaire à utiliser...

C'est un processus -relativement- naturel dans notre langue maternelle mais qui nécessite toujours beaucoup d'énergie et de concentration dans une langue que l'on apprend: autant réserver cette concentration au sens de la phrase en automatisant certains de ces processus. Si on doit déjà réfléchir pour accorder le verbe parce qu'on ne se rappelle plus du présent de l'indicatif, autant dire que la genèse de la phrase s'en trouve considérablement ralentie.

La solution trouvée par environ 50% des élèves est de ne tout simplement pas conjuguer les verbes et d'hispaniser vaguement le français pis c'est marre.

alt

C'est sans doute la meilleure solution si 1- on s'en branle complètement et 2- on refuse de réviser et d'apprendre un truc

alt

En plus, ceux qui veulent réviser restent soumis à l'erreur de lecture en révisant ou en recopiant le cours et, chose curieuse, quand un élève a appris une chose fausse, il n'existe pratiquement aucune force sur terre pour la lui faire désapprendre et la corriger .

Voilà pourquoi j'ai opté pour une appli:

  1. c'est automatique,
  2. c'est plus amusant,
  3. l'élève obtient un message d'erreur adapté aux erreurs les plus courantes,
  4. ça ne prend pas longtemps sur le planning serré du combo télé-smartphone-Fortnite...

Bon ok, mais ça ressemble à quoi ?

A une page d'accueil qui liste les notions disponibles

capt1

Et à une page de travail dans laquelle on retrouve la consigne, la zone dans laquelle l'élève tape sa réponse et un espace dans lequel le message d'erreur apparaît.

capt2

capt2

En fin de travail, le môme obtient un résumé contenant le nombre d'items trouvés et le pourcentage de tâtonnement global. Il a aussi une appréciation, mais je bosse encore dessus (marche pas trop)

Et au niveau du code, ça donne quoi ?!

Si quelqu'un veut reprendre le truc, bon courage déjà... Non, j'déconne. La structure est assez simple:

  • index.php
    • assets/get.php
      • charge le template correspondant à la notion choisie
      • charge les données nécessaires (verbes/noms/sujets etc)
      • génère les réponses correctes
      • prépare les données à transmettre à JS lors du rendu de la page
    • assets/functions.php
      • fonctions de génération de réponse (conjugaisons régulières, numération, passage au pluriel etc)
      • fonctions diverses
    • assets/functions.js
      • Gestion des entrées par les élèves
      • gestion du passage d'un tiem à l'autre
      • gestion des erreurs et des messages si l'erreur est interprétable
    • assets/templates
      • accueil.php : le tpl de la page d'accueil
      • interro.php : le tpl de la page d'interro
      • questions.php : un tableau contenant les tpl spécifiques à utiliser dans la génération de l'item.
    • data/ le dossier contenant
      • les fichiers de la base
      • les titres de chaque notion

Pour le moment, ça fonctionne très bien pour moi mais il manque sans doute des choses qui paraîtront essentielles à un non programmeur, comme une page de configuration ou un espace de gestion des ressources (édition/création/suppression de banques, upload d'images ou de sons etc).

Je dois encore ajouter un espace pour les conjugaisons irrégulières autres que la diphtongue et les verbes spéciaux qui ne peuvent être automatisés (et pour lesquels il faudra une banque et un menu spécial)

alt

Et si on veut adapter à d'autres langues ?

C'est possible sans trop de modifications mais ça peut demander du boulot quand même.

Premier truc à changer: l'accueil

Bien entendu, il faudra adapter les notions; je pense qu'on retrouvera sans doute la conjugaison, la numération, le pluriel...

Puis les banques d'items

ça va de soi: les contenus devront être édités à la main pour correspondre à la langue

Et les fonctions de génération de réponses

J'ai codé des fonctions qui conjuguent seules, comptent seules, mettent au pluriel seules... ainsi, pas besoin de base lourde à maintenir: pour un verbe régulier, on fournit l'infinitif et le temps et on obtient les personnes. Bien entendu, ça ne fonctionnera pas avec les verbes très irréguliers.

Mais aussi la gestion des messages d'erreur

Les messages dépendent de l'analyse des erreurs habituelles, comme le doublement de lettres incorrects, les e et i intervertis, la confusion entre r et j etc.

Comment Aprendomatico essaie-t-il d'interpréter l'erreur ?

function.js contient une routine qui va chercher les différences entre le mot à trouver et le mot entré. Selon les combinaisons de lettres formant ces différences, on est à même de deviner le problème. Exemples:


// on crée deux chaines contenant le premier caractère différent entre la réponse et la chaine tapée
    one_car_error=user_diffs.substring(0,1)+phrase_diffs.substring(0,1);
    two_cars_error=user_diffs.substring(0,2)+phrase_diffs.substring(0,2);
// Puis ensuite on trie en fonction de ces chaines:
    // ordre des lettres
    if (two_cars_error=='eiie'||two_cars_error=='ieei'){ return "Attention à l'ordre du e et du i";}
    if (two_cars_error=='euue'||two_cars_error=='ueeu'){ return "Attention à l'ordre du e et du u";}
    // confusion de lettres
    if (one_car_error=='yi'||one_car_error=='iy'){ return "Tu confonds y et i";}
    if (one_car_error=='cs'||one_car_error=='sc'){ return "Tu confonds c et s";}
    if (one_car_error=='zs'||one_car_error=='sz'){ return "Tu confonds c et s";}
    if (one_car_error=='cq'||one_car_error=='qc'){ return "Tu confonds c et q";}
    if (one_car_error=='nm'||one_car_error=='mn'){ return "Tu confonds m et n";}
    if (one_car_error=='jr'||one_car_error=='rj'){ return "Tu confonds j et r";}
    if (one_car_error=='jg'||one_car_error=='gj'){ return "Tu confonds j et g";}
// gestion des accents
if (
    one_car_error=='eé'
    ||one_car_error=='aá'
    ||one_car_error=='oó'
    ||one_car_error=='uú'
    ||one_car_error=='ií'
){ 
    lettre=one_car_error.substring(0,1);
    return "Il manque un accent sur le "+lettre;
}
if (
    one_car_error=='ée'
    ||one_car_error=='áa'
    ||one_car_error=='óo'
    ||one_car_error=='úu'
    ||one_car_error=='íi'
){ 
    lettre=one_car_error.substring(1,2);
    return "Il ne faut pas d'accent sur le "+lettre;
}

Bref, vous voyez le topo...

Conclusion

Pour le moment -et comme tout ce que je fais, il faut bien l'admettre - c'est encore au stade de beta version mais ça marche pour moi et mes collègues d'espagnol: les élèves se sont bien amusés à réviser avec et ils ont même organisé des concours entre eux.

A quoi ça tient, quand-même...

alt

Pour le moment, je débugge, donc ce n'est pas pour de suite. Mais si vous êtes intéressé, lâchez-vous sur les commentaires !

Getlib: ramener des bibliotheques & frameworks en local en une ligne

Certains se souviennent peut-être de goofi, pour récupérer des google fonts en local; sur la base de ce script, j'ai bricolé une version qui permettra de faire la même chose avec les bibliothèques et frameworks (notamment js) que tout un chacun utilise et dont l'appel participe aux stats de google et consorts à chaque requête sur leur serveur.

Donc, en gros, il suffit de remplacer l'appel du script dans le en ajoutant getlib.php?url= devant.

Ainsi

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

deviendra

<script src="https://www.warriordudimanche.net/getlib.php?url=https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Le fichier est récupéré une seule fois et seule la vertsion locale sera renvoyée par la suite.

Au cas où vous voulez que le script récupère une éventuelle mise à jour, il suffit d'ajouter update dans l'url:

<script src="https://www.warriordudimanche.net/getlib.php?update&url=https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Getlib vérifiera alors si le fichier distant a changé et le retéléchargera si c'est nécessaire.

Comme avec Goofi, seule l'IP du serveur qui héberge le script est connue du serveur distant, jamais celle du visiteur.

C'est tout! Je n'ai pas testé à fond encore et les erreurs ne sont pas gérées pour le moment, mais ça fonctionne quand même pas mal !

<?php 
# get libs from distant servers to local (& avoid unnecessary requests to servers who can log user's connections)
# ex:  
# https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
# becomes
# getlib.php?url=https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
# if you want to update local file if the distant one changes, just add "update" 
# getlib.php?update&url=https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
# author: warriordudimanche.net
# 
$lib_folder='libs/';
$check_updates=isset($_GET['update']);

if (!empty($_GET['url'])){
    if (!is_dir($lib_folder)){mkdir($lib_folder);}

    $url=strip_tags($_GET['url']);
    $local_filename=$lib_folder.basename($url);
    $flag='non';
    if (
        !is_file($local_filename)
        ||
        ($check_updates && !isSameFile())

    ){
        $lib=file_get_contents($url);
        file_put_contents($local_filename,$lib);
        $head = array_change_key_case(get_headers($url, TRUE));
        file_put_contents($local_filename.'.info', $head['last-modified']);
        $flag='oui';
    }
    header('Content-Type: '.mime_content_type($local_filename));
    exit(file_get_contents($local_filename));
}

function getDistantFile($url){
    global $local_filename;
    $lib=file_get_contents($url);
    file_put_contents($local_filename,$lib);
    $head = array_change_key_case(get_headers($url, TRUE));
    file_put_contents($local_filename.'.info', $head['last-modified']);
}

function isSameFile(){
    global $local_filename,$url;
    $head = array_change_key_case(get_headers($url, TRUE));
    $local=file_get_contents($local_filename.'.info');
    $distant=$head['last-modified'];
    return $distant==$local;
}

getlib.zip le dépôt

Comme toujours,
c'est aux autres de débugger
les scripts que tu commets, heu... commit...
super.
🗦
Et je vais t'avouer un truc, j'ai même pas honte !
C'est même ma marque de fabrique: une genre de «Bronco's touch»

T'as perdu une occasion de la fermer !

Quand M.Fion, en septembre dernier, chiait abondamment sur l'inconséquence des médias qui ne s'intéressent aux malversations des politiques que pendant «deux ou trois jours», il ignorait sans doute qu'il serait exaucé par la fée réalité quelques mois plus tard, à ses dépends

Il ne mérite AUCUNE pitié... AUCUNE.

En cadeau bonus, Laura Laune et léa la girafe


Laura Laune - Léa La Girafe par comedycontestfrance

Goofi: ramener des google fonts en local en une ligne

Ceux qui, avec une ténacité et une abnégation forçant le respect autant que l'admiration, me suivent depuis longtemps se souviennent sans doute de Goofy, un script php permettant de récupérer les fontes de google sous forme de zip prêt à l'emploi...

Ben je trouvais ça encore un peu lourd, sans compter qu'il faut tout le temps modifier le script pour qu'il continue à fonctionner. Par voie de conséquence, j'ai repris l'idée mais en la modifiant quelque peu...

Ce nouveau script s'utilise de façon radicalement différente: en effet, il suffit de l'appeler via la balise du header, comme le fait la balise proposée par google, sauf qu'on remplace l'url de google par celle de goofi:

<link href="https://fonts.googleapis.com/css?family=Nunito+Sans|Roboto" rel="stylesheet">

devient

<link href="http://monserveur.com/goofi.php?family=Nunito+Sans|Roboto" rel="stylesheet">

Et... c'est tout.

Goofi.php va :

  1. chercher le css fourni par Google,
  2. récupérer les fontes pour les copier en local
  3. recrér le css en remplaçant les chemins google par les chemins locaux,
  4. stocker le tout sur le serveur
  5. et renvoyer le css sous forme de feuille de style.

Le téléchargement ne se fait que la première fois, et seulement depuis le serveur, ainsi l'usager n'a-t-il rien à craindre du flicage goorwellien

Le script en question:

<?php 
header("Content-Type: text/css");
$font_folder='fonts';
if (!empty($_GET['family'])){
    if (!is_dir($font_folder)){mkdir($font_folder);}
    $family=strip_tags($_GET['family']);
    $css_filename=urlencode($family).'.css';
    $css_file_url='http://fonts.googleapis.com/css?family='.urlencode($family);
    if (!is_file($css_filename)){
        $css=file_get_contents($css_file_url);

        preg_match_all("#font-family: '(?P<name>[^']+)[<img class="smile normal" src="https://www.warriordudimanche.net/plugins/WDD_replace/img/normal/satisfait.png"/>]*?url\((?P<url>[^\)]+)\)#", $css, $urls);

        foreach($urls['url'] as $nb=>$url){
            $font_file=$urls['name'][$nb].basename($url);
            if (!is_file($font_folder.'/'.$font_file)){
                $font=file_get_contents($url);
                file_put_contents($font_folder.'/'.$font_file, $font);
            }
            $css=str_replace($url,$font_folder.'/'.$font_file,$css);
        }
        file_put_contents($css_filename,$css );
    }else{
        $css=file_get_contents($css_filename);
    }
    exit($css);
}

Le Zip et le dépôt

Trois plugins pour le prix de zéro: c'est Mercredi, c'est cadeau !

Toujours plus loin, toujours plus haut... Sky is the limit. Oui, bon, j'en fais un peu trop, mais les rares qui s'entêtent encore à me lire sont habitués

Donc, aujourd'hui, ce n'est pas un, ce n'est pas deux mais bien trois plugins que je vous propose. D'un coup. Chuis comme ça, généreux ! (si, si, c'est vrai, même que Cyrille Borne le dit )

Il ajoute même de façon tout-à-fait pertinente que ma générosité n'a d'égal que mon aspect bordélique, c'est vous dire l'ampleur !

Bon, plus sérieusement, les trois plugins ne sont que trois versions d'un seul et même script.

Pourquoi en faire trois alors ?

Excellente question, j'y réponds en dessous.


Comme je le disais il n'y a pas longtemps, j'ai décidé de cumuler toutes mes façons d'écrire dans le même espace dédié... C'était autant une volonté de n'avoir qu'un seul espace admin, qu'un désir de cohérence «éditoriale». De plus, j'avais tendance à utiliser Shaarli comme un outil de blog/expression d'opinion/communication, ce qu'il n'est pas.

Seulement pour ça, il fallait écrire dans des catégories séparées: blog, touit et links.

Le problème, quand on est, comme moi, éleveur d'enfants compulsif, impulsif et bordélique, c'est qu'on se retrouve rapidement à renoncer à poster sur le blog par manque de temps ou par flemme d'aller sur la page admin, se connecter, aller sur nouvel article, sélectionner la bonne catégorie, copier-coller le lien qui m'intéresse etc.

Faut que ça pulse, la vie est trop courte pour tout ça !

Du coup, j'ai pris le temps de ressortir mon plugin Quickpost et de le modifier.

Ainsi, chaque plugin permet de poster d'une façon différente à partir d'un clic sur un bookmarklet: un seul clic et la fenêtre apparaît, prête à l'emploi, la catégorie utile présélectionnée, le lien collecté (si Weblinks), le titre pré rempli.

Mieux: si on n'est pas connecté au moment du clic, une case mot de passe est ajoutée pour éviter le passage par la page de login.

Téléchargement

WDDQuickpost, pour poster un article

WDDTouit, pour touiter vite fait

WDDWeblinks, pour partager un lien

Captures

capture

capture

capture

Réjouissez-vous, mes amis, car en vérité, je vous le dis, ce post est terminé !

Fil RSS des articles de cette catégorie