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/colour.go

145 lines
3.7 KiB
Go

package output
import (
"fmt"
"strconv"
"strings"
"time"
)
// ---------------------------------------------------------------------
// RGB STRUCTS & HELPERS
// ---------------------------------------------------------------------
type RGB struct {
R int
G int
B int
}
func (c RGB) ANSI() string {
return fmt.Sprintf("\033[38;2;%d;%d;%dm", c.R, c.G, c.B)
}
func RGBFromInts(r, g, b int) RGB {
return RGB{R: r, G: g, B: b}
}
func RGBFromHex(hex string) RGB {
hex = strings.TrimPrefix(hex, "#")
if len(hex) != 6 {
return RGB{255, 255, 255} // fail-safe
}
r, _ := strconv.ParseInt(hex[0:2], 16, 0)
g, _ := strconv.ParseInt(hex[2:4], 16, 0)
b, _ := strconv.ParseInt(hex[4:6], 16, 0)
return RGB{int(r), int(g), int(b)}
}
func Blend(a, b RGB, factor float64) RGB {
return RGB{
R: int(float64(a.R)*(1-factor) + float64(b.R)*factor),
G: int(float64(a.G)*(1-factor) + float64(b.G)*factor),
B: int(float64(a.B)*(1-factor) + float64(b.B)*factor),
}
}
// ---------------------------------------------------------------------
// TIME-OF-DAY COLOUR PHASES (CANADIAN ENGLISH)
// ---------------------------------------------------------------------
// These were recreated from the original Python _get_time_phase logic.
type Phase struct {
Name string
Primary RGB // top gradient
Secondary RGB // bottom gradient
}
func getTimePhase() Phase {
h := time.Now().Hour()
switch {
case h >= 5 && h < 8:
return Phase{
Name: "dawn",
Primary: RGBFromHex("#FFB478"), // orange-peach morning sky
Secondary: RGBFromHex("#8C64A0"), // purple base
}
case h >= 8 && h < 17:
return Phase{
Name: "day",
Primary: RGBFromHex("#4696FF"), // bright sky blue
Secondary: RGBFromHex("#78BEFF"), // lighter blue
}
case h >= 17 && h < 20:
return Phase{
Name: "sunset",
Primary: RGBFromHex("#FF6E3C"), // deep orange
Secondary: RGBFromHex("#643C78"), // muted purple
}
default:
return Phase{
Name: "night",
Primary: RGBFromHex("#323C64"), // deep navy
Secondary: RGBFromHex("#141E3C"), // darker base
}
}
}
// Public so other modules (logo, TUI, Telefact) can use it.
func GetTimePhaseColours() (RGB, RGB, string) {
phase := getTimePhase()
return phase.Primary, phase.Secondary, phase.Name
}
// ---------------------------------------------------------------------
// WEATHER TONES — CANADIAN ENGLISH (GREY, COLOUR, METRE, etc.)
// ---------------------------------------------------------------------
// This is used as a tint on top of the base time-of-day palette.
var WeatherTones = map[string]RGB{
"sunny": RGBFromHex("#FFD700"), // gold
"clear": RGBFromHex("#FFD700"),
"cloudy": RGBFromHex("#B4B4B4"),
"mostly_cloudy": RGBFromHex("#B4B4B4"),
"rain": RGBFromHex("#2870C8"),
"drizzle": RGBFromHex("#2870C8"),
"snow": RGBFromHex("#E6E6F0"),
"fog": RGBFromHex("#82828C"),
"mist": RGBFromHex("#82828C"),
"thunderstorm": RGBFromHex("#C878FF"),
"smoke": RGBFromHex("#8C7864"),
}
// Normalises Environment Canada text into our tone keys.
func NormaliseCondition(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 "mist"
case strings.Contains(c, "cloud"):
return "cloudy"
case strings.Contains(c, "smoke"):
return "smoke"
}
return "clear"
}