Line data Source code
1 : // (The MIT License) 2 : // 3 : // Copyright (c) 2016 Prakhar Srivastav <prakhar@prakhar.me> 4 : // Copyright (c) 2019 David Tellenbach <david.tellenbach@in.tum.de> 5 : // 6 : // Permission is hereby granted, free of charge, to any person obtaining 7 : // a copy of this software and associated documentation files (the 8 : // 'Software'), to deal in the Software without restriction, including 9 : // without limitation the rights to use, copy, modify, merge, publish, 10 : // distribute, sublicense, and/or sell copies of the Software, and to 11 : // permit persons to whom the Software is furnished to do so, subject to 12 : // the following conditions: 13 : // 14 : // The above copyright notice and this permission notice shall be 15 : // included in all copies or substantial portions of the Software. 16 : // 17 : // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 18 : // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 : // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 : // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 : // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 : // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 : // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 : 25 : /** 26 : * @file ProgressBar.h 27 : * @brief Implements a progessbar 28 : * @author Prakhar Srivastav <prakhar@prakhar.me> 29 : * @author David Tellenbach <david.tellenbach@in.tum.de> 30 : */ 31 : #pragma once 32 : 33 : #include <chrono> 34 : #include <iostream> 35 : #include <string> 36 : #include <iomanip> 37 : 38 : namespace elsa::ml 39 : { 40 : namespace detail 41 : { 42 : /** 43 : * \ingroup Internal 44 : * \class ProgressBar 45 : * @brief A progress bar 46 : * 47 : * Usage example: 48 : * 49 : * ``` 50 : * uint32_t total = 100; 51 : * ProgressBar bar(total, 50); 52 : * for (uint32_t i = 0; i < 100; ++t) { 53 : * // Do something 54 : * ++bar; 55 : * bar.display(); 56 : * } 57 : * bar.done(); 58 : * ``` 59 : * 60 : * Output: 61 : * 62 : * ``` 63 : * [========================> ] 50% 0.034s 64 : * [==================================================] 100% 0.094s 65 : * ``` 66 : */ 67 : class ProgressBar 68 : { 69 : public: 70 : /** 71 : * @brief Constructor 72 : * @param total The total number of ticks in the progress bar 73 : * @param width The width of the progress bar in chars 74 : * @param complete The char that will be displayed to indicate already 75 : * completed parts of the progress bar. This is optional and defaults to '=' 76 : * @param incomplete The char that will be displayed to indicate yet 77 : * uncompleted parts of the progress bar. This is optional and defaults to ' ' 78 : * @param head The char that will be displayed the head of the progress bar. 79 : * This is optional and defaults to '>' 80 : */ 81 0 : ProgressBar(uint32_t total, uint32_t width, char complete = '=', char incomplete = ' ', 82 : char head = '>') 83 0 : : total_ticks(total), 84 : bar_width(width), 85 : complete_char(complete), 86 : incomplete_char(incomplete), 87 0 : head_char(head) 88 : { 89 0 : } 90 : 91 : /** 92 : * @brief Increment the progress bar 93 : * @return The value of \p ticks after incrementing it 94 : */ 95 0 : uint32_t operator++() { return ++ticks; } 96 : 97 : /** 98 : * @brief Display the progress bar 99 : * @param preMessage A message to display right before the progressbar 100 : * @param postMessage A message to display right after the progressbar 101 : */ 102 0 : void display(const std::string& preMessage = std::string(""), 103 : const std::string& postMessage = std::string("")) const 104 : { 105 0 : float progress = static_cast<float>(ticks) / static_cast<float>(total_ticks); 106 0 : uint32_t pos = static_cast<uint32_t>(static_cast<float>(bar_width) * progress); 107 : 108 0 : std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); 109 : auto time_elapsed = 110 0 : std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time).count(); 111 : 112 0 : std::cout << preMessage << "["; 113 : 114 0 : for (uint32_t i = 0; i < bar_width; ++i) { 115 0 : if (i < pos) 116 0 : std::cout << complete_char; 117 0 : else if (i == pos) 118 0 : std::cout << head_char; 119 : else 120 0 : std::cout << incomplete_char; 121 : } 122 0 : std::cout << "] " << static_cast<int>(progress * 100.f) << "% " 123 0 : << std::setprecision(2) << std::fixed 124 0 : << static_cast<float>(time_elapsed) / 1000.f << "s "; 125 0 : std::cout << postMessage << "\r"; 126 0 : std::cout.flush(); 127 0 : } 128 : 129 : /** 130 : * @brief Indicate that the progressbar has finished 131 : * @param preMessage A message to display right before the progressbar 132 : * @param postMessage A message to display right after the progressbar 133 : */ 134 0 : void done(const std::string& preMessage = std::string(""), 135 : const std::string& postMessage = std::string("")) 136 : { 137 0 : ticks = total_ticks; 138 0 : display(preMessage, postMessage); 139 0 : ticks = 0; 140 0 : start_time = std::chrono::steady_clock::now(); 141 0 : std::cout << std::endl; 142 0 : } 143 : 144 : private: 145 : uint32_t ticks = 0; 146 : const uint32_t total_ticks; 147 : const uint32_t bar_width; 148 : const char complete_char; 149 : const char incomplete_char; 150 : const char head_char; 151 : std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now(); 152 : }; 153 : } // namespace detail 154 : } // namespace elsa::ml