Mes débuts en Ruby


7 avril 2007

Programmation Ruby

puts pour afficher quelque chose en output, un nombre, une expression arithmétique, une chaîne de caractères etc.

L'opérateur de concaténation de chaîne est '+', mais l'opérateur '*' fonctionne. Par exemple :

puts 1+2*3/7.5
puts "exemple"
puts 'Chaîne '+'concaténée '*2
1.8
exemple
Chaîne concaténée concaténée
Bien faire attention au retour de l'opérateur '*' sur la chaîne

Les variables doivent commencer par une lettre minuscules. Les conversions de types simples sont faisables avec des fonctions du genre : to_s (to string) et to_i (to integer).

name = "flubb"  #Assignement, name commence par une minuscule
age="32"        #C\'est un nombre mais je le stocke en tant que chaîne pour illustrer les conversion
puts "Je m\'appelle "+name+", et dans "+age+" années, j\'aurai : "+(age.to_i*2).to_s+" ans."
puts age+"/5 (en entier) = "+(age.to_i/5).to_s
puts age+"/5 (en flottant) = "+(age.to_f/5).to_s
Je m'appelle flubb, et dans 32 années, j'aurai : 64 ans.
32/5 (en entier) = 6
32/5 (en flottant) = 6.4

A retenir : puts signifie 'put string', donc à chaque appel puts something, Ruby exécute 'put something.to_s'.

Gets et chomp : deux méthodes pour attendre la saisie d'une chaîne de la part de l'utilisateur (gets) et pour supprimer le retour à la ligne final (l'appui sur entrée).

puts "Entrez votre nom :"
name=gets
puts "Votre nom : "+name+"."
puts "Votre nom chompé : "+name.chomp+"."
puts "Entrez votre age :"
age = gets.chomp
puts "Vous avez "+age+" ans."   #Pas besoin de faire age.to_s
Entrez votre nom :
Flubb
Votre nom : Flubb
.
Votre nom chompé : Flubb.
Entrez votre age :
56
Vous avez 56 ans.

Les 'objets' puts, gets, chomp, to_s, to_i et to_f sont des méthodes, mais les opérateurs arithmétiques +, -, * et / le sont également (appliqués à des nombres le plus souvent). puts, gets et chomp sont des méthodes de l'objet 'self', le programme qui s'exécute. Apparemment puts est protégée...

age=32
str="Mon age : "+age.to_s
puts str
self.puts str
Mon age : 32
1:4: private method `puts' called for main:Object (NoMethodError)

D'autres méthodes de string à présent, length et reverse :

str1="J'apprend à programmer en Ruby"
puts "La chaîne <"+str1+"> fait "+str1.length.to_s+" caractères."
puts "Et à l'envers :"
puts str1.reverse
puts "ça fait toujours "+str1.reverse.length.to_s+" caractères."
La chaîne <J'apprend à programmer en Ruby> fait 31 caractères.
Et à l'envers :
ybuR ne remmargorp 
Noter les problèmes d'encodage...

Des méthodes de string pour le formatage de l'affichage :

str1="j'apprend à programmer en RUBY"
puts "Chaîne de test : <"+str1+">"
puts "upcase : "+str1.upcase
puts "downcase : "+str1.downcase
puts "capitalize : "+str1.capitalize    #Capitalise le premier caractère
puts "swapcase : "+str1.swapcase
Chaîne de test : <j'apprend à programmer en RUBY>
upcase : J'APPREND à PROGRAMMER EN RUBY
downcase : j'apprend à programmer en ruby
capitalize : J'apprend à programmer en ruby
swapcase : J'APPREND à PROGRAMMER EN ruby

Et maintenant center.(%nbColumns%), ljust.(%nbColumns%) et rjust.(%nbColumns%), pour le formatage, avec une précision sur la passage de paramètres :

str1="j'apprend à programmer en RUBY"
puts "Chaîne de test : <"+str1+">"
puts str1.center(80)
puts str1.center 80         #Même résultat que la ligne précédente mais avec un warning
puts str1.ljust(80)
puts str1.rjust(80)
puts str1.ljust(40)+str1.rjust(40)
1:4: warning: parenthesize argument(s) for future version
Chaîne de test : <j'apprend à programmer en RUBY>
                       j'apprend à programmer en RUBY
                       j'apprend à programmer en RUBY
j'apprend à programmer en RUBY
                                                 j'apprend à programmer en RUBY
j'apprend à programmer en RUBY                  j'apprend à programmer en RUBY
Bien noter le warning suite au passage de paramètre sans parenthèses

Quelques autres exemples sur les nombres aléatoires, les valeurs absolues et l'objet Math (le premier objet que l'on utilise en en ayant conscience) :

#Exemples sur les RNGs
srand                   #Seed = temps courant de l'ordinateur
puts rand(101)          #Pour avoir un nombre entre 0 et 100
srand(1812)             #La seed est fixée
puts rand(101)          #Le nombre sera toujours le même : 91
srand                   #Seed = temps courant de l'ordinateur
puts rand(101)          #Pour avoir un nombre entre 0 et 100

#L'objet Math
puts "Pi = "+Math::PI.to_s
puts "e = "+(Math::E).to_s
MonCosinus=Math.cos(2*Math::PI/3)
puts "cos(2PI/3) = "+MonCosinus.to_s
puts "Valeur absolue du cosinus précédent : "+MonCosinus.abs.to_s
puts "Le nombre d'or : "+((1+Math.sqrt(5))/2).to_s
4
91
26
Pi = 3.14159265358979
e = 2.71828182845905
cos(2PI/3) = -0.5
Valeur absolue du cosinus précédent : 0.5
Le nombre d'or : 1.61803398874989

Les test : les opérateurs sont les mêmes que ceux de PHP (sans le triple égal) et C++, true et false sont des objets (true.to_s renvoie "true")

Après les tests : le if...else...end, note : pas de blocs d'exécution pour l'instant, pas d'accolades etc.

Boucle while %test%...end

command=""
puts "Entrez une commande ou "bye" pour quitter :"
while command!="bye"
    if command.length!=0
        puts command
    end
    command=gets.chomp
end
puts "Kassos"', "Programme qui attend une commande et la répète, jusqu'à ce qu'on rentre 'bye'.

Les tableaux :

[]
[5]
['Hello', 'Goodbye']
[89.9, flavor, [true, false]]

Parcours connu :

names = ['Ada', 'Belle', 'Chris']
puts names
puts names[0]
puts names[1]
puts names[2]
puts names[3]  #  This is out of range. >> objet nil !!!

Parcours automatique (while + méthode Array::length) :

names = ['Ada', 'Belle', 'Chris']
puts names
i = 0
while i <= names.length
    puts names[i]
    i = i+1     #Je ne connais pas encore l'opérateur ++
end

Each :

users = []
users.each do |user|
    puts "utilisateur "+user+" enregistré !"
end

équivalence des do...end et des blocs d'accolades {...}

parler des hash

parler du 3.times do...end

parler du Array::join, très pratique.

Retour d'une fonction : implicite (dernière ligne d'une fonction) ou explicite (return)

Programme implémentant et illustrant le bubble sort en ajoutant des méthodes à la classe Array :

class   Array
    #�change de deux éléments contigus du tableau
    def     swapSlot(i) self[i], self[i+1] = self[i+1], self[i] end
    #Raccourci, pour diminuer la taille de la méthode bubbleSort
    def     dc(i) self[i].downcase end
    def     bubbleSort comp
            i=0
            while (i<self.length-1)
                    if ((self.dc(i) <=> self.dc(i+1)) == comp and self.swapSlot i) i=0
                    else    i=i+1   end
            end
            self
    end
end

puts [ "jill", "norbert", "françois", "toto", "alphonse", "ZORRO", "JM", "Gilles" ].bubbleSort(1)
atoms=["zéro", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf", "dix", "onze", "douze", "treize", "quatorze", "quinze", "seize", "dix-dept", "dix-huit", "dix-neuf"]
dizaines=["", "dix", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante-dix", "quatre-vingt", "quatre-vingt dix"]

while ((nb=gets.chomp) != "bye")
    if (nb.to_i<10)
            puts atoms[nb.to_i]
    else
            Rang2=nb.to_i/10
            Rang1=nb.to_i%10
            FrenchFlag=dizaines[Rang2][dizaines[Rang2].length-3, 3]=="dix"
            puts "FrenchFlag : "+FrenchFlag.to_s
            Output = ""
            if (FrenchFlag)
                    if (Rang2>1)
                            Output=dizaines[Rang2-1]
                    end
                    #Output=Output+atomsEx[Rang1]
                    Rang1=Rang1+10
            else
                    Output=dizaines[Rang2]
            end
            if (Rang2 > 1)
                    if (Rang1 == 1)
                            Output = Output+" et"
                    end
                    if (Rang1 >=1)
                            Output = Output+" "+atoms[Rang1]
                    end
            else
                    Output=atoms[Rang1]
            end
            puts Output
            puts "Dizaine : "+dizaines[nb.to_i/10]+", unités : "+atoms[nb.to_i%10]
    end
end
C'est limite du pseudo-code, arranger ça...

Un Wiki stand-alone en PHP


7 avril 2007

Présentation

J'avais besoin d'un composant Wiki pour que cette fonctionnalité puisse être inclue dans n'importe quelle application, et pourquoi pas sur ce site même ?

Mon objectif était simple :

  • Un script court et auto-suffisant
  • De la rapidité/performance
  • Une bonne résilience aux données d'entrées invalides
  • La syntaxe Wiki doit être un paramètre du code et pas hardcodée
  • Doit être extensible par le biais de plug-ins (pour de nouveaux objets) ou de templates (pour leurs présentations)

Ce Wiki devait permettre de transformer une chaîne comme :

[[toc]]
==Titre principal

Voici une formule **très importante** pour la compréhension de la suite du chapitre :

<math>I_2=\frac{x-a}{2}f^{\prime\prime}(a)+\int_{a}^x\frac{x-t}{2}f^{(3)}(t)dt</math>

C'est un résultat capital à plus d'un titre :
# Il est élégant
# Il est aisé à dériver
# Il se retient facilement

==Deuxième partie

Texte **totalement** //non-important//

en une présentation HTML (par exemple) comme suit :

Le schéma

Pour obtenir ce résultat, j'aurai pu utiliser un des nombreux wikis disponibles, mais comme d'habitude, j'ai préféré le faire moi-même.

Pour ça, j'ai mixé un lexer et un parseur récursifs dans un même code et mis tout ça sous la forme d'une machine à états, décrite par des données et non pas du code.

Le raisonnement

Le premier constat c'est que les blocs à transformer ont des marqueurs de début et de fin, un mode de concrétisation, ou une template, et des options.

Par exemple pour transformer un bloc en gras le marqueur de début est '**', identique à celui de fin avec la possibilité d'être récursif (ce qui est mis en gras peut lui-même contenir d'autres mises en forme).

Un autre exemple est l'ajoût d'un titre. Cette fois le marqueur de début est '==', celui de fin est la fin de la ligne (\"\\n\") et l'option principale est de référencer le bloc produit dans la table des matières.

Le schéma est donc très simple et j'aboutit à un code de moins de 200 lignes, en comptant les options que je décris ci-dessous.

La syntaxe

'==', '===' etc.pour titres qui seront référencés dans la table des matières.
'http://www.example.com'une adresse web se transforme automatiquement en lien.
//pour mettre en italique un bloc de texte
**pour mettre en gras un bloc de texte
[URL ALT]pour ajouter un texte \"ALT\" qui pointe vers l'URL donnée
[{URL ALT}]pour ajouter une image d'URL donnée qui a \"ALT\" comme texte alternatif
----pour une ligne horizontale (eq. <hr/>)
\\nun simple retour à la ligne (eq. <br/>)
\\n\\ndébut d'un nouveau paragraphe (eq. <p>)
`deux backtick délimitent un bloc qui ne sera pas parsé par le module
\"> \"pour mettre en exergue un bloc de texte multiligne (eq. <blockquote>)
\"- \"un élément d'une liste à puces non-numérotées
\"# \"un élément d'une liste à puces numérotées
[[refs]]indique l'emplacement des notes de bas de page (créés par [URL])
[[toc]]crée la table des matières (contenant des pointeurs vers les titres décrits plus haut)
<math>...</math>insère une formule au format TeX

Les plug-ins

Comme plug-in de base, j'ai inclus celui des formules mathématique que je décris par ailleurs.

Les deux autres sont la possibilité d'avoir des notes en bas de pages (issu des blocs utilisant la notation [...]) et une table des matières automatique, créée à partir des titres.

Applications

Je n'ai pas écrit ce code uniquement pour m'amuser mais parce que l'édition de contenu des applications que je développe à titre professionnel m'imposait d'avoir une façon simple de créer des documents sans outils préalables.

Ainsi des sites commerciaux ou professionnels (donc privés) utilisent ce composant aujourd'hui même.

Reste à faire

La gestion des renvois des notes en bas de page n'est pas élégante du tout, c'est plus du hard-code qu'autre chose.

La gestion des tableaux est à faire, c'est crucial !

Au niveau du visuel, il faut : 1- générer le flux HTML et associer des classes CSS aux éléments comme les titres etc., 2- améliorer les templates existantes (qui sont basiques) et permettre de les modifier ou d'en ajouter de nouvelles, sur le schéma de [[toc]] et [[refs]].

Il faut gérer les antislashes pour indiquer que la ligne se poursuit à la suivante (c'est une pré-passe très courte à faire au début de la fonction principale).

Améliorer les notes en bas de page pour ajouter la possibilité d'ajouter des commentaires aux liens.

Marching methods


7 avril 2007

Poursuite du livre de Sethian

Deux méthodes pour suivre un front (d'onde, de fluide etc), connaissant sa vitesse normale, F, de propagation : l'une basée sur la valeur initiale (valable quelque soit F) et une autre sur les conditions aux limites (valable pour F>0).

Poursuite du livre de Sethian

On introduit plus formellement l'expression du problème et ses équations principales. On parle alors de métrique, de variation des oscillations en intégrant sur l'ensemble du front pour un t donné, de courbature etc. On aborde également la notion "d'entropie", que Sethian utilise et qui a du sens, même si ça n'est pas le même qu'en thermo ou en physique stat. On voit pour la première fois les effets d'un avancement du temps et les éventuelles pertes d'information que cela entraîne : comment intégrer ça dans la résolution d'une équation ? Une équation importante est la (2.16) qu'il faut redémontrer facilement.

Chapitre 3

Honnêtement je ne vois pas la pertinence de ce chapitre, non pas qu'il soit inutile, mais je ne le suis pas. C'est à relire car il est sûrement très intéressant pour la suite. Pour l'instant j'hypothèque...

Format iCal


7 avril 2007

Note sur le format iCalendar

ICal divers

Core Object :

    BEGIN:VCALENDAR
    <icalbody>
    END:VCALENDAR

<icalbody> :

    <calendarProperties>*
    <calendarComponent>*

<calendarComponent> :

VEVENT
VTODO
VJOURNAL
VFREEBUSY
VTIMEZONE
VALARM

Les vins en bases de données


7 avril 2007

Les vins

On décrit ici les différentes tables d'une base de données modélisant des 'vins'. Ce terme est un peu vague quand on se penche dessus : ça peut être une bouteille donnée ou un vin d'un producteur ou encore le vin d'une région.

Les utilisateurs
    Ils peuvent se connecter en administrateur sur le site et peuvent modifier le contenu, poser leurs critiques etc.

Les vins
    Un chateau-margot grand-cru de chez Rossignol de 1964 à base de Chardonnay.
    Cette table
    Type du vin : blanc, rouge, rosé

Les terroirs
    Chablis etc
    Map binaire de coordonnées GPS (c'est peut-être un peu extrème mais ça m'intéresse)

Les cépages
    Chardonnay, Pinot noir, Chablis blanc etc
    Liés à un terroir
    Petit descriptif
    Type de raisin : blanc/noir
    Q : peut-il y avoir un même cépage dans plusieurs terroirs ? A priori oui, mais je veux une vision claire...

Vins<-->Cépages
    Many2many pour indiquer les cépages entrant dans la composition d'un vin donné

Terroir<-->Cépage = Parcelle

Les années : table représentant la bouteille sur une table (enfin !)
    Lien vers un vin
    Lien vers un producteur/récoltant

Récolte
    Date de début et de fin
    Nombre d'ouvriers

Les producteurs/récoltants/coopérative
    Nom, date de la première vendange
    Si récoltant :
        cépages récoltés et/ou utilisés (il peut acheter du raisin ailleurs et mélanger avec sa propre récolte)

Adresses
    Lien vers un producteur

Les critiques
    Une critique peut être formulée par un utilisateur ou pas
1 2 3..... 9 10 11 12.... 17 18 19 20