package main import ( "bufio" "fmt" "os" "regexp" "strconv" "strings" "github.com/pterm/pterm" "github.com/schollz/progressbar/v3" ) func main() { // Set Welcome Header // pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgCyan)).WithTextStyle(pterm.NewStyle(pterm.FgBlack)).Println("Welcome to Checkdigit Calculator") pterm.DefaultSection.Printfln(pterm.Cyan("Welcome to Check Digit Calculator")) // Check what directory the commandline is on when the program is launched. directory, err := os.Getwd() Error(err) // Get name of file to be processed. args := os.Args[1:] var input string if len(args) > 0 { input = args[0] } else { pterm.Printf(pterm.LightGreen("What is the name of the file in this directory?: ")) reader := bufio.NewReader(os.Stdin) input, err = reader.ReadString('\n') Error(err) } // Create upcs array and push all upc strings into it input = strings.TrimSpace(input) file, err := os.Open(input) Error(err) var upcs []string scanner := bufio.NewScanner(file) for scanner.Scan() { upcs = append(upcs, scanner.Text()) } err = file.Close() Error(err) if scanner.Err() != nil { fmt.Println(scanner.Err()) } // Create gtins array that will eventually be returned var gtins []string // Using regex compile so the program stays fast regex, err := regexp.Compile("[^0-9]") Error(err) checkBar := progressbar.NewOptions(len(upcs), progressbar.OptionEnableColorCodes(true), progressbar.OptionSetDescription("[cyan][1/2][reset] Calculating Check Digits..."), progressbar.OptionUseANSICodes(true), progressbar.OptionSetTheme(progressbar.Theme{ Saucer: "[green]=[reset]", SaucerHead: "[green]>[reset]", SaucerPadding: " ", BarStart: "[", BarEnd: "]", })) for _, upc := range upcs { upcLength := len(upc) // Check Digit Formula // Take all the digits in odd positions, add them and multiply by three // Take all the digits in even positions (except for the last one) and add to the number you got above // Divide that number by 10 and take the remainder // If the remainder is not 0, subtract it from 10 // // 12/8/2023: New git updates from https://www.gs1.org/services/how-calculate-check-digit-manually oddNumber := 0 evenNumber := 0 var remainder int checkForNonNumber := regex.MatchString(upc) if checkForNonNumber { gtins = append(gtins, upc) continue } if upcLength < 8 { gtins = append(gtins, "Cannot process upcs less than 8 digits") continue } if upcLength > 17 { gtins = append(gtins, "Invalid barcode") continue } if upcLength%2 == 0 { for i, num := range upc { if i%2 != 0 { convertedOddNumber, err := strconv.Atoi(string(num)) Error(err) convertedOddNumber = convertedOddNumber * 3 oddNumber += convertedOddNumber } else { if upcLength-1 > i { convertedEvenNumber, err := strconv.Atoi(string(num)) Error(err) evenNumber += convertedEvenNumber } } } } else { for i, num := range upc { if i%2 == 0 { convertedOddNumber, err := strconv.Atoi(string(num)) Error(err) convertedOddNumber = convertedOddNumber * 3 oddNumber += convertedOddNumber } else { if upcLength-1 > i { convertedEvenNumber, err := strconv.Atoi(string(num)) Error(err) evenNumber += convertedEvenNumber } } } } remainder = (oddNumber + evenNumber) % 10 if remainder != 0 { remainder = 10 - remainder } remainderString := strconv.Itoa(remainder) gtins = append(gtins, upc+remainderString) checkBar.Add(1) } answerBar := progressbar.NewOptions(len(gtins), progressbar.OptionEnableColorCodes(true), progressbar.OptionSetDescription("[cyan][2/2][reset] Writing answers into file..."), progressbar.OptionUseANSICodes(true), progressbar.OptionClearOnFinish(), progressbar.OptionSetTheme(progressbar.Theme{ Saucer: "[green]=[reset]", SaucerHead: "[green]>[reset]", SaucerPadding: " ", BarStart: "[", BarEnd: "]", })) // Check if answer.txt already exists and if so, delete it if _, err := os.Stat(directory + "/answer.txt"); err == nil { e := os.Remove(directory + "/answer.txt") Error(e) } // Create new answer.txt answerFile, err := os.Create(directory + "/answer.txt") Error(err) defer answerFile.Close() // Fill the answers.txt file for _, gtin := range gtins { _, err := answerFile.WriteString(gtin + "\n") Error(err) answerBar.Add(1) } // Print Success message and exit pterm.Printf("\n") pterm.Success.Println("The answer.txt file has been successfully generated with check digits.") os.Exit(0) }