handle dimension
This commit is contained in:
142
internal/entity/dimension.go
Normal file
142
internal/entity/dimension.go
Normal file
@ -0,0 +1,142 @@
|
||||
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: "м",
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user