made the time description more malleable ,added support for none size update estimation (ie.. deletion), made the estimation more responsive at start and less jittery after some time

This commit is contained in:
Eran 2014-05-14 10:55:04 +03:00
parent 71ea2b582c
commit 1509c4ffba
4 changed files with 64 additions and 38 deletions

View file

@ -405,12 +405,10 @@ void ownCloudGui::slotUpdateProgress(const QString &folder, const Progress::Info
QString totalSizeStr = Utility::octetsToString( progress._totalSize );
if(progress._totalSize == 0 ) {
quint64 completedSize = progress.completedSize();
quint64 currentFile = progress._completedFileCount + progress._currentItems.count();
QString completedSizeStr = Utility::octetsToString( completedSize );
_actionStatus->setText( tr("Syncing %1 of %2 ( %3 of %4 )")
_actionStatus->setText( tr("Syncing %1 of %2 ( %3 left )")
.arg( currentFile ).arg( progress._totalFileCount )
.arg( completedSizeStr, totalSizeStr ) );
.arg( Utility::timeToDescriptiveString(progress.totalEstimate().getEtaEstimate()) ) );
} else {
_actionStatus->setText( tr("Syncing %1 ( %2 left )")
.arg( totalSizeStr )

View file

@ -45,20 +45,22 @@ namespace Progress
// Should this be in a separate file?
struct EtaEstimate {
EtaEstimate() : _startedTime(QDateTime::currentMSecsSinceEpoch()), _agvEtaMSecs(0),_effectivProgressPerSec(0) {}
EtaEstimate() : _startedTime(QDateTime::currentMSecsSinceEpoch()), _agvEtaMSecs(0),_effectivProgressPerSec(0),_sampleCount(1) {}
static const int AVG_DIVIDER=10;
static const int MAX_AVG_DIVIDER=120;
static const int INITAL_WAIT_TIME=5;
quint64 _startedTime ;
quint64 _agvEtaMSecs;
quint64 _effectivProgressPerSec;
quint16 _sampleCount;
/**
* reset the estiamte.
*/
void reset() {
_startedTime = QDateTime::currentMSecsSinceEpoch();
_sampleCount =1;
_effectivProgressPerSec = _agvEtaMSecs = 0;
}
@ -71,6 +73,7 @@ namespace Progress
quint64 elapsedTime = QDateTime::currentMSecsSinceEpoch() - this->_startedTime ;
//don't start until you have some good data to process, prevents jittring estiamtes at the start of the syncing process
if(total != 0 && completed != 0 && elapsedTime > INITAL_WAIT_TIME ) {
if(_sampleCount < MAX_AVG_DIVIDER) { _sampleCount++; }
// (elapsedTime-1) is an hack to avoid float "rounding" issue (ie. 0.99999999999999999999....)
_agvEtaMSecs = _agvEtaMSecs + (((static_cast<float>(total) / completed) * elapsedTime) - (elapsedTime-1)) - this->getEtaEstimate();
_effectivProgressPerSec = ( total - completed ) / (1+this->getEtaEstimate()/1000);
@ -82,7 +85,7 @@ namespace Progress
* @return quint64 the estimate amount of milliseconds to end the process.
*/
quint64 getEtaEstimate() const {
return _agvEtaMSecs / AVG_DIVIDER;
return _agvEtaMSecs / _sampleCount;
}
/**
@ -113,6 +116,7 @@ namespace Progress
}
_completedFileCount++;
_lastCompletedItem = item;
this->updateEstimation();
}
void setProgressItem(const SyncFileItem &item, quint64 size) {
@ -120,10 +124,18 @@ namespace Progress
_currentItems[item._file]._completedSize = size;
_lastCompletedItem = SyncFileItem();
_totalEtaEstimate.updateTime(this->completedSize(),this->_totalSize);
this->updateEstimation();
_currentItems[item._file]._etaEstimate.updateTime(size,item._size);
}
void updateEstimation() {
if(this->_totalSize > 0) {
_totalEtaEstimate.updateTime(this->completedSize(),this->_totalSize);
} else {
_totalEtaEstimate.updateTime(this->_completedFileCount,this->_totalFileCount);
}
}
quint64 completedSize() const {
quint64 r = _completedSize;
foreach(const ProgressItem &i, _currentItems) {

View file

@ -455,32 +455,45 @@ qint64 Utility::qDateTimeToTime_t(const QDateTime& t)
QString Utility::timeToDescriptiveString(quint64 msecs)
{
QList<QPair<QString,quint32> > timeMapping = QList<QPair<QString,quint32> >();
//timeMapping.append(QPair<QString,quint32>("years",86400*365));
//timeMapping.append(QPair<QString,quint32>("months",86400*30));
//timeMapping.append(QPair<QString,quint32>("days",86400));
timeMapping.append(QPair<QString,quint32>("years",86400*365));
timeMapping.append(QPair<QString,quint32>("months",86400*30));
timeMapping.append(QPair<QString,quint32>("days",86400));
timeMapping.append(QPair<QString,quint32>("hours",3600));
timeMapping.append(QPair<QString,quint32>("minutes",60));
timeMapping.append(QPair<QString,quint32>("seconds",1));
return timeToDescriptiveString(timeMapping, msecs, 1);
}
QString Utility::timeToDescriptiveString(QList<QPair<QString,quint32> > &timeMapping, quint64 msecs, quint8 precision)
{
quint64 secs = msecs / 1000;
QString units = "seconds";
qint64 minor =-1, major = -1;
QString retStr = "0 seconds"; // default value in case theres no actual time in msecs.
qint64 values[6];
int idx = 0;
QList<QPair<QString,quint32> >::Iterator itr = timeMapping.begin();
for(; itr != timeMapping.end(); itr++) {
major = secs / itr->second;
secs -= (major * itr->second);
if(major > 0 ) {
units = itr->first;
break;
for(QList<QPair<QString,quint32> >::Iterator itr = timeMapping.begin(); itr != timeMapping.end() && idx <= precision; itr++) {
quint64 result = secs / itr->second;
if(idx == 0) {
if(result == 0 ) {
continue;
} else {
retStr = itr->first;
retStr.prepend(" ");
}
}
secs -= result * itr->second;
values[idx++] = result;
}
for(idx--; idx >= 0; idx--) {
retStr = retStr.prepend("%1").arg(values[idx], 2, 10, QChar('0'));
if(0 < idx) {
retStr.prepend(":");
}
if(itr < timeMapping.end() ) {
minor = secs / (++itr)->second;
}
return (QString("%1").arg(major)).append(minor > -1 ? QString(":%1").arg(minor, 2, 10, QChar('0')) : "" ).append(" ").append(units);
return retStr;
}

View file

@ -61,12 +61,15 @@ namespace Utility
QDateTime qDateTimeFromTime_t(qint64 t);
qint64 qDateTimeToTime_t(const QDateTime &t);
QString timeToDescriptiveString(quint64 msecs);
/**
* Convert milliseconds to HMS string.
* @param quint64 msecs the milliseconds to convert to string
* @brief Convert milliseconds to HMS string.
* @param quint64 msecs the milliseconds to convert to string.
* @param uint precision the amount of sub dviving scale to include in the result.
* @return an HMS representation of the milliseconds value.
*/
QString timeToDescriptiveString(quint64 msecs);
QString timeToDescriptiveString(QList<QPair<QString,quint32> > &timeMapping, quint64 msecs, quint8 precision);
// convinience OS detection methods
bool isWindows();