diff --git a/slownie.go b/slownie.go index c05b42d..3589bb0 100644 --- a/slownie.go +++ b/slownie.go @@ -1,7 +1,16 @@ -package slownie +package main + +import ( + "errors" + "fmt" + "math" + "math/rand" + "strings" + "time" +) var _smallNumbers = []string{ - "jeden", "dwa", "trzy", "cztery", "pięć", "sześć", "siedem", + "zero", "jeden", "dwa", "trzy", "cztery", "pięć", "sześć", "siedem", "osiem", "dziewięć", "dziesięć", "jedenaście", "dwanaście", "trzynaście", "czternaście", "piętnaście", "szesnaście", "siedemnaście", "osiemnaście", "dziewiętnaście"} @@ -12,27 +21,131 @@ var _tens = []string{ "osiemdziesiąt", "dziewięćdziesiąt"} var _hundrets = []string{ - "sto", "dwieście", "trzysta", "czterysta", + "", "sto", "dwieście", "trzysta", "czterysta", "pięćset", "sześćset", "siedemset", "osiemset", "dziewięćset"} -var _thousand = []string{"tysiąc", "tysiące", "tysięcy"} - -var _million = []string{"milion", "miliony", "milionów"} - -func numberToText(input int) string { - +var _bigones = [][]string{ + {"", "", ""}, + {"tysiąc", "tysiące", "tysięcy"}, + {"milion", "miliony", "milionów"}, + {"miliard", "miliardy", "miliardów"}, + {"bilion", "biliony", "bilionów"}, } -func Slownie(input float32) string { - var output string = "" - zloty := int(input) - groszy := int((input - float32(int(input))) * 100) +var _zlotyWord = []string{"złoty", "złote", "złotych"} - if zloty == 0 { - output += "zero" - goto calc_groszy +var _groszyWord = []string{"grosz", "grosze", "groszy"} + +func split(value float64) (int64, int32) { + pre := int64(value) + post := int32(math.Mod((value*100 + 0.5), 100)) + return pre, post +} + +func caseWord(value int) int32 { + single := value % 10 + tens := (value / 10) % 10 + var caseWord int32 + if value == 1 { + caseWord = 0 + } else if tens == 1 && single > 1 { + caseWord = 2 + } else if 2 <= single && single <= 4 { + caseWord = 1 + } else { + caseWord = 2 + } + return caseWord +} + +func threeNumberWord(value int32) string { + single := value % 10 + tens := (value / 10) % 10 + hundrets := (value / 100) % 10 + + var words []string + if hundrets > 0 { + words = append(words, _hundrets[hundrets]) + } + if tens == 1 { + words = append(words, _smallNumbers[single+10]) + } else { + if tens > 0 { + words = append(words, _tens[tens]) + } + if single > 0 { + words = append(words, _smallNumbers[single]) + } + } + return strings.Join(words, " ") +} + +func slownie(value int64) string { + var threePairs []int32 + if value == 0 { + return "zero" + } + for value > 0 { + threePairs = append(threePairs, int32(value%1000)) + value = value / 1000 } -calc_groszy: + var words []string + + for i, n := range threePairs { + if n > 0 { + if i > 0 { + words = append(words, threeNumberWord(n)+" "+_bigones[i][caseWord(int(n))]) + } else { + words = append(words, threeNumberWord(n)) + } + } + } + + //reverse + for i := len(words)/2 - 1; i >= 0; i-- { + opp := len(words) - 1 - i + words[i], words[opp] = words[opp], words[i] + } + + return strings.Join(words, " ") +} + +func someSlownie(value int64, some []string) string { + return slownie(value) + " " + some[caseWord(int(value))] +} + +func kwotaSlownie(input float64) (output string, err error) { + defer func() { + if r := recover(); r != nil { + err = errors.New("too big number") + } + }() + var minusword = "" + if input < 0 { + minusword = "minus " + input = -input + } + zloty, grosze := split(input) + return minusword + someSlownie(zloty, _zlotyWord) + fmt.Sprintf(" %d/100", grosze), nil +} + +func main() { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + + for i := 0; i < 10; i++ { + x := r.Float64() * 10000000000000000 + if kwota, err := kwotaSlownie(x); err == nil { + fmt.Printf("%.2f %s\n", x, kwota) + } else { + fmt.Printf("%.2f %s\n", x, err) + } + } + x := 4831179.50 + if kwota, err := kwotaSlownie(x); err == nil { + fmt.Printf("%.2f %s\n", x, kwota) + } else { + fmt.Printf("%.2f %s\n", x, err) + } }