180 lines
4.7 KiB
Go
180 lines
4.7 KiB
Go
package output
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// ---------------------------------------------------------------------
|
|
// SKYFEED ASCII LOGO
|
|
// ---------------------------------------------------------------------
|
|
|
|
var SkyfeedLogoLines = []string{
|
|
" ______ ___ __",
|
|
" / __/ /____ __/ _/__ ___ ___/ /",
|
|
" _\\ \\/ '_/ // / _/ -_) -_) _ / ",
|
|
"/___/_/\\_\\\\_, /_/ \\__/\\__/\\_,_/ ",
|
|
" /___/ ",
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// ANSI HELPERS
|
|
// ---------------------------------------------------------------------
|
|
|
|
func ansi(r, g, b int) string {
|
|
return fmt.Sprintf("\033[38;2;%d;%d;%dm", r, g, b)
|
|
}
|
|
|
|
func reset() string {
|
|
return "\033[0m"
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// TIME-OF-DAY PALETTES (MATCHING PYTHON LOGIC)
|
|
// ---------------------------------------------------------------------
|
|
//
|
|
// Python version used a function _get_time_phase() which returned
|
|
// two hex colours: primary (top) and secondary (bottom).
|
|
// We reproduce that behaviour exactly here.
|
|
//
|
|
|
|
type PhaseColors struct {
|
|
Primary [3]int // top colour
|
|
Secondary [3]int // bottom colour
|
|
}
|
|
|
|
func getTimePhaseColors() PhaseColors {
|
|
h := time.Now().Hour()
|
|
|
|
switch {
|
|
case h >= 5 && h < 8:
|
|
// Dawn
|
|
return PhaseColors{
|
|
Primary: [3]int{255, 180, 120},
|
|
Secondary: [3]int{140, 100, 160},
|
|
}
|
|
case h >= 8 && h < 17:
|
|
// Noon
|
|
return PhaseColors{
|
|
Primary: [3]int{70, 150, 255},
|
|
Secondary: [3]int{120, 190, 255},
|
|
}
|
|
case h >= 17 && h < 20:
|
|
// Sunset
|
|
return PhaseColors{
|
|
Primary: [3]int{255, 110, 60},
|
|
Secondary: [3]int{100, 60, 120},
|
|
}
|
|
default:
|
|
// Night
|
|
return PhaseColors{
|
|
Primary: [3]int{50, 60, 100},
|
|
Secondary: [3]int{20, 30, 60},
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// WEATHER TONE MAPPING (ANSI-256 FOREGROUND)
|
|
//
|
|
// These match the Python "tone_color_map" used for verbose mode,
|
|
// but here they are used as coloration tint.
|
|
// ---------------------------------------------------------------------
|
|
|
|
var weatherToneMap = map[string][3]int{
|
|
"sunny": {255, 215, 0}, // yellow(ish)
|
|
"clear": {255, 215, 0},
|
|
"cloudy": {180, 180, 180},
|
|
"mostly_cloudy": {180, 180, 180},
|
|
"rain": {40, 110, 200},
|
|
"drizzle": {40, 110, 200},
|
|
"snow": {230, 230, 240},
|
|
"fog": {130, 130, 140},
|
|
"mist": {130, 130, 140},
|
|
"thunderstorm": {200, 120, 255},
|
|
"smoke": {140, 120, 100},
|
|
}
|
|
|
|
// Normalize a condition to a known tone key.
|
|
func normalizeCondition(cond string) string {
|
|
c := strings.ToLower(cond)
|
|
|
|
switch {
|
|
case strings.Contains(c, "sun"):
|
|
return "sunny"
|
|
case strings.Contains(c, "clear"):
|
|
return "clear"
|
|
case strings.Contains(c, "snow"):
|
|
return "snow"
|
|
case strings.Contains(c, "storm"):
|
|
return "thunderstorm"
|
|
case strings.Contains(c, "rain"):
|
|
return "rain"
|
|
case strings.Contains(c, "drizzle"):
|
|
return "drizzle"
|
|
case strings.Contains(c, "fog"):
|
|
return "fog"
|
|
case strings.Contains(c, "mist"):
|
|
return "fog"
|
|
case strings.Contains(c, "cloud"):
|
|
return "cloudy"
|
|
case strings.Contains(c, "smoke"):
|
|
return "smoke"
|
|
}
|
|
|
|
return "clear"
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// BLENDING FUNCTIONS
|
|
// ---------------------------------------------------------------------
|
|
|
|
func blend(a, b [3]int, factor float64) [3]int {
|
|
return [3]int{
|
|
int(float64(a[0])*(1-factor) + float64(b[0])*factor),
|
|
int(float64(a[1])*(1-factor) + float64(b[1])*factor),
|
|
int(float64(a[2])*(1-factor) + float64(b[2])*factor),
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RENDER LOGO: RETURNS A STRING
|
|
// ---------------------------------------------------------------------
|
|
|
|
func RenderLogoString(weatherCond string) string {
|
|
phase := getTimePhaseColors()
|
|
toneKey := normalizeCondition(weatherCond)
|
|
tone := weatherToneMap[toneKey]
|
|
|
|
var b strings.Builder
|
|
total := len(SkyfeedLogoLines)
|
|
|
|
for i, line := range SkyfeedLogoLines {
|
|
// Vertical gradient: bottom → top
|
|
factor := float64(i) / float64(total-1)
|
|
|
|
// Blend primary→secondary vertically
|
|
lineCol := blend(phase.Secondary, phase.Primary, factor)
|
|
|
|
// Weather tint applied lightly (0.0 → 0.25)
|
|
tintFactor := 0.25
|
|
tinted := blend(lineCol, tone, tintFactor)
|
|
|
|
b.WriteString(ansi(tinted[0], tinted[1], tinted[2]))
|
|
b.WriteString(line)
|
|
b.WriteString(reset())
|
|
b.WriteString("\n")
|
|
}
|
|
|
|
return b.String()
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// PRINT LOGO — For CLI / debug-logo command
|
|
// ---------------------------------------------------------------------
|
|
|
|
func PrintLogo(weatherCond string) {
|
|
fmt.Print(RenderLogoString(weatherCond))
|
|
}
|