From e2c95c114d69c8f38ee8e8e29fae6636b1288a0d Mon Sep 17 00:00:00 2001 From: Egor Romanov Date: Wed, 16 Feb 2022 22:31:59 +0300 Subject: [PATCH 1/2] Added Faker::Code.isbn --- README.md | 9 +++++++++ spec/code_spec.cr | 17 +++++++++++++++++ src/faker/code.cr | 29 +++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 spec/code_spec.cr create mode 100644 src/faker/code.cr diff --git a/README.md b/README.md index 264ac7f..058617f 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,15 @@ Faker::Business.credit_card_type #=> "visa" ``` +### Faker::Code + +```crystal + +Faker::Code.isbn #=> 640354399-7 + +``` + + ### Faker::Commerce ```crystal diff --git a/spec/code_spec.cr b/spec/code_spec.cr new file mode 100644 index 0000000..cde794e --- /dev/null +++ b/spec/code_spec.cr @@ -0,0 +1,17 @@ +require "./spec_helper" + +describe Faker::Code do + it "base 10 isbn" do + Faker::Code.isbn.match(/^\d{9}-[\d|X]$/).should_not eq nil + end + + it "base 13 isbn" do + Faker::Code.isbn(13).match(/^\d{12}-\d$/).should_not eq nil + end + + it "should return deterministic results when seeded" do + Faker.seed 123456 + Faker::Code.isbn.should eq "394314441-0" + Faker::Code.isbn(13).should eq "205982563728-9" + end +end diff --git a/src/faker/code.cr b/src/faker/code.cr new file mode 100644 index 0000000..46209a5 --- /dev/null +++ b/src/faker/code.cr @@ -0,0 +1,29 @@ +module Faker + class Code < Base + def self.isbn(base : Int32 = 10) + case base + when 10 then generate_base10_isbn + when 13 then generate_base13_isbn + else raise ArgumentError.new("base must be 10 or 13") + end + end + + private def self.generate_base10_isbn + values = Faker.regexify(/\d{9}/) + remainder = sum(values) { |value, index| (index + 1) * value.to_i } % 11 + values += "-#{remainder == 10 ? 'X' : remainder}" + end + + private def self.generate_base13_isbn + values = Faker.regexify(/\d{12}/) + remainder = sum(values) { |value, index| index.even? ? value.to_i : value.to_i * 3 } % 10 + values += "-#{(10 - remainder) % 10}" + end + + private def self.sum(values) + values.split(//).each_with_index.reduce(0) do |sum, (value, index)| + sum + yield(value, index) + end + end + end +end From 7f32a1197bf69019d7159adf083c877576a1aa33 Mon Sep 17 00:00:00 2001 From: Egor Romanov Date: Wed, 16 Feb 2022 22:46:05 +0300 Subject: [PATCH 2/2] Added Faker::Code.imei --- README.md | 4 +++- spec/code_spec.cr | 5 +++++ src/faker/code.cr | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 058617f..f585417 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,9 @@ Faker::Business.credit_card_type #=> "visa" ```crystal -Faker::Code.isbn #=> 640354399-7 +Faker::Code.isbn #=> "640354399-7" + +Faker::Code.imei #=> "531691246033652" ``` diff --git a/spec/code_spec.cr b/spec/code_spec.cr index cde794e..ce3c710 100644 --- a/spec/code_spec.cr +++ b/spec/code_spec.cr @@ -9,9 +9,14 @@ describe Faker::Code do Faker::Code.isbn(13).match(/^\d{12}-\d$/).should_not eq nil end + it "imei" do + Faker::Code.imei.match(/\A[\d.:\-\s]+\z/i).should_not eq nil + end + it "should return deterministic results when seeded" do Faker.seed 123456 Faker::Code.isbn.should eq "394314441-0" Faker::Code.isbn(13).should eq "205982563728-9" + Faker::Code.imei.should eq "860839366575918" end end diff --git a/src/faker/code.cr b/src/faker/code.cr index 46209a5..fe520ae 100644 --- a/src/faker/code.cr +++ b/src/faker/code.cr @@ -1,5 +1,7 @@ module Faker class Code < Base + RBI = %w[01 10 30 33 35 44 45 49 50 51 52 53 54 86 91 98 99] + def self.isbn(base : Int32 = 10) case base when 10 then generate_base10_isbn @@ -8,6 +10,41 @@ module Faker end end + def self.imei + str = Array.new(15, 0) + sum = 0 + len = 15 + + # Fill in the first two values of the string based with the specified prefix. + arr = RBI.sample(Faker.rng) + str[0] = arr[0].to_i + str[1] = arr[1].to_i + pos = 2 + + # Fill all the remaining numbers except for the last one with random values. + while pos < (len - 1) + str[pos] = Faker.rng.rand(0..9) + pos += 1 + end + + # Calculate the Luhn checksum of the values thus far + len_offset = (len + 1) % 2 + (0..(len - 1)).each do |position| + if (position + len_offset).odd? + t = str[position] * 2 + + t -= 9 if t > 9 + + sum += t + else + sum += str[position] + end + end + str[len - 1] = (10 - (sum % 10)) % 10 + + str.join("") + end + private def self.generate_base10_isbn values = Faker.regexify(/\d{9}/) remainder = sum(values) { |value, index| (index + 1) * value.to_i } % 11