/
main.go
117 lines (113 loc) · 3.38 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Wave draws arcsine curves!
// Specify period, amplitude, frequency and number for some pretty pictures.
package main
import (
"flag"
"fmt"
"math"
"math/rand"
"strings"
"time"
)
// Wave draws asin curve with given period and amplitude and sends out
// the string on given channel, colorizing the output with the color defined by
// color, a terminal color code string (such as "32" for green)
// The length of each string is amp*2. Spaces are padded to the front and end.
func Wave(period, amp float64, offset int, sig chan<- string, color, character string) {
step := 1.0 / period
color_reset := "39"
for {
for x := 1.0; x >= 0.0; x -= step {
l := int(math.Ceil((2 * math.Asin(x) / math.Pi) * amp))
r := int(math.Floor((amp - float64(l)) * 2))
e := int(amp)*2 - l - r
// fix rounding misalignment
if x == 1.0 {
e--
}
// whether to colorize the output
if color != color_reset {
sig <- fmt.Sprintf("\033[%sm%*s%*s%*s\033[%sm", color,
l+offset, character, r+offset, character, e+offset, "", color_reset)
} else {
sig <- fmt.Sprintf("%*s%*s%*s", l+offset, character,
r+offset, character, e+offset, "")
}
}
for x := step; x < 1.0; x += step {
l := int(math.Ceil((2 * math.Asin(x) / math.Pi) * amp))
r := int(math.Floor((amp - float64(l)) * 2))
e := int(amp)*2 - l - r
// fix rounding misalignment
if x > 1.0-step {
e--
}
if color != color_reset {
sig <- fmt.Sprintf("\033[%sm%*s%*s%*s\033[%sm", color,
l+offset, character, r+offset, character, e+offset, "", color_reset)
} else {
sig <- fmt.Sprintf("%*s%*s%*s", l+offset, character,
r+offset, character, e+offset, "")
}
}
}
}
func main() {
// initialize rand seed
rand.Seed(time.Now().UnixNano())
// parse arguments
period := flag.Int("p", 25, "Period: length (lines) of wave")
amp := flag.Int("a", 25, "Amplitude: width (chars) of wave")
num := flag.Int("n", 2, "Number of waves")
freq := flag.Int("f", 40, "Frequency of waves (Hz)")
colorize := flag.String("color", "lgreen", "Output color (default for none)")
character := flag.String("char", "*", "Output character")
flag.Parse()
// map color names to color codes
colors := map[string]string{
"red": "31",
"green": "32",
"yellow": "33",
"blue": "34",
"magenta": "35",
"cyan": "36",
"lred": "91",
"lgreen": "92",
"lcyan": "96",
"white": "97",
"default": "39",
}
// color themes
color_themes := map[string][]string{
"christmas": []string{"lred", "lgreen", "white"},
}
sigs := make([]chan string, *num)
// start up the waves
for i, _ := range sigs {
color := colors["default"]
if _, ok := colors[*colorize]; ok {
// a default color
color = colors[*colorize]
} else if _, ok := color_themes[*colorize]; ok {
// iterate through theme's colors
color = colors[color_themes[*colorize][i%len(color_themes[*colorize])]]
}
sigs[i] = make(chan string)
go Wave(float64(*period), float64(*amp), 0, sigs[i], color, *character)
}
// sync up the waves at some frequency in Hz
go func(frequency int, sigs []chan string) {
for {
line := make([]string, len(sigs))
for i, s := range sigs {
line[i] = <-s
}
// join up the parts and put a newline at the end
fmt.Printf("%s\n", strings.Join(line, ""))
time.Sleep(time.Second / time.Duration(frequency))
}
}(*freq, sigs)
// press any key + enter to exit
var exit string
fmt.Scan(&exit)
}