Progressbar made of characters - javascript

I have been trying to get a progress bar representation that looks like this:
The user has to enter an input, and as of the input, the loop will run and get to a 100%.
Enter State: 70
[####### ] 70 %
[######## ] 80 %
[######### ] 90 %
[##########] 100 %
Here is what I have ade so far, but I am stuck now:
let hashtag = "";
for (let i = 1; i <= 3; i++) {
hashtag += "#";
}
console.log(
"[" + hashtag + " ",
" ",
" ",
" ",
" ",
" ",
" " + "]" + " " + "30%"
);
Any ideas of how to solve this problem? I a a total beginner, please go easy on me" :)

Math.floor() the percent value
Use String.prototype.repeat() to create the hashes "#"
Use String.prototype.padEnd() to fill the remaining spaces " "
const generateOutput = (pct, width = 10) => {
const flr = Math.floor(pct * width / 100);
const str = "#".repeat(flr).padEnd(width, " ");
return `[${str}] ${pct}%`;
};
// Example 90% (width 10)
console.log(generateOutput(90));
// Example 80% (width 30)
console.log(generateOutput(80, 30));
Given the above Formatted String generator, if you need a loop that will change the output:
const generateOutput = (pct, width = 10) => {
const flr = Math.floor(pct * width / 100);
const str = "#".repeat(flr).padEnd(width, "-");
return `[${str}] ${pct}%`;
};
const EL_output = document.querySelector("#output");
const step = 1; // Increment step
const width = 30; // Progressbar width
const time = 80; // Timeout ms
const progress = (val) => {
EL_output.textContent = generateOutput(val, width);
if (val >= 100) return; // Stop
setTimeout(() => progress(val += step), time);
};
// DEMO TIME! Start at 30
progress(30);
#output {white-space: pre;}
<code id="output"></code>

Related

Grading Calculator Equation for lesser grades

I'm trying to create a calculator that when you input your points, and the total amount of points in the class you receive a lot of information about it, I currently have working the letter grade, percentage, and the amount of points that you need to get to the next grade up.
Ex. 95/100
A 95%
Points Needed = 5
I want to do the same thing with Points needed but opposite. So with the same example it would be
Points Lost = 5
I currently have the script for my current Points Needed if it helps, but I really can't figure out the equation for this, luckily not necessary for a school project, just for a solo project so I can learn how to code.
Here is the code for the Points Needed
var pointsNeeded = totalGrade.value - grade.value;
if (gradePercentage > 100) {
pointsNeeded = pointsNeeded * -1;
document.getElementById("pointsNeeded").innerHTML = "You can lose " + pointsNeeded + " point(s) and still have 100%";
}
else {
document.getElementById("pointsNeeded").innerHTML = pointsNeeded;
}
}
else if (gradePercentage < 89, gradePercentage > 79) {
var pointsNeeded = Math.round(10 * ((totalGrade.value * 0.9) -
grade.value)) / 10;
document.getElementById("pointsNeeded").innerHTML = pointsNeeded;
}
else if (gradePercentage < 79, gradePercentage > 69) {
var pointsNeeded = Math.round(10 * ((totalGrade.value * 0.8) -
grade.value)) / 10;
document.getElementById("pointsNeeded").innerHTML = pointsNeeded;
}
else if (gradePercentage < 69, gradePercentage > 59) {
var pointsNeeded = Math.round(10 * ((totalGrade.value * 0.7) -
grade.value)) / 10;
document.getElementById("pointsNeeded").innerHTML = pointsNeeded;
}
else if (gradePercentage < 59) {
var pointsNeeded = Math.round(10 * ((totalGrade.value * 0.6) -
grade.value)) / 10;
document.getElementById("pointsNeeded").innerHTML = pointsNeeded;
}
gradePercentage being the actual percentage, totalGrade being the full grade, and grade being the grade you have.
Also these are the grade values,
var gradeLetter = "A"
document.getElementById("result").innerHTML = gradeLetter + " " + result + "%";
}
if (gradePercentage > 79.9, gradePercentage < 90) {
var gradeLetter = "B"
document.getElementById("result").innerHTML = gradeLetter + " " + result + "%";
}
if (gradePercentage > 69.9, gradePercentage < 80) {
var gradeLetter = "C"
document.getElementById("result").innerHTML = gradeLetter + " " + result + "%";
}
if (gradePercentage > 59.9, gradePercentage < 70) {
var gradeLetter = "D"
document.getElementById("result").innerHTML = gradeLetter + " " + result + "%";
}
if (gradePercentage < 59.9) {
var gradeLetter = "F"
document.getElementById("result").innerHTML = gradeLetter + " " + result + "%";
}
This code is pretty self-explanatory:
let startingPoints = 952.3 // How many points you got on the test
let maxPoints = 1049 // Max possible points you could have gotten
// Your grade (0-100%):
let gradePercentage = 100 * startingPoints / maxPoints; // E.g. 90.7816968541468
// How much less you'd need (as a percentage) to get the next lowest grade:
let extraPercentage = ( gradePercentage % 10 ) + 0.01; // E.g. 0.7916968541468015
// Your new grade (as a percentage) if you bumped it down:
let newGrade = gradePercentage - extraPercentage; // E.g. 89.99
// How many points you'd have to reduce your score by to bump it down to the next lowest
let extraPoints = ( extraPercentage / 100 * maxPoints ) // E.g. 8.304899999999947
// What your score would be if you bumped it down to the next level:
let newExtraPoints = startingPoints - extraPoints; // E.g. 943.9951
console.log( `Your grade is ${gradePercentage}% (${startingPoints} points out of a possible ${maxPoints}). If you subtract ${extraPercentage}% (or ${extraPoints} points), your grade will be ${newGrade}% (${newExtraPoints} points)` );
The only trickiness is that we're adding 0.01, which technically could be 0.001, or 0.0001, or...well, we have to add something to drop below the limit, and with no set "right" amount, I'm choosing 0.01 because it works out nicely.
Example output:
Your grade is 90.7816968541468% (952.3 points out of a possible 1049).
If you subtract 0.7916968541468015% (or 8.304899999999947 points),
your grade will be 89.99% (943.9951 points)

Problems with when trying to sum time using function in javascript

I have tried several suggestions on how to sum hours and minutes but all have failed to me.
I'm using this script as a start https://olanaso.github.io/Leaflet-Select-Polygons/# and need to have more rows with other totals from selected polygons, one of them is time (h:mm 00:00). Every polygon has properties with hour and minute, some has 00:00. I have manage to add more totals but when it comes to sum the time it has not worked for me. When you select polygons the totals adds up and when deselect a polygon the totals updates with removing that value. This function "timestrToSec" is one I have been trying, but getting the error "time.split is not a function". Also I don't need days just hours and minutes summed together like "300:15 h:mm" (3 hundred hours and 15 minutes) when selecting polygons och deselecting.
$.each(statesData.features, function(index, feature) {
var name = `${feature.properties.ZIPCODE} ${feature.properties.Name} ( ${feature.properties.average_time} - ${feature.properties.CITY})`
placenames.push(name);
zipcodes[name] = feature.properties.ZIPCODE;
time = feature.properties.average_time
});
More....
// Now get the totals of selected polygons
var detailshow = function() {
var result = ''
var total = 0
var total1 = 0
var total2 = 0
for (var i = 0; i < featuresSelected.length; i++) {
var properties = featuresSelected[i].feature.properties
result +=
`
${properties.CITY}<br>
Zipcode: ${properties.ZIPCODE}
<a href="#" onclick=dellayer(${properties.ZIPCODE})>Delete</a>
<hr>`;
total += properties.amount,
total1 += properties.average_time,
total2 += properties.distance
var convertTime = function (input, separator) {
var pad = function(input) {return input < 10 ? "0" + input : input;};
return [
pad(Math.floor(input / 3600)),
pad(Math.floor(input % 3600 / 60)),
pad(Math.floor(input % 60)),
].join(typeof separator !== 'undefined' ? separator : ':' );
}
var resultTime = convertTime(total1);
}
return {
result: result,
total: total,
resultTime: resultTime,
total2: total2
};
}
detailsselected.update = function(arrayselected) {
var details = detailshow()
this._div.innerHTML =
'<b>Zipcodes</b><br>' +
'Total time: <b>' + details.resultTime + ' hh:mm:ss</b><br>' +
'Amount: <b>' + details.total + ' st</b><br>' +
'Distance: <b>' + details.total2.toFixed(1) + ' km</b><br>';
$('#suma', window.parent.document).val(details.total, details.resultTime, details.total2);
};
detailsselected.addTo(map);
This is part of the json file structure:
var statesData = new L.LayerGroup;
var statesData = {"type":"FeatureCollection","features":[{"type":"Feature","properties":{"ZIPCODE":12345,"CITY":"LONDON","REGION":"REGION SOUTH","amount":1088,"average_time":"06:39","distance":2.2},"geometry":{"type":"MultiPolygon","coordinates":...
I didn't really try to follow everything you're doing, but if all you're trying to do is to add together hh:mm times, then something like this should work:
const addTimes = (hhmm1, hhmm2) => {
const [h1, m1] = hhmm1.split(':').map(Number)
const [h2, m2] = hhmm2.split(':').map(Number)
const minutes = 60 * h1 + m1 + 60 * h2 + m2
return `${Math.floor(minutes / 60)}:${String(minutes % 60).padStart(2, '0')}`
}
const addManyTimes = (ts) => ts.reduce(addTimes, '0:00')
console .log (addTimes ('3:41', '7:55')) //=> '11:36'
console .log (addManyTimes (['2:12', '3:07', '8:39', '6:21', '5:59'])) //=> '26:18'
It would be easy enough to extend this to seconds as well if that were necessary.

Limit to 2 decimals result in JavaScript

I have an issue with the decimals in a result in my script, it gives unlimited decimals, I want to limit it to 2, I have tried using to.fixed(2) without luck, but the script broke.
This is my script:
$.each(rows, function () {
quantity = $(this).find('[data-quantity]').val();
if (quantity == '') {
quantity = 1;
$(this).find('[data-quantity]').val(1);
}
_amount = parseFloat($(this).find('td.rate input').val()) * quantity;
$(this).find('td.amount').html(_amount);
subtotal += _amount;
row = $(this);
item_taxes = $(this).find('select.tax').selectpicker('val');
if (item_taxes) {
$.each(item_taxes, function (i, taxname) {
taxrate = row.find('select.tax [value="' + taxname + '"]').data('taxrate');
calculated_tax = (_amount / 100 * taxrate);
if (!taxes.hasOwnProperty(taxname)) {
if (taxrate != 0) {
_tax_name = taxname.split('|');
tax_row = '<tr class="tax-area"><td>' + _tax_name[0] + '(' + taxrate + '%)</td><td id="tax_id_' + slugify(taxname) + '"></td></tr>';
$(discount_area).after(tax_row);
taxes[taxname] = calculated_tax;
}
} else {
// Increment total from this tax
taxes[taxname] = taxes[taxname] += calculated_tax;
}
});
}
});
The code line that does the operation is:
calculated_tax = (_amount / 100 * taxrate);
The correct is toFixed(), not to.fixed(), see the example:
let number = 12.128361;
let _amount = number.toFixed(2);
let calculated_tax = (_amount / 100 * 100);
console.log(calculated_tax);
Use this method to round to any amount of decimal places:
let v = 3.486894716724;
let rounded = Math.round(v * 100) / 100; // => 3.49
Multiply and divide by 10 to round to one DP, 100 for 2DP, 1000 for 3, etc...

How to hide the output if var = 0

1How to hide the output if var m1000 = 0, I want to hide the text1000 for example if i input less than 1000 in the field I want the text1000 or 0 * 1000 Bank Bill to disappear from the output line
function doMoneyExchange() {
var inp1 = parseInt(document.getElementById("input1").value);
var m1000 = parseInt(inp1 / 1000);
var text1000 = m1000 + " * 1000 Bank Bill <br>"
inp1 = inp1 % 1000;
if (m1000 == "0") {
("text1000").hide();
}
var m500 = parseInt(inp1 / 500);
var text500 = m500 + " * 500 Bank Bill <br>"
inp1 = inp1 % 500;
var m100 = parseInt(inp1 / 100);
var text100 = m100 + " * 100 Bank Bill <br>"
inp1 = inp1 % 100;
var out = text1000 + text500 + text100;
document.getElementById("output").innerHTML = out;
It looks like you are trying to use jQuery. Is that correct? ("text1000").hide(); is my evidence. If so, $("text1000").hide(); might work better.
Okay, you're using $.hide() incorrectly. This method is used to hide elements but your program is concatenating everything at the end into a single string, which is then output to an HTML element.
What you should do instead is initialize your string variables to an empty string and then assign them a value on the condition that corresponding number variable is greater than 0. For example,
var text1000 = "";
if(m1000 > 0) {
text1000 = m1000 + " * 1000 Bank Bill <br/>";
}
Rinse and repeat and your resulting output string should only contain lines for numbers greater than 0.
P.S. If you're intent on using string concatenation for your output, there's no need for multiple substring variables. This makes your code less easily maintained. Rather, consider using a single string variable and concatenating in parts rather than all at the end.
var outputString = "";
if(m1000 === "0") {
outputString = outputString.concat(m1000 + " * 1000 Bank Bill <br>";
}
if(m100 === "0") {
outputString = outputString.concat(m100 + " * 100 Bank Bill <br>";
}
// repeat
document.getElementById("output").innerHTML = outputString;

Always display number with 3 digits and descriptor

Using Javascript, I want to format a number to always display 3 digits, along with it's proper identifier (ex: Million, Thousand). If under 100,000, the number should only show the "thousands" digits
All numbers will be integers above zero, and the highest numbers will be in the trillions.
A few examples of what I'm looking for:
1 Thousand
13 Thousand
627 Thousand
2.85 Million
67.9 Million
153 Million
9.52 Billion
etc...
All of the solutions I tried ended up becoming spaghetti code, and I am hoping someone can find a clean, smart solution.
EDIT:
I ended up using part of RobG's solution, but worked out the specifics on my own. I added rounding as well
function getNumberName(num) {
var numNames = ['', 'Thousand', 'Million', 'Billion', 'Trillion'];
num = num.toString();
var len = num.length - 1;
return numNames[len / 3 | 0];
}
function test(num) {
var numStr = num.toString();
if (num < 1000) {
return numStr;
} else if (num < 1000000) {
return numStr.slice(0, -3) + "," + numStr.slice(-3);
}
numStr = Math.round(parseFloat(numStr.slice(0, 3) + "." + numStr[3])).toString() + Array(numStr.slice(3).length + 1).join("0");
var remainder = numStr.length % 3;
var before = numStr.slice(0, remainder);
var after = numStr.slice(remainder, 3);
var sep = "";
if (before.length) {
sep = ".";
}
return before + sep + after + " " + getNumberName(num);
}
var nums = [0, 1, 12, 123, 1234, 12345, 123456, 1237567, 12325678, 123856789, 123e7, 125e8, 123.6e9, 123e10];
nums.forEach(function(num) {
document.write(num + ": $" + test(num) + "<br/>");
});
For integers, you can try shortening the number to the required number of places, then adding a name, e.g.
// For integers
function getNumberName(num) {
var numNames = ['','Thousand','Million','Billion'];
var num = num.toString()
var len = num.length - 1;
var pow = numNames[len/3 | 0];
return pow;
}
// For integers
function abbreviateNumber(num, places) {
places = places || 0;
var len = num.toString().length - 1;
var pow = len/3 | 0
return (num < 1000? num : num/Math.pow(10, pow*3)).toFixed(places);
}
function getNumberAbbr(num, places) {
return abbreviateNumber(num, places) + ' ' + getNumberName(num);
}
var nums = [0,1,12,123,1234,12345,123456,1234567,12345678,123456789,123e7]
nums.forEach(function(num) {
console.log(num + ' : ' + getNumberAbbr(num,1));
});
The above is not complete. There should be a limit applied so that beyond, say 1 trillion, it stops shortening the number.
There might be a better way but this will work:
function getTextNums(number) {
if ((number/1000000) < 1) {
var n = number.toString();
var first3 = n.substring(0, 3);
console.log(first3 + "Thousand");
} else if((number/1000000000) < 1) {
var n = number.toString();
var first3 = n.substring(0, 3);
console.log(first3 + "Million");
} else if((number/1000000000000) < 1) {
var n = number.toString();
var first3 = n.substring(0, 3);
console.log(first3 + "Billion");
} else if((number/1000000000000000) < 1) {
var n = number.toString();
var first3 = n.substring(0, 3);
console.log(first3 + "Trillion");
} else {
}
}
getTextNums(4533544433000)

Categories