UNPKG

@beenotung/tslib

Version:
188 lines (187 loc) 6.18 kB
"use strict"; 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}`; }