JODA  0.13.1 (59b41972)
JSON On-Demand Analysis
ProgressBar.h
Go to the documentation of this file.
1 //(The MIT License)
2 //
3 // Copyright (c) 2016 Prakhar Srivastav <prakhar@prakhar.me>
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 //'Software'), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 
24 #ifndef JODA_PROGRESSBAR_H
25 #define JODA_PROGRESSBAR_H
26 
27 #include <chrono>
28 #include <iomanip>
29 #include <ios>
30 #include <iostream>
31 #include <limits>
32 #include <sstream>
33 
34 template <typename IntType>
35 class ProgressBar {
36  private:
37  IntType max_limit;
38  IntType ticks = 0;
39  const IntType total_ticks;
40  const IntType bar_width;
41  const char complete_char = '=';
42  const char incomplete_char = ' ';
43  std::chrono::steady_clock::time_point start_time =
44  std::chrono::steady_clock::now();
45 
46  public:
47  const IntType getBar_width() const { return bar_width; }
48 
49  private:
50  static void output_time(std::stringstream& ss, double seconds) {
51  std::size_t s_in_h(60 * 60), s_in_m(60) /*, m_in_h(60)*/;
52 
53  IntType hours_rem = seconds / s_in_h;
54 
55  IntType minutes_rem = (seconds - (hours_rem * s_in_h)) / s_in_m;
56 
57  IntType seconds_rem =
58  seconds - ((hours_rem * s_in_h) + (minutes_rem * s_in_m));
59 
60  std::ios init(nullptr), time_fmt(nullptr);
61  init.copyfmt(ss);
62  ss << std::setfill('0') << std::setw(2);
63  time_fmt.copyfmt(ss);
64  // hours
65  ss.copyfmt(time_fmt);
66  ss << hours_rem;
67  ss.copyfmt(init);
68  // minutes
69  ss << ":";
70  ss.copyfmt(time_fmt);
71  ss << minutes_rem;
72  ss.copyfmt(init);
73  // seconds
74  ss << ":";
75  ss.copyfmt(time_fmt);
76  ss << seconds_rem;
77  // restore format
78  ss.copyfmt(init);
79  }
80 
81  public:
82  ProgressBar(IntType total, IntType width, char complete, char incomplete)
83  : max_limit(std::numeric_limits<IntType>().max()),
84  total_ticks{total},
85  bar_width{width},
86  complete_char{complete},
87  incomplete_char{incomplete} {}
88 
89  ProgressBar(IntType total, IntType width)
90  : max_limit(std::numeric_limits<IntType>().max()),
91  total_ticks{total},
92  bar_width{width} {}
93 
95  if (ticks != max_limit) {
96  ++ticks;
97  }
98  return *this;
99  }
100 
101  const ProgressBar operator++(int) {
102  ProgressBar tmp = *this;
103  ++(*this);
104  return tmp;
105  }
106 
108  if (ticks != 0) {
109  --ticks;
110  }
111  return *this;
112  }
113 
114  const ProgressBar operator--(int) {
115  ProgressBar tmp = *this;
116  --(*this);
117  return tmp;
118  }
119 
120  template <typename NumberType>
121  void set_progress(NumberType prog) {
122  if (prog >= 0) {
123  ticks = std::min(prog, max_limit);
124  }
125  }
126 
127  template <typename NumberType>
128  void add_progress(NumberType prog) {
129  if (prog < 0) {
130  remove_progress(-prog);
131  };
132  IntType dist_from_limit = max_limit - ticks;
133  if (prog <= dist_from_limit) {
134  ticks = ticks + prog;
135  } else {
136  ticks = max_limit;
137  }
138  }
139  template <typename NumberType>
140  void remove_progress(NumberType prog) {
141  if (prog < 0) {
142  add_progress(-prog);
143  };
144  IntType dist_from_limit = ticks - 0;
145  if (prog <= dist_from_limit) {
146  ticks = ticks - prog;
147  } else {
148  ticks = 0;
149  }
150  }
151  std::string toString() const {
152  double progress =
153  static_cast<double>(ticks) / static_cast<double>(total_ticks);
154  IntType pos = (IntType)(bar_width * progress);
155 
156  std::chrono::steady_clock::time_point now =
157  std::chrono::steady_clock::now();
158  auto time_elapsed =
159  std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time)
160  .count();
161 
162  double seconds = static_cast<double>(time_elapsed) / 1000.0;
163  // double ticks_per_second = static_cast<double>(ticks) / seconds;
164  // double remaining_ticks = total_ticks - ticks;
165  // double total_seconds_rem = remaining_ticks / ticks_per_second;
166 
167  std::stringstream ss;
168  ss << "\033[2K"
169  << "\r";
170  ss << "[";
171 
172  for (IntType i = 0; i < bar_width; ++i) {
173  if (i < pos)
174  ss << complete_char;
175  else if (i == pos)
176  ss << ">";
177  else
178  ss << incomplete_char;
179  }
180 
181  ss << "] " << static_cast<IntType>(progress * 100.0) << "% (";
182 
183  ss << ticks << "/" << total_ticks << ") ";
184 
185  ProgressBar::output_time(ss, seconds);
186 
187  // ss<<" {";
188 
189  // ProgressBar::output_time(ss, total_seconds_rem);
190 
191  // ss <<" remaining}";
192 
193  // ss<<" (" << static_cast<std::size_t>(ticks_per_second) << " t/s)";
194  return ss.str();
195  }
196 
197  void display() const {
198  double progress =
199  static_cast<double>(ticks) / static_cast<double>(total_ticks);
200  IntType pos = (IntType)(bar_width * progress);
201 
202  std::chrono::steady_clock::time_point now =
203  std::chrono::steady_clock::now();
204  auto time_elapsed =
205  std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time)
206  .count();
207 
208  double seconds = static_cast<double>(time_elapsed) / 1000.0;
209  double ticks_per_second = static_cast<double>(ticks) / seconds;
210  double remaining_ticks = total_ticks - ticks;
211  double total_seconds_rem = remaining_ticks / ticks_per_second;
212 
213  std::stringstream ss;
214  ss << "\033[2K"
215  << "\r";
216  ss << "[";
217 
218  for (IntType i = 0; i < bar_width; ++i) {
219  if (i < pos)
220  ss << complete_char;
221  else if (i == pos)
222  ss << ">";
223  else
224  ss << incomplete_char;
225  }
226 
227  ss << "] " << static_cast<IntType>(progress * 100.0) << "% ";
228 
229  ss << ticks << " / " << total_ticks << " ticks ";
230 
231  ProgressBar::output_time(ss, seconds);
232 
233  ss << " {";
234 
235  ProgressBar::output_time(ss, total_seconds_rem);
236 
237  ss << " remaining}";
238 
239  ss << " (" << static_cast<std::size_t>(ticks_per_second) << " t/s)";
240 
241  std::cout << ss.str() << std::flush;
242  }
243 
244  void done() const {
245  display();
246  std::cout << std::endl;
247  }
248 
249  void reset() {
250  start_time = std::chrono::steady_clock::now();
251  ticks = 0;
252  }
253 };
254 #endif // JODA_PROGRESSBAR_H
Definition: ProgressBar.h:35
void remove_progress(NumberType prog)
Definition: ProgressBar.h:140
ProgressBar & operator--()
Definition: ProgressBar.h:107
void add_progress(NumberType prog)
Definition: ProgressBar.h:128
const ProgressBar operator--(int)
Definition: ProgressBar.h:114
std::string toString() const
Definition: ProgressBar.h:151
const ProgressBar operator++(int)
Definition: ProgressBar.h:101
void reset()
Definition: ProgressBar.h:249
ProgressBar & operator++()
Definition: ProgressBar.h:94
ProgressBar(IntType total, IntType width, char complete, char incomplete)
Definition: ProgressBar.h:82
void display() const
Definition: ProgressBar.h:197
void done() const
Definition: ProgressBar.h:244
const IntType getBar_width() const
Definition: ProgressBar.h:47
void set_progress(NumberType prog)
Definition: ProgressBar.h:121
ProgressBar(IntType total, IntType width)
Definition: ProgressBar.h:89