Acter la liste d'envies dans CLAUDE.md et nettoyer IDEES.md
Retire d'IDEES.md la section « Pour plus tard — livres souhaités », désormais implémentée, et acte dans CLAUDE.md les trois décisions structurantes : table dédiée pour la liste d'envies, SRU BnF par bib.author pour la bibliographie, export en .txt et .csv. Consigne dans CLAUDE.md ce que la source renvoie réellement (Werber 203 notices -> 51 œuvres, Zola 2692 annoncées -> 87 œuvres sur 200 lues) et ce que le rapprochement par titre rate, l'interface énonçant la même limite à l'écran. Deux points relevés en passant et laissés à IDEES.md : la ligature « œ » que NormalisationTexte ne réduit pas à « oe » (L'Œuvre de Zola y échappe, et le défaut touche aussi la recherche du catalogue), et le plafond de 200 notices. Corrige au passage une ponctuation bancale du bandeau de bibliographie, et restreint le BOM UTF-8 au seul CSV. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,9 @@ Application self-hosted de gestion de bibliothèque personnelle, à héberger su
|
||||
| Statut de lecture | **Par utilisateur**, pas commun (décidé le 2026-08-17, après la phase 3) | Le livre est commun, sa lecture est personnelle : deux membres du foyer lisent le même exemplaire à des rythmes différents. Sort `Statut` de `Livre` vers une table dédiée |
|
||||
| Prêts | **Communs au foyer**, jamais filtrés par utilisateur ; un seul prêt ouvert par livre, garanti par index unique partiel | Un livre absent l'est pour tout le monde, et n'importe qui doit pouvoir noter son retour. Voir « Prêts » |
|
||||
| Auteurs | **Table dédiée** avec nom normalisé, remplaçant le champ texte libre | Nécessaire au regroupement par auteur et à la recherche insensible aux accents. Regroupement **automatique seulement quand c'est sûr**, sinon proposé à l'utilisateur |
|
||||
| Liste d'envies | **Table dédiée `LivreSouhaite`**, personnelle (par `YNH_USER`), jamais dans `Livres` | Un livre souhaité n'est pas possédé. Dans `Livres`, il entrerait dans le catalogue, les compteurs et les prêts, et il faudrait répéter « et qui n'est pas souhaité » à chaque lecture. Voir « Liste d'envies » |
|
||||
| Bibliographie par auteur | **SRU BnF, index `bib.author`**, avec post-filtre obligatoire sur l'auteur réel de la notice | Vérifié le 2026-08-18. `all` rapproche les mots sur l'ensemble des auteurs d'une notice : sans post-filtre, « Émile Zola » remonte l'œuvre de sa fille. Voir « Bibliographie par auteur » |
|
||||
| Export de la liste d'envies | **`.txt` et `.csv`**, produits côté serveur, sans dépendance | Les deux usages d'IDEES.md diffèrent : le texte s'emporte en librairie, le CSV s'ouvre dans un tableur. Voir « Export » |
|
||||
| Ebooks | **Fiches uniquement**, pas de stockage de fichiers | Inventaire, pas hébergement. Évite l'espace disque YunoHost, les sauvegardes lourdes, et garde le cache hors-ligne léger |
|
||||
| Architecture serveur | **x86_64** → publish `linux-x64` | Serveur PC/VPS confirmé par l'utilisateur |
|
||||
| Production des binaires | **Compilation locale + release manuelle**, via un script réutilisable en CI plus tard | Ne pas se bloquer sur l'outillage ; Gitea Actions nécessiterait un runner, non vérifié |
|
||||
@@ -367,6 +370,18 @@ Pret
|
||||
├── DateRetour (UTC, nullable — NULL tant que non rendu)
|
||||
└── UNIQUE (LivreId) WHERE DateRetour IS NULL
|
||||
un seul prêt ouvert par livre ; les prêts clos se répètent librement
|
||||
|
||||
LivreSouhaite (la liste d'envies est PERSONNELLE — voir sa section)
|
||||
├── Id
|
||||
├── Utilisateur (YNH_USER — une FRONTIÈRE, contrairement à AjoutePar)
|
||||
├── Titre
|
||||
├── TitreNormalise (clé d'ŒUVRE : « / » et « : » coupés — CleOeuvre)
|
||||
├── Auteur (texte libre — PAS de FK vers Auteur, volontairement)
|
||||
├── AuteurNormalise (jamais NULL, sinon l'unicité ci-dessous ne tient pas)
|
||||
├── Editeur / Annee / Isbn / CoverUrl / Note
|
||||
├── DateAjout
|
||||
└── UNIQUE (Utilisateur, TitreNormalise, AuteurNormalise)
|
||||
une œuvre par personne ; deux personnes peuvent souhaiter le même livre
|
||||
```
|
||||
|
||||
Garder `Pret` comme table séparée (pas un champ sur `Livre`) pour conserver l'historique complet des prêts passés, pas juste l'état actuel.
|
||||
@@ -465,6 +480,152 @@ livre sorti depuis six mois qu'on avait oublié, pas celui prêté hier.
|
||||
(`ServiceLivresApi.EnUtc`). Sans cela le prêt se décalerait d'un jour pour la moitié du globe.
|
||||
Vérifié en exécution : saisie du 12/08 → `2026-08-11 22:00` en base (CEST).
|
||||
|
||||
## Liste d'envies — implémentée le 2026-08-18
|
||||
|
||||
### Une table à part, et non un statut de plus
|
||||
|
||||
`LivreSouhaite` ne dépend pas de `Livre`. Le choix se joue sur un invariant, pas sur le confort :
|
||||
un souhait logé dans `Livres` serait entré **mécaniquement** dans le catalogue, dans les
|
||||
compteurs, dans les prêts et dans le cache hors-ligne, et il aurait fallu ajouter « et qui n'est
|
||||
pas souhaité » à **chaque** lecture. Un invariant qu'on réécrit à chaque requête finit par être
|
||||
oublié quelque part. Ici les deux tables ne se croisent pas — vérifié en exécution : une envie
|
||||
n'apparaît ni au catalogue, ni dans la recherche, ni dans le compteur de livres d'un auteur.
|
||||
|
||||
C'est aussi la seule forme qui accepte une envie **sans édition arrêtée** : on souhaite une
|
||||
œuvre, on possède un exemplaire. Un souhait n'a donc ni `Format`, ni prêt, et son ISBN est
|
||||
facultatif.
|
||||
|
||||
```
|
||||
LivreSouhaite (la liste d'envies est PERSONNELLE)
|
||||
├── Id
|
||||
├── Utilisateur (YNH_USER — ⚠️ une vraie FRONTIÈRE, voir ci-dessous)
|
||||
├── Titre
|
||||
├── TitreNormalise (clé d'ŒUVRE : sous-titre coupé — voir CleOeuvre)
|
||||
├── Auteur (texte libre, PAS une FK vers Auteur)
|
||||
├── AuteurNormalise (jamais NULL : SQLite tient deux NULL pour distincts)
|
||||
├── Editeur / Annee / Isbn / CoverUrl / Note
|
||||
├── DateAjout
|
||||
├── INDEX (Utilisateur)
|
||||
└── UNIQUE (Utilisateur, TitreNormalise, AuteurNormalise)
|
||||
```
|
||||
|
||||
### `Utilisateur` est une frontière, contrairement à `Livre.AjoutePar`
|
||||
|
||||
C'est le point à ne pas confondre, les trois portées du projet coexistant désormais :
|
||||
|
||||
| Donnée | Portée | Filtre-t-on dessus ? |
|
||||
|---|---|---|
|
||||
| Catalogue (`AjoutePar`) | **commune** au foyer | **jamais** — ce serait un bug de conception |
|
||||
| Prêt | **commun** au foyer | jamais |
|
||||
| Statut de lecture | **personnel** | oui, sur l'appelant |
|
||||
| **Liste d'envies** | **personnelle** | **oui, toujours, sans exception** |
|
||||
|
||||
Aucun point d'entrée n'accepte de nom d'utilisateur. Supprimer l'envie d'un autre renvoie **404**,
|
||||
pas 403 : l'inexistence et l'appartenance à autrui sont volontairement indiscernables. Le sens
|
||||
même de la fonctionnalité est de préparer un cadeau sans que l'autre le voie venir.
|
||||
|
||||
**L'auteur reste du texte libre**, pas une FK vers `Auteur` : cette table décrit qui est *dans la
|
||||
bibliothèque*. Y insérer les auteurs souhaités les ferait apparaître sur `/auteurs` avec
|
||||
« 0 livre » — et trahirait la liste d'envies de son propriétaire à tout le foyer.
|
||||
|
||||
### Export — `.txt` et `.csv`, aucun des deux ne demande de dépendance
|
||||
|
||||
IDEES.md décrit deux usages qui n'appellent pas le même fichier :
|
||||
|
||||
| Format | Usage | Forme |
|
||||
|---|---|---|
|
||||
| `.txt` | l'emporter en librairie | groupé **par auteur**, lisible tel quel sur un téléphone |
|
||||
| `.csv` | le partager avant un anniversaire | tableau, pour se répartir les achats dans un tableur |
|
||||
|
||||
Deux points à ne pas « corriger » :
|
||||
|
||||
- **Séparateur point-virgule**, pas la virgule. Le CSV n'a qu'un travail — s'ouvrir dans un
|
||||
tableur — et Excel en locale française attend `;`. Un fichier à virgules atterrit entièrement
|
||||
dans la colonne A. La collection est francophone : c'est ce cas-là qu'il faut servir.
|
||||
- **BOM UTF-8 en tête du CSV uniquement.** Sans lui Excel affiche « Émile Zola », soit à peu
|
||||
près chaque ligne d'un fonds français. Le `.txt` s'en passe : certains lecteurs simples
|
||||
l'affichent comme un caractère parasite.
|
||||
|
||||
Le fichier est produit **côté serveur** (`Results.File` pose un `Content-Disposition:
|
||||
attachment`). ⚠️ Le lien de téléchargement **doit** porter l'attribut `download` : sans lui, le
|
||||
routeur Blazor intercepte le clic comme une navigation interne et affiche sa page « introuvable »
|
||||
au lieu de télécharger. Vérifié dans le navigateur.
|
||||
|
||||
## Bibliographie par auteur — SRU BnF, validé le 2026-08-18
|
||||
|
||||
Le déclencheur décrit dans IDEES.md : depuis un auteur déjà présent, voir tout ce qu'il a écrit,
|
||||
les livres possédés grisés, et marquer les autres comme souhaités.
|
||||
|
||||
```
|
||||
https://catalogue.bnf.fr/api/SRU?version=1.2&operation=searchRetrieve
|
||||
&query=bib.author all "{nom}"&recordSchema=dublincore
|
||||
&maximumRecords=100&startRecord={1|101}
|
||||
```
|
||||
|
||||
L'index **`bib.author`** fonctionne, sans clé, en ~0,85 s par page. Deux pages de 100 sont
|
||||
lancées **en parallèle** (200 notices au plus).
|
||||
|
||||
### ⚠️ Deux filtres sont indispensables, et le second est critique
|
||||
|
||||
Sans eux, l'écran ment à l'utilisateur.
|
||||
|
||||
1. **Type de document.** L'index auteur ne distingue pas un livre d'un livre audio, d'un jeu ou
|
||||
d'un spectacle. Sur 200 notices de Werber : 180 imprimés, 13 enregistrements sonores, 3 images
|
||||
animées, 2 jeux, 1 spectacle. Liste **positive** (`texte imprimé`, `ressource électronique`) :
|
||||
un type inconnu est écarté.
|
||||
2. **Auteur réel de la notice.** `all` exige que tous les mots soient présents — mais sur
|
||||
l'**ensemble** des auteurs d'une notice. Un livre signé d'un « Émile » quelconque et d'un
|
||||
« Zola » quelconque remonte donc aussi. Mesuré sur 200 notices d'« Émile Zola » : **67 écartées**,
|
||||
dont toute l'œuvre de sa fille **Denise Le Blond-Zola** (*Émile Zola raconté par sa fille*),
|
||||
qui parle de lui sans qu'il l'ait écrite. On exige donc qu'un `dc:creator` nettoyé corresponde
|
||||
au nom demandé au sens de `RapprochementAuteurs`.
|
||||
|
||||
**Coût assumé du second filtre** : les adaptations dont l'auteur n'est pas le scénariste
|
||||
disparaissent (les BD tirées de Werber sont signées Corbeyran — 17 notices sur 200). C'est le bon
|
||||
compromis : afficher l'œuvre d'un tiers sous le nom de l'auteur est une erreur visible et gênante,
|
||||
en omettre une adaptation ne l'est pas.
|
||||
|
||||
### Ce que ça donne réellement
|
||||
|
||||
| Auteur | Notices annoncées | Lues | Retenues | **Œuvres distinctes** |
|
||||
|---|---|---|---|---|
|
||||
| Bernard Werber | 203 | 200 | 166 | **51** |
|
||||
| Émile Zola | 2692 | 200 | 118 | **87** |
|
||||
| Amélie Nothomb | 277 | 200 | 169 | **63** |
|
||||
|
||||
Le regroupement des rééditions est ce qui rend l'écran utilisable : sans lui, « Les fourmis »
|
||||
occupe onze lignes. Le représentant retenu est la notice **la plus ancienne** (l'édition
|
||||
originale situe l'œuvre dans la carrière), mais l'ISBN est pris sur n'importe quelle notice qui
|
||||
en porte un — les éditions anciennes n'en ont souvent pas.
|
||||
|
||||
⚠️ **Le plafond de 200 notices est un extrait pour les auteurs très réédités** (Zola en annonce
|
||||
2692). L'interface **doit** le dire (`BibliographieDto.Tronquee`) : une bibliographie partielle
|
||||
présentée comme complète ferait croire qu'un livre n'existe pas.
|
||||
|
||||
### Le rapprochement se fait par TITRE, pas par ISBN — et il rate des choses
|
||||
|
||||
**Pourquoi pas l'ISBN** : il désigne une *édition*, pas une œuvre. Le poche, le grand format et
|
||||
la réédition portent trois ISBN pour le même roman — mesuré : 183 notices de livres de Werber
|
||||
pour 51 œuvres, trois éditions par œuvre en moyenne. Comparer les ISBN répondrait « vous ne
|
||||
l'avez pas » à propos d'un livre posé sur l'étagère. L'ISBN ne sert donc qu'en **confirmation**.
|
||||
|
||||
`CleOeuvre` coupe la mention de responsabilité (` / `) puis le sous-titre (` : `) et met à plat.
|
||||
C'est ce qui réunit « Les thanatonautes », « Les thanatonautes : roman » et
|
||||
« Les thanatonautes / Bernard Werber ». **Ce qu'elle rate**, et qu'il ne faut pas prétendre
|
||||
autrement :
|
||||
|
||||
- un titre **retraduit ou changé** n'est pas rapproché du tout ;
|
||||
- une œuvre possédée **à l'intérieur d'une intégrale** n'est pas repérée ;
|
||||
- un **tome** n'est pas rapproché de son recueil (`Troisième humanité` ≠ `Troisième humanité. Tome 1`) ;
|
||||
- deux œuvres partageant leur **titre principal** sont confondues (risque borné : la comparaison
|
||||
n'a lieu qu'**à auteur donné**, jamais sur tout le catalogue) ;
|
||||
- la **ligature `œ`** n'est pas réduite à `oe` — *L'Œuvre* de Zola échappe au rapprochement
|
||||
(limite héritée de `NormalisationTexte`, voir IDEES.md).
|
||||
|
||||
Conséquence de conception : l'écran **grise** ce qu'il reconnaît et ne **masque jamais** de ligne.
|
||||
Un faux négatif se voit et se corrige d'un coup d'œil ; une ligne masquée à tort serait invisible.
|
||||
L'interface énonce cette limite en bas de liste plutôt que de laisser l'utilisateur la découvrir.
|
||||
|
||||
## Interface — décisions actées le 2026-08-18
|
||||
|
||||
Retours d'usage d'`IDEES.md`, appliqués et donc retirés de ce fichier-là.
|
||||
|
||||
@@ -31,18 +31,34 @@ Correction envisagée : une fois `dc:creator` nettoyé, si le titre **se termine
|
||||
|
||||
---
|
||||
|
||||
## Pour plus tard — livres souhaités
|
||||
## Recherche : la ligature « œ » n'est pas réduite à « oe »
|
||||
|
||||
Idée de fonctionnalité, **hors périmètre v1**, à ne pas implémenter sans décision explicite.
|
||||
Repéré le 2026-08-18 en implémentant la liste d'envies. `NormalisationTexte.Normaliser`
|
||||
décompose en **NFD**, qui sépare les accents mais laisse les ligatures intactes — seul NFKD les
|
||||
défait. Conséquence : `L'Œuvre` et `L'oeuvre` ne se rencontrent jamais.
|
||||
|
||||
**La liste d'envies est personnelle**, pas commune : chacun la sienne, comme le statut de lecture. C'est le pendant naturel de la décision actée sur les statuts.
|
||||
Ce n'est pas propre à la liste d'envies : la même fonction alimente la **recherche du catalogue**
|
||||
et la **clé unique des auteurs**. Zola a écrit *L'Œuvre*, que la BnF orthographie avec la
|
||||
ligature ; un utilisateur qui tape « oeuvre » ne le trouvera pas, et ne verra pas non plus le
|
||||
livre grisé dans la bibliographie.
|
||||
|
||||
**Export de la liste d'envies** souhaité — pour l'emporter en librairie ou la partager avant un anniversaire. Format à choisir le moment venu ; du texte simple ou du CSV suffira probablement, et reste lisible partout sans dépendance.
|
||||
Correction envisagée : passer en NFKD, ou traiter explicitement `œ`/`Œ` et `æ`/`Æ`. **Non fait
|
||||
volontairement** — changer cette fonction déplace deux invariants en base (les colonnes
|
||||
normalisées et l'index unique `CleRegroupement`). `ServiceRenormalisation` sait recalculer les
|
||||
colonnes au démarrage, mais la fusion d'auteurs que la nouvelle règle provoquerait mérite d'être
|
||||
regardée avant. Documenté par un test (`CleOeuvreTests.Ne_reduit_pas_la_ligature_oe`) pour que
|
||||
la limite reste visible.
|
||||
|
||||
Pouvoir suivre les livres qu'on aimerait acquérir. Le déclencheur serait le regroupement par auteur : en cliquant sur un auteur déjà présent dans la bibliothèque (exemple donné : Bernard Werber), afficher **sa bibliographie complète**, avec les ouvrages déjà possédés grisés — et la possibilité de marquer les autres comme souhaités.
|
||||
---
|
||||
|
||||
Ce que ça impliquerait, à évaluer le moment venu :
|
||||
## Bibliographie : ce qui reste à creuser
|
||||
|
||||
- Une source pour les bibliographies par auteur. La BnF sait interroger par auteur, mais l'ordre et l'exhaustivité restent à vérifier ; OpenLibrary expose les œuvres liées à un auteur.
|
||||
- Un moyen d'identifier un auteur de façon stable, donc probablement une **table `Auteur`** plutôt que le champ texte actuel — c'est le changement de modèle le plus lourd de cette idée.
|
||||
- Un statut « souhaité » distinct des statuts de lecture existants, ou une entité séparée pour ne pas mélanger inventaire et liste d'envies.
|
||||
La bibliographie par auteur est implémentée (voir `CLAUDE.md`). Deux pistes non traitées :
|
||||
|
||||
- **Plafond de 200 notices.** Suffisant pour un auteur contemporain (Werber : 203, Nothomb : 277),
|
||||
très insuffisant pour un classique (Zola : 2692). L'écran le dit, mais on pourrait charger les
|
||||
pages suivantes à la demande plutôt que d'annoncer un extrait.
|
||||
- **OpenLibrary en second rideau.** La BnF ne connaît pas les auteurs étrangers non traduits ;
|
||||
l'écran affiche alors une liste vide et l'explique. OpenLibrary expose les œuvres d'un auteur
|
||||
(`/authors/{id}/works.json`) et pourrait prendre le relais — à ne faire que si le cas se
|
||||
présente réellement en usage.
|
||||
|
||||
Reference in New Issue
Block a user