Coverage Summary for Class: CardNumberGenerator (ru.eda.plgn.bizgen.core.generator.impl)

Class Method, % Branch, % Line, % Instruction, %
CardNumberGenerator 100% (2/2) 100% (3/3) 100% (19/19)
CardNumberGenerator$CardBrand 100% (4/4) 100% (4/4) 100% (43/43)
CardNumberGenerator$Companion 100% (2/2) 100% (8/8) 100% (51/51)
Total 100% (8/8) 100% (15/15) 100% (113/113)


 package ru.eda.plgn.bizgen.core.generator.impl
 
 import ru.eda.plgn.bizgen.core.generator.GeneratorResult
 import ru.eda.plgn.bizgen.core.generator.GeneratorResultWithEscape
 import ru.eda.plgn.bizgen.core.generator.GeneratorStr
 import ru.eda.plgn.bizgen.core.utils.LuhnAlgorithm
 import kotlin.random.Random.Default.nextInt
 
 /**
  * Генератор номеров карт.
  *
  * Общая длина генерируемого номера = 16.
  *
  * Поддерживается генерация следующих систем: VISA, Mastercard, МИР.
  *
  * Структура полученного номера: XYN, где:
  * - X - Начальный BIN
  * - Y - случайный номер
  * - N - проверочная цифра, вычисленная на основе алгоритма Луна [LuhnAlgorithm]
  *
  * @author Dmitry_Emelyanenko
  */
 class CardNumberGenerator : GeneratorStr {
   override val uniqueDistance: Int = 130
 
   override fun generate(): GeneratorResult<String> = GeneratorResultWithEscape(data = generateNumber(CardBrand.entries.random()))
 
   /**
    * Тип карты.
    *
    * @property startBin начальный бин, который уникален для каждого типа
    */
   private enum class CardBrand(val startBin: () -> String) {
 
     /** Visa. */
     VISA(startBin = { "4070" }),
 
     /** Mastercard. */
     MASTER(startBin = { "5" + nextInt(1, 5) }),
 
     /** МИР. */
     MIR(startBin = { "220" }),
   }
 
   private companion object {
     private const val PAN_LENGTH = 16
 
     fun generateNumber(cardBrand: CardBrand): String {
       val bin = cardBrand.startBin()
       val randomPartLength = PAN_LENGTH - 1 - bin.length
 
       val accountPart = randomDigits(randomPartLength)
       val withoutCheckDigit = bin + accountPart
       val checkDigit = LuhnAlgorithm.calculateCheckDigit(withoutCheckDigit)
 
       return withoutCheckDigit + checkDigit
     }
 
     fun randomDigits(count: Int): String = (1..count)
       .joinToString("") { ('0'..'9').random().toString() }
   }
 }