SWE
/import/home/rettenbs/src/SWE/src/tools/ProgressBar.hh
Go to the documentation of this file.
00001 
00028 #ifndef PROGRESSBAR_H
00029 #define PROGRESSBAR_H
00030 
00031 #include <cassert>
00032 #include <cmath>
00033 #include <ctime>
00034 #include <algorithm>
00035 #include <iostream>
00036 #include <limits>
00037 
00038 #include <unistd.h>
00039 #include <sys/ioctl.h>
00040 
00041 namespace tools
00042 {
00043 
00044 class ProgressBar
00045 {
00046 private:
00048         int m_rank;
00049 
00051         float m_totalWork;
00052 
00054         time_t m_startTime;
00055 
00057         unsigned int m_terminalSize;
00058 
00060         unsigned char m_rotatingBar;
00061 
00062 public:
00063         ProgressBar(float totalWork = 1., int rank = 0)
00064                 : m_rank(rank),
00065                   m_totalWork(totalWork),
00066                   m_startTime(time(0)),
00067                   m_rotatingBar(0)
00068         {
00069                 if (rank != 0)
00070                         return;
00071 
00072 #ifdef TIOCGSIZE
00073                 struct ttysize ts;
00074                 ioctl(STDIN_FILENO, TIOCGSIZE, &ts);
00075                 m_terminalSize = ts.ts_cols;
00076 #elif defined(TIOCGWINSZ)
00077                 struct winsize ts;
00078                 ioctl(STDIN_FILENO, TIOCGWINSZ, &ts);
00079                 m_terminalSize = ts.ws_col;
00080 #else
00081                 m_terminalSize = 0;
00082 #endif
00083                 if (m_terminalSize > 300)
00084                         // Probably an error due to MPI
00085                         m_terminalSize = MIN_TERM_SIZE;
00086         }
00087 
00091         void update(float done)
00092         {
00093                 if (m_rank != 0 || m_terminalSize < MIN_TERM_SIZE)
00094                         return;
00095 
00096                 unsigned int printed = 2;
00097                 std::cout << '\r';
00098                 printed += printTimeLeft(done);
00099                 std::cout << ' ';
00100                 printed += printPercentage(done);
00101                 std::cout << ' ';
00102                 printProgressBar(done, m_terminalSize-printed-2);
00103                 std::cout << ' ';
00104                 printRotatingBar();
00105                 std::cout << std::flush;
00106         }
00107 
00108         void clear()
00109         {
00110                 if (m_rank != 0 || m_terminalSize < MIN_TERM_SIZE)
00111                         return;
00112 
00113                 std::cout << '\r';
00114                 for (unsigned int i = 0; i < m_terminalSize; i++)
00115                         std::cout << ' ';
00116                 std::cout << '\r';
00117         }
00118 
00119 private:
00123         unsigned int printTimeLeft(float done)
00124         {
00125                 float timeLeft;
00126                 if (done <= 0)
00127                         timeLeft = std::numeric_limits<float>::max();
00128                 else
00129                         timeLeft = (time(0) - m_startTime) * (m_totalWork - done) / done;
00130 
00131                 std::cout << "Time left: ";
00132 
00133                 if (timeLeft < 1) {
00134                         for (int i = 3; i < TIME_SIZE; i++)
00135                                 std::cout << ' ';
00136                         std::cout << "< 1";
00137                 } else {
00138                         int digits = ceil(log(timeLeft)/log(10));
00139                         if (digits > TIME_SIZE) {
00140                                 // Maximum number we can show
00141                                 for (int i = 0; i < TIME_SIZE; i++)
00142                                         std::cout << '9';
00143                         } else {
00144                                 streamsize oldPrec = std::cout.precision();
00145                                 std::ios::fmtflags oldFlags = std::cout.flags();
00146                                 streamsize oldWidth = std::cout.width();
00147 
00148                                 std::cout.precision(std::max(0, TIME_SIZE-digits-2));
00149                                 std::cout.setf(std::ios::fixed);
00150                                 std::cout.width(TIME_SIZE);
00151 
00152                                 std::cout << timeLeft;
00153 
00154                                 std::cout.precision(oldPrec);
00155                                 std::cout.flags(oldFlags);
00156                                 std::cout.width(oldWidth);
00157                         }
00158                 }
00159 
00160                 std::cout << " sec";
00161 
00162                 return 11+TIME_SIZE+4;
00163         }
00164 
00168         unsigned int printPercentage(float done)
00169         {
00170                 int per = floor(done/m_totalWork*100);
00171 
00172                 std::cout << '(';
00173 
00174                 streamsize oldWidth = std::cout.width();
00175 
00176                 std::cout.width(3);
00177                 std::cout << per;
00178 
00179                 std::cout.width(oldWidth);
00180 
00181                 std::cout << "% done)";
00182 
00183                 return 1+3+7;
00184         }
00185 
00186         void printProgressBar(float done, unsigned int size)
00187         {
00188                 if (size < 3)
00189                         return;
00190 
00191                 size -= 2; // leave space for []
00192                 unsigned int per = floor(done/m_totalWork * size);
00193 
00194                 std::cout << '[';
00195 
00196                 for (unsigned int i = 0; i < per; i++)
00197                         std::cout << '=';
00198 
00199                 if (per < size) {
00200                         std::cout << '>';
00201                         per++;
00202                 }
00203 
00204                 for (unsigned int i = per; i < size; i++)
00205                         std::cout << ' ';
00206 
00207                 std::cout << ']';
00208         }
00209 
00210         void printRotatingBar()
00211         {
00212                 static const char* CHARS = "|/-\\";
00213 
00214                 std::cout << CHARS[m_rotatingBar];
00215 
00216                 m_rotatingBar = (m_rotatingBar + 1) % 4;
00217         }
00218 
00219         static const unsigned int MIN_TERM_SIZE = 80;
00220         static const int TIME_SIZE = 8;
00221 };
00222 
00223 }
00224 
00225 #endif // PROGRESSBAR_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends