From 90ad8c0c33b519d5830c69d4128bdc984b5e9de8 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Mon, 5 Oct 2026 14:22:14 -0400 Subject: feat: cryptocurrency exchange added to casino --- internal/cryptomarket/chart.go | 78 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 internal/cryptomarket/chart.go (limited to 'internal/cryptomarket/chart.go') diff --git a/internal/cryptomarket/chart.go b/internal/cryptomarket/chart.go new file mode 100644 index 0000000..c1fef29 --- /dev/null +++ b/internal/cryptomarket/chart.go @@ -0,0 +1,78 @@ +package cryptomarket + +import ( + "fmt" + "math" + "strings" + "time" +) + +// Chart uses one column per completed daily candle, auto-scales for BTC and +// tiny tokens alike, and delegates color to the player's configured palette. +func Chart(candles []Candle, width int, unicode bool, paint func(string, bool) string) []string { + width = max(12, min(80, width)) + label := 12 + count := width - label - 2 + if count < 2 || len(candles) < 2 { + return []string{"Not enough completed daily candles."} + } + if len(candles) > count { + candles = candles[len(candles)-count:] + } + type bar struct{ o, h, l, c float64 } + bars := []bar{} + low, high := math.Inf(1), math.Inf(-1) + for _, c := range candles { + if c.Validate() != nil { + return []string{"Invalid candle history."} + } + o, _ := rat(c.Open).Float64() + h, _ := rat(c.High).Float64() + l, _ := rat(c.Low).Float64() + v, _ := rat(c.Close).Float64() + bars = append(bars, bar{o, h, l, v}) + low = math.Min(low, l) + high = math.Max(high, h) + } + if high == low { + padding := math.Max(high*0.01, 1e-18) + low -= padding + high += padding + } + const height = 10 + row := func(p float64) int { return max(0, min(height-1, int(math.Round((high-p)/(high-low)*(height-1))))) } + grid := make([][]string, height) + for y := range grid { + grid[y] = make([]string, len(bars)) + for x := range grid[y] { + grid[y][x] = " " + } + } + wick, body, doji, axis := "|", "#", "-", "|" + if unicode { + wick, body, doji, axis = "│", "█", "━", "│" + } + for x, b := range bars { + top, bottom := min(row(b.o), row(b.c)), max(row(b.o), row(b.c)) + for y := row(b.h); y <= row(b.l); y++ { + ch := wick + if y >= top && y <= bottom { + ch = body + if top == bottom { + ch = doji + } + } + if paint != nil { + ch = paint(ch, b.c >= b.o) + } + grid[y][x] = ch + } + } + out := []string{"USD / credits; daily candles (UTC). Up/down colored; body=open-close, wick=range."} + for y := range grid { + v := high - float64(y)*(high-low)/(height-1) + out = append(out, fmt.Sprintf("%11.5g %s%s", v, axis, strings.Join(grid[y], ""))) + } + out = append(out, fmt.Sprintf("%s to %s", time.Unix(candles[0].Time, 0).UTC().Format("2006-01-02"), time.Unix(candles[len(candles)-1].Time, 0).UTC().Format("2006-01-02"))) + return out +} -- cgit v1.2.3