// // Created by versustune on 23.02.20. // #include #include #include #include #include #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(now - start_time).count(); double seconds = static_cast(time_elapsed) / 1000.0; double ticks_per_second = static_cast(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(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(now - start_time).count(); double seconds = static_cast(time_elapsed) / 1000.0; double ticks_per_second = static_cast(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(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; }