Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UPC-E fix #207

Merged
merged 2 commits into from
Jun 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions BarcodeStandard/BarcodeStandard.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>3.1.2</Version>
<Version>3.1.3</Version>
<PackageId>BarcodeLib</PackageId>
<Company>Pnuema Productions</Company>
<Product>BarcodeLib</Product>
Expand All @@ -18,8 +18,8 @@
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
<PackageIcon>upca.jpg</PackageIcon>
<PackageIconUrl />
<AssemblyVersion>3.1.2.0</AssemblyVersion>
<FileVersion>3.1.2.0</FileVersion>
<AssemblyVersion>3.1.3.0</AssemblyVersion>
<FileVersion>3.1.3.0</FileVersion>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>latest</LangVersion>
<SignAssembly>true</SignAssembly>
Expand Down
229 changes: 162 additions & 67 deletions BarcodeStandard/Symbologies/UPCE.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Linq;
using System.Text;

namespace BarcodeStandard.Symbologies
{
Expand All @@ -10,7 +12,6 @@
{
private readonly string[] EAN_Code_A = { "0001101", "0011001", "0010011", "0111101", "0100011", "0110001", "0101111", "0111011", "0110111", "0001011" };
private readonly string[] EAN_Code_B = { "0100111", "0110011", "0011011", "0100001", "0011101", "0111001", "0000101", "0010001", "0001001", "0010111" };
private readonly string[] EAN_Pattern = { "aaaaaa", "aababb", "aabbab", "aabbba", "abaabb", "abbaab", "abbbaa", "ababab", "ababba", "abbaba" };
private readonly string[] UPC_E_Code0 = { "bbbaaa", "bbabaa", "bbaaba", "bbaaab", "babbaa", "baabba", "baaabb", "bababa", "babaab", "baabab" };
private readonly string[] UPC_E_Code1 = { "aaabbb", "aababb", "aabbab", "aabbba", "abaabb", "abbaab", "abbbaa", "ababab", "ababba", "abbaba" };

Expand All @@ -27,93 +28,187 @@
/// </summary>
private string Encode_UPCE()
{
if (RawData.Length != 6 && RawData.Length != 8 && RawData.Length != 12)
Error("EUPCE-1: Invalid data length. (8 or 12 numbers only)");
if (RawData.Length != 6 && RawData.Length != 8 && RawData.Length != 12)
{
Error("EUPCE-1: Invalid data length. (6, 8 or 12 numbers only)");
}

if (!IsNumericOnly(RawData))
Error("EUPCE-2: Numeric only.");
int numberSystem = 0;
//check numeric only
if (!IsNumericOnly(RawData))
{
Error("EUPCE-2: Numeric Data Only");
}

//check for a valid number system
var numberSystem = Int32.Parse(RawData[0].ToString());
if (numberSystem != 0 && numberSystem != 1)
Error("EUPCE-3: Invalid Number System (only 0 & 1 are valid)");
if (RawData.Length == 8)
{
//strip check digit off to recalculate
RawData = RawData.Substring(1, 6);
}

var CheckDigit = Int32.Parse(RawData[RawData.Length - 1].ToString());

//Convert to UPC-E from UPC-A if necessary
if (RawData.Length == 12)
{
var UPCECode = "";

//break apart into components
var manufacturer = RawData.Substring(1, 5);
var productCode = RawData.Substring(6, 5);

if (manufacturer.EndsWith("000") || manufacturer.EndsWith("100") || manufacturer.EndsWith("200") && Int32.Parse(productCode) <= 999)
{
//rule 1
UPCECode += manufacturer.Substring(0, 2); //first two of manufacturer
UPCECode += productCode.Substring(2, 3); //last three of product
UPCECode += manufacturer[2].ToString(); //third of manufacturer
}//if
else if (manufacturer.EndsWith("00") && Int32.Parse(productCode) <= 99)
{
//rule 2
UPCECode += manufacturer.Substring(0, 3); //first three of manufacturer
UPCECode += productCode.Substring(3, 2); //last two of product
UPCECode += "3"; //number 3
}//else if
else if (manufacturer.EndsWith("0") && Int32.Parse(productCode) <= 9)
{
//rule 3
UPCECode += manufacturer.Substring(0, 4); //first four of manufacturer
UPCECode += productCode[4]; //last digit of product
UPCECode += "4"; //number 4
}//else if
else if (!manufacturer.EndsWith("0") && Int32.Parse(productCode) <= 9 && Int32.Parse(productCode) >= 5)
{
//rule 4
UPCECode += manufacturer; //manufacturer
UPCECode += productCode[4]; //last digit of product
}//else if
else
Error("EUPCE-4: Illegal UPC-A entered for conversion. Unable to convert.");
numberSystem = Int16.Parse(RawData[0].ToString());
RawData = convertUPCAToUPCE();
}

RawData = UPCECode;
}//if
int checkDigit = Int16.Parse(calculateCheckDigit(convertUPCEToUPCA(RawData)));

//get encoding pattern
var pattern = "";

if (numberSystem == 0) pattern = UPC_E_Code0[CheckDigit];
else pattern = UPC_E_Code1[CheckDigit];
String pattern = getPattern(checkDigit, numberSystem);

//encode the data
var result = "101";
StringBuilder result = new StringBuilder("101");

var pos = 0;
foreach (var c in pattern)
int pos = 0;
foreach (char c in pattern)
{
var i = Int32.Parse(RawData[pos++].ToString());
int i = Int16.Parse(RawData[pos++].ToString());
if (c == 'a')
{
result += EAN_Code_A[i];
}//if
result.Append(EAN_Code_A[i]);
}
else if (c == 'b')
{
result += EAN_Code_B[i];
}//else if
}//foreach

//guard bars
result += "01010";
result.Append(EAN_Code_B[i]);
}
}

//end bars
result += "1";
//end-guard bars
result.Append("010101");

return result;
return result.ToString();
}//Encode_UPCE

private String getPattern(int checkDigit, int numberSystem)
{
if (numberSystem != 0 && numberSystem != 1)
{
Error("EUPCE-3: Invalid Number System (only 0 & 1 are valid)");
}

String pattern;

if (numberSystem == 0)
{
pattern = UPC_E_Code0[checkDigit];
}
else
{
pattern = UPC_E_Code1[checkDigit];
}

return pattern;
}

private String convertUPCAToUPCE()
{
String UPCECode = "";

//break apart into components
String manufacturer = RawData.Substring(1, 5);
String productCode = RawData.Substring(6, 5);

int numericProductCode = Int32.Parse(productCode);

if ((manufacturer.EndsWith("000") || manufacturer.EndsWith("100") || manufacturer.EndsWith("200")) && numericProductCode <= 999)
{
//rule 1
UPCECode += manufacturer.Substring(0, 2); //first two of manufacturer
UPCECode += productCode.Substring(2, 3); //last three of product
UPCECode += manufacturer[2]; //third of manufacturer
}
else if (manufacturer.EndsWith("00") && numericProductCode <= 99)
{
//rule 2
UPCECode += manufacturer.Substring(0, 3); //first three of manufacturer
UPCECode += productCode.Substring(3, 2); //last two of product
UPCECode += "3"; //number 3
}
else if (manufacturer.EndsWith("0") && numericProductCode <= 9)
{
//rule 3
UPCECode += manufacturer.Substring(0, 4); //first four of manufacturer
UPCECode += productCode[4]; //last digit of product
UPCECode += "4"; //number 4
}
else if (!manufacturer.EndsWith("0") && numericProductCode <= 9 && numericProductCode >= 5)
{
//rule 4
UPCECode += manufacturer; //manufacturer
UPCECode += productCode[4]; //last digit of product
}
else
{
Error("EUPCE-4: Illegal UPC-A entered for conversion. Unable to convert.");
}

return UPCECode;
}

private String convertUPCEToUPCA(String UPCECode)
{
String UPCACode = "0";
if (UPCECode.EndsWith("0") || UPCECode.EndsWith("1") || UPCECode.EndsWith("2"))
{
//rule 1
UPCACode += UPCECode.Substring(0, 2) + UPCECode[5] + "00"; //manufacturer
UPCACode += "00" + UPCECode.Substring(2, 3); //product
}
else if (UPCECode.EndsWith("3"))
{
//rule 2
UPCACode += UPCECode.Substring(0, 3) + "00"; //manufacturer
UPCACode += "000" + UPCECode.Substring(3, 2); //product
}
else if (UPCECode.EndsWith("4"))
{
//rule 3
UPCACode += UPCECode.Substring(0, 4) + "0"; //manufacturer
UPCACode += "0000" + UPCECode[4]; //product
}
else
{
//rule 4
UPCACode += UPCECode.Substring(0, 5); //manufacturer
UPCACode += "0000" + UPCECode[5]; //product
}

return UPCACode;
}

private String calculateCheckDigit(String upcA)
{
int cs = 0;
try
{
//calculate check digit
int sum = 0;

for (int i = 0; i < upcA.Length; i++)
{
int parseInt = Int16.Parse(upcA.Substring(i, 1));
if (i % 2 == 0)
{
sum += parseInt * 3;
}
else
{
sum += parseInt;
}
}

cs = (10 - sum % 10) % 10;
}
catch (Exception ex)

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (6.0.x, ubuntu-latest)

The variable 'ex' is declared but never used

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (6.0.x, ubuntu-latest)

The variable 'ex' is declared but never used

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (6.0.x, ubuntu-latest)

The variable 'ex' is declared but never used

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (6.0.x, windows-latest)

The variable 'ex' is declared but never used

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (6.0.x, windows-latest)

The variable 'ex' is declared but never used

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (6.0.x, windows-latest)

The variable 'ex' is declared but never used

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (7.0.x, ubuntu-latest)

The variable 'ex' is declared but never used

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (7.0.x, ubuntu-latest)

The variable 'ex' is declared but never used

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (7.0.x, ubuntu-latest)

The variable 'ex' is declared but never used

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (7.0.x, windows-latest)

The variable 'ex' is declared but never used

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (7.0.x, windows-latest)

The variable 'ex' is declared but never used

Check warning on line 204 in BarcodeStandard/Symbologies/UPCE.cs

View workflow job for this annotation

GitHub Actions / build (7.0.x, windows-latest)

The variable 'ex' is declared but never used
{
Error("EUPCE-5: Error calculating check digit.");
}

return cs.ToString();
}

#region IBarcode Members

public string Encoded_Value => Encode_UPCE();
Expand Down
25 changes: 25 additions & 0 deletions BarcodeStandardTests/Symbologies/UpcETests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using BarcodeStandard;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace BarcodeStandardTests.Symbologies
{
[TestClass]
public class UpcETests
{
private readonly Barcode _barcode = new()
{
EncodedType = Type.UpcE,
};

[DataTestMethod]
[DataRow("038000000216", "101010000101101110100111001001100110010100111010101")]
[DataRow("654321", "101000010101100010011101011110100110110011001010101")]
[DataRow("06543214", "101000010101100010011101011110100110110011001010101")]
[DataRow("065100004327", "101000010101100010011101011110100110110011001010101")]
public void EncodeBarcode(string data, string expected)
{
_barcode.Encode(data);
Assert.AreEqual(expected, _barcode.EncodedValue, $"{_barcode.EncodedType}");
}
}
}