@beenotung/tslib
Version:
utils library in Typescript
188 lines (187 loc) • 6.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.startTimer = startTimer;
exports.defaultTimerWriteStream = defaultTimerWriteStream;
const format_1 = require("./format");
const node_1 = require("./node");
const number_1 = require("./number");
/**
* @description create timer with progress report and finish-time estimation
* */
function startTimer(options) {
let name;
let writeStream;
let sampleOver;
let estimateTime = false;
let sampleTimeInterval;
if (typeof options === 'string') {
name = options;
writeStream = defaultTimerWriteStream();
sampleOver = 1;
sampleTimeInterval = 5000;
}
else {
name = options.name;
writeStream = options.writeStream || defaultTimerWriteStream();
sampleOver = options.sampleOver || 1;
sampleTimeInterval = options.sampleTimeInterval ?? 5000;
}
let msgLen = 0;
const print = (msg) => {
if (writeStream.moveCursor) {
writeStream.moveCursor(-msgLen, 0);
}
writeStream.write(msg);
const newMsgLen = msg.length;
(0, node_1.eraseChars)(writeStream, msgLen - newMsgLen);
msgLen = newMsgLen;
};
let startTime;
const start = () => {
writeStream.write(new Date().toLocaleString() + ': ' + name);
print(' ...');
startTime = Date.now();
};
start();
const end = () => {
if (!name) {
return; // already ended before
}
print('');
if (writeStream.moveCursor) {
writeStream.moveCursor(-name.length, 0);
}
const usedTime = Date.now() - startTime;
writeStream.write(`${name}: ${(0, format_1.format_time_duration)(usedTime, 2)}\n`);
name = undefined;
};
let totalTick = 0;
let currentTick = 0;
let startTick;
let lastSampleTime = 0;
const progress = (msg) => {
print(msg);
};
const tickProgressWithoutEstimateTime = () => {
progress(` (${formatProgress(currentTick, totalTick)})`);
};
const tickProgressWithEstimateTime = () => {
const tickLeft = totalTick - currentTick;
const tickedAmount = currentTick - startTick;
const tickedTime = Date.now() - startTime;
const tickSpeed = tickedAmount / tickedTime;
const timeLeft = tickLeft / tickSpeed;
const timeLeftText = (0, format_1.format_time_duration)(timeLeft);
progress(` (${formatProgress(currentTick, totalTick)}, estimated time left: ${timeLeftText})`);
};
let tickProgress = estimateTime
? tickProgressWithEstimateTime
: tickProgressWithoutEstimateTime;
const setProgress = (totalTick_or_options, _initialTick, _sampleOver) => {
if (typeof totalTick_or_options === 'object') {
const option = totalTick_or_options;
totalTick = option.totalTick;
currentTick = option.initialTick || 0;
sampleOver = option.sampleOver || sampleOver;
if (typeof option.estimateTime === 'boolean') {
estimateTime = option.estimateTime;
tickProgress = estimateTime
? tickProgressWithEstimateTime
: tickProgressWithoutEstimateTime;
}
}
else {
totalTick = totalTick_or_options;
currentTick = _initialTick || 0;
if (_sampleOver) {
sampleOver = _sampleOver;
}
}
timer.tick = sampleOver === 1 ? tickWithOutSample : tickWithSample;
if (estimateTime) {
startTick = currentTick;
startTime = Date.now();
}
tickProgress();
};
const setEstimateProgress = (totalTick, sampleRate = 1 / 100) => {
setProgress({
totalTick: totalTick,
estimateTime: true,
sampleOver: totalTick * sampleRate,
});
};
const tickWithOutSample = (step = 1) => {
currentTick += step;
tickProgress();
};
const updateByInterval = () => {
const now = Date.now();
const passed = now - lastSampleTime;
if (passed >= sampleTimeInterval) {
lastSampleTime = now;
return true;
}
};
const tickWithSample = (step = 1) => {
const oldMod = currentTick % sampleOver;
currentTick += step;
const newMod = currentTick % sampleOver;
if (newMod === 0 ||
newMod < oldMod ||
(sampleTimeInterval > 0 && updateByInterval())) {
tickProgress();
}
};
const timer = {
end,
next(newName) {
end();
name = newName;
start();
},
get sampleTimeInterval() {
return sampleTimeInterval;
},
set sampleTimeInterval(
/** @description set zero or negative limit to disable update by interval */
value) {
sampleTimeInterval = value;
},
progress,
setProgress,
setEstimateProgress,
tick: sampleOver === 1 ? tickWithOutSample : tickWithSample,
};
return timer;
}
function defaultTimerWriteStream() {
if (typeof process !== 'undefined' && process.stdout) {
return process.stdout;
}
const writeStream = {};
writeStream.write = function () {
console.debug.apply(console, arguments);
return true;
};
return writeStream;
}
function formatProgress(current, total) {
const value = current / total;
let new_current = current;
let new_total = total;
if (!Number.isInteger(current) && (0, number_1.countFractionDigits)(current) > 2) {
new_current = +current.toFixed(2);
}
if (!Number.isInteger(total) && (0, number_1.countFractionDigits)(total) > 2) {
new_total = +total.toFixed(2);
}
const new_value = new_current / new_total;
if (value != new_value) {
const error = Math.abs(value - new_value);
if (error < 0.01) {
return `${new_current}/${new_total}`;
}
}
return `${current}/${total}`;
}