Gestion de bibliothèque personnelle auto-hébergée : catalogue, prêts, scan de code-barres, consultation hors-ligne. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
95 lines
3.3 KiB
C#
95 lines
3.3 KiB
C#
using MaBibli.Shared.Textes;
|
|
|
|
namespace MaBibli.Shared.Entites;
|
|
|
|
/// <summary>
|
|
/// Un auteur du catalogue. Table dédiée, et non plus un champ texte sur <see cref="Livre"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Deux besoins imposaient la table : regrouper les livres d'un même auteur d'un clic, et
|
|
/// retrouver « Émile » en tapant « Emile ». Un champ texte libre ne sait faire ni l'un ni l'autre.
|
|
/// </remarks>
|
|
public class Auteur
|
|
{
|
|
public int Id { get; set; }
|
|
|
|
/// <summary>Nom tel qu'affiché, accents et casse compris : « Émile Zola ».</summary>
|
|
public string Nom { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Forme normalisée du nom (minuscules, sans accents), dans l'ordre de saisie.
|
|
/// Sert à la <b>recherche</b>.
|
|
/// </summary>
|
|
public string NomNormalise { get; set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Clé de regroupement : mêmes mots normalisés mais <b>triés</b>, ce qui rend l'ordre
|
|
/// indifférent. <b>Unique</b> en base : c'est elle qui empêche « Zola, Émile » et
|
|
/// « Émile Zola » de coexister.
|
|
/// </summary>
|
|
public string CleRegroupement { get; set; } = string.Empty;
|
|
|
|
public List<LivreAuteur> Livres { get; set; } = [];
|
|
|
|
/// <summary>Renseigne les deux formes dérivées à partir du nom d'affichage.</summary>
|
|
public void RecalculerFormes()
|
|
{
|
|
Nom = Nom.Trim();
|
|
NomNormalise = NormalisationTexte.Normaliser(Nom);
|
|
CleRegroupement = RapprochementAuteurs.Cle(Nom);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Table de liaison livre ↔ auteur : un livre peut avoir plusieurs auteurs.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Le cas n'est pas théorique : le lookup ISBN d'<i>Introduction to Algorithms</i> renvoie
|
|
/// quatre noms (Cormen, Leiserson, Rivest, Stein). <see cref="Position"/> conserve l'ordre de
|
|
/// la couverture, qui n'est pas alphabétique et fait partie de l'information.
|
|
/// </remarks>
|
|
public class LivreAuteur
|
|
{
|
|
public int LivreId { get; set; }
|
|
|
|
public Livre? Livre { get; set; }
|
|
|
|
public int AuteurId { get; set; }
|
|
|
|
public Auteur? Auteur { get; set; }
|
|
|
|
/// <summary>Rang de l'auteur sur la couverture, à partir de 0.</summary>
|
|
public int Position { get; set; }
|
|
|
|
/// <summary>
|
|
/// Rôle sur <b>ce livre</b> : scénario, dessin, couleurs. Voir <see cref="RoleAuteur"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Il est porté par le lien et non par l'auteur : le même dessinateur peut avoir scénarisé
|
|
/// un autre album, et il ne doit pas pour autant exister en deux fiches.
|
|
/// </remarks>
|
|
public RoleAuteur Role { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rapprochement d'auteurs <b>explicitement refusé</b> par l'utilisateur.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Sans cette mémoire, une suggestion écartée reviendrait à chaque affichage : « Hamilton » et
|
|
/// « Peter F. Hamilton » se ressembleront toujours autant. On ne stocke <b>que</b> les refus ;
|
|
/// les suggestions elles-mêmes sont recalculées à la demande, et une acceptation ne laisse rien
|
|
/// à mémoriser puisque l'un des deux auteurs disparaît.
|
|
/// <para>
|
|
/// Le couple est toujours rangé avec le plus petit identifiant en premier, pour qu'un refus vaille
|
|
/// dans les deux sens.
|
|
/// </para>
|
|
/// </remarks>
|
|
public class RapprochementRefuse
|
|
{
|
|
public int Id { get; set; }
|
|
|
|
public int AuteurAId { get; set; }
|
|
|
|
public int AuteurBId { get; set; }
|
|
}
|