Files
farmcal/cmd/server/domain.go

123 lines
3.1 KiB
Go

package main
import (
"errors"
"fmt"
"sort"
"strconv"
"strings"
)
func buildPlanningTargets(fields []Field) []PlanningTarget {
groupMap := make(map[string][]Field)
var out []PlanningTarget
for _, f := range fields {
if !f.Owned {
continue
}
if f.GroupKey == "" {
out = append(out, PlanningTarget{Ref: fmt.Sprintf("f:%d", f.ID), Label: fieldLabel(f)})
continue
}
groupMap[f.GroupKey] = append(groupMap[f.GroupKey], f)
}
groupKeys := make([]string, 0, len(groupMap))
for k := range groupMap {
groupKeys = append(groupKeys, k)
}
sort.Strings(groupKeys)
for _, k := range groupKeys {
members := groupMap[k]
sort.Slice(members, func(i, j int) bool { return members[i].Number < members[j].Number })
name := members[0].GroupName
if strings.TrimSpace(name) == "" {
name = autoGroupName(members)
}
out = append(out, PlanningTarget{Ref: "g:" + k, Label: name})
}
sort.Slice(out, func(i, j int) bool { return out[i].Label < out[j].Label })
return out
}
func buildFieldGroups(fields []Field) []FieldGroup {
groupMap := make(map[string][]Field)
for _, f := range fields {
if strings.TrimSpace(f.GroupKey) == "" {
continue
}
groupMap[f.GroupKey] = append(groupMap[f.GroupKey], f)
}
var out []FieldGroup
for key, members := range groupMap {
sort.Slice(members, func(i, j int) bool { return members[i].Number < members[j].Number })
nums := make([]string, 0, len(members))
for _, m := range members {
nums = append(nums, strconv.Itoa(m.Number))
}
name := members[0].GroupName
if strings.TrimSpace(name) == "" {
name = autoGroupName(members)
}
out = append(out, FieldGroup{Key: key, Name: name, Numbers: strings.Join(nums, "+")})
}
sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
return out
}
func autoGroupName(fields []Field) string {
sort.Slice(fields, func(i, j int) bool { return fields[i].Number < fields[j].Number })
parts := make([]string, 0, len(fields))
for _, f := range fields {
parts = append(parts, strconv.Itoa(f.Number))
}
return "Feld " + strings.Join(parts, "+")
}
func fieldLabel(f Field) string {
base := fmt.Sprintf("Feld %d", f.Number)
if strings.TrimSpace(f.Name) != "" {
base += " (" + f.Name + ")"
}
return base
}
func monthOptions() []MonthOption {
out := make([]MonthOption, 0, 12)
for i, m := range monthNames {
out = append(out, MonthOption{Value: i + 1, Label: m})
}
return out
}
func monthInWindow(month, start, end int) bool {
if start <= end {
return month >= start && month <= end
}
return month >= start || month <= end
}
func wrapMonth(v int) int {
m := v % 12
if m == 0 {
return 12
}
return m
}
func validateCropInput(name string, start, end, grow, regrowCycles int) error {
if name == "" {
return errors.New("Name der Feldfrucht fehlt")
}
if start < 1 || start > 12 || end < 1 || end > 12 {
return errors.New("Aussaatmonat muss 1-12 sein")
}
if grow < 1 || grow > 24 {
return errors.New("Wachstumsdauer muss 1-24 sein")
}
if regrowCycles < 0 || regrowCycles > 120 {
return errors.New("Regrow-Zyklen muessen 0-120 sein")
}
return nil
}