Documentation
¶
Overview ¶
Package moteur lit une ligne d'ingrédient à l'aide d'un pack de langue.
Le moteur ne connaît aucune langue : ni les unités, ni les prépositions, ni la règle d'accord ne sont écrites ici. Tout vient du pack (`lang/fr.toml`). Ajouter l'espagnol, c'est écrire `lang/es.toml` — pas toucher au Go.
Ce fichier est le portage de `crawler/langpack.py`. Le portage est volontairement littéral : à comportement identique, une divergence se lit comme une erreur de traduction et non comme une variante d'écriture.
Index ¶
- Constants
- Variables
- func BlocRestitue(p *Pack, bloc string, lu *Ingredient) bool
- func ExtraitNotes(texte string, p *Pack) (reste, note string, optionnel bool)
- func FR() (*Pack, *Lexique, error)
- func Nettoie(brut string) string
- func PartitifA(p *Pack, texte string, i int) string
- func Span(p *Pack, aliment, note string) string
- func TexteQuantite(valeur *float64) string
- type Aliments
- type Desaccord
- type Ensemble
- type Ingredient
- type LectureUnite
- type Lexique
- type LigneRef
- type Pack
- func (p *Pack) Accorde(unite *Unite, valeur *float64) string
- func (p *Pack) EstIndefinie(texte string) bool
- func (p *Pack) LireUnite(texte string) *LectureUnite
- func (p *Pack) LitUniteExacte(texte string) *Unite
- func (p *Pack) Nombre(texte string) (float64, bool)
- func (p *Pack) NombreDeFormes() int
- func (p *Pack) Normalise(texte string) string
- func (p *Pack) Partitif(texte string) string
- func (p *Pack) Quantite(texte string) *Quantite
- type Quantite
- type Unite
- type Verdict
Constants ¶
const ( SourceAliments = "https://github.com/Rouzax/MealieSync" LicenceAliments = "MIT" CopyrightAliment = "Copyright (c) 2025 Rouzax" )
SourceAliments décrit la provenance du lexique livré avec le moteur.
const Tolerance = 0.011
Tolerance : deux quantités sont les mêmes à un centième près. Le corpus écrit « 0,33 » là où le pack calcule 1/3 — exiger l'égalité stricte compterait faux une lecture juste.
Variables ¶
var ChampsMesures = []string{"quantite", "unite", "partitif", "aliment"}
ChampsMesures sont les quatre champs sur lesquels une ligne se juge.
Functions ¶
func BlocRestitue ¶
func BlocRestitue(p *Pack, bloc string, lu *Ingredient) bool
BlocRestitue dit si notre découpe rend le bloc que la source publie, sans rien perdre.
La comparaison est **textuelle**, et elle ne peut pas être autre chose : relire le bloc seul avec le parser donnerait toujours un aliment et jamais une unité, puisque « une unité sans rien derrière est un aliment » — « 4 pavé(s) » isolé se lit *pavé*, aliment. C'est une règle du parser, pas un accident, et elle rend le bloc illisible hors de sa ligne.
Donc : ce que la ligne revendique comme quantité et comme unité, remis bout à bout, doit couvrir le bloc publié — ni plus, ni moins. Contrôle de frontière, pas d'exactitude.
func ExtraitNotes ¶
ExtraitNotes sort les parenthèses de la ligne : ce sont des notes, pas des aliments. Marmiton balise d'ailleurs le complément à part (« (vieilles) », « (bio) »), ce qui confirme la lecture.
Les marqueurs « facultatif » et « optionnel » sont cherchés partout, y compris dans la note qu'on vient de sortir.
func FR ¶
FR rend le couple prêt à l'emploi — c'est le point d'entrée attendu de la plupart des appelants :
pack, lexique, err := moteur.FR()
ingredient := moteur.Lit("500 g de beurre demi-sel", pack, lexique)
func PartitifA ¶
PartitifA rend le partitif qui commence exactement à l'octet i, le plus long d'abord, tel qu'écrit dans le texte (« d' », « de la »…).
La frontière de mot est exigée des deux côtés, sinon « des » serait trouvé dans « dessert » et « de » dans « demi ».
func Span ¶
Span recolle l'aliment et sa note, débarrassés de ce qui n'est que du découpage : les parenthèses qui isolent le qualificatif chez un site et l'espace qui l'en sépare chez l'autre.
« Bœuf (carpaccio) » et « Bœuf » + « carpaccio » deviennent la même chaîne. Ce qui reste différent l'est vraiment.
func TexteQuantite ¶
TexteQuantite rend une quantité sous la forme « %g » de Python, ou la chaîne vide s'il n'y en a pas.
Types ¶
type Aliments ¶
Aliments est le lexique, quand il existe : n'importe quoi qui sache dire si un nom normalisé lui appartient.
type Desaccord ¶
Desaccord est une ligne que le parser ne lit pas comme l'annotateur.
type Ingredient ¶
type Ingredient struct {
Brut string
Motif string
Quantite *float64
QuantiteMax *float64 // « 2 à 3 gousses »
QuantiteTexte string
Approximative bool // « quelques », « environ »
Indefinie bool // « un peu de lait »
Unite *Unite
UniteTexte string
Qualificatifs []string
Partitif string
Aliment string
Note string
Optionnel bool
}
Ingredient est une ligne lue. Motif dit quelle règle a servi — c'est ce qui rend le résidu analysable au lieu d'être un tas d'échecs indistincts.
func Lit ¶
func Lit(brut string, p *Pack, aliments Aliments) *Ingredient
Lit lit une ligne d'ingrédient. N'échoue jamais : une ligne illisible rend un aliment nu, ce qui est la lecture la moins fausse possible.
func (*Ingredient) EnBase ¶
func (i *Ingredient) EnBase() *float64
EnBase rend la quantité convertie dans l'unité de base (g, ml, cm), si la conversion est possible.
func (*Ingredient) UniteCle ¶
func (i *Ingredient) UniteCle() string
UniteCle rend la clé de l'unité, ou la chaîne vide s'il n'y en a pas.
type LectureUnite ¶
LectureUnite est ce qu'on a lu dans un texte d'unité : l'unité, et ce qui l'habillait.
Facteur porte les multiplicateurs décollés en chemin : « demi litre » rend l'unité litre et 0,5. Les qualificatifs, eux, ne changent rien à la quantité — « grosse cuillère à soupe » reste une cuillère à soupe.
type Lexique ¶
type Lexique struct {
Entrees int
// contains filtered or unexported fields
}
Lexique est un ensemble de formes normalisées, et rien de plus.
func AlimentsFR ¶
AlimentsFR rend le lexique d'aliments embarqué, normalisé avec le pack donné.
func ChargeAliments ¶
ChargeAliments lit le lexique et normalise ses formes avec le pack — sans quoi « Cœur d'artichaut » et « coeur d'artichaut » seraient deux entrées différentes et aucune ne répondrait.
func LisAliments ¶
LisAliments fait le même travail depuis un lexique déjà en mémoire — celui que le module embarque, notamment.
type LigneRef ¶
type LigneRef struct {
Source string
Brut string
Quantite string
Unite string
Partitif string
Aliment string
Note string
}
LigneRef est une ligne du jeu de référence annoté à la main.
func AnalyseJeu ¶
AnalyseJeu relit `testdata/fr.txt` : les lignes, et le plancher inscrit dans l'entête.
type Pack ¶
type Pack struct {
Langue string
Version int
Unites map[string]*Unite
ClesUnites []string // ordre stable, pour tout ce qui énumère
Partitifs []string // du plus long au plus court
PartitifsEnTete []string
PartitifsAccentues bool
Litterales map[string]Quantite
Fractions map[string]Quantite
Indefinies []string // du plus long au plus court
QualificatifsAvant map[string]bool
QualificatifsApres map[string]bool
Multiplicateurs map[string]float64
Notes map[string][]string
Delimiteurs [][2]string
SeuilPluriel float64
SeparateurDecimal string
SeparateursIntervalle []string
Apostrophes []rune // la canonique en tête
MarquesPluriel []string
// contains filtered or unexported fields
}
Pack est un pack de langue chargé.
func Construit ¶
Construit bâtit un pack depuis la structure d'un TOML déjà lu. C'est le point d'entrée des tests : un pack factice suffit à prouver que le moteur ne connaît aucune langue.
func Lis ¶
Lis bâtit un pack depuis un TOML déjà en mémoire. origine ne sert qu'aux messages d'erreur : c'est ce qui permet de charger aussi bien un fichier que le pack embarqué dans le module.
func (*Pack) Accorde ¶
Accorde rend « 1,5 cuillère à soupe » mais « 2 cuillères à soupe ». Le seuil vient du pack : l'anglais mettrait 1, le français met 2.
func (*Pack) EstIndefinie ¶
EstIndefinie : « un peu de lait » — il en faut, on ne dit pas combien.
func (*Pack) LireUnite ¶
func (p *Pack) LireUnite(texte string) *LectureUnite
LireUnite rend l'unité, débarrassée de ses adjectifs.
Marmiton publie 162 « unités » dont une quarantaine ne sont qu'une unité de base habillée : « grosse cuillère à soupe », « petite boîte ». La construction est productive — on décolle plutôt que d'énumérer.
func (*Pack) LitUniteExacte ¶
LitUniteExacte rend l'unité écrite exactement comme ça, sans qualificatif.
func (*Pack) Nombre ¶
Nombre lit « 0,5 », « 1/2 », « 1 1/2 ». Le second retour est faux si ce n'est pas un nombre.
func (*Pack) NombreDeFormes ¶
NombreDeFormes rend le nombre d'écritures d'unité reconnues, toutes unités confondues.
func (*Pack) Normalise ¶
Normalise rend comparables « Càs », « càs » et « CaS » — les trois existent dans le corpus. Sans cette étape, le pack devrait énumérer les casses, ce qui est sans fin.
plierAccents est levé pour les prépositions, et pour elles seules : « 16 dés de foies gras » ne doit pas donner le partitif « des ».
type Unite ¶
type Unite struct {
Cle string
Dimension string // masse · volume · longueur · compte · imprecise
Singulier string
Pluriel string
Abrev string
Formes []string
Base *float64 // en grammes, millilitres ou centimètres
Facteur *float64 // douzaine = 12, moitié = 0,5
}
Unite est une unité du pack, avec toutes ses écritures.
func (*Unite) Convertible ¶
Convertible dit si l'unité a une valeur de base connue. Un verre n'en a pas : lui en inventer une serait le genre de supposition que ce projet refuse.
type Verdict ¶
Verdict porte le jugement champ par champ. Une valeur absente signifie « non mesuré » — le champ n'a pas été publié par la source.
func Compare ¶
func Compare(attendu LigneRef, lu *Ingredient, p *Pack, videAbsent, uniteParFamille bool) Verdict
Compare juge une ligne lue face à ce qui était attendu.
videAbsent distingue les deux références du projet : chez un site, un champ vide veut dire « non publié » et ne doit rien coûter au parser ; dans l'annotation, il veut dire « cette ligne n'a pas d'unité » et doit être mesuré. C'est le seul paramètre qui les sépare, et c'est ce qui rend les deux taux comparables.
uniteParFamille rattrape une convention de Jow, qui publie la famille et non l'unité écrite : « 80 g Bœuf » y sort avec l'unité « Kilogramme », sans que la quantité soit convertie pour autant.