From c770704697fc8eae456af6fb1c553ccced5e6c60 Mon Sep 17 00:00:00 2001 From: Pranav Srinivas Kumar Date: Tue, 17 Dec 2019 09:06:46 -0600 Subject: [PATCH] Draft implementation of time elapsed/remaining meter --- include/indicators/progress_bar.hpp | 68 +++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/include/indicators/progress_bar.hpp b/include/indicators/progress_bar.hpp index 4fe3f92..7131f4d 100644 --- a/include/indicators/progress_bar.hpp +++ b/include/indicators/progress_bar.hpp @@ -27,7 +27,10 @@ SOFTWARE. #pragma once #include #include +#include +#include #include +#include #include #include #include @@ -88,11 +91,20 @@ public: void hide_percentage() { _show_percentage = false; } + void show_elapsed_time() { _show_elapsed_time = true; } + + void hide_elapsed_time() { _show_elapsed_time = false; } + + void show_remaining_time() { _show_remaining_time = true; } + + void hide_remaining_time() { _show_remaining_time = false; } + void set_progress(float value) { { std::unique_lock lock{_mutex}; _progress = value; } + _save_start_time(); _print_progress(); } @@ -101,12 +113,11 @@ public: std::unique_lock lock{_mutex}; _progress += 1; } + _save_start_time(); _print_progress(); } - size_t current() { - return std::min(static_cast(_progress), size_t(100)); - } + size_t current() { return std::min(static_cast(_progress), size_t(100)); } bool is_completed() const { return _completed; } @@ -128,11 +139,47 @@ private: std::atomic _max_postfix_text_length{0}; std::atomic _completed{false}; std::atomic _show_percentage{true}; + std::atomic _show_elapsed_time{true}; + std::atomic _show_remaining_time{true}; + std::atomic _saved_start_time{false}; + std::chrono::time_point _start_time_point; std::mutex _mutex; Color _foreground_color; + std::ostream &_print_duration(std::ostream &os, std::chrono::nanoseconds ns) { + using namespace std; + using namespace std::chrono; + typedef duration> days; + char fill = os.fill(); + os.fill('0'); + auto d = duration_cast(ns); + ns -= d; + auto h = duration_cast(ns); + ns -= h; + auto m = duration_cast(ns); + ns -= m; + auto s = duration_cast(ns); + if (d.count() > 0) + os << setw(2) << d.count() << "d:"; + if (h.count() > 0) + os << setw(2) << h.count() << "h:"; + os << setw(2) << m.count() << "m:" << setw(2) << s.count() << 's'; + os.fill(fill); + return os; + }; + + void _save_start_time() { + if (_show_elapsed_time && !_saved_start_time) { + _start_time_point = std::chrono::high_resolution_clock::now(); + _saved_start_time = true; + } + } + void _print_progress() { std::unique_lock lock{_mutex}; + auto now = std::chrono::high_resolution_clock::now(); + auto elapsed = std::chrono::duration_cast(now - _start_time_point); + std::cout << termcolor::bold; switch (_foreground_color) { case Color::GREY: @@ -175,6 +222,21 @@ private: if (_show_percentage) { std::cout << " " << std::min(static_cast(_progress), size_t(100)) << "%"; } + + if (_show_elapsed_time) { + std::cout << " ["; + _print_duration(std::cout, elapsed); + } + + if (_show_remaining_time) { + std::cout << "<"; + auto eta = std::chrono::nanoseconds( + _progress > 0 ? static_cast(elapsed.count() * 100 / _progress) : 0); + auto remaining = eta > elapsed ? (eta - elapsed) : (elapsed - eta); + _print_duration(std::cout, remaining); + std::cout << "]"; + } + if (_max_postfix_text_length == 0) _max_postfix_text_length = 10; std::cout << " " << _postfix_text << std::string(_max_postfix_text_length, ' ') << "\r";