diff --git a/build.gradle b/build.gradle index 26a8fe7..612fc7d 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group = 'com.labelzoom.api' -version = '1.3.0' +version = '1.3.1' java { sourceCompatibility = JavaVersion.VERSION_1_8 diff --git a/src/main/java/com/labelzoom/api/util/CheckDigitUtils.java b/src/main/java/com/labelzoom/api/util/CheckDigitUtils.java new file mode 100644 index 0000000..f2ab433 --- /dev/null +++ b/src/main/java/com/labelzoom/api/util/CheckDigitUtils.java @@ -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"); + } + } + + /** + *

+ * MOD10 Check Digit Calculator + *

+ * + *

+ * How to calculate your check digit yourself + *

+ * + *

+ * Example barcode number: 501234576421 + *

+ * + *

+ * Step 1: add together all alternate numbers starting from the right
+ * 5 0 1 2 3 4 5 7 6 4 2 1
+ * 0 + 2 + 4 + 7 + 4 + 1 = 18 + *

+ * + *

+ * Step 2: multiply the answer by 3
+ * 18 x 3 = 54 + *

+ * + *

+ * Step 3: now add together the remaining numbers
+ * 5 0 1 2 3 4 5 7 6 4 2 1
+ * 5 + 1 + 3 + 5 + 6 + 2 = 22 + *

+ * + *

+ * Step 4: add step 2 and 3 together
+ * 54 + 22 = 76 + *

+ * + *

+ * Step 5: the difference between step 4 and the next 10th number:
+ * 76 + 4 = 80
+ * Check digit = 4 + *

+ * + * @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); + } +} diff --git a/src/test/java/com/labelzoom/api/util/CheckDigitUtilsTests.java b/src/test/java/com/labelzoom/api/util/CheckDigitUtilsTests.java new file mode 100644 index 0000000..6e32109 --- /dev/null +++ b/src/test/java/com/labelzoom/api/util/CheckDigitUtilsTests.java @@ -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)); } +}