Correct typos related to Angle naming and update calculations for start and end ranges in direction mapping. This ensures accurate and valid directional values are used in the application.
135 lines
3.8 KiB
Go
135 lines
3.8 KiB
Go
// SPDX-FileCopyrightText: 2023 Winni Neessen <wn@neessen.dev>
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package meteologix
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
// DirectionMinAngle is the minimum angel for a direction
|
|
DirectionMinAngle = 0
|
|
// DirectionMaxAngle is the maximum angel for a direction
|
|
DirectionMaxAngle = 360
|
|
)
|
|
|
|
// WindDirAbbrMap is a map to associate a wind direction degree value with
|
|
// the abbreviated direction string
|
|
var WindDirAbbrMap = map[float64]string{
|
|
0: "N", 11.25: "NbE", 22.5: "NNE", 33.75: "NEbN", 45: "NE", 56.25: "NEbE",
|
|
67.5: "ENE", 78.75: "EbN", 90: "E", 101.25: "EbS", 112.5: "ESE", 123.75: "SEbE",
|
|
135: "SE", 146.25: "SEbS", 157.5: "SSE", 168.75: "SbE", 180: "S",
|
|
191.25: "SbW", 202.5: "SSW", 213.75: "SWbS", 225: "SW", 236.25: "SWbW",
|
|
247.5: "WSW", 258.75: "WbS", 270: "W", 281.25: "WbN", 292.5: "WNW",
|
|
303.75: "NWbW", 315: "NW", 326.25: "NWbN", 337.5: "NNW", 348.75: "NbW",
|
|
}
|
|
|
|
// WindDirFullMap is a map to associate a wind direction degree value with
|
|
// the full direction string
|
|
var WindDirFullMap = map[float64]string{
|
|
0: "North", 11.25: "North by East", 22.5: "North-Northeast",
|
|
33.75: "Northeast by North", 45: "Northeast", 56.25: "Northeast by East",
|
|
67.5: "East-Northeast", 78.75: "East by North", 90: "East",
|
|
101.25: "East by South", 112.5: "East-Southeast", 123.75: "Southeast by East",
|
|
135: "Southeast", 146.25: "Southeast by South", 157.5: "South-Southeast",
|
|
168.75: "South by East", 180: "South", 191.25: "South by West",
|
|
202.5: "South-Southwest", 213.75: "Southwest by South", 225: "Southwest",
|
|
236.25: "Southwest by West", 247.5: "West-Southwest", 258.75: "West by South",
|
|
270: "West", 281.25: "West by North", 292.5: "West-Northwest",
|
|
303.75: "Northwest by West", 315: "Northwest", 326.25: "Northwest by North",
|
|
337.5: "North-Northwest", 348.75: "North by West",
|
|
}
|
|
|
|
// Direction is a type wrapper of an WeatherData for holding directional
|
|
// values in WeatherData
|
|
type Direction WeatherData
|
|
|
|
// IsAvailable returns true if an Direction value was
|
|
// available at time of query
|
|
func (d Direction) IsAvailable() bool {
|
|
return !d.na
|
|
}
|
|
|
|
// DateTime returns true if an Direction value was
|
|
// available at time of query
|
|
func (d Direction) DateTime() time.Time {
|
|
return d.dt
|
|
}
|
|
|
|
// Value returns the float64 value of an Direction in degrees
|
|
// If the Direction is not available in the WeatherData
|
|
// Vaule will return math.NaN instead.
|
|
func (d Direction) Value() float64 {
|
|
if d.na {
|
|
return math.NaN()
|
|
}
|
|
return d.fv
|
|
}
|
|
|
|
// String satisfies the fmt.Stringer interface for the Direction type
|
|
func (d Direction) String() string {
|
|
return fmt.Sprintf("%.0f°", d.fv)
|
|
}
|
|
|
|
// Source returns the Source of a Direction
|
|
// If the Source is not available it will return SourceUnknown
|
|
func (d Direction) Source() Source {
|
|
return d.s
|
|
}
|
|
|
|
// Direction returns the abbreviation string for a given Direction type
|
|
func (d Direction) Direction() string {
|
|
if d.fv < DirectionMinAngle || d.fv > DirectionMaxAngle {
|
|
return ErrUnsupportedDirection
|
|
}
|
|
if ds, ok := WindDirAbbrMap[d.fv]; ok {
|
|
return ds
|
|
}
|
|
return findDirection(d.fv, WindDirAbbrMap)
|
|
}
|
|
|
|
// DirectionFull returns the full string for a given Direction type
|
|
func (d Direction) DirectionFull() string {
|
|
if d.fv < DirectionMinAngle || d.fv > DirectionMaxAngle {
|
|
return ErrUnsupportedDirection
|
|
}
|
|
if ds, ok := WindDirFullMap[d.fv]; ok {
|
|
return ds
|
|
}
|
|
return findDirection(d.fv, WindDirFullMap)
|
|
}
|
|
|
|
// findDirection takes a Direction and tries to estimate the nearest
|
|
// direction string from a map
|
|
func findDirection(v float64, m map[float64]string) string {
|
|
ks := make([]float64, 0, len(m))
|
|
for k := range m {
|
|
ks = append(ks, k)
|
|
}
|
|
sort.Float64s(ks)
|
|
|
|
sv := 0.0
|
|
ev := 0.0
|
|
for i := range ks {
|
|
if v > ks[i] {
|
|
sv = ks[i]
|
|
continue
|
|
}
|
|
if v < ks[i] {
|
|
ev = ks[i]
|
|
break
|
|
}
|
|
}
|
|
sr := v - sv
|
|
er := ev - v
|
|
if er > sr {
|
|
return m[sv]
|
|
}
|
|
return m[ev]
|
|
}
|