-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathtree.cpp
180 lines (148 loc) · 3.8 KB
/
tree.cpp
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright (c) 2018 Antony Polukhin.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// TODO:
// * clean up the mess in code
// * clean up after the cleanup
// * add falling snow or glowing stars
// * more modes for lamps
#include <cstdlib>
#include <chrono>
#include <thread>
#include <iostream>
#include <random>
#include <iterator>
#include <fstream>
#include <algorithm>
#include <atomic>
enum class color_t : unsigned char {};
constexpr color_t operator"" _c(unsigned long long int v) { return color_t(v); }
std::ostream& operator<< (std::ostream& os, color_t val) {
return os << "\033[38;5;" << static_cast<int>(val) << 'm';
}
struct green_state {
color_t color() const {
return *(std::min(std::begin(kGreenColors) + dark, std::end(kGreenColors) - 1));
}
void increase_darkness() { ++dark; }
void reset_darkness() { dark = 0; }
private:
constexpr static color_t kGreenColors[] = { 22_c, 22_c, 28_c, 28_c, 34_c };
int dark = 0;
};
struct lamps {
void operator()(char c) {
if (mode % max_state == 0)
new_color();
std::cout << col << c;
}
void end_cycle() {
if (mode % max_state == 1) {
new_color();
} else if (mode % max_state == 2) {
auto i = static_cast<int>(col);
++i;
i %= 226;
i = std::clamp(i, 154, 226);
//i %= 202;
//i = std::clamp(i, 196, 202);
col = static_cast<color_t>(i);
}
}
void change_mode() {
++mode;
}
void stop() {
stopped = true;
}
bool was_stopped() {
return stopped;
}
private:
void new_color() {
std::sample(std::begin(kPrettyColors), std::end(kPrettyColors), &col, 1, rand);
}
std::atomic<bool> stopped = false;
std::atomic<size_t> mode{0};
static constexpr size_t max_state = 3;
std::mt19937 rand{std::random_device{}()};
color_t col = 0_c;
// https://misc.flogisoft.com/bash/tip_colors_and_formatting
static constexpr color_t kPrettyColors[] = {
1_c, 9_c, 11_c, 15_c, 45_c, 87_c, 118_c, 154_c, 155_c, 165_c, 193_c, 196_c, 198_c,208_c, 226_c, 15_c
};
};
std::string get_tree(int args, const char** argv) {
std::string filename = "xtree.txt";
if (args > 1) {
filename = argv[1];
}
std::string tree;
std::ifstream ifs{filename.c_str()};
std::getline(ifs, tree, '\0');
return tree;
}
int main(int args, const char** argv) {
using namespace std::literals::chrono_literals;
auto tree = get_tree(args, argv);
lamps lamp;
std::thread t([&lamp]() {
char c;
while (std::cin >> c) {
if (c == 'q') {
lamp.stop();
break;
}
lamp.change_mode();
}
});
for (;;) {
if (lamp.was_stopped()) {
break;
}
std::system("clear");
green_state g;
auto it = tree.begin();
auto end = tree.end();
auto prev_width = 0;
for (; it != end; ++it) {
const auto c = *it;
switch (c) {
case '*': [[fall_through]]
case ' ':
std::cout << g.color() << c;
break;
case 'o': [[fall_through]]
case 'O':
lamp(c);
break;
case '#':
std::cout << 94_c << c;
break;
case '\n': {
const auto next_new_line = std::find(it + 1, end, '\n');
const auto new_width = std::count_if(
it,
next_new_line,
[](char s) { return s == '*' || s == 'o' || s == 'O'; }
);
if (prev_width < new_width) {
g.increase_darkness();
} else {
g.reset_darkness();
}
prev_width = new_width;
}
[[fall_through]]
default:
std::cout << 0_c << c;
}
}
std::cout << 0_c << std::endl;
lamp.end_cycle();
std::this_thread::sleep_for(400ms);
}
t.join();
}