slownie/slownie.go
2019-10-07 15:08:41 +02:00

147 lines
3.3 KiB
Go

package slownie
import (
"errors"
"fmt"
"math"
"strings"
)
var _smallNumbers = []string{
"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"}
var _tens = []string{
"", "", "dwadzieścia", "trzydzieści", "czterdzieści",
"pięćdziesiąt", "sześćdziesiąt", "siedemdziesiąt",
"osiemdziesiąt", "dziewięćdziesiąt"}
var _hundrets = []string{
"", "sto", "dwieście", "trzysta", "czterysta",
"pięćset", "sześćset", "siedemset", "osiemset",
"dziewięćset"}
var _bigones = [][]string{
{"", "", ""},
{"tysiąc", "tysiące", "tysięcy"},
{"milion", "miliony", "milionów"},
{"miliard", "miliardy", "miliardów"},
{"bilion", "biliony", "bilionów"},
}
var _zlotyWord = []string{"złoty", "złote", "złotych"}
var _groszyWord = []string{"grosz", "grosze", "groszy"}
func round(num float64) int {
return int(num + math.Copysign(0.5, num))
}
func toFixed(num float64, precision int) float64 {
output := math.Pow(10, float64(precision))
return float64(round(num*output)) / output
}
func split(value float64) (int64, int64) {
pre := int64(value)
// post := int32((value - float64(pre)) * 100)
post := int64((round(value*100) % 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
}
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))]
}
// KwotaSlownie - return value in words of zloty and groszy
func KwotaSlownie(input float64, numbers bool) (output string, err error) {
input = toFixed(input, 2)
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)
if numbers {
return minusword + someSlownie(zloty, _zlotyWord) + fmt.Sprintf(" %02d/100", grosze), nil
}
return minusword + someSlownie(zloty, _zlotyWord) + " " + someSlownie(grosze, _groszyWord), nil
}