using System;
using Developpez.Dotnet.Properties;
namespace Developpez.Dotnet.Algorithms
{
///
/// Type de vérification par l'algorithme de Luhn.
///
public enum LuhnCheckType
{
///
/// Aucun.
///
None = 0,
///
/// Carte de crédit.
///
CreditCard = 1,
///
/// Siren.
///
Siren = 2,
///
/// Siret.
///
Siret = 3
}
///
/// Algorithme de Luhn.
///
/// L'algorithme de Luhn est décrit ici :
/// http://en.wikipedia.org/wiki/Luhn_algorithm.
///
public static class Luhn
{
///
/// Utilise l'algorithme de Luhn pour vérifier la validité d'un nombre donné.
///
/// Nombre à vérifier.
/// Vrai si le nombre est valide selon l'algorithme de Luhn, faux sinon.
public static bool Check(long number)
{
return Luhn.Check(number.ToString(), -1);
}
///
/// Utilise l'algorithme de Luhn pour vérifier la validité d'un nombre donné.
///
/// Nombre à vérifier.
/// Vrai si le nombre est valide selon l'algorithme de Luhn, faux sinon.
public static bool Check(string number)
{
return Luhn.Check(number, -1);
}
///
/// Utilise l'algorithme de Luhn pour vérifier la validité d'un nombre donné.
///
/// Nombre à vérifier.
/// Longueur de la chaîne.
/// Vrai si le nombre est valide selon l'algorithme de Luhn, faux sinon.
private static bool Check(string number, int length)
{
#region Exceptions
// La chaîne ne doit pas être vide :
if (string.IsNullOrEmpty(number))
throw new ArgumentNullException(ExceptionMessages.StringNullOrEmpty);
// La chaîne doit être de la longueur donnée :
if (length > -1 && number.Length != length)
throw new ArgumentException(string.Format(ExceptionMessages.StringWrongLength, length));
// La chaîne doit être un nombre :
long result = 0;
if (!long.TryParse(number, out result))
throw new ArgumentException(ExceptionMessages.StringNotANumber);
// Le nombre doit être supérieur à zéro :
if (result <= 0)
throw new ArgumentOutOfRangeException(
"number",
string.Format(ExceptionMessages.NumberMustBeStrictlyPositive, "number"));
#endregion
int numberLength = number.Length;
int figure = 0;
int total = 0;
int position = 1;
for (int i = numberLength; i > 0; i--)
{
// Récupérer le chiffre en position courante :
figure = int.Parse(number[i - 1].ToString());
// Multiplier ce chiffre par 2 ou 1 en fonction de sa position :
figure = figure * ((position % 2 == 0) ? 2 : 1);
// Retirer 9 si le résultat obtenu est > 10
// (équivaut à ajouter le chiffre des dizaines et celui des unités) :
figure = (figure >= 10) ? figure - 9 : figure;
total += figure;
position++;
}
// Le chiffre valide pour la formule de Luhn, s'il est congru au modulo 10 :
return (total % 10 == 0);
}
///
/// Utilise l'algorithme de Luhn pour vérifier la validité d'un nombre donné.
///
/// Nombre à vérifier.
/// Type de vérification.
/// Vrai si le nombre est valide selon l'algorithme de Luhn, faux sinon.
public static bool Check(long number, LuhnCheckType checkType)
{
return Luhn.Check(number.ToString(), checkType);
}
///
/// Utilise l'algorithme de Luhn pour vérifier la validité d'un nombre donné.
///
/// Nombre à vérifier.
/// Type de vérification.
/// Vrai si le nombre est valide selon l'algorithme de Luhn, faux sinon.
public static bool Check(string number, LuhnCheckType checkType)
{
switch (checkType)
{
case LuhnCheckType.CreditCard:
return Luhn.Check(number, 16);
case LuhnCheckType.Siren:
return Luhn.Check(number, 9);
case LuhnCheckType.Siret:
return Luhn.Check(number, 14);
case LuhnCheckType.None:
default:
return Luhn.Check(number, -1);
}
}
}
}