I'm using the CLI-Progress package from:
https://www.npmjs.com/package/cli-progress.
This is my implementation according to the documentation example:
https://github.com/npkgz/cli-progress/blob/master/examples/example-visual.js)
const b1 = new progress.Bar({
format: colors.cyan('[{bar}]') + ' {percentage}% || {value}/{total} Chunks || Speed: {speed}',
barCompleteChar: '\u2588',
barIncompleteChar: '\u2591',
hideCursor: true,
});
b1.start(200, 0, {
speed: "N/A"
});
let value = 0;
const speedData: number[] = [];
const timer = setInterval(() => {
value++;
speedData.push(Math.random() * 2 + 5);
const currentSpeedData = speedData.splice(-10);
b1.update(value, {
speed: (currentSpeedData.reduce((a, b) => {
return a + b;
}, 0) / currentSpeedData.length).toFixed(2) + "Mb/s"
});
if (value >= b1.getTotal()) {
clearInterval(timer);
b1.stop();
}
}, 20);
Which renders :
I have two questions about this :
Why is there two bars (I would like to get rid of the first one) ?
Why does it work since the timer function is never called (it is called recursively but there is no first call) ?
Thank you.
Related
So for example I have an array with 3 waypoints:
[ [ 526, 1573, 24 ], [ 2224, 809, -1546 ], [ 6869, 96, -3074 ] ]
I also know I want to rest for lets say n times between between arriving at the first and last waypoint. So in the end I want an array of n points.
How do I go about finding those n resting-points in JS?
Thanks in advance!
EDIT: Note this is not a single object! Imagine each axis being one person. They have to stop the same amount of time and at the same time but they do not have to be at the same place obviously.
You want to use linear interpolation.
A quick example:
const POINTS = [ [ 526, 1573, 24 ], [ 2224, 809, -1546 ], [ 6869, 96, -3074 ] ];
const N = 10;
function getDistance(point1, point2) {
// speed in 3d space is mutated according only to the X distance,
// to keep speed constant in X dimension
return Math.abs(point1[0] - point2[0]);
}
function go(points, n) {
const pointDistances = points.slice(1).map((point, index) => getDistance(points[index], point));
const fullDistance = pointDistances.reduce((sum, distance) => sum + distance, 0);
const distancePerSection = fullDistance / n;
return points.slice(1)
.reduce((last, point, index) => {
const thisDistance = pointDistances[index];
const numRestPoints = Math.max(0, Math.floor(thisDistance / distancePerSection) - 1);
if (!numRestPoints) {
return last.concat([point]);
}
const thisYVector = point[1] - points[index][1];
const thisZVector = point[2] - points[index][2];
return last.concat(new Array(numRestPoints).fill(0)
.reduce((section, item, restIndex) => {
return section.concat([[
points[index][0] + (restIndex + 1) * distancePerSection,
points[index][1] + (restIndex + 1) * thisYVector * distancePerSection / thisDistance,
points[index][2] + (restIndex + 1) * thisZVector * distancePerSection / thisDistance
]]);
}, [])
.concat([point])
);
}, points.slice(0, 1));
}
function test() {
const result = go(POINTS, N);
if (result.length !== N) {
throw new Error('Must be N length');
}
if (!result[0].every((value, index) => value === POINTS[0][index])) {
throw new Error('Doesn\'t start at the first point');
}
if (!result[N - 1].every((value, index) => value === POINTS[POINTS.length - 1][index])) {
throw new Error('Doesn\'t end at the last point');
}
if (!POINTS.slice(1, N - 1).every(point =>
result.some(resultPoint => resultPoint.every((value, index) => value === point[index]))
)) {
throw new Error('Doesn\'t go through every provided point');
}
console.log(result.slice(1).map((point, index) => getDistance(point, result[index])));
console.log('The result passed the tests!');
console.log(JSON.stringify(result, null, 2));
}
test();
I'm basically going through the list of points, and determining if there should exist any rest points between them, inserting them if so.
Please comment if you want further clarification!
I also solved this problem now with linear interpolation:
My solution:
var waypoints = [[526,1573,24],[2224,809,-1546],[6869,96,-3074]];
var pauses = 20;
generateWaypopints();
function generateWaypopints(){
var newWaypoints = [];
var progressAtMainPoints = 1 / (waypoints.length - 1)
var pausesBetweenWaypoints = pauses * progressAtMainPoints;
var progressAtPauses = 1 / pausesBetweenWaypoints;
newWaypoints.push(waypoints[0]);
var sector = 0;
var pausesInSector = 0;
for(var i = 0; i < pauses; i++){
var progress = progressAtPauses * (pausesInSector + 1)
var x = Math.round(waypoints[sector][0] + (waypoints[sector + 1][0] - waypoints[sector][0]) * progress);
var y = Math.round(waypoints[sector][1] + (waypoints[sector + 1][1] - waypoints[sector][1]) * progress);
var z = Math.round(waypoints[sector][2] + (waypoints[sector + 1][2] - waypoints[sector][2]) * progress);
if(progress >= 1){
sector++;
pausesInSector = 0;
}else
pausesInSector++;
newWaypoints.push([x,y,z]);
}
console.log(newWaypoints);
return newWaypoints;
}
So I am looking to create look up tables. However I am running into a problem with integer ranges instead of just 1, 2, 3, etc. Here is what I have:
var ancient = 1;
var legendary = 19;
var epic = 251;
var rare = 1000;
var uncommon = 25000;
var common = 74629;
var poolTotal = ancient + legendary + epic + rare + uncommon + common;
var pool = general.rand(1, poolTotal);
var lootPool = {
1: function () {
return console.log("Ancient");
},
2-19: function () {
}
};
Of course I know 2-19 isn't going to work, but I've tried other things like [2-19] etc etc.
Okay, so more information:
When I call: lootPool[pool](); It will select a integer between 1 and poolTotal Depending on if it is 1 it will log it in the console as ancient. If it hits in the range of 2 through 19 it would be legendary. So on and so forth following my numbers.
EDIT: I am well aware I can easily do this with a switch, but I would like to try it this way.
Rather than making a huge lookup table (which is quite possible, but very inelegant), I'd suggest making a (small) object, choosing a random number, and then finding the first entry in the object whose value is greater than the random number:
// baseLootWeight: weights are proportional to each other
const baseLootWeight = {
ancient: 1,
legendary: 19,
epic: 251,
rare: 1000,
uncommon: 25000,
common: 74629,
};
let totalWeightSoFar = 0;
// lootWeight: weights are proportional to the total weight
const lootWeight = Object.entries(baseLootWeight).map(([rarity, weight]) => {
totalWeightSoFar += weight;
return { rarity, weight: totalWeightSoFar };
});
console.log(lootWeight);
const randomType = () => {
const rand = Math.floor(Math.random() * totalWeightSoFar);
return lootWeight
.find(({ rarity, weight }) => weight >= rand)
.rarity;
};
for (let i = 0; i < 10; i++) console.log(randomType());
Its not a lookup, but this might help you.
let loots = {
"Ancient": 1,
"Epic": 251,
"Legendary": 19
};
//We need loots sorted by value of lootType
function prepareSteps(loots) {
let steps = Object.entries(loots).map((val) => {return {"lootType": val[0], "lootVal": val[1]}});
steps.sort((a, b) => a.lootVal > b.lootVal);
return steps;
}
function getMyLoot(steps, val) {
let myLootRange;
for (var i = 0; i < steps.length; i++) {
if((i === 0 && val < steps[0].lootVal) || val === steps[i].lootVal) {
myLootRange = steps[i];
break;
}
else if( i + 1 < steps.length && val > steps[i].lootVal && val < steps[i + 1].lootVal) {
myLootRange = steps[i + 1];
break;
}
}
myLootRange && myLootRange['lootType'] ? console.log(myLootRange['lootType']) : console.log('Off Upper Limit!');
}
let steps = prepareSteps(loots);
let pool = 0;
getMyLoot(steps, pool);
I'm trying to create a 'beats per minute' (BPM) calculator, identical (for now) to the one you can find here. But for some reason, when I use the BPM calculator at that link on a test song, it gets within 1 BPM of the actual value of 85.94 within of 7 keypresses and just gets more accurate from there, ending within 0.05 of the actual BPM, whereas with my (essentially identically-coded) Vue.js version, it starts much higher (182-->126-->110) and goes down from there, but even after 60 keypresses it's still off by ~2 BPM, and after a full song, it was still off by about 0.37 BPM.
Here's the code for the plain-JavaScript version at that link:
var count = 0;
var msecsFirst = 0;
var msecsPrevious = 0;
function ResetCount()
{
count = 0;
document.TAP_DISPLAY.T_AVG.value = "";
document.TAP_DISPLAY.T_TAP.value = "";
document.TAP_DISPLAY.T_RESET.blur();
}
function TapForBPM(e)
{
document.TAP_DISPLAY.T_WAIT.blur();
timeSeconds = new Date;
msecs = timeSeconds.getTime();
if ((msecs - msecsPrevious) > 1000 * document.TAP_DISPLAY.T_WAIT.value)
{
count = 0;
}
if (count == 0)
{
document.TAP_DISPLAY.T_AVG.value = "First Beat";
document.TAP_DISPLAY.T_TAP.value = "First Beat";
msecsFirst = msecs;
count = 1;
}
else
{
bpmAvg = 60000 * count / (msecs - msecsFirst);
document.TAP_DISPLAY.T_AVG.value = Math.round(bpmAvg * 100) / 100;
document.TAP_DISPLAY.T_WHOLE.value = Math.round(bpmAvg);
count++;
document.TAP_DISPLAY.T_TAP.value = count;
}
msecsPrevious = msecs;
return true;
}
document.onkeypress = TapForBPM;
// End -->
And here's my version:
computed: {
tappedOutBpm: function() {
let totalElapsedSeconds = (this.timeOfLastBpmKeypress - this.timeOfFirstBpmKeypress) / 1000.0
let bpm = (this.numberOfTapsForBpm / totalElapsedSeconds) * 60.0
return Math.round(100*bpm)/100;
},
},
methods: {
tapForBPM: function() {
let now = new Date;
now = now.getTime();
// let now = window.performance.now()
if (this.timeOfFirstBpmKeypress === 0 || now - this.timeOfLastBpmKeypress > 5000) {
this.timeOfFirstBpmKeypress = now
this.timeOfLastBpmKeypress = now
this.numberOfTapsForBpm = 1
} else {
this.timeOfLastBpmKeypress = now
this.numberOfTapsForBpm++
}
}
}
I figured it out by stepping through both of our code.
The problem was that I was setting the number of taps to 1 as soon as the user tapped the key the first time, when in reality it's not taps that I want to count, but beats, and the first beat requires not one tap, but two: the start and the end of that beat. So what I should do is rename the variable to numberOfTappedOutBeats and set it to 0 after the first tap rather than 1.
I am trying to generate fixed length nonce (length 9).
But my code is printing sometimes nonce of 8 length and sometime 9 length.
this is what I am trying to do but with different approach (I have modified it for fixed nonce length)
I am not able to understand why it is printing nonce of length 8 when i am passing length as 9 as argument??
It would be great if someone can tell why this is happening.
Below is complete Nodejs code
var last_nonce = null;
var nonce_incr = null;
// if you call new Date to fast it will generate
// the same ms, helper to make sure the nonce is
// truly unique (supports up to 999 calls per ms).
module.exports = {
getNonce: function(length) {
if (length === undefined || !length) {
length = 8;
}
var MOD = Math.pow(10, length);
var now = (+new Date());
if (now !== last_nonce) {
nonce_incr = -1;
}
nonce_incr++;
last_nonce = now;
var nonce_multiplier = ((nonce_incr < 10) ? 10 : ((nonce_incr < 100) ? 100 : 1000));
var s = (((now % MOD) * nonce_multiplier) + nonce_incr) % MOD;
return s;
}
}
//test code
if(require.main === module) {
console.time("run time");
//importing async module
var async = require('async');
var arr = [];
//generating 1000 length array to use it in making 1000 async calls
//to getNonce function
for(var i=0; i<1000; i++) arr.push(i);
//this will call getNonce function 1000 time parallely
async.eachLimit(arr, 1000, function(item, cb) {
console.log(module.exports.getNonce(9));
cb();
}, function(err) {console.timeEnd("run time");});
}
Sample output:
708201864 --> nonce length 9
708201865
708201866
70820190 --> nonce length 8 (why it is coming 8?? when passed length is 9)
70820191
70820192
70820193
70820194
70820195
70820196
70820197
70820198
70820199
708201910
708201911
708201912
708201913
708201914
708201915
708201916
708201917
708201918
In case someone needs it, here is a nonce generator free from convoluted logic, allowing you to control both character sample and nonce size:
const generateNonce = (options) => {
const {
length = 32,
sample = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
} = options || {};
const getRand = () => Math.floor(Math.random() * sample.length);
return Array.from({ length }, () => sample.charAt(getRand())).join('');
};
If you prefer Typescript:
const generateNonce = (options?: { sample?: string, length?: number }) => {
const {
length = 32,
sample = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
} = options || {};
const getRand = () => Math.floor(Math.random() * sample.length);
return Array.from({ length }, () => sample.charAt(getRand())).join('');
};
Trying to create a function that lets you animate any number of numerical properties with a given easing function, but it doesn't quite work... calling it doesn't result in any motion. Everything is set up correctly as when I change what the values change to, it does show, so that means it's the equation that's the problem here. It's either not giving the right value, or not getting the right ones.
function animate(obj, props, options) {
var start = Date.now(),
total = start + options.duration,
diff = total - start,
vals = {},
id;
for (var v in props) {
vals[v] = props[v];
}
(function update() {
var curr = Date.now(),
progress = Math.min((options.duration - (total - curr)) / options.duration, 1);
for (var p in props) {
console.log(obj[p] = options.equation(curr, vals[p], obj[p] - vals[p], total));
}
if (progress < 1) {
id = requestAnimationFrame(update);
} else {
id = cancelAnimationFrame(id);
if (typeof options.callback === 'function') {
options.callback();
}
}
}());
}
animate(rect, {
x: map.width / 2,
y: map.height / 2
}, {
duration: 2000,
equation: function(t, b, c, d) {
return c * (t /= d) * t + b;
},
callback: function() {
console.log('Whoa... it works.'); // ...yeah, nope. ;(
}
});
t = time, b = beginning value, c = change in value, d = duration.
Am I giving it the wrong arguments? How would I make this work?
Your time & duration arguments should not be summed with Date.now().
If you want your easing to take 2000ms then send 2000 (d) into the easing equation.
The time to send into the easing equation is the elapsed time, so send Date.now()-startTime (t) into the easing equation.
I assume you have properly set the beginning value (b) and net change in value (c).