MaBibli 1.0.0
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>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace MaBibli.Shared.Isbn;
|
||||
|
||||
/// <summary>
|
||||
/// Reconnaissance des codes-barres de <b>périodiques</b> et extraction de leur ISSN.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Un livre porte un EAN-13 préfixé <c>978</c> ou <c>979</c> ; un magazine porte <c>977</c>,
|
||||
/// qui encode un <b>ISSN</b> — c'est-à-dire un <i>titre de revue</i>, pas un ouvrage. Aucune
|
||||
/// recherche <c>bib.isbn</c> ne peut donc aboutir sur un tel code, et l'application répondait
|
||||
/// « aucun résultat » là où le code lui-même dit qu'on ne cherche pas au bon endroit.
|
||||
/// <para>
|
||||
/// Structure du code, vérifiée sur <c>9772466671438</c> le 2026-08-18 :
|
||||
/// <c>977</c> + les <b>7 premiers chiffres de l'ISSN</b> (sa clé n'y figure pas, elle est
|
||||
/// recalculée) + <b>2 chiffres de parution</b> + la clé EAN-13. Les deux chiffres de parution
|
||||
/// sont la raison pour laquelle un même ISSN couvre tous les numéros d'une revue : ils ne sont
|
||||
/// <b>pas</b> exploitables comme numéro d'édition fiable, et ne sont donc pas exposés ici.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static class CodePeriodique
|
||||
{
|
||||
/// <summary>Préfixe EAN-13 réservé aux publications en série.</summary>
|
||||
public const string Prefixe = "977";
|
||||
|
||||
/// <summary>
|
||||
/// Vrai si <paramref name="ean"/> (déjà normalisé) est un EAN-13 valide de périodique.
|
||||
/// </summary>
|
||||
public static bool EstCodePeriodique(string? ean) =>
|
||||
IsbnUtils.EstIsbn13Valide(ean) && ean!.StartsWith(Prefixe, StringComparison.Ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// ISSN porté par le code-barres, sous sa forme canonique à tiret (<c>2466-6718</c>),
|
||||
/// ou <c>null</c> si le code n'est pas celui d'un périodique.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// La clé de l'ISSN n'est pas dans le code-barres : elle se recalcule (somme pondérée 8→2,
|
||||
/// modulo 11, <c>X</c> si le complément vaut 10). C'est le même principe que la clé ISBN-10,
|
||||
/// sur sept chiffres au lieu de neuf.
|
||||
/// </remarks>
|
||||
public static string? IssnDepuis(string? ean)
|
||||
{
|
||||
if (!EstCodePeriodique(ean))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Chiffres 4 à 10 du code : l'ISSN amputé de sa clé.
|
||||
var corps = ean!.Substring(3, 7);
|
||||
|
||||
var somme = 0;
|
||||
for (var i = 0; i < 7; i++)
|
||||
{
|
||||
somme += (corps[i] - '0') * (8 - i);
|
||||
}
|
||||
|
||||
var cle = (11 - (somme % 11)) % 11;
|
||||
var caractereCle = cle == 10 ? "X" : cle.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
return $"{corps[..4]}-{corps[4..]}{caractereCle}";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user