I am currently solving the following JS challenge.
We want to display the progress that a TV show or ad has made.
We have already prepared a pretty cool progressbar to display the
progress. But the length of the progressbar and the duration of the
shows vary. Implement the getProgress(width:int, duration:int,
current:int) function that returns the position of the progressbar in
pixel, px.
As an example, the function call getProgress(500, 90, 16) should
return 89. Always round to the nearest whole number.
The problem here is, that I don't get the expected result 89 when I do the math. Why they expect 89 is a riddle to me...Below my code.
export function getProgress(width, duration, current) {
const currentMin = duration / 100 * current
const pixPerMin = width / duration
const currentPosition = currentMin * pixPerMin
return Math.ceil(currentPosition)
}
With my function I get 80 which should be correct - or at least I think it's correct. I am probably overlooking something or making a obvious mistake but can't see it.
The total duration is 90, and the current position is 16, so the process is around 18% complete:
console.log(16 / 90);
For a bar that's 500 pixels wide, 17.7778% of that is 88.88889 pixels:
const ratioDone = 16 / 90; // 0 to 1
console.log(500 * ratioDone);
That's where 89 comes from.
So you need:
function getProgress(width, duration, current) {
const ratioDone = current / duration;
return Math.round(ratioDone * width);
}
console.log(getProgress(500, 90, 16));
Related
I am developing an XP/Leveling system for a website. Think of it like Call of Duty levels.
For example
Level 1 = 0 - 100XP
Level 2 = 100 - 200XP
Level 3 = 200 - 300XP
Now obviously for level 1, since it's 100 level max, I can do
const currentXp = 50;
const nextLevel = 100;
function calculateProgress(currentXp ,nextLevel) {
return (currentXp / nextLevel) * 100;
}
// returns 50% (which is correct), this means the progress bar would be halfway full.
However, when you get past 100, this equation does not work anymore. For example,
const currentXp = 150
const nextLevel = 200
function calculateProgress(currentXp, nextLevel) {
return (currentXp / nextLevel) * 100;
}
// returns 75%, and the progress bar is 75% full, when it should be 50% full, because 150 is halfway in between 100 and 200 i.e 50% progress in between the levels.
This is where thinking of call of duty comes into play. I am trying to calculate the progress between 2 levels. Not simply the percentage a particular number is of another number.
I have spent numerous hours trying to come up with a solution and have utterly failed.
Any insight/advice/help would be so very much appreciated. Thank you so much for your time.
you should use:
((currentXp - previousLevel) / (nextLevel - previousLevel)) * 100
example:
((150 - 100) / (200 - 100)) * 100 = 50
I have this progress bar in JS and I'm filling up progress by increasing its width using this code:
function move(ValueSC) {
var elem = document.getElementById("scaleOrig");
var width = 0;
var internalVlue = ValueSC;
var id = setInterval(frame(internalVlue), 50);
function frame(internalVlue) {
if (width >= internalVlue) {
clearInterval(id);
} else {
width += internalVlue;
elem.style.width = width + '%';
}
}
}
This works perfectly but the problem is that I will get a value (result) from my calculator which is something between numbers 15 to 40, so with this stated 15 will be 0% and 40 will 100%. I want the width of progress bar to go up to 100 percent if the result (from my calculator) is 40 and if it is 15 the value of progress bar should be 0%. Basically I need the logic to convert all the 25 numbers from 15 to 40 to have a percentage value between 0 to 100%.
As a broader answer, the formula you're looking for is ((value - min) / (max - min)) * 100. max and min are the bounds of your value and value is the current progress. This will return the percentage of the progress so far for any given value between two other values.
var percent = ((value - 15) / (40 - 15)) * 100
40 will give you 100 and 15 will give you 0
Before you call your method do this:
ValueSC= ((Max-Min)/100)*(Current-Min))
Where:
Current: Your value
Min = Minimum Value
Max = Max Value
First you have to divide up 100 to smaller steps. There can be 25 (40-15) different values for your number, so the length of a step should be 100 / 25, and your starting number is 15. Something like this should work:
function getPercentage(number) {
return (number - 15) * (100 / 25);
}
My project currently features quizzes, which have a countdown timer using Javascript. This time then resets to 7 seconds after it has counted down fully or a the user selects a multiple-choice answer.
That function is working, but it just shows how much time is left, in text. I want to make a "bar" (think: column) that counts down (so, if a quiz gives you 7 seconds, the bar reduces 1/7th each time). jQuery and Javascript seem to be the easiest way to do this, so I added:
var height = 50;
var timePassed = 0;
var totalSeconds = 7;
var reduceHeight = function(elem, totalSeconds){
timePassed++;
height = 100 - (100/totalSeconds * timePassed);
elem.css({height: height + "%"});
if(height > 0){
window.setTimeout(function(){
reduceHeight(elem, totalSeconds)
}, 1000)
}
}
$(document).ready(function(){
var inner = $('#inner');
reduceHeight(inner, 20);
});
The bar now appears and does count down, but it is not completing reduceHeight at the correct rate.
Since I am defining the totalSeconds variable, it seems like it should since height is being set at 100/totalSeconds * timePassed. To reiterate, as the timer will run for 7 seconds, I would want it to become 1/7th smaller in each passing second.
Any idea where I went wrong?
I think your height calculation logic is incorrect
it should be
height = 100 - ( ( timePassed/totalSeconds ) * 100 );
since for example totalSeconds is 20 and timePassed is 10
then you height should be 50,
height = 100 - ( ( 10/20 ) * 100 ) = 50;
Which means that you need to
get the ratio of timePassed with totalSeconds
and then get the percentage out of that ratio
so that you can reduce that percentage value from 100
I have a logarithmic scale going from 0 to 100:
0.00
0.10
1.00
10.00
100.00
I need to make a pie chart which has 4 quarters.
the first is going from 0 to 0.10
the second is from 0.10 to 1 etc.etc.
So if I have the value 25, it should be calculated which percentage this is in the logarithmic scale. Considering the scale it should end up somewhere in the last quarter of the chart.
Unfortunately my understanding of Maths does not reach this far ;)
Could you help out and tell me where to start.
I thought of looking at each quarter as a 100% piece, and then calculate where this might be in this quarter..
per example:
32 > 10 so it should be in the last quarter (percentage wise above 75%)
So in this last quarter 32 will be in:
((32-10) x 100) / (100 - 10) = 24.44% in this quarter
Making this 24.44 / 4 = 6.11% over 4 quarters and thus 75 + 6.11 = 81.11% of the whole chart.
Now this would work, but I am looking for a shorter and simpler way of calculating this.
Can you please help out.
This is surely a maths question about plotting values on a logarithmic
scale, and not really anything to do with JavaScript in particular or
programming in general. Anyhow ...
You need to decide on a minimum value, since the logarithm of zero is
undefined. Once you have your maximum and minimum logarithms, you can
scale your values as you wish. Slightly ontopic: JavaScript has
Math.log10 in more up-to-date engines (and can be readily
defined if not, e.g. as in #NinaScholz's answer or using the polyfill here).
var minval = 0.01,
maxval = 100,
minlog = Math.log10(minval),
maxlog = Math.log10(maxval),
range = maxlog - minlog,
lineartolog = function(n){
return (Math.log10(n) - minlog) / range;
},
logplots = [
0.01,
0.1,
1,
3.2,
10,
32,
75,
100
].map(lineartolog);
document.body.innerHTML = '<pre>' + logplots + '</pre>';
Adjust as required for percentages, radians, etc.
Consideration:
q0 q1 q2 q3
01234567890123456789012345678901234567890
| | | | |
0.01 0.1 1 10 100
0.32 3.2 32
because log10(32) = 1.505 = 1 + 0.505
because log10(3.2) = 0.505 = 0 + 0.505
because log10(0.32) = -0,495 = -1 + 0.505
^ ^
quadrant after adding 2 amount to fill
together, fill is the amount in %:
function log10(f) {
return Math.log(f) / Math.log(10);
}
function getValue(v) {
var l = log10(v),
quadrant = Math.floor(l) + 2,
fill = (l - Math.floor(l)) * 100;
return { quadrant: quadrant, fill: fill };
}
console.log('0.32', getValue(0.32));
console.log('3.2', getValue(3.2));
console.log('32', getValue(32));
I'm using the jquery ui slider for zooming. It's supposed to zoom from 25% to %500, and about half of the range is used for the first %100 of the size.
The slider has values from 1 to 100. I need some function that can be used to calculate zooming based on the slider value, e.g.
function getZoom(sliderVal) {
//return number from 25 to 500
}
Any suggestions?
I think it's better for the user if you provide exponential fitting.
Javascript has Math.pow(a,b) which calculates ab.
The setting makes more sense if you map range [0,100] to [25%,400%], because then 50 is at the exact midpoint and can be made easily to map too 100%. 50 points on the slider then correspond to division or multiplication by four, so you can set
scaling = Math.pow(2,(slider - 50) / 25);
So then you get the mapping below:
slider scaling
------------------
0 2**-2 = 1/4 = 25%
25 2**-1 = 1/2 = 50%
50 2**0 = 1 = 100%
75 2**1 = 2 = 200%
100 2**2 = 4 = 400%
Now I see that this doesn't answer your question completely because your scale is [1,100] instead of [0,100], and you want to reach 500% instead of 400%.
To get there, you can first normalize the slider:
slider_n = (slider - 1) * (100/99);
(this maps [1,100] to [0,100]), and then, if you want, multiply positive values of the exponent by (log 5)/(log 4) so that your scale ends at 500%, i.e.
exp = (slider_n - 50) / 25.0;
if (exp > 0) exp = exp * Math.log(5)/Math.log(4);
scaling = Math.pow(2,exp);
Basically you want to rescale something from 1-100 to 25-500.
100-1 = 99
500-25 = 475
so that's your scaling factor - every point of difference on your slider is 475/99 points of difference on the zoom.
And the fixed offset is just 1 and 25, giving you a simple formula of:
f( slider_value ) =
( slider_value - 1 ) * ( 475 / 99 ) + 25
Of course, if you want to generalize, two scales from (a,b) to (c,d):
f( slider_value ) =
( slider_value - a ) * ( ( d - c ) / ( b - a ) ) + c
Now, if you want to do some kind of half-half thing, you can just use the above formula to divide the portions you want, and call different functions varying on the slider's value. As long as they are continuous (the values are the same for the border cases) it should feel fine.
For your case, try mapping 1-50.5 to 25%-100%, 50.5-100 to 100%-500%.