Javascript loop taking too long to execute - javascript

I have been implementing an EMI calculator for a hybrid mobile application and within one of the loops the execution takes too long and ultimately the page goes unresponsive. Here is my code
var EMICalculator = {
basicEMI: function (amount, rate, tenure) {
// body...
var rate_yearly = parseFloat((rate/12)/100);
var amt = parseFloat(amount*rate_yearly*Math.pow((rate_yearly+1),tenure)/(Math.pow((rate_yearly+1),tenure)-1));
return amt.toFixed(2);
},
getBalanceClassic: function (amount, rate, tenure, emi, openingBal, toReturn){
var interest_per_month = 0.0;
var schedule = [];
for(var i=1; i<=tenure; i++){
var dataJson = {};
interest_per_month = amount*rate;
amount = parseFloat(amount - emi - interest_per_month);
dataJson['installment_no'] = i;
dataJson['installment'] = Math.round(interest_per_month + (emi - interest_per_month)).toFixed(2);
dataJson['interest'] = Math.round(interest_per_month).toFixed(2);
dataJson['principal'] = Math.round(emi - interest_per_month).toFixed(2);
dataJson['balance_principal'] = Math.round(amount).toFixed(2);
dataJson['opening_balance'] = Math.round(openingBal).toFixed(2);
amt_initially = Math.round(amount).toFixed(2);
schedule.push(dataJson);
}
if(toReturn){
return schedule;
}else {
return parseFloat(amount);
}
},
rateBasedClassic: function (amount, rate, tenure) {
var rate_per_yr = parseFloat((rate/12)/100);
var amt_initially = amount;
var emi_basic = parseFloat(this.basicEMI(amount,rate,tenure));
var total_interest = Math.round((emi_basic*tenure)-amount);
var total_amount = Math.round(emi_basic*tenure);
var interest_per_month = Math.round(total_interest/tenure);
var amount_paid = 0.0;
var toReturn = [];
for(var i=1; i<=tenure; i++){
var dataJson = {};
amount_paid = parseFloat(amount_paid + emi_basic);
interest_per_month = amount * rate_per_yr;
amount = (amount - (emi_basic - interest_per_month));
dataJson['installment_no'] = i;
dataJson['installment'] = Math.round(interest_per_month + (emi_basic - interest_per_month)).toFixed(2);
dataJson['interest'] = Math.round(interest_per_month).toFixed(2);
dataJson['principal'] = Math.round(emi_basic - interest_per_month).toFixed(2);
dataJson['balance_principal'] = Math.round(amount).toFixed(2);
dataJson['opening_balance'] = Math.round(amt_initially).toFixed(2);
amt_initially = Math.round(amount).toFixed(2);
toReturn.push(dataJson);
}
return toReturn;
},
EMIBasedClassic : function (amount, tenure, emi) {
var amt_initially = amount;
var total_amount = emi*tenure;
var total_interest = total_amount - amount;
var rate = 0.0;
var toReturn = false;
var balance = this.getBalanceClassic(amount,rate,tenure,emi,amt_initially,toReturn);
while(balance<0){
rate += 0.1;
var rate2 = parseFloat((rate/12)/100);
balance = this.getBalanceClassic(amount,rate2,tenure,emi,amt_initially,toReturn);
}
while(balance>0){
rate -= 0.0000001;
var rate2 = parseFloat((rate/12)/100);
balance = this.getBalanceClassic(amount,rate2,tenure,emi,amt_initially,toReturn);
}
toReturn = true;
var rate2 = parseFloat((rate/12)/100);
balance = this.getBalanceClassic(amount,rate2,tenure,emi,amt_initially,toReturn);
return balance;
}}
Calling the EMIBasedClassic method with parameters (600000,9,19080) causes the issue where the incremental increase/decrease has been done in the while loops. The same logic is working fine in Java. What's wrong here?

When you call getBalance classic, you're using the same parameters every single time. That means balance, will always be the same value. I'm not sure which value you want to pass to the function, but the current setup will always run an infinite loop no matter what value you pass. It'd be super easy to over look such a minor thing.
function (amount, tenure, emi) {
var amt_initially = amount;
var total_amount = emi*tenure;
var total_interest = total_amount - amount;
var rate = 0.0;
var toReturn = false;
var balance = this.getBalanceClassic(amount,rate,tenure,emi,amt_initially,toReturn);
while(balance<0){
rate += 0.1;
var rate2 = parseFloat((rate/12)/100);
balance = this.getBalanceClassic(amount,rate2,tenure,emi,amt_initially,toReturn);
}
while(balance>0){
console.log("__BALANCE__: ", balance);
rate -= 0.0000001;
var rate2 = parseFloat((rate/12)/100);
//Balance will always be the same. Do we want to pass balance or amount?
balance = this.getBalanceClassic(amount,rate2,tenure,emi,amt_initially,toReturn);
}
toReturn = true;
var rate2 = parseFloat((rate/12)/100);
balance = this.getBalanceClassic(amount,rate2,tenure,emi,amt_initially,toReturn);
return balance;
}
You only want to use amount in the function on the very first time. After that, you want to use balance.
I changed it from amount to balance in the while loops and it worked.
Here's my code in repl:

Related

localStorage("clicked", "")but when you click a button, set it to to ("clicked", "yes")and this cannot be reversed until you quit (close) the page

I want to set localStorage to ("clicked", "") at all times, but when a button is clicked, change it to ("clicked", "yes") and this shouldn't be undone unless you leave the page and enter it again. Are there any ways to do this?
localStorage.setItem("clicked", "");
(function checkFunction(){
if (localStorage.getItem("clicked") === "yes") {
localStorage.setItem("discountCode", "iloveventurebox0943");
document.getElementById("discount-code-input").value = localStorage.getItem("discountCode");
var discountPercentageStringFilter = parseFloat(localStorage.getItem("Percentage"));
discountPercentage.innerHTML = ("(20%)");
var discountPercentageLS = localStorage.setItem("Percentage", "(20%)");
var Subtotal = localStorage.getItem("Enterprise");
toFixedFetch = (Subtotal * discountPercentageStringFilter);
discountPricePrice.innerHTML = toFixedFetch.toFixed(2);
var discountPricePriceLS = localStorage.setItem("Enterprise", toFixedFetch.toFixed(2));
document.getElementById("discount-trigger").setAttribute("disabled", "");
document.getElementById("discount-trigger").classList.add("disabled");
}
let discountTriggerBtn = document.getElementById("discount-trigger");
discountTriggerBtn.addEventListener("click", function() {
let targetVar = document.getElementById("discount-code-input");
(function checkDiscount() {
var valueFiller = targetVar.value;
let discountCode = "iloveventurebox0943";
if (valueFiller === discountCode) {
var discountPercentageStringFilter = parseFloat(localStorage.getItem("Percentage"));
discountPercentage.innerHTML = ("(20%)");
var discountPercentageLS = localStorage.setItem("Percentage", "(20%)");
var Subtotal = localStorage.getItem("Enterprise");
toFixedFetch = (Subtotal * discountPercentageStringFilter);
discountPricePrice.innerHTML = toFixedFetch.toFixed(2);
var discountPricePriceLS = localStorage.setItem("Enterprise", toFixedFetch.toFixed(2));
document.getElementById("discount-trigger").setAttribute("disabled", "");
document.getElementById("discount-trigger").classList.add("disabled");
localStorage.setItem("clicked", "yes");
var Total = document.getElementById("total");
Total.innerHTML = (Subtotal - discountPricePrice);
}
}
)();
})
}())
I thought I could loop over and over but I just ended up going in hopeless circles :((

JavaScript function not working if values passed are blank or null

I have created a JavaScript function for calculating status of the given offer value which is passed as a parameter.
Suppose, if we have Values.NE_LEG as " " or NULL then it gives as isNan error and if affects my function and doesn't gives status properly.
Below is the function which I am using.
function getHotoStatusIDFTTX(OfferValue) {
var Values = JSON.parse(OfferValue);
var ne_leg = parseFloat(Values.NE_LEG).toFixed(4); //isNan if the value is blank
var hotoFttxValue = parseFloat(Values.OFFERHOTO).toFixed(4);
var hotoFttxValuecomplete = parseFloat(Values.HOTOCOMPLETED).toFixed(4);
var total_hoto = parseFloat(hotoFttxValuecomplete) + parseFloat(hotoFttxValue);
var pendhotoFttxValue = 0;
var calPerhotofttx = 0;
var pendPartialfttx = 0;
var calPartialfttx = 0;
if (parseFloat(total_hoto).toFixed(2) > 0 && parseFloat(ne_leg).toFixed(2) > parseFloat(total_hoto).toFixed(2)) {
pendhotoFttxValue = ne_leg - total_hoto;
calParhotoFttx = (100 - (pendhotoFttxValue * 100 / ne_leg)).toFixed(2);
} else if (parseFloat(ne_leg).toFixed(2) == parseFloat(total_hoto).toFixed(2)) {
calParhotoFttx = 100;
}
var status = 0;
var toleranceValuefttX = parseFloat(100 - tolerance.percentage);
if (calParhotoFttx >= toleranceValuefttX) {
status = HotoStatusId.hoto;
// status = 11;
}
else if (calParhotoFttx < toleranceValuefttX) {
status = HotoStatusId.hotopartial;
}
return status;
}
What is wrong, and what steps should I take?
Use isNan() function.
I think it would help you....
Here's some code for test.
https://jsfiddle.net/pf4mjgnL/2/
var str = "avc";
var num = 1234;
console.log(isNaN(str));
console.log(isNaN(num));

How to fix undefined variables after program runs

The program will ask for all inputs and print everything but the variables all come up as undefined.
This is for a web application tied to a HTML document. No errors are thrown when it runs.
function driver(){
var plan1Code = "S";
var plan1Cost = 450;
var plan1Hours = 2.5;
var plan1Pics = 75;
var plan2Code = "G";
var plan2Cost = 750;
var plan2Hours = 5;
var plan2Pics = 125;
var plan3Code = "P";
var plan3Cost = 1000;
var plan3Hours = 8;
var plan3Pics = 225;
var retName = getName();
var retPlan = getPlan();
var retHours = getHours();
var retPics = getPics();
var baseCost, totalCost, upchargeTime, upchargeTimeCost, upchargePics, upchargePicsCost;
if (retPlan == plan1Code){
baseCost = plan1Cost;
upchargeTime, upchargeTimeCost = calcTimeUpcharge(retHours, plan1Hours);
upchargePics, upchargePicsCost = calcPicsUpcharge(retPics, plan1Pics);
}
else if (retPlan == plan2Code){
baseCost = plan2Cost;
upchargeTime, upchargeTimeCost = calcTimeUpcharge(retHours, plan2Hours);
upchargePics, upchargePicsCost = calcPicsUpcharge(retPics, plan2Pics);
}
else if (retPlan == plan3Code){
baseCost = plan3Cost;
upchargeTime, upchargeTimeCost = calcTimeUpcharge(retHours, plan3Hours);
upchargePics, upchargePicsCost = calcPicsUpcharge(retPics, plan3Pics);
}
totalCost = calcTotalCost(baseCost, upchargeTimeCost, upchargePicsCost);
print(retName, retPlan, baseCost, upchargeTime, upchargeTimeCost, upchargePics, upchargePicsCost, totalCost);
}
function getName(){
var text;
var name = prompt("Enter your name");
if (name == null) {
text = "Please enter a valid name";
}
}
function getPlan(plan){
var plan = prompt("Enter the selected package");
}
function getHours(hours){
var hours = prompt("Enter anticipated coverage hours");
}
function getPics(pics){
var pics = prompt("Enter anticipated number of pictures");
}
function calcTimeUpcharge(hours, baseHours){
upchargeTime = hours - baseHours;
var price;
if (upchargeTime>0){
var upchargeTimeUnits = Math.ceil((upchargeTime)/.5);
upchargeTimeCost = upchargeTimeUnits * 50;
}
else {
upchargeTime = 0;
upchargeTimeCost = 0;
}
return upchargeTime, upchargeTimeCost;
}
function calcPicsUpcharge(pics, basePics){
upchargePics = pics - basePics;
if (upchargePics>0){
upchargePicsunits = Math.ceil((upchargePics)/10);
upchargePicsCost = upchargePicsunits*40;
}
else {
upchargePics = 0;
upchargePicsunits = 0;
}
return upchargePics, upchargePicsCost;
}
function calcTotalCost(baseCost, timeCost, picsCost){
return baseCost + timeCost + picsCost;
}
function print(retName, retPlan, baseCost, upchargeTime, upchargeTimeCost, upchargePics, upchargePicsCost, totalCost){
document.write(retName + ", thanks for using Photosarus!" + "\n");
document.write("<br><br>");
document.write("You selected plan " + retPlan + " at a cost of "+ baseCost );
document.write("<br><br>");
document.write(upchargeTime + "additional hours at a cost of "+ upchargeTimeCost);
document.write("<br><br>");
document.write(upchargePics + "additional pictures at a cost of "+ upchargePicsCost);
}
I expect the output to say
Bill, thanks for using Photosarus!
You selected plan S at a cost of $450
0 additional hours at a cost of $0
0 additional pictures at a cost of $0
But instead I get
undefined, thanks for using Photosarus!
You selected plan undefined at a cost of undefined
undefined additional hours at a cost of undefined
undefined additional pictures at a cost of undefined
You need to return the values from the functions:
function getName(){
var text;
var name = prompt("Enter your name");
if (name == null) {
text = "Please enter a valid name";
}
return name;
}
function getPlan(plan){
var plan = prompt("Enter the selected package");
return plan;
}
function getHours(hours){
var hours = prompt("Enter anticipated coverage hours");
return hours;
}
function getPics(pics){
var pics = prompt("Enter anticipated number of pictures");
return pics;
}

Trying to generate a random number for a loop but it doesn't seem to be working. Why is this?

So I'm trying to make a loop but I need a random number to actually get it to work.
var j=0;
while(j < patrons.length){
var books = patrons[j].booksOut;
var fine = patrons[j].fine;
var randomnumber = Math.floor(Math.random() * (20 - 5 + 1)) + 1; //the random number
for(var i=randomnumber;i<books.length;i++){ //me trying to replace i with the random number
if(books[i].isOverdue()){
fine = fine + 5.00;
}
}
patrons[j].fine = fine;
j++;
}
The problem is that when I try to replace the i in my for loop with the random number it doesn't seem to work properly. Anyone know why?
My complete code:
var Author = function(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
};
var Book = function(title, Available, publicationDate, checkoutDate, callNumber, Authors) {
this.title = title;
this.Available = Available;
this.publicationDate = publicationDate;
this.checkoutDate = checkoutDate;
this.callNumber = callNumber;
this.Authors = Authors;
};
Book.prototype.checkOut = function(){
this.Available = false;
var temp = new Date(1000000000);
var d = new Date()-temp;
var res = new Date(d);
this.checkoutDate = res;
};
Book.prototype.isOverdue = function(){
//Get 1 day in milliseconds
var singleDay=1000*60*60*24;
var todayDate = new Date().getTime();
var difference = todayDate - this.checkoutDate.getTime();
if(Math.round(difference/singleDay) >= 14){
return true;
}
return false;
};
var Patron = function(firstName, lastName, libraryCardNumber, booksOut, fine) {
this.firstName = firstName;
this.lastName = lastName;
this.libraryCardNumber = libraryCardNumber;
this.booksOut = booksOut;
this.fine = fine;
};
Patron.prototype.read = function(book){
this.booksOut.add(book);
}
Patron.prototype.read = function(book){
this.booksOut.remove(this.booksOut.length);
}
//creating author objects
var authors = []
authors[0] = new Author("Edgar","A. Poe");
authors[1] = new Author("George","Orwell");
var mybooks = []
mybooks[0] = new Book('Animal Farm',true,new Date(2000,5,20), new Date(), 10,authors);
mybooks[1] = new Book('1984',true,new Date(2000,5,20), new Date(), 11,authors);
mybooks[2] = new Book('A Tale of Two Cities',true,new Date(2000,5,20), new Date(), 12,authors);
mybooks[3] = new Book('The Raven',true,new Date(2000,5,20), new Date(), 13,authors);
mybooks[4] = new Book('Forgotten Lore',true,new Date(2000,5,20), new Date(), 14,authors);
var patrons = []
patrons[0] = new Patron('Patrick','fill1',1,mybooks,0.00);
patrons[1] = new Patron('Lira','fill2',1,mybooks,0.00);
patrons[2] = new Patron('May','fill3',1,mybooks,0.00);
patrons[3] = new Patron('Kyle','fill3',1,mybooks,0.00);
patrons[4] = new Patron('Bob','fill4',1,mybooks,0.00);
var j=0;
while(j < patrons.length){
var books = patrons[j].booksOut;
var fine = patrons[j].fine;
var randomnumber = Math.floor(Math.random() * (20 - 5 + 1)) + 1;
for(var i=randomnumber;i<books.length;i++){
if(books[i].isOverdue()){
fine = fine + 5.00;
}
}
patrons[j].fine = fine;
j++;
}
for(i=0; i < patrons.length;i++){
console.log(patrons[i].firstName+" has taken the following books:");
for(j=0;j<patrons[i].booksOut.length;j++){
console.log(patrons[i].booksOut[j].title);
}
console.log(patrons[i].firstName+" has fine = "+patrons[i].fine);
}
Without sample values for patrons, the best I can offer is to use books.length as your max value. Why are you even picking them at random? Is there a broader problem you are trying to solve?
const isOverdue = () => true;
const patrons = [
{ booksOut: [{ isOverdue }], fine: 1.0 },
{ booksOut: [{ isOverdue }], fine: 2.0 },
{ booksOut: [{ isOverdue }], fine: 3.0 },
];
let j = 0;
while(j < patrons.length) {
const books = patrons[j].booksOut;
let fine = patrons[j].fine;
const randomnumber = Math.floor(Math.random() * books.length);
for(let i = randomnumber; i < books.length; i++) {
if(books[i].isOverdue()) {
fine += 5.00;
}
}
patrons[j].fine = fine;
j += 1;
}
console.log(JSON.stringify(patrons, null, 2));
Edit per comment:
Book.prototype.isOverdue = function() {
return [true, false][Math.floor(Math.random() * 2)]
}
Something like the above will make isOverdue() answer randomly yes or no.
In the sample you have provided, you are using new Date() to set the checkout date for each book, which is setting it to the time of execution.
Therefore, when you are calling isOverdue() it is always checking whether today minus now is >= 14 days, which it never will be, so isOverdue() will always return false.

Multiplying variables and showing result in a box

I'm having a problem when trying to multiply the totalPallets by the price-per-pallet ($25) and then showing that in the productSubTotal box. With the code as it is right now, the quatity total shows but when I try to get the price result, it doesn't show the operation. Also, if I try changing anythung from the code, the whole thing breaks down. I'll be thankful if anyone could help me. Thanks
// UTILITY FUNCTIONS
function IsNumeric(n) {
return !isNaN(n);
}
function calcTotalPallets() {
var totalPallets = 0;
$(".num-pallets-input").each(function() {
var thisValue = parseInt($(this).val());
if ( (IsNumeric(thisValue)) && (thisValue != '') ) {
totalPallets += parseInt(thisValue);
};
});
$("#quantitytotal").val(totalPallets);
}
function calcProdSubTotal() {
var prodSubTotal = 0;
$(".totalprice").each(function() {
var valString = parseInt(totalPallets) * multiplier;
prodSubTotal += parseInt(valString);
});
$("#product-subtotal").val(CommaFormatted(prodSubTotal));
};
// "The Math" is performed pretty much whenever anything happens in the quanity inputs
$('.num-pallets-input').bind("focus blur change keyup", function(){
// Caching the selector for efficiency
var $el = $(this);
// Grab the new quantity the user entered
var numPallets = CleanNumber($el.val());
var totalPallets = CleanNumber($el.val());
var prodSubTotal = CleanNumber($el.val());
// Find the pricing
var multiplier = $el
.parent().parent()
.find("td.price-per-pallet span")
.text();
};
// Calcuate the overal totals
calcProdSubTotal();
calcTotalPallets();
});
function CommaFormatted(amount) {
var delimiter = ",";
var i = parseInt(amount);
if(isNaN(i)) { return ''; }
i = Math.abs(i);
var minus = '';
if (i < 0) { minus = '-'; }
var n = new String(i);
var a = [];
while(n.length > 3)
{
var nn = n.substr(n.length-3);
a.unshift(nn);
n = n.substr(0,n.length-3);
}
if (n.length > 0) { a.unshift(n); }
n = a.join(delimiter);
amount = "$" + minus + n;
return amount;
}
});

Categories

Resources