156 lines
4.5 KiB
C++
156 lines
4.5 KiB
C++
//
|
|
// Created by versustune on 23.02.20.
|
|
//
|
|
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <cmath>
|
|
#include <zconf.h>
|
|
#include <thread>
|
|
#include "ProgressBar.h"
|
|
|
|
ProgressBar::ProgressBar(std::string name, int maxTicks, int showAfterTicks) {
|
|
ProgressBar::maxTicks = maxTicks + 0;
|
|
ProgressBar::ticks = 0 + 0;
|
|
ProgressBar::name = "\033[1;32m" + std::move(name) + "\033[0m";
|
|
ProgressBar::showAfterTicks = showAfterTicks;
|
|
if (maxTicks == -1) {
|
|
isUnlimited = true;
|
|
}
|
|
}
|
|
|
|
ProgressBar::~ProgressBar() = default;
|
|
|
|
void ProgressBar::update() {
|
|
//only update if ticks reached
|
|
if (ticks % showAfterTicks == 0 || (isFinished && !finishedDraw)) {
|
|
if (isUnlimited) {
|
|
renderUnknown();
|
|
} else {
|
|
renderNormal();
|
|
}
|
|
if (isFinished) {
|
|
finishedDraw = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ProgressBar::tick() {
|
|
++ticks;
|
|
if (ticks > maxTicks && maxTicks != -1) {
|
|
ticks = maxTicks;
|
|
isFinished = true;
|
|
}
|
|
}
|
|
|
|
void ProgressBar::setFinished(bool isThread) {
|
|
isFinished = true;
|
|
if (!isThread) {
|
|
this->update();
|
|
}
|
|
}
|
|
|
|
void ProgressBar::start() {
|
|
start_time = std::chrono::steady_clock::now();
|
|
this->update();
|
|
}
|
|
|
|
void ProgressBar::renderUnknown() {
|
|
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
|
|
auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();
|
|
double seconds = static_cast<double>(time_elapsed) / 1000.0;
|
|
double ticks_per_second = static_cast<double>(ticks) / seconds;
|
|
std::stringstream stream;
|
|
stream << "\033[2K" << "\r";
|
|
stream << "[" << name << "] \033[1;34m[" << unlimitedChars.at(++lastIcon % unlimitedChars.length());
|
|
stream << "]\033[1;36m [" << ticks << "]" << " (" << static_cast<std::size_t>(ticks ? ticks_per_second : 0.0)
|
|
<< " t/s)\033[0m";
|
|
std::cout << stream.str() << std::flush;
|
|
}
|
|
|
|
void ProgressBar::renderNormal() {
|
|
int pos = 0;
|
|
double progress = 0;
|
|
if (ticks > 0) {
|
|
progress = double(ticks) / double(maxTicks);
|
|
pos = (50 * progress);
|
|
}
|
|
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
|
|
auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count();
|
|
double seconds = static_cast<double>(time_elapsed) / 1000.0;
|
|
double ticks_per_second = static_cast<double>(ticks) / seconds;
|
|
double remaining_ticks = maxTicks - ticks;
|
|
double total_seconds_rem = remaining_ticks / ticks_per_second;
|
|
|
|
std::stringstream stream;
|
|
stream << "\033[2K" << "\r";
|
|
stream << "[" << name << "]\033[1;34m[";
|
|
for (int i = 0; i < 50; ++i) {
|
|
if (i < pos) stream << '=';
|
|
else if (i == pos) stream << ">";
|
|
else stream << ' ';
|
|
}
|
|
stream << "]\033[1;35m " << std::roundf(progress * 100.0f) << "% ";
|
|
stream << ticks << " / " << maxTicks << " [";
|
|
convertTime(stream, seconds);
|
|
stream << " / ";
|
|
if (ticks) {
|
|
convertTime(stream, total_seconds_rem);
|
|
} else {
|
|
stream << "??:??:??";
|
|
}
|
|
stream << "]";
|
|
stream << " (" << static_cast<std::size_t>(ticks ? ticks_per_second : 0.0) << " t/s)\033[0m";
|
|
std::cout << stream.str() << std::flush;
|
|
}
|
|
|
|
void ProgressBar::convertTime(std::stringstream &stream, double seconds) {
|
|
std::size_t s_in_h(60 * 60), s_in_m(60)/*, m_in_h(60)*/;
|
|
int hours_rem = seconds / s_in_h;
|
|
int minutes_rem = (seconds - (hours_rem * s_in_h)) / s_in_m;
|
|
int seconds_rem = seconds - ((hours_rem * s_in_h) + (minutes_rem * s_in_m));
|
|
std::ios init(nullptr), time_fmt(nullptr);
|
|
init.copyfmt(stream);
|
|
stream << std::setfill('0') << std::setw(2);
|
|
time_fmt.copyfmt(stream);
|
|
//hours
|
|
stream.copyfmt(time_fmt);
|
|
stream << hours_rem;
|
|
stream.copyfmt(init);
|
|
//minutes
|
|
stream << ":";
|
|
stream.copyfmt(time_fmt);
|
|
stream << minutes_rem;
|
|
stream.copyfmt(init);
|
|
//seconds
|
|
stream << ":";
|
|
stream.copyfmt(time_fmt);
|
|
stream << seconds_rem;
|
|
//restore format
|
|
stream.copyfmt(init);
|
|
}
|
|
|
|
bool ProgressBar::isDone() const {
|
|
return isFinished && finishedDraw;
|
|
}
|
|
|
|
void ProgressBar::runInThread() {
|
|
while(!runThread) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
}
|
|
this->start();
|
|
while (!isDone()) {
|
|
this->update();
|
|
}
|
|
std::cout << "\n";
|
|
delete this;
|
|
}
|
|
|
|
void ProgressBar::setMaxTicks(int newMaxTicks) {
|
|
maxTicks = newMaxTicks;
|
|
}
|
|
|
|
void ProgressBar::startThread() {
|
|
runThread = true;
|
|
}
|