github.com/mundipagg/boleto-api@v0.0.0-20230620145841-3f9ec742599f/util/math.go (about) 1 package util 2 3 import ( 4 "strconv" 5 ) 6 7 type ModFunc int 8 9 const ( 10 MOD10 ModFunc = 1 + iota 11 MOD11 12 ) 13 14 //mod11 calculate Mod11 DV from string 15 func mod11(valueSequence string, baseNum ...int) int { 16 base := 9 17 digit := 0 18 sum := 0 19 weight := 2 20 21 var values []int 22 23 if baseNum != nil { 24 base = baseNum[0] 25 } 26 27 for _, r := range valueSequence { 28 c := string(r) 29 n, _ := strconv.Atoi(c) 30 values = append(values, n) 31 } 32 for i := len(values) - 1; i >= 0; i-- { 33 sum += values[i] * weight 34 35 if weight < base { 36 weight = weight + 1 37 } else { 38 weight = 2 39 } 40 } 41 digit = 11 - (sum % 11) 42 return digit 43 } 44 45 //mod10 calculate Mod10 DV from string 46 func mod10(valueSequence string) int { 47 sum := 0 48 49 multiplyByTwo := true 50 51 for i := len(valueSequence) - 1; i >= 0; i-- { 52 c := string(valueSequence[i]) 53 54 num, _ := strconv.Atoi(c) 55 56 if multiplyByTwo { 57 num = num * 2 58 sum += (num / 10) + (num % 10) 59 multiplyByTwo = false 60 } else { 61 sum += num 62 multiplyByTwo = true 63 } 64 } 65 66 remainder := sum % 10 67 68 if remainder == 0 { 69 return 0 70 } 71 72 return 10 - remainder 73 } 74 75 //OurNumberDv calculate DV from OurNumber 76 func OurNumberDv(valueSequence string, modFunc ModFunc, base ...int) string { 77 digit := 0 78 79 if modFunc == MOD10 { 80 digit = mod10(valueSequence) 81 } else if modFunc == MOD11 && base != nil { 82 digit = mod11(valueSequence, base[0]) 83 } else if modFunc == MOD11 { 84 digit = mod11(valueSequence) 85 } 86 87 if base != nil && digit == 10 { 88 return "P" 89 } else if digit > 9 { 90 digit = 0 91 } 92 return strconv.Itoa(digit) 93 } 94 95 //BarcodeDv calculate DV from barcode 96 func BarcodeDv(valueSequence string) string { 97 digit := mod11(valueSequence) 98 if digit <= 1 || digit > 9 { 99 digit = 1 100 } 101 return strconv.Itoa(digit) 102 }