User_FTW
User_FTW

Reputation: 524

Percentage in JavaScript when over a certain input value

My client needs a formula to work in a certain way.

Here's my code:

/* Daily rate */
var rate = 50;

/* If 18 days or less, discount is 20% */
if (this.value <= 18) {
    var discount = 20;
} 
/* Otherwise if more than 18 days */
else if (this.value > 18) {
    var discount = 30;
}

/* Total - I realise this is wrong and needs to be changed */
total = rate / 100 * discount; 

console.log(total);

Basically the way it needs to work is that if this.value is more than 18 days, then the discount needs to only be 30% of every day past 18.

So for example, if this.value is 22, then the 20% discount still applies for every day up to 18 days, but 30% discount also needs to apply for every day after 18 days, in this case, 4 days.

The expected result would be 860.

Because...

20% of 50 x 18 = 720

30% of 50 x 4 = 140

Total = 860

How can I modify my code to accommodate?

Upvotes: 0

Views: 72

Answers (2)

VLAZ
VLAZ

Reputation: 29010

You can calculate the rate for each day in a for loop and then total them. To do this, a little helper function discountForDay can handle the variable discount rate for each day, this can make it easier to refactor later:

//fake the value by putting it in an object
var obj = {
  value: 5,
  discountForDay: function(day) {
    if (day <= 18) {
        return 0.20;
    } 
    /* Otherwise if more than 18 days */
    else if (day > 18) {
        return 0.30;
    }
  },
  calculate: function() {
    /* Daily rate */
    var rate = 50;

    var total = 0;
    
    for(var i = 0; i < this.value; i++) {
      var discount = this.discountForDay(i + 1);
      var rateForDay = rate - discount * rate;
      
      total += rateForDay;
    }

    return total
  }
}

console.log("total for 5 days:", obj.calculate());

obj.value = 18;
console.log("total for 18 days:", obj.calculate());

obj.value = 22;
console.log("total for 22 days:", obj.calculate());

So, this would work. If you wish to collapse it into a single mathematical formula, then you need:

Total = (rate * min(days, 18) -  rate * min(days, 18) * 0.2) + (rate * max((days-18), 0) -  rate * max((days-18), 0) * 0.3)
      = rate * min(days, 18) * (1 - 0.2) + rate * max((days-18), 0) * (1 - 0.3)
      = rate * (min(days, 18) * 0.8 + max((days-18), 0) * 0.7)

So, when encoded as a function this is:

function calculate(rate, days) {
  return rate * (Math.min(days, 18) * 0.8 + Math.max((days-18), 0) * 0.7)
}

console.log("total for 5 days:", calculate(50, 5));
console.log("total for 18 days:", calculate(50, 18));
console.log("total for 22 days:", calculate(50, 22));

However, the mathematical formula will only work for this specific division of days and rates. It's not very maintainable if it changes and has to change often. It's not hard to derive new formulas, but it's probably not the best use of your time. You better embrace the iterative approach, as it's easier to extend in the future.

Upvotes: 2

Binh
Binh

Reputation: 396

This could be one solution:

var value = 22
var rate = 50
var total = 0
var baseDiscount = 20
var more18DaysDiscount = 30

if (this.value <= 18) {
    total = value * rate * (100-baseDiscount)/100
} else {
    var baseTotal = 18 * rate * (100-baseDiscount)/100
    var more18DaysTotal = (value - 18) * rate * (100-more18DaysDiscount)/100
    total = baseTotal + more18DaysTotal
}

console.log(total)

Upvotes: 1

Related Questions