143 lines
2.9 KiB
Go
143 lines
2.9 KiB
Go
package entity
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
var DefaultLocale = DimensionLocalRU
|
|
|
|
type DimensionLocale uint8
|
|
|
|
const (
|
|
DimensionLocalUnspecified DimensionLocale = iota
|
|
DimensionLocalRU
|
|
|
|
dimensionLocalEnd
|
|
)
|
|
|
|
type DimensionKind uint8
|
|
|
|
func (k DimensionKind) GetPos() float64 {
|
|
switch k {
|
|
case DimensionKindMilimeter:
|
|
return 1
|
|
case DimensionKindCentimeter:
|
|
return 10
|
|
case DimensionKindMeter:
|
|
return 1000
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func (k DimensionKind) String() string {
|
|
m := getLocaleKindToStringMap()[DefaultLocale]
|
|
return m[k]
|
|
}
|
|
|
|
const (
|
|
DimensionKindUnspecified DimensionKind = iota
|
|
DimensionKindMilimeter
|
|
DimensionKindCentimeter
|
|
DimensionKindMeter
|
|
)
|
|
|
|
type Dimension struct {
|
|
Value float64
|
|
Kind DimensionKind
|
|
}
|
|
|
|
func (d Dimension) MarshalText() ([]byte, error) {
|
|
value := strconv.FormatFloat(d.Value, 'f', 4, 64) + " " + d.Kind.String()
|
|
return []byte(value), nil
|
|
}
|
|
|
|
func (d *Dimension) UnmarshalText(data []byte) (err error) {
|
|
*d, err = ParseDimention(string(data), DefaultLocale)
|
|
return err
|
|
}
|
|
|
|
func (d Dimension) AdjustTo(kind DimensionKind) Dimension {
|
|
from := d.Kind.GetPos()
|
|
to := kind.GetPos()
|
|
|
|
switch {
|
|
case from < to:
|
|
mult := to / from
|
|
return Dimension{
|
|
Kind: kind,
|
|
Value: d.Value / float64(mult),
|
|
}
|
|
case from > to:
|
|
mult := from / to
|
|
return Dimension{
|
|
Kind: kind,
|
|
Value: d.Value * float64(mult),
|
|
}
|
|
}
|
|
|
|
return d
|
|
}
|
|
|
|
func ParseDimention(value string, locale DimensionLocale) (Dimension, error) {
|
|
switch locale {
|
|
case DimensionLocalRU:
|
|
default:
|
|
return Dimension{}, SimpleError("unknown locale for parse")
|
|
}
|
|
|
|
dimensionStrToKind := getLocaleToKindMap()[locale]
|
|
lastSpaceIdx := strings.LastIndex(value, " ")
|
|
if lastSpaceIdx == -1 {
|
|
return Dimension{}, SimpleError("expected 2 values after split for value " + value)
|
|
}
|
|
|
|
var splitted [2]string
|
|
splitted[0] = strings.ReplaceAll(value[:lastSpaceIdx], " ", "")
|
|
splitted[1] = value[lastSpaceIdx+1:]
|
|
|
|
var out Dimension
|
|
var ok bool
|
|
out.Kind, ok = dimensionStrToKind[splitted[1]]
|
|
if !ok {
|
|
return Dimension{}, SimpleError("dimension map not found for kind " + splitted[1])
|
|
}
|
|
|
|
var err error
|
|
out.Value, err = strconv.ParseFloat(splitted[0], 64)
|
|
if err != nil {
|
|
return Dimension{}, fmt.Errorf("parsing value: %w", err)
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
func NewMilimeterDimension(value float64) Dimension {
|
|
return Dimension{
|
|
Value: value,
|
|
Kind: DimensionKindMilimeter,
|
|
}
|
|
}
|
|
|
|
func getLocaleToKindMap() map[DimensionLocale]map[string]DimensionKind {
|
|
return map[DimensionLocale]map[string]DimensionKind{
|
|
DimensionLocalRU: {
|
|
"мм": DimensionKindMilimeter,
|
|
"см": DimensionKindCentimeter,
|
|
"м": DimensionKindMeter,
|
|
},
|
|
}
|
|
}
|
|
|
|
func getLocaleKindToStringMap() map[DimensionLocale]map[DimensionKind]string {
|
|
return map[DimensionLocale]map[DimensionKind]string{
|
|
DimensionLocalRU: {
|
|
DimensionKindMilimeter: "мм",
|
|
DimensionKindCentimeter: "см",
|
|
DimensionKindMeter: "м",
|
|
},
|
|
}
|
|
}
|