Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split unit systems per type #195

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions frontends/ascii-art-table.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import (
type aatConfig struct {
coords bool
monochrome bool
unit iface.UnitSystem
units iface.Units
}

//TODO: replace s parameter with printf interface?
// TODO: replace s parameter with printf interface?
func aatPad(s string, mustLen int) (ret string) {
ansiEsc := regexp.MustCompile("\033.*?m")
ret = s
Expand Down Expand Up @@ -61,11 +61,11 @@ func (c *aatConfig) formatTemp(cond iface.Cond) string {
break
}
}
t, _ := c.unit.Temp(temp)
t, _ := c.units.ConvertTemp(temp)
return fmt.Sprintf("\033[38;5;%03dm%d\033[0m", col, int(t))
}

_, u := c.unit.Temp(0.0)
_, u := c.units.ConvertTemp(0.0)

if cond.TempC == nil {
return aatPad(fmt.Sprintf("? %s", u), 15)
Expand Down Expand Up @@ -104,11 +104,11 @@ func (c *aatConfig) formatWind(cond iface.Cond) string {
}
}

s, _ := c.unit.Speed(spdKmph)
s, _ := c.units.ConvertSpeed(spdKmph)
return fmt.Sprintf("\033[38;5;%03dm%d\033[0m", col, int(s))
}

_, u := c.unit.Speed(0.0)
_, u := c.units.ConvertSpeed(0.0)

if cond.WindspeedKmph == nil {
return aatPad(windDir(cond.WinddirDegree), 15)
Expand All @@ -128,13 +128,13 @@ func (c *aatConfig) formatVisibility(cond iface.Cond) string {
if cond.VisibleDistM == nil {
return aatPad("", 15)
}
v, u := c.unit.Distance(*cond.VisibleDistM)
v, u := c.units.ConvertDistance(*cond.VisibleDistM)
return aatPad(fmt.Sprintf("%d %s", int(v), u), 15)
}

func (c *aatConfig) formatRain(cond iface.Cond) string {
if cond.PrecipM != nil {
v, u := c.unit.Distance(*cond.PrecipM)
v, u := c.units.ConvertDistance(*cond.PrecipM)
u += "/h" // it's the same in all unit systems
if cond.ChanceOfRainPercent != nil {
return aatPad(fmt.Sprintf("%.1f %s | %d%%", v, u, *cond.ChanceOfRainPercent), 15)
Expand Down Expand Up @@ -367,8 +367,8 @@ func (c *aatConfig) Setup() {
flag.BoolVar(&c.monochrome, "aat-monochrome", false, "aat-frontend: Monochrome output")
}

func (c *aatConfig) Render(r iface.Data, unitSystem iface.UnitSystem) {
c.unit = unitSystem
func (c *aatConfig) Render(r iface.Data, units iface.Units) {
c.units = units

fmt.Printf("Weather for %s%s\n\n", r.Location, c.formatGeo(r.GeoLoc))
stdout := colorable.NewColorableStdout()
Expand Down
28 changes: 14 additions & 14 deletions frontends/emoji.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
)

type emojiConfig struct {
unit iface.UnitSystem
units iface.Units
}

func (c *emojiConfig) formatTemp(cond iface.Cond) string {
Expand All @@ -34,11 +34,11 @@ func (c *emojiConfig) formatTemp(cond iface.Cond) string {
break
}
}
t, _ := c.unit.Temp(temp)
t, _ := c.units.ConvertTemp(temp)
return fmt.Sprintf("\033[38;5;%03dm%d\033[0m", col, int(t))
}

_, u := c.unit.Temp(0.0)
_, u := c.units.ConvertTemp(0.0)

if cond.TempC == nil {
return aatPad(fmt.Sprintf("? %s", u), 12)
Expand Down Expand Up @@ -94,19 +94,19 @@ func (c *emojiConfig) formatCond(cur []string, cond iface.Cond, current bool) (r
}

func (c *emojiConfig) printAstro(astro iface.Astro) {
// print sun astronomy data if present
// print sun astronomy data if present
if astro.Sunrise != astro.Sunset {
// half the distance between sunrise and sunset
noon_distance := time.Duration(int64(float32(astro.Sunset.UnixNano() - astro.Sunrise.UnixNano()) * 0.5))
// time for solar noon
noon := astro.Sunrise.Add(noon_distance)
// half the distance between sunrise and sunset
noon_distance := time.Duration(int64(float32(astro.Sunset.UnixNano()-astro.Sunrise.UnixNano()) * 0.5))
// time for solar noon
noon := astro.Sunrise.Add(noon_distance)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These seem like non standard indents. Please don't reformat code in PRs unless you are changing the line. This makes the diff harder to read.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I know, not the best practice. Sorry. But go extensions just format the whole file. I will remove it


// the actual print statement
fmt.Printf("🌞 rise↗ %s noon↑ %s set↘ %s\n", astro.Sunrise.Format(time.Kitchen), noon.Format(time.Kitchen), astro.Sunset.Format(time.Kitchen))
// the actual print statement
fmt.Printf("🌞 rise↗ %s noon↑ %s set↘ %s\n", astro.Sunrise.Format(time.Kitchen), noon.Format(time.Kitchen), astro.Sunset.Format(time.Kitchen))
}
// print moon astronomy data if present
// print moon astronomy data if present
if astro.Moonrise != astro.Moonset {
fmt.Printf("🌚 rise↗ %s set↘ %s\n", astro.Moonrise.Format(time.Kitchen), astro.Moonset)
fmt.Printf("🌚 rise↗ %s set↘ %s\n", astro.Moonrise.Format(time.Kitchen), astro.Moonset)
}
}

Expand Down Expand Up @@ -159,8 +159,8 @@ func (c *emojiConfig) printDay(day iface.Day) (ret []string) {
func (c *emojiConfig) Setup() {
}

func (c *emojiConfig) Render(r iface.Data, unitSystem iface.UnitSystem) {
c.unit = unitSystem
func (c *emojiConfig) Render(r iface.Data, units iface.Units) {
c.units = units

fmt.Printf("Weather for %s\n\n", r.Location)
stdout := colorable.NewColorableStdout()
Expand Down
2 changes: 1 addition & 1 deletion frontends/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func (c *jsnConfig) Setup() {
flag.BoolVar(&c.noIndent, "jsn-no-indent", false, "json frontend: do not indent the output")
}

func (c *jsnConfig) Render(r iface.Data, unitSystem iface.UnitSystem) {
func (c *jsnConfig) Render(r iface.Data, units iface.Units) {
var b []byte
var err error
if c.noIndent {
Expand Down
24 changes: 12 additions & 12 deletions frontends/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (
)

type mdConfig struct {
coords bool
unit iface.UnitSystem
coords bool
units iface.Units
}

func mdPad(s string, mustLen int) (ret string) {
Expand All @@ -39,11 +39,11 @@ func mdPad(s string, mustLen int) (ret string) {

func (c *mdConfig) formatTemp(cond iface.Cond) string {

cvtUnits := func (temp float32) string {
t, _ := c.unit.Temp(temp)
cvtUnits := func(temp float32) string {
t, _ := c.units.ConvertTemp(temp)
return fmt.Sprintf("%d", int(t))
}
_, u := c.unit.Temp(0.0)
_, u := c.units.ConvertTemp(0.0)

if cond.TempC == nil {
return mdPad(fmt.Sprintf("? %s", u), 15)
Expand All @@ -66,11 +66,11 @@ func (c *mdConfig) formatWind(cond iface.Cond) string {
return arrows[((*deg+22)%360)/45]
}
color := func(spdKmph float32) string {
s, _ := c.unit.Speed(spdKmph)
s, _ := c.units.ConvertSpeed(spdKmph)
return fmt.Sprintf("| %d ", int(s))
}

_, u := c.unit.Speed(0.0)
_, u := c.units.ConvertSpeed(0.0)

if cond.WindspeedKmph == nil {
return mdPad(windDir(cond.WinddirDegree), 15)
Expand All @@ -90,13 +90,13 @@ func (c *mdConfig) formatVisibility(cond iface.Cond) string {
if cond.VisibleDistM == nil {
return mdPad("", 15)
}
v, u := c.unit.Distance(*cond.VisibleDistM)
v, u := c.units.ConvertDistance(*cond.VisibleDistM)
return mdPad(fmt.Sprintf("%d %s", int(v), u), 15)
}

func (c *mdConfig) formatRain(cond iface.Cond) string {
if cond.PrecipM != nil {
v, u := c.unit.Distance(*cond.PrecipM)
v, u := c.units.ConvertDistance(*cond.PrecipM)
u += "/h" // it's the same in all unit systems
if cond.ChanceOfRainPercent != nil {
return mdPad(fmt.Sprintf("%.1f %s | %d%%", v, u, *cond.ChanceOfRainPercent), 15)
Expand Down Expand Up @@ -197,7 +197,7 @@ func (c *mdConfig) printDay(day iface.Day) (ret []string) {
}
dateFmt := day.Date.Format("Mon Jan 02")
ret = append([]string{
"\n### Forecast for "+dateFmt+ "\n",
"\n### Forecast for " + dateFmt + "\n",
"| Morning | Noon | Evening | Night |",
"| ------------------------- | ------------------------- | ------------------------- | ------------------------- |"},
ret...)
Expand All @@ -208,8 +208,8 @@ func (c *mdConfig) Setup() {
flag.BoolVar(&c.coords, "md-coords", false, "md-frontend: Show geo coordinates")
}

func (c *mdConfig) Render(r iface.Data, unitSystem iface.UnitSystem) {
c.unit = unitSystem
func (c *mdConfig) Render(r iface.Data, units iface.Units) {
c.units = units
fmt.Printf("## Weather for %s%s\n\n", r.Location, c.formatGeo(r.GeoLoc))
stdout := colorable.NewNonColorable(os.Stdout)
out := c.formatCond(make([]string, 5), r.Current, true)
Expand Down
122 changes: 99 additions & 23 deletions iface/iface.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,59 +108,135 @@ type Data struct {
GeoLoc *LatLon
}

type UnitSystem int
type Unit int

const (
UnitsMetric UnitSystem = iota
UnitsImperial
UnitsSi
UnitsMetricMs
Celsius Unit = iota
Fahrenheit
Kelvin
Kmh
Mph
Ms
Beaufort
Metric
Imperial
)

func (u UnitSystem) Temp(tempC float32) (res float32, unit string) {
if u == UnitsMetric || u == UnitsMetricMs {
type Units struct {
Temp Unit
Speed Unit
Distance Unit
}

func NewUnits(tempUnit, speedUnit, distanceUnit string) Units {
units := Units{
Temp: Celsius,
Speed: Kmh,
Distance: Metric,
}

unitMap := map[string]Unit{
"celsius": Celsius,
"fahrenheit": Fahrenheit,
"kelvin": Kelvin,
"kmh": Kmh,
"mph": Mph,
"ms": Ms,
"beaufort": Beaufort,
"metric": Metric,
"imperial": Imperial,
}

if unit, ok := unitMap[tempUnit]; ok {
units.Temp = unit
}
if unit, ok := unitMap[speedUnit]; ok {
units.Speed = unit
}
if unit, ok := unitMap[distanceUnit]; ok {
units.Distance = unit
}

return units
}

func (u Units) ConvertTemp(tempC float32) (res float32, unit string) {
switch u.Temp {
case Celsius:
return tempC, "°C"
} else if u == UnitsImperial {
case Fahrenheit:
return tempC*1.8 + 32, "°F"
} else if u == UnitsSi {
return tempC + 273.16, "°K"
case Kelvin:
return tempC + 273.16, "K"
}
log.Fatalln("Unknown unit system:", u)
log.Fatalln("Unknown temperature unit:", u)
return
}

func (u UnitSystem) Speed(spdKmph float32) (res float32, unit string) {
if u == UnitsMetric {
func (u Units) ConvertSpeed(spdKmph float32) (res float32, unit string) {
switch u.Speed {
case Kmh:
return spdKmph, "km/h"
} else if u == UnitsImperial {
case Mph:
return spdKmph / 1.609, "mph"
} else if u == UnitsSi || u == UnitsMetricMs {
case Ms:
return spdKmph / 3.6, "m/s"
case Beaufort:
switch {
case spdKmph < 1:
return 0, "Bft"
case spdKmph < 6:
return 1, "Bft"
case spdKmph < 12:
return 2, "Bft"
case spdKmph < 20:
return 3, "Bft"
case spdKmph < 29:
return 4, "Bft"
case spdKmph < 39:
return 5, "Bft"
case spdKmph < 50:
return 6, "Bft"
case spdKmph < 62:
return 7, "Bft"
case spdKmph < 75:
return 8, "Bft"
case spdKmph < 89:
return 9, "Bft"
case spdKmph < 103:
return 10, "Bft"
case spdKmph < 118:
return 11, "Bft"
default:
return 12, "Bft"
}
}
log.Fatalln("Unknown unit system:", u)

log.Fatalln("Unknown speed unit:", u)
return
}

func (u UnitSystem) Distance(distM float32) (res float32, unit string) {
if u == UnitsMetric || u == UnitsSi || u == UnitsMetricMs {
func (u Units) ConvertDistance(distM float32) (res float32, unit string) {
switch u.Distance {
case Metric:
if distM < 1 {
return distM * 1000, "mm"
} else if distM < 1000 {
return distM, "m"
} else {
return distM / 1000, "km"
}
} else if u == UnitsImperial {
case Imperial:
res, unit = distM/0.0254, "in"
if res < 3*12 { // 1yd = 3ft, 1ft = 12in
if res < 3*12 {
return
} else if res < 8*10*22*36 { //1mi = 8fur, 1fur = 10ch, 1ch = 22yd
} else if res < 8*10*22*36 {
return res / 36, "yd"
} else {
return res / 8 / 10 / 22 / 36, "mi"
}
}
log.Fatalln("Unknown unit system:", u)
log.Fatalln("Unknown distance unit:", u)
return
}

Expand All @@ -171,7 +247,7 @@ type Backend interface {

type Frontend interface {
Setup()
Render(weather Data, unitSystem UnitSystem)
Render(weather Data, unitSystem Units)
}

var (
Expand Down
Loading