forked from prakhar1989/progress-cpp
-
Notifications
You must be signed in to change notification settings - Fork 1
/
progress_tracker.cpp
119 lines (97 loc) · 4.2 KB
/
progress_tracker.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
#include "progress_tracker.h"
namespace ProgressIndicator {
using std::chrono::steady_clock;
using std::chrono::system_clock;
using std::chrono::milliseconds;
// ========== ProgressTrackerImpl ==========
ProgressTrackerImpl::ProgressTrackerImpl(unsigned int total, std::ostream &ostream) :
total_ticks(total), ostream(ostream) {}
void ProgressTrackerImpl::update() {
now = steady_clock::now();
speed = timeElapsed().count() / double(ticks); // update milliseconds per tick
}
void ProgressTrackerImpl::updateTimeWidth() {
int number_width = 3; // 0.0
for (auto t = 10; t <= (timeTotal().count() + 500) * 0.001; t *= 10) {
++number_width;
}
if (number_width > time_width) {
time_width = number_width;
}
}
milliseconds ProgressTrackerImpl::timeElapsed() const {
return std::chrono::duration_cast<milliseconds>(now - start_time);
}
milliseconds ProgressTrackerImpl::timeLeft() const {
return milliseconds((int) (speed * (total_ticks - ticks)));
}
milliseconds ProgressTrackerImpl::timeTotal() const {
return milliseconds((int) (speed * total_ticks));
}
void ProgressTrackerImpl::done() { display(); }
// ========== ProgressBar ==========
ProgressBar::ProgressBar(unsigned int total, std::ostream &ostream,
unsigned int bar_width, char complete, char incomplete) :
ProgressTrackerImpl(total, ostream),
bar_width(bar_width), complete_char(complete), incomplete_char(incomplete) {}
ProgressBar::ProgressBar(unsigned int total, unsigned int bar_width, char complete, char incomplete) :
ProgressBar(total, std::cout, bar_width, complete, incomplete) {}
void ProgressBar::display() {
update();
auto millisec_elapsed = timeElapsed().count();
auto millisec_total = timeTotal().count();
int pos = (int) (bar_width * progress());
ostream << "[";
for (int i = 0; i < bar_width; ++i) {
if (i < pos)
ostream << complete_char;
else if (i == pos)
ostream << ">";
else
ostream << incomplete_char;
}
ostream << "]";
ostream << std::fixed;
ostream << " " << std::setw(3) << std::setprecision(0) << 100 * progress() << "%";
updateTimeWidth();
ostream << std::setprecision(1)
<< " " << std::setw(time_width) << double(millisec_elapsed) / 1000.0
<< "/" << std::setw(time_width) << double(millisec_total) / 1000.0 << "s\r";
ostream.flush();
}
void ProgressBar::done() {
display();
ostream << std::endl;
}
// ========== ProgressLog ==========
ProgressLog::ProgressLog(unsigned int total, std::ostream &ostream) : ProgressTrackerImpl(total, ostream) {}
void ProgressLog::display() {
update();
auto millisec_elapsed = timeElapsed().count();
auto millisec_total = timeTotal().count();
auto system_now = system_clock::now();
// auto time_now = system_clock::to_time_t(system_now);
auto time_end = system_clock::to_time_t(
system_now + std::chrono::duration_cast<system_clock::duration>(start_time + timeTotal() - now));
ostream << std::fixed << std::setw(3) << std::setprecision(0) << 100 * progress() << "%";
updateTimeWidth();
ostream << std::setprecision(1)
<< " " << std::setw(time_width) << double(millisec_elapsed) / 1000.0
<< "/" << std::setw(time_width) << double(millisec_total) / 1000.0 << "s";
// ostream << " [" << std::put_time(std::localtime(&time_now), "%F %T %z") << "]";
ostream << " ETA [" << std::put_time(std::localtime(&time_end), "%F %T %z") << "]" << std::endl;
ostream.flush();
}
// ========== TaciturnDecorator ==========
TaciturnDecorator::TaciturnDecorator(std::shared_ptr <ProgressTracker> progress_tracker,
milliseconds time_interval, double progress_interval) :
ProgressTrackerDecorator(progress_tracker),
time_interval(time_interval), progress_interval(progress_interval) {}
void TaciturnDecorator::display() {
if (last_progress + progress_interval < progress() || last_time + time_interval < steady_clock::now()) {
ProgressTrackerDecorator::display();
last_progress = progress();
last_time = steady_clock::now();
}
}
} // end namespace ProgressIndicator