progress_meter.C

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 // Unix headers
00021 #include <sys/time.h>
00022 #include <unistd.h>
00023 
00024 // ANSI-C headers
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 
00028 // ANSI-C++ headers:
00029 #include <iostream>
00030 
00031 #include <archon/util/time.H>
00032 #include <archon/util/progress_meter.H>
00033 
00034 
00035 namespace Archon
00036 {
00037   namespace Utilities
00038   {
00039     ProgressBase::ProgressBase(unsigned long totalWorkUnits):
00040       totalWorkUnits(totalWorkUnits), completedWorkUnits(0),
00041       updateTime(getTimeInMilliSeconds()),
00042       skippedWorkUnits(0), workUnitsPerUpdate(1) {}
00043 
00044     unsigned long ProgressBase::getTimeInMilliSeconds()
00045     {
00046       return Time::now().getMilliSeconds();
00047     }
00048 
00049     void ProgressBase::update()
00050     {
00051       if(completedWorkUnits == totalWorkUnits) return;
00052 
00053       skippedWorkUnits = 0;
00054       completedWorkUnits += workUnitsPerUpdate;
00055 
00056       // Estimate how many ticks to skip until next update
00057       const unsigned long now = getTimeInMilliSeconds();
00058       unsigned long timeSinceLastUpdate = now - updateTime;
00059       if(timeSinceLastUpdate == 0) timeSinceLastUpdate = 1;
00060       workUnitsPerUpdate = int(double(workUnitsPerUpdate) / timeSinceLastUpdate * millisBetweenUpdates);
00061       if(workUnitsPerUpdate == 0) workUnitsPerUpdate = 1;
00062       if(workUnitsPerUpdate > totalWorkUnits - completedWorkUnits) workUnitsPerUpdate = totalWorkUnits - completedWorkUnits;
00063 
00064       updateTime = now;
00065 
00066       display();
00067     }
00068 
00069     void ProgressBar::display()
00070     {
00071       const div_t d = div(static_cast<int>(width * 10 * static_cast<float>(completedWorkUnits)/totalWorkUnits), 10);
00072 
00073       std::cout << leadText << "|";
00074       int i=0;
00075       while(i<d.quot) ++i, std::cout << "#";
00076       if(extraResolution && i<width) ++i, std::cout << static_cast<char>(d.rem + '0');
00077       while(i<width) ++i, std::cout << "-";
00078       std::cout << "|";
00079 
00080       if(completedWorkUnits == totalWorkUnits) std::cout << "\n";
00081       else std::cout << std::flush << "\r";
00082     }
00083 
00084     void ProgressStatus::display()
00085     {
00086       char buffer[64];
00087 
00088       const float fraction = static_cast<float>(completedWorkUnits)/totalWorkUnits;
00089 
00090       sprintf(buffer, "%.1f", fraction*100);
00091       std::cout << leadText << completedWorkUnits << "/" << totalWorkUnits << ", " << buffer << "%, ";
00092 
00093       const unsigned long elapsedTime = updateTime - startTime;
00094       if(elapsedTime >= millisUntilFirstTotalTimeEstimate)
00095       {
00096         const unsigned long totalTime = static_cast<unsigned long>(elapsedTime/fraction);
00097 
00098         int seconds, minutes, hours;
00099         div_t d;
00100 
00101         seconds = (totalTime-elapsedTime)/1000;
00102         d = div(seconds, 60);
00103         seconds = d.rem;
00104         d = div(d.quot, 60);
00105         minutes = d.rem;
00106         hours = d.quot;
00107         sprintf(buffer, "%02d:%02d:%02d", hours, minutes, seconds);
00108         std::cout << "time left: " << buffer << ", ";
00109 
00110         seconds = totalTime/1000;
00111         d = div(seconds, 60);
00112         seconds = d.rem;
00113         d = div(d.quot, 60);
00114         minutes = d.rem;
00115         hours = d.quot;
00116         sprintf(buffer, "%02d:%02d:%02d", hours, minutes, seconds);
00117         std::cout << "time total: " << buffer;
00118       }
00119       else std::cout << "time left: ??:??:??, time total: ??:??:??";
00120 
00121       if(completedWorkUnits == totalWorkUnits) std::cout << "\n";
00122       else std::cout << std::flush << "  \r";
00123     }
00124   }
00125 }

Generated on Sun Jul 30 22:55:45 2006 for Archon by  doxygen 1.4.4