This repository has been archived on 2025-11-19. You can view files and clone it, but cannot push or open issues or pull requests.
Skyfeed_archive/internal/output/logo.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))
}