29 basic_width_of_label_(0), show_legend_(false) {
35 explicit Asciichart(
const std::vector<std::vector<double>> &series)
38 basic_width_of_label_(0), show_legend_(false) {
46 const std::unordered_map<std::string, std::vector<double>> &series)
49 basic_width_of_label_(0), show_legend_(false) {
95 legend_padding_ = padding;
115 return PlotLineChart();
118 return PlotCircleChart();
126 std::map<std::string, std::string> symbols_;
127 std::unordered_map<std::string, std::vector<double>> series_;
128 std::vector<Style> styles_;
135 size_t legend_padding_;
136 size_t basic_width_of_label_;
140 void InitSeries(
const std::vector<double> &series) {
141 series_[
"series 0"] = series;
144 void InitSeries(
const std::vector<std::vector<double>> &series) {
146 for (
const auto &s : series) {
147 series_[
"series " + std::to_string(n++)] = s;
152 const std::unordered_map<std::string, std::vector<double>> &series) {
170 symbols_ = {{
"empty",
" "}, {
"center",
"┼"}, {
"axis",
"┤"},
171 {
"c1",
"╶"}, {
"c2",
"╴"}, {
"parellel",
"─"},
172 {
"down",
"╰"}, {
"up",
"╭"}, {
"ldown",
"╮"},
173 {
"lup",
"╯"}, {
"vertical",
"│"}};
183 void PutString(std::vector<std::vector<Text>> &screen,
const std::string &str,
184 const Style &style,
unsigned row,
unsigned col) {
185 for (
unsigned i = 0; i < str.length(); i++) {
186 if (str[i] ==
'\n') {
189 screen[row][col + i] = Text(str.substr(i, 1), style);
194 std::string FormatLabel(
int x) {
195 std::stringstream ss;
196 ss << std::setw(show_legend_ ? legend_padding_ + basic_width_of_label_
197 : basic_width_of_label_)
198 << std::setfill(
' ') << std::setprecision(2);
203 std::string Print(
const std::vector<std::vector<Text>> &screen) {
204 std::stringstream os;
205 for (
auto &line : screen) {
206 for (
auto &item : line) {
214 std::string PlotLineChart() {
216 for (
auto &label_trace_pair : series_) {
217 for (
auto &item : label_trace_pair.second) {
218 min_ = std::min(item, min_);
219 max_ = std::max(item, max_);
224 auto range = max_ - min_;
225 if (range == 0) range = 1;
228 basic_width_of_label_ = std::max(std::to_string((
int)max_).length(),
229 std::to_string((
int)min_).length());
233 for (
auto &label_trace_pair : series_) {
234 width = std::max(width, (
int)label_trace_pair.second.size());
237 int legend_cols = 0, legend_rows = 0;
240 for (
auto &label_trace_pair : series_) {
243 std::max(legend_cols, (
int)label_trace_pair.first.length());
247 auto offset = offset_ + legend_cols;
251 if (std::isnan(height_)) {
257 height_ = std::max((
double)legend_rows, height_);
260 auto ratio = height_ / range;
262 int min2 = std::round(min_ * ratio);
263 int max2 = std::round(max_ * ratio);
266 auto rows = max2 - min2;
269 if (rows == 0) rows = 1;
272 std::vector<std::vector<Text>> screen(
273 rows + 1, std::vector<Text>(cols, symbols_[
"empty"]));
276 for (
double y = min2; y <= max2; y++) {
277 auto label = FormatLabel(std::round(min_ + (y - min2) * range / rows));
279 screen[rows - (y - min2)][legend_cols] =
282 screen[rows - (y - min2)][
offset - 1] =
283 Text((y == 0) ? symbols_[
"center"] : symbols_[
"axis"],
291 for (
auto &label_trace_pair : series_) {
292 auto style = styles_[j % styles_.size()];
293 PutString(screen, label_trace_pair.first, style, j++, 0);
301 for (
auto &label_trace_pair : series_) {
302 auto &trace = label_trace_pair.second;
303 auto style = styles_[j++ % styles_.size()];
304 auto y0 = std::round(trace[0] * ratio) - min2;
306 screen[rows - y0][
offset - 1] = Text(symbols_[
"center"], style);
308 for (
size_t i = 0; i < trace.size() - 1; i++) {
309 auto y0 = std::round(trace[i] * ratio) - min2;
310 auto y1 = std::round(trace[i + 1] * ratio) - min2;
313 screen[rows - y0][i +
offset] = Text(symbols_[
"parellel"], style);
315 screen[rows - y1][i +
offset] =
316 Text(y0 > y1 ? symbols_[
"down"] : symbols_[
"up"], style);
317 screen[rows - y0][i +
offset] =
318 Text(y0 > y1 ? symbols_[
"ldown"] : symbols_[
"lup"], style);
319 auto from = std::min(y0, y1);
320 auto to = std::max(y0, y1);
321 for (
size_t y = from + 1; y < to; y++) {
322 screen[rows - y][i +
offset] = Text(symbols_[
"vertical"], style);
329 return Print(screen);
332 std::string PlotCircleChart() {
return ""; }