Skip to content

Commit

Permalink
Adding check digit utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
RobFaustLZ committed Oct 12, 2024
1 parent 3b574b6 commit ee90715
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
}

group = 'com.labelzoom.api'
version = '1.3.0'
version = '1.3.1'

java {
sourceCompatibility = JavaVersion.VERSION_1_8
Expand Down
85 changes: 85 additions & 0 deletions src/main/java/com/labelzoom/api/util/CheckDigitUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.labelzoom.api.util;

public class CheckDigitUtils
{
public enum CheckDigitType
{
MOD10,
}

public static int getCheckDigit(final String barcode, final CheckDigitType type)
{
switch (type)
{
case MOD10: return getMod10CheckDigit(barcode);
default: throw new IllegalArgumentException("Invalid check digit type");
}
}

/**
* <p>
* <a href="https://www.axicon.com/checkdigitcalculator.html">MOD10 Check Digit Calculator</a>
* </p>
*
* <p>
* How to calculate your check digit yourself
* </p>
*
* <p>
* Example barcode number: 501234576421
* </p>
*
* <p>
* Step 1: add together all alternate numbers starting from the right<br>
* <code>5 0 1 2 3 4 5 7 6 4 2 1</code><br>
* <code>0 + 2 + 4 + 7 + 4 + 1 = 18</code>
* </p>
*
* <p>
* Step 2: multiply the answer by 3<br>
* <code>18 x 3 = 54</code>
* </p>
*
* <p>
* Step 3: now add together the remaining numbers<br>
* <code>5 0 1 2 3 4 5 7 6 4 2 1</code><br>
* <code>5 + 1 + 3 + 5 + 6 + 2 = 22</code>
* </p>
*
* <p>
* Step 4: add step 2 and 3 together<br>
* <code>54 + 22 = 76</code>
* </p>
*
* <p>
* Step 5: the difference between step 4 and the next 10th number:<br>
* <code>76 + 4 = 80</code><br>
* Check digit = <code>4</code>
* </p>
*
* @param barcode the barcode data
* @return the check digit
*/
private static int getMod10CheckDigit(final String barcode)
{
char[] digits = barcode.toCharArray();
/* Sum odds and evens separately so that we only perform one multiplication. In practice, one large
* multiplication was faster than several small multiplications
*/
int evens = 0;
int odds = 0;
boolean isEven = false; // Use alternating boolean variable rather than modular division (e.g., i % 2)
for (int i = digits.length - 1; i >= 0; i--)
{
if (isEven = !isEven) // Invert and update value as we read it. Ignore IntelliJ, it doesn't appreciate my l33tness
{
evens += Character.getNumericValue(digits[i]);
}
else
{
odds += Character.getNumericValue(digits[i]);
}
}
return 10 - (((evens * 3) + odds) % 10);
}
}
17 changes: 17 additions & 0 deletions src/test/java/com/labelzoom/api/util/CheckDigitUtilsTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.labelzoom.api.util;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class CheckDigitUtilsTests
{
@Test
void testAxiconExample() { assertEquals(4, CheckDigitUtils.getCheckDigit("501234576421", CheckDigitUtils.CheckDigitType.MOD10)); }

@Test
void testSsccExample() { assertEquals(8, CheckDigitUtils.getCheckDigit("0000123456000000001", CheckDigitUtils.CheckDigitType.MOD10)); }

@Test
void testCode128Example() { assertEquals(8, CheckDigitUtils.getCheckDigit("0008100887950411637", CheckDigitUtils.CheckDigitType.MOD10)); }
}

0 comments on commit ee90715

Please sign in to comment.