using System.Globalization; namespace MaBibli.Shared.Isbn; /// /// Reconnaissance des codes-barres de périodiques et extraction de leur ISSN. /// /// /// Un livre porte un EAN-13 préfixé 978 ou 979 ; un magazine porte 977, /// qui encode un ISSN — c'est-à-dire un titre de revue, pas un ouvrage. Aucune /// recherche bib.isbn 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. /// /// Structure du code, vérifiée sur 9772466671438 le 2026-08-18 : /// 977 + les 7 premiers chiffres de l'ISSN (sa clé n'y figure pas, elle est /// recalculée) + 2 chiffres de parution + 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 /// pas exploitables comme numéro d'édition fiable, et ne sont donc pas exposés ici. /// /// public static class CodePeriodique { /// Préfixe EAN-13 réservé aux publications en série. public const string Prefixe = "977"; /// /// Vrai si (déjà normalisé) est un EAN-13 valide de périodique. /// public static bool EstCodePeriodique(string? ean) => IsbnUtils.EstIsbn13Valide(ean) && ean!.StartsWith(Prefixe, StringComparison.Ordinal); /// /// ISSN porté par le code-barres, sous sa forme canonique à tiret (2466-6718), /// ou null si le code n'est pas celui d'un périodique. /// /// /// La clé de l'ISSN n'est pas dans le code-barres : elle se recalcule (somme pondérée 8→2, /// modulo 11, X si le complément vaut 10). C'est le même principe que la clé ISBN-10, /// sur sept chiffres au lieu de neuf. /// 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}"; } }