Skip to content

Commit

Permalink
Add support and tests for other GTIN formats
Browse files Browse the repository at this point in the history
  • Loading branch information
jeroenvisser101 committed Sep 7, 2021
1 parent c678c60 commit 9d03f40
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 13 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Add `barcode_generator` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[{:barcode_generator, "~> 1.0.0"}]
[{:barcode_generator, "~> 1.1.0"}]
end
```

Expand Down
27 changes: 16 additions & 11 deletions lib/barcode_generator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ defmodule BarcodeGenerator do
iex> BarcodeGenerator.valid?(6291041500206)
true
iex> BarcodeGenerator.valid?(619659161415)
true
iex> BarcodeGenerator.valid?("6291041500200")
false
Expand Down Expand Up @@ -171,8 +174,8 @@ defmodule BarcodeGenerator do

@compile {:inline, multiplicator: 1}
@spec multiplicator(integer()) :: 3 | 1
defp multiplicator(index) when is_odd(index), do: 3
defp multiplicator(_index), do: 1
defp multiplicator(index) when is_odd(index), do: 1
defp multiplicator(_index), do: 3

@spec fetch_stack(non_neg_integer(), stack_with_base() | nil) :: stack_with_base()
defp fetch_stack(base, nil), do: {init_stack(base), div(base, 10)}
Expand All @@ -184,23 +187,25 @@ defmodule BarcodeGenerator do
end
end

@spec init_stack(non_neg_integer() | [digit()]) :: stack()
defp init_stack(base_or_digits, offset \\ 0, sum \\ 0)
@spec init_stack(non_neg_integer() | [digit()], integer()) :: stack()
defp init_stack(base_or_digits, sum \\ 0)

defp init_stack(base, offset, sum) when is_integer(base),
do: base |> Integer.digits() |> init_stack(offset, sum)
defp init_stack(base, sum) when is_integer(base),
do: base |> Integer.digits() |> init_stack(sum)

defp init_stack(digits, sum) do
length = length(digits) - 1

defp init_stack(digits, offset, sum) do
digits
|> Enum.with_index(offset)
|> Enum.with_index(fn element, index -> {element, length - index} end)
|> Enum.map_reduce(sum, fn
{digit, index}, acc when is_odd(index) ->
acc = acc + digit * 3
acc = acc + digit

{{digit, index, acc}, acc}

{digit, index}, acc ->
acc = acc + digit
acc = acc + digit * 3

{{digit, index, acc}, acc}
end)
Expand All @@ -224,7 +229,7 @@ defmodule BarcodeGenerator do
end

defp do_update_stack(digits, [{prev_digit, index, sum} | _stack], acc) do
init_stack(digits, index, sum - multiplicator(index) * prev_digit) ++ acc
init_stack(digits, sum - multiplicator(index) * prev_digit) ++ acc
end

@compile {:inline, base: 1}
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule BarcodeGenerator.MixProject do
use Mix.Project

@version "1.0.0"
@version "1.1.0"
@repo_url "https://github.com/jeroenvisser101/barcode_generator"

def project do
Expand Down
82 changes: 82 additions & 0 deletions test/barcode_generator_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -66,51 +66,133 @@ defmodule BarcodeGeneratorTest do

describe "BarcodeGenerator.generate/2" do
test "generates valid barcodes" do
# GTIN-12
barcodes = BarcodeGenerator.generate(619_659_161_415, 619_659_161_509)

assert length(barcodes) == 10
assert Enum.all?(barcodes, &BarcodeGenerator.valid?/1)

# GTIN-13
barcodes = BarcodeGenerator.generate(6_291_041_500_200, 6_291_041_500_299)

assert length(barcodes) == 10
assert Enum.all?(barcodes, &BarcodeGenerator.valid?/1)

# GTIN-14
barcodes = BarcodeGenerator.generate(62_910_415_000_200, 62_910_415_000_299)

assert length(barcodes) == 10
assert Enum.all?(barcodes, &BarcodeGenerator.valid?/1)
end

test "handles stack-exceeding barcodes" do
# GTIN-12
barcodes = BarcodeGenerator.generate(619_659_161_415, 619_659_162_509)

assert length(barcodes) == 110
assert Enum.all?(barcodes, &BarcodeGenerator.valid?/1)

# GTIN-13
barcodes = BarcodeGenerator.generate(6_291_041_500_200, 6_291_041_501_299)

assert length(barcodes) == 110
assert Enum.all?(barcodes, &BarcodeGenerator.valid?/1)

# GTIN-14
barcodes = BarcodeGenerator.generate(62_910_415_000_200, 62_910_415_001_299)

assert length(barcodes) == 110
assert Enum.all?(barcodes, &BarcodeGenerator.valid?/1)
end
end

describe "BarcodeGenerator.generate_stream/2" do
test "generates valid barcodes" do
# GTIN-12
barcode_stream = BarcodeGenerator.generate_stream(619_659_161_415, 619_659_161_509)

assert Enum.count(barcode_stream) == 10
assert Enum.all?(barcode_stream, &BarcodeGenerator.valid?/1)

# GTIN-13
barcode_stream = BarcodeGenerator.generate_stream(6_291_041_500_200, 6_291_041_500_299)

assert Enum.count(barcode_stream) == 10
assert Enum.all?(barcode_stream, &BarcodeGenerator.valid?/1)

# GTIN-14
barcode_stream = BarcodeGenerator.generate_stream(62_910_415_000_200, 62_910_415_000_299)

assert Enum.count(barcode_stream) == 10
assert Enum.all?(barcode_stream, &BarcodeGenerator.valid?/1)
end

test "handles stack-exceeding barcodes" do
# GTIN-12
barcode_stream = BarcodeGenerator.generate_stream(619_659_161_415, 619_659_162_509)

assert Enum.count(barcode_stream) == 110
assert Enum.all?(barcode_stream, &BarcodeGenerator.valid?/1)

# GTIN-13
barcode_stream = BarcodeGenerator.generate_stream(6_291_041_500_200, 6_291_041_501_299)

assert Enum.count(barcode_stream) == 110
assert Enum.all?(barcode_stream, &BarcodeGenerator.valid?/1)

# GTIN-14
barcode_stream = BarcodeGenerator.generate_stream(62_910_415_000_200, 62_910_415_001_299)

assert Enum.count(barcode_stream) == 110
assert Enum.all?(barcode_stream, &BarcodeGenerator.valid?/1)
end
end

describe "BarcodeGenerator.generate_flow/2" do
test "generates valid barcodes" do
# GTIN-12
barcode_flow = BarcodeGenerator.generate_flow(619_659_161_415, 619_659_161_509)

assert %Flow{} = barcode_flow
assert Enum.count(barcode_flow) == 10
assert Enum.all?(barcode_flow, &BarcodeGenerator.valid?/1)

# GTIN-13
barcode_flow = BarcodeGenerator.generate_flow(6_291_041_500_200, 6_291_041_500_299)

assert %Flow{} = barcode_flow
assert Enum.count(barcode_flow) == 10
assert Enum.all?(barcode_flow, &BarcodeGenerator.valid?/1)

# GTIN-14
barcode_flow = BarcodeGenerator.generate_flow(62_910_415_000_200, 62_910_415_000_299)

assert %Flow{} = barcode_flow
assert Enum.count(barcode_flow) == 10
assert Enum.all?(barcode_flow, &BarcodeGenerator.valid?/1)
end

test "handles stack-exceeding barcodes" do
# GTIN-12
barcode_flow = BarcodeGenerator.generate_flow(619_659_161_415, 619_659_162_509)

assert %Flow{} = barcode_flow
assert Enum.count(barcode_flow) == 110
assert Enum.all?(barcode_flow, &BarcodeGenerator.valid?/1)

# GTIN-13
barcode_flow = BarcodeGenerator.generate_flow(6_291_041_500_200, 6_291_041_501_299)

assert %Flow{} = barcode_flow
assert Enum.count(barcode_flow) == 110
assert Enum.all?(barcode_flow, &BarcodeGenerator.valid?/1)

# GTIN-14
barcode_flow = BarcodeGenerator.generate_flow(62_910_415_000_200, 62_910_415_001_299)

assert %Flow{} = barcode_flow
assert Enum.count(barcode_flow) == 110
assert Enum.all?(barcode_flow, &BarcodeGenerator.valid?/1)
end
end
end

0 comments on commit 9d03f40

Please sign in to comment.