transfer-stats
Version:
Track download/upload and provide transfer stats
165 lines (137 loc) • 4.72 kB
JavaScript
'use strict';
/**
* Track download/upload and provide transfer stats
*/
const FixedArray = require('fixed-array');
module.exports = class Transfer {
constructor(options) {
this.bpsLog = FixedArray(5);
const settings = typeof options === 'object' ? options : {};
this.bytesTotal = typeof settings.bytesTotal === 'number' ? settings.bytesTotal : null;
this.bytesCompleted = typeof settings.bytesCompleted === 'number' ? settings.bytesCompleted : 0;
this.lastBytesCompleted = this.bytesCompleted;
this.startDateTime = null;
this.pausedTotalTime = 0;
this.started = false;
this.finished = false;
this.paused = false;
const klass = this;
this.stats = {
get started() {
return klass.started;
},
get paused() {
return klass.paused;
},
get finished() {
return klass.finished;
},
get bytesTotal() {
return klass.bytesTotal;
},
get bytesCompleted() {
return klass.bytesCompleted;
},
get startDateTime() {
return klass.startDateTime;
},
get endDateTime() {
return klass.endDateTime;
},
get percentage() {
const bytesRemaining = this.bytesRemaining,
bytesTotal = this.bytesTotal;
if (typeof bytesRemaining !== 'number' || typeof bytesTotal !== 'number') return null;
return parseFloat((1 - bytesRemaining / bytesTotal).toFixed(10));
},
get bytesRemaining() {
const bytesTotal = this.bytesTotal,
bytesCompleted = this.bytesCompleted;
if (typeof bytesTotal !== 'number') return null;
return bytesTotal - bytesCompleted;
},
get msElapsed() {
const startDateTime = this.startDateTime;
if (!startDateTime) return 0;
const currentDateTime = new Date().getTime();
return currentDateTime - klass.pausedTotalTime - startDateTime;
},
get bytesPerSecond() {
const bpsLog = klass.bpsLog;
const mean = bpsLog.mean();
if (mean < 0.0001) return 0;
return mean;
},
get bytesPerSecondSharp() {
// Get's the exact BPS of the last update rather than the mean of the last 5
const bpsLog = klass.bpsLog;
const bpsArr = bpsLog.values();
return bpsArr[bpsArr.length - 1];
},
get msTotal() {
const bytesPerSecond = this.bytesPerSecond,
bytesTotal = this.bytesTotal;
if (typeof bytesTotal !== 'number') return null;
return Math.floor(bytesTotal / bytesPerSecond * 1000);
},
get msRemaining() {
const msTotal = this.msTotal,
msElapsed = this.msElapsed,
bytesRemaining = this.bytesRemaining;
if (typeof msTotal !== 'number') return null;
if (bytesRemaining === 0) return 0;
return msTotal - msElapsed;
}
};
}
updateBytes(newBytesCompleted) {
if (!this.started) {
throw new Error('Transfer not started. Call start() before you call updateBytes()');
}
if (!this.paused) {
const lastBytesCompleted = this.bytesCompleted || 0;
const currentTime = new Date().getTime();
const lastUpdatedDateTime = this.updatedDateTime || new Date().getTime();
const updatedDateTime = currentTime;
const bps = (newBytesCompleted - lastBytesCompleted) / (updatedDateTime - lastUpdatedDateTime) * 1000;
this.bpsLog.push(bps);
this.lastUpdatedDateTime = lastUpdatedDateTime;
this.updatedDateTime = updatedDateTime;
this.lastBytesCompleted = lastBytesCompleted;
}
this.bytesCompleted = newBytesCompleted;
}
start() {
this.started = true;
if (!this.startDateTime) {
const currentTime = new Date().getTime();
this.startDateTime = currentTime;
this.lastUpdatedDateTime = currentTime;
this.updatedDateTime = currentTime;
}
}
pause() {
const paused = this.paused;
if (paused) return;
const currentTime = new Date().getTime();
this.pausedStartDateTime = currentTime;
this.bpsLog = FixedArray(5);
this.paused = true;
}
resume() {
const pausedStartDateTime = this.pausedStartDateTime,
pausedTotalTime = this.pausedTotalTime,
paused = this.paused;
if (!paused) return;
const currentTime = new Date().getTime();
const msPauseDuration = currentTime - (pausedStartDateTime || 0);
this.pausedTotalTime = pausedTotalTime + msPauseDuration;
this.updatedDateTime = currentTime;
this.paused = false;
}
finish() {
this.finished = true;
this.started = false;
this.endDateTime = new Date().getTime();
}
};