function ChangePts(pts) {
this.pts = pts;
this.win = function() {
console.log(this.pts + 30)
return this.pts += 30
}
this.lose = function() {
console.log(this.pts - 30)
return this.pts -= 30;
}
};
I made it to calculate how many games you need to lose, to get certain ratingw with while loop. This implies that win% is 0%, how do I calculate amount of games if we declare starting pts for example 5000, how many games it takes to get to 1000 pts if your winrate is 27%
P.S.: For this case I need only negative amount of win%.
You can just calculate it like this (variables should be explanation enough). There is no real coding necessary for it, just math calculations
const winRate = 0.27
const loseRate = 1-winRate
const pointsWin = 30
const pointsLose = 30
const startingPoints = 5000
const targetPoints = 1000
const pointsGainedOnAverage = pointsWin*winRate - pointsLose*loseRate
const pointsDistance = targetPoints - startingPoints
const games = pointsDistance / pointsGainedOnAverage
console.log('games', games)
From MDN, I have this:
Be sure to always use the first argument (or some other method for
getting the current time) to calculate how much the animation will
progress in a frame, otherwise the animation will run faster on high
refresh rate screens.
With this, Can I assume that with a 144hz monitor, for instance, I could have requestAnimationFrame running faster than 60 fps?
Exactly true.
Here is a simple example to measure:
let i = 0;
const start = Date.now();
const stop = start + 5000;
function raf() {
requestAnimationFrame(() => {
const now = Date.now();
if (now < stop){
i++;
raf();
}else{
const elapsedSeconds = (now - start) / 1000;
console.log('Frame rate is: %f fps', i / elapsedSeconds);
}
});
}
console.log('Testing frame rate...')
raf();
On my machine, it shows 143.7401178670024. And I am using 144HZ monitor.
I've encountered this problem and still trying to solve this problem:
You want to log the number of hits to a site.
Implement two functions,
log_hit() which gets called when a hit is registered, and
get_hits_in_last_five_minutes() which returns the total number of hits
in the last five minutes.
Assume that all timestamps come in increasing order.
My idea (attempt to solve the problem):
Datastructure: Array.
My Logic:
When log_hit() is called, we basically store the time in ms (Date().getTime() in ms) in the array and store the hits on the particular second in hashmap.
function Counter() {
this.map = {};
this.store = [];
}
Counter.prototype.log_hit = function() {
const d = new Date().getTime()/1000;
this.store.push(d);
this.map[d] = this.map[d] ? this.map[d]++ : 1;
}
Counter.prototype.get_hits_in_last_five_minutes = function() {
const fiveMin = 60 * 60; //seconds.
const initalPointer = new Date().getTime() / 1000 - fiveMin;
// Somehow retrieve the value and return it back
}
However, I don't think this is the most optimal way of solving it , if I wanted to extend the solution for hour or some other granularity.
How would I solve this kind of problem?
Using queue would be the right way to deal with this problem.
var HitCounter = function() {
this.queue = [];
};
/**
* Record a hit.
#param timestamp - The current timestamp (in seconds granularity).
* #param {number} timestamp
* #return {void}
*/
HitCounter.prototype.hit = function(timestamp) {
this.queue.push(timestamp);
};
/**
* Return the number of hits in the past 5 minutes.
#param timestamp - The current timestamp (in seconds granularity).
* #param {number} timestamp
* #return {number}
*/
HitCounter.prototype.getHits = function(timestamp) {
while(this.queue.length && this.queue[0] <= timestamp-300) {
this.queue.shift();
}
return this.queue.length;
};
const counter = new HitCounter();
counter.hit(1);
counter.hit(2);
counter.hit(3);
counter.getHits(4);
counter.hit(300);
counter.getHits(300);
console.log(counter.getHits(301)); // should output 3.
We need to exploit this fact-
Assume that all timestamps come in increasing order.
Algorithm:
We record every hit in an array and increase it's size gradually by 1.
To get the no. of hits in the last 5 minutes(excluding current hit), we do a binary search to get our answer since all timestamps come in increasing order, which would be sorted by default.
First, we do a binary search on the array to get the last valid upper bound index with respect to time t provided to get_hits_in_last_five_minutes().
Upper bound used is the limit till which we could use the hits to judge the no. of calls in the last 5 minutes. This is necessary because the problem statement says get_hits_in_last_five_minutes() which returns the total number of hits in the last five minutes. So, technically it means that it will be used as an API to check how many calls were made till 5 minutes prior to the parameter passed time t. It doesn't guarantee that the time t passed to this method will always be the last inserted timestamp in the counter. Due to this, we need to search for the upper bound in the array, i.e, till which index the hits stored in the array could be counted as valid for our answer.
Second, we do a binary search from 0 till upper_bound to get all the valid hits that were under last 5 minutes prior to t.
Space complexity: O(n) where n is the no. of hits registered.
Time Complexity:
O(log(n)) to search for the upper bound.
O(log(n)) to get the actual hits registered in last 5 minutes.
Total Complexity = O(log(n)) + O(log(n)) = 2 * O(log(n)) = O(log(n))
Note: I converted time t in to seconds while storing and searching.
Code:
function Counter() {
this.hits = [];
this.hits_size = 0;
}
Counter.prototype.log_hit = function(t) {
this.hits[this.hits_size++] = t * 60;
}
Counter.prototype.get_hits_in_last_five_minutes = function(t) {
if (this.hits_size < 2) return 0;
t *= 60;
var upper_bound = this.getUpperBound(t);
this.last_call_type = 2;
var low = 0,
high = upper_bound;
while (low <= high) {
var mid = low + parseInt((high - low) / 2);
if (this.hits[mid] > t - 300) high = mid - 1;
else if (this.hits[mid] < t - 300) low = mid + 1;
else return upper_bound - mid + 1;
}
return upper_bound - low + 1;
}
Counter.prototype.getUpperBound = function(t) {
var low = 0,
high = t > this.hits[this.hits_size - 1] ? this.hits_size - 1 : this.hits_size - 2;
var ans = 0;
while (low <= high) {
var mid = low + parseInt((high - low) / 2);
if (this.hits[mid] >= t) {
high = mid - 1;
} else {
ans = mid;
low = mid + 1;
}
}
if (high < 0) return -1;
return ans;
}
console.log("*****Counter 1******");
var c1 = new Counter();
c1.log_hit(1);
console.log("Registered, 1 = " + c1.get_hits_in_last_five_minutes(1));
c1.log_hit(2);
console.log("Registered, 2 = " + c1.get_hits_in_last_five_minutes(2));
c1.log_hit(3);
console.log("Registered, 3 = " + c1.get_hits_in_last_five_minutes(3));
c1.log_hit(4);
console.log("Registered, 4 = " + c1.get_hits_in_last_five_minutes(4));
c1.log_hit(5);
console.log("Registered, 5 = " + c1.get_hits_in_last_five_minutes(5));
c1.log_hit(6);
console.log("Registered, 6 = " + c1.get_hits_in_last_five_minutes(6));
c1.log_hit(7);
console.log("Registered, 7 = " + c1.get_hits_in_last_five_minutes(7));
c1.log_hit(8);
console.log("Registered, 8 = " + c1.get_hits_in_last_five_minutes(8));
c1.log_hit(9);
console.log("Registered, 9 = " + c1.get_hits_in_last_five_minutes(9));
c1.log_hit(10);
console.log("Registered, 10 = " + c1.get_hits_in_last_five_minutes(10));
console.log("*****Counter 2******");
var c2 = new Counter();
c2.log_hit(2);
console.log("Registered, 2 = " + c2.get_hits_in_last_five_minutes(2));
c2.log_hit(7);
console.log("Registered, 7 = " + c2.get_hits_in_last_five_minutes(7));
c2.log_hit(8);
console.log("Registered, 8 = " + c2.get_hits_in_last_five_minutes(8));
c2.log_hit(9);
console.log("Registered, 9 = " + c2.get_hits_in_last_five_minutes(9));
c2.log_hit(10);
console.log("Registered, 10 = " + c2.get_hits_in_last_five_minutes(10));
c2.log_hit(11);
console.log("Registered, 11 = " + c2.get_hits_in_last_five_minutes(11));
c2.log_hit(12);
console.log("Registered, 12 = " + c2.get_hits_in_last_five_minutes(12));
c2.log_hit(17);
console.log("Registered, 17 = " + c2.get_hits_in_last_five_minutes(17));
console.log("Unregistered, 18 = " + c2.get_hits_in_last_five_minutes(18));
c2.log_hit(19);
console.log("Registered, 19 = " + c2.get_hits_in_last_five_minutes(19));
console.log("Unregistered, 20 = " + c2.get_hits_in_last_five_minutes(20));
c2.log_hit(21);
console.log("Registered, 21 = " + c2.get_hits_in_last_five_minutes(21));
console.log("Unregistered, 6 = " + c2.get_hits_in_last_five_minutes(6));
console.log("Unregistered, 500 = " + c2.get_hits_in_last_five_minutes(500));
console.log("Unregistered, 15 = " + c2.get_hits_in_last_five_minutes(15));
console.log("Registered, 17 = " + c2.get_hits_in_last_five_minutes(17));
Why binary search?
You might wonder as to why not loop backwards and get all those values' count that are under t - 300. This way, it could be O(1) per call.
Note that our search space is just under t - 300. If this increases, for example, t - 9000 then our backward iteration also increases till 9000, and if the number of calls for get_hits_in_last_five_minutes() happens to be 10000 or more, then the complexity of just looping multiplies to the overall complexity. So, it could be
10000 calls to get_hits_in_last_five_minutes() * 9000
If we use the algorithm described above, it will be
10000 calls to get_hits_in_last_five_minutes() * log(n)
What if the calls are never ending(Infinite)?
This depends upon how we choose to use the get_hits_in_last_five_minutes() method.
If time t passed to the calls made to get_hits_in_last_five_minutes() will always be in non-decreasing manner, then we could truncate/remove hits from our storage.
To do that, we can again do a binary search to get the index of the maximum value from our storage that doesn't come under t - 300. After that, we could just do an array slice and reset this.hits_size to the new length.
We need to do this in log_hit() method and not get_hits_in_last_five_minutes() since time t passed to it need not necessarily be a part of our registered hits.
Using array slice could add up to the complexity a bit since it returns a shallow copy of the original array and it's complexity is O(N) where N is end - start. See array slice complexity. To avoid this, we can make a linked list and store data in it and use a map to store the nodes. This way, we could reset the list's head and make the trimming/truncating O(1). We will need to maintain a count of truncated nodes too as we can't reset the map with new values.
If the time t passed to the calls made to get_hits_in_last_five_minutes() for your website are in any random order, then we can't truncate anything since we need all data to give an answer. In that case, probably store data in the database. The good part is, you could just query your answer from DB and instead of doing computation in javascript.
I'm working on a game loop and can't get past a specific issue: A bunch of objects start with an incremented delay and should move a certain distance.
The expected behaviour is that all objects should move in an even diagonal line, yet they move in uneven groups.
I realize the issue lies in 16.667ms interval updates which "groups" objects in update cycles. Is it possible to achieve sub-17ms precision?
I have tried separating update and render methods and run the update inside a delta while loop - all to no avail.
Here's the relevant part from the tick function:
function tick() {
if (this._stopped) return;
let now = performance.now();
if (now < this._lastTick + this._interval - 1) {
this._rafId = requestAnimationFrame(this.tick);
return;
}
this._rafId = requestAnimationFrame(this.tick);
let frameTime = (now - this._lastTick);
this._lastTick = now;
this._delta += frameTime;
let acc = 0;
while (this._delta >= this._interval) {
this._delta -= this._interval;
//this.update(this._interval);
acc++;
}
this.update(acc * this._interval);
//this.render(time);
this.count++;
}
Here's the codepen.
Would really appreciate any input.
First of all, I have to warn you, my English is not so good...
OK, here is my problem: I have a progress bar that gets wider every second based on percents.
Every second I want to add 1.67 / [max] percent.
[max] = 100% (how many minutes it'll take).
(if [max] = 10 - the progress bar will take 10 minutes)
My code WORKS, but only if the number (after dividing) is bigger than 0.3 (something like that).
So it means that if the progress bar will take 1 minute ([max] = 1) the code will work, because the number is 1.67 after dividing.
But if I make max to be 15 minutes, it wont work - WHY?!
This is my code: (I added some comments to make it easier)
<script>
function updateProgress() {
/*Get Progress Width (in percents)*/ var progress = ( 100 * parseFloat($('#arena_bar').css('width')) / parseFloat($('#arena_bar').parent().css('width')) );
var corrent = progress;
var max = 1; // one minute
var add = 1.67 / max;
if (progress < 100) {
corrent += add;
$("#arena_bar").css("width", corrent + "%");
setTimeout(updateProgress, 1000); // update every second
}
}
updateProgress();
</script>
Please Help !
The problem is that you're not making the width grow enough for the percentage to change in CSS, so it stays constant (at least that's what it looks like). The thing is, you don't really need all that.
Here's a js fiddle of your code, changed to work. I changed the time delay to make it run faster, you can change it back to 1000ms if you want.
And the code:
HTML:
<div style="width:400px; background-color:black">
<div id="arena_bar" style="background-color:navy; width:10px"> </div>
</div>
JS:
/*Get Progress Width (in percents)*/ var corrent = ( 100 * parseFloat($('#arena_bar').css('width')) / parseFloat($('#arena_bar').parent().css('width')) );
function updateProgress() {
var max = 15; // one minute
var add = 1.67 / max;
if (corrent < 100) {
corrent += add;
$("#arena_bar").css("width", corrent + "%");
setTimeout(updateProgress, 50); // update every second
}
}
updateProgress();
For the record, jQuery is not setting your computed widths as real percentage values, it sets them using pixel values.
In this example you can see your written widths and the read ones.
function updateProgress() {
var progress = (parseInt($('#arena_bar').css('width')) / parseInt($('#arena_bar').parent().css('width')))*100;
$('.progress').text('Read: ' + progress + ' %');
var max = 1;
var add = 1.67 / max;
if (progress < 100) {
progress += add;
$('.debug').html('Written: ' + progress + ' %');
$("#arena_bar").css("width", progress + "%");
setTimeout(updateProgress, 1000); // update every second
}
}
updateProgress();
http://jsfiddle.net/9PjqZ/1/
As you can see there is a difference to the values when you read them in the next function call. There are no problems when the difference between written and read values is above an unknown limit. When they come too close to each other your idea won't work anymore.
You need to save the current percentage outside the css and only write to css but not read from css.