Skip to content

Commit

Permalink
Improve Concept Exercise: Freelancer Rates (#1472)
Browse files Browse the repository at this point in the history
  • Loading branch information
JaPrad authored Nov 10, 2021
1 parent 00e5c6b commit b7da090
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 147 deletions.
2 changes: 1 addition & 1 deletion concepts/numbers/.meta/config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"blurb": "There are two different kinds of numbers in JavaScript - numbers and bigints. Numbers are for everyday use and are always floating point numbers.",
"authors": ["SleeplessByte"],
"contributors": []
"contributors": ["junedev", "JaPatGitHub"]
}
9 changes: 9 additions & 0 deletions concepts/numbers/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ There are two built-in objects that are useful when dealing with numbers:
- [`Number`][built-in-number]: static properties for common / useful values, static methods for [type-checking][concept-type-checking] and [type-conversion][concept-type-conversion], instance methods for [type-conversion][concept-type-conversion] and [formatting numbers as strings][string-formatting].
- [`Math`][built-in-math]: properties and methods for mathematical constants and functions, does **not** work with `BigInt`.

`Math` also includes methods for rounding numbers.
You can read more about the available rounding options in this [javascript.info article on rounding][ref-math-object-rounding].

```javascript
Math.floor(234.34); // => 234
Math.ceil(234.34); // => 235
```

The `Number` built-in global `object` is _also_ a global `function` that can be used to convert _almost anything_ number-like to a `number`.
It is less forgiving than _parsing_ a `string` to a `number`.

Expand Down Expand Up @@ -86,6 +94,7 @@ See [0.30000000000000004.com](https://0.30000000000000004.com/) for a brief expl
[comparison]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness
[lexical-grammar]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#numeric_literals
[string-formatting]: /tracks/javascript/concepts/string-formatting
[ref-math-object-rounding]: https://javascript.info/number#rounding
[concept-comparison]: /tracks/javascript/concepts/comparison
[concept-type-checking]: /tracks/javascript/concepts/type-checking
[concept-type-conversion]: /tracks/javascript/concepts/type-conversion
11 changes: 11 additions & 0 deletions concepts/numbers/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,14 @@ Many programming languages have specific numeric types to represent different ty

If you require arbitrary precision or work with extremely large numbers, use the `bigint` type.
Otherwise, the `number` type is likely the better option.

## Rounding

There is a built-in global object called `Math` that provides various [rounding functions][ref-math-object-rounding]. For example, you can round-down (`floor`) or round-up (`ceil`) decimal numbers to nearest whole numbers.

```javascript
Math.floor(234.34); // => 234
Math.ceil(234.34); // => 235
```

[ref-math-object-rounding]: https://javascript.info/number#rounding
18 changes: 8 additions & 10 deletions exercises/concept/freelancer-rates/.docs/hints.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@

## 1. Calculate the day rate given an hourly rate

- Use the [numeric operators][ref-numeric-operators] from Lucian's Luscious Lasagna.
- Use the arithmetic operators as mentioned in the introduction of this exercise.

[ref-numeric-operators]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators
## 2. Calculate the number of workdays given a budget

## 2. Calculate the month rate, given an hourly rate and a discount
- First determine the day rate, then calculate the number of days, and finally round that number down.

- `100% - discount` equals the percentage after the discount is applied.
- There is a built-in global object called [`Math`][ref-math-object] with functions to, for example, round-down (`floor`) or round-up (`ceil`).
## 3. Calculate the discounted rate for large projects

[ref-math-object]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math

## 3. Calculate the number of workdays given a budget, rate and discount

- First determine the dayRate, given the discount, then calculate the number of days, and finally round that number down.
- Round down the result from division to get the number of full months.
- `100% - discount` equals the percentage charged after the discount is applied.
- Use `%`, the remainder operator, to calculate the number of days exceeding full months.
- Add the discounted month rates and full day rates and round it up
42 changes: 19 additions & 23 deletions exercises/concept/freelancer-rates/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
# Instructions

In this exercise you will be writing code to help a freelancer communicate with a project manager by providing a few utility functions to quickly calculate day- and month rates, optionally with a given discount.

We first establish a few rules between the freelancer and the project manager:

- The daily rate is 8 times the hourly rate;
- A month has 22 billable days.

If the freelancer bills the project manager per month or more, there is a discount applied. This can be handy if the project manager has a fixed budget.

Discounts are modeled as fractional numbers (percentage) between `0.0` (`0%`, no discount) and `0.90` (`90%`, maximum discount).
In this exercise you will be writing code to help a freelancer communicate with his clients about the prices of certain projects. You will write a few utility functions to quickly calculate the costs for the clients.

## 1. Calculate the day rate given an hourly rate

Implement a function to calculate the day rate given an hourly rate:
A client contacts the freelancer to enquire about his rates.
The freelancer explains that he **_works 8 hours a day._**
However, the freelancer knows only his hourly rates for the project.
Help him estimate a day rate given an hourly rate.

```javascript
dayRate(89);
Expand All @@ -22,24 +16,26 @@ dayRate(89);

The day rate does not need to be rounded or changed to a "fixed" precision.

## 2. Calculate the month rate, given an hourly rate and a discount
## 2. Calculate the number of workdays given a fixed budget

Implement a function to calculate the month rate, and apply a discount:
Another day, a project manager offers the freelancer to work on a project with a fixed budget.
Given the fixed budget and the freelancer's hourly rate, help him calculate the number of days he would work until the budget is exhausted.
The result _must_ be **rounded down** to the nearest whole number.

```javascript
monthRate(89, 0.42);
// => 9086
daysInBudget(20000, 89);
// => 28
```

The discount is always passed as a number, where `42%` becomes `0.42`. The result _must_ be rounded up to the nearest whole number.

## 3. Calculate the number of workdays given a budget, rate and discount
## 3. Calculate the discounted rate for large projects

Implement a function that takes a budget, a rate per hour and a discount, and calculates how many full days of work that covers.
Often, the freelancer's clients hire him for projects spanning over multiple months.
In these cases, the freelancer decides to offer a discount for every full month, and the remaining days are billed at day rate.
**_Every month has 22 billable days._**
Help him estimate his cost for such projects, given an hourly rate, the number of days the project spans, and a monthly discount rate.
The discount is always passed as a number, where `42%` becomes `0.42`. The result _must_ be **rounded up** to the nearest whole number.

```javascript
daysInBudget(20000, 89, 0.2002);
// => 35
priceWithMonthlyDiscount(89, 230, 0.42);
// => 97972
```

The discount is always passed as a `number`. `20.02%` is passed as `0.2002`. The result is the number of days should be rounded down to full days of work.
10 changes: 10 additions & 0 deletions exercises/concept/freelancer-rates/.docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ Many programming languages have specific numeric types to represent different ty
If you require arbitrary precision or work with extremely large numbers, use the `bigint` type.
Otherwise, the `number` type is likely the better option.

### Rounding

There is a built-in global object called `Math` that provides various [rounding functions][ref-math-object-rounding]. For example, you can round-down (`floor`) or round-up (`ceil`) decimal numbers to nearest whole numbers.

```javascript
Math.floor(234.34); // => 234
Math.ceil(234.34); // => 235
```

## Arithmetic Operators

JavaScript provides 6 different operators to perform basic arithmetic operations on numbers.
Expand Down Expand Up @@ -72,3 +81,4 @@ y %= 3; // y is now 1
```
[mdn-operator-precedence]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table
[ref-math-object-rounding]: https://javascript.info/number#rounding
4 changes: 2 additions & 2 deletions exercises/concept/freelancer-rates/.meta/config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"blurb": "Learn about numbers whilst helping a freelancer communicate with a project manager about day- and month rates.",
"authors": ["SleeplessByte"],
"contributors": [],
"authors": ["SleeplessByte", "JaPatGitHub"],
"contributors": ["junedev"],
"files": {
"solution": ["freelancer-rates.js"],
"test": ["freelancer-rates.spec.js"],
Expand Down
3 changes: 3 additions & 0 deletions exercises/concept/freelancer-rates/.meta/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
- Know their underlying type (double precision).
- Know their basic limitations (not all numbers can be represented, e.g. `0.1 + 0.2`).
- Know how to truncate floating point numbers to a certain decimal place (`Math.ceil`, `Math.floor`, `Math.round`)
- Know how to use arithmetic operators (`+`, `-`, `*`, `/`, `%`, `**`)
- Learn about shorthand assignment operators (`+=`, etc.)

## Out of scope

Expand All @@ -15,6 +17,7 @@
## Concepts

- `numbers`
- `arithmetic-operators`

## Prerequisites

Expand Down
39 changes: 16 additions & 23 deletions exercises/concept/freelancer-rates/.meta/exemplar.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,39 +29,32 @@ export function dayRate(ratePerHour) {
return ratePerHour * 8;
}

/**
* Calculates the rate per month
*
* @param {number} ratePerHour
* @param {number} discount for example 20% written as 0.2
* @returns {number} the rounded up monthly rate
*/
export function monthRate(ratePerHour, discount) {
const monthly = dayRate(ratePerHour) * 22;
const discounted = applyDiscount(monthly, discount);
return Math.ceil(discounted);
}

/**
* Calculates the number of days in a budget, rounded down
*
* @param {number} budget the total budget
* @param {number} ratePerHour the rate per hour
* @param {number} discount to apply, example 20% written as 0.2
* @returns {number} the number of days
*/
export function daysInBudget(budget, ratePerHour, discount) {
const discounted = applyDiscount(dayRate(ratePerHour), discount);
return Math.floor(budget / discounted);
export function daysInBudget(budget, ratePerHour) {
return Math.floor(budget / dayRate(ratePerHour));
}

/**
* Applies a discount to the value
* Calculates the discounted rate for large projects, rounded up
*
* @param {number} value
* @param {number} percentage for example 20% written as 0.2
* @returns {number} the discounted value
* @param {number} ratePerHour
* @param {number} numDays: number of days the project spans
* @param {number} discount: for example 20% written as 0.2
* @returns {number} the discounted rate, rounded up
*/
function applyDiscount(value, percentage) {
return (1 - percentage) * value;
export function priceWithMonthlyDiscount(ratePerHour, numDays, discount) {
const numMonths = Math.floor(numDays / 22);
const monthlyRate = 22 * dayRate(ratePerHour);
const monthlyDiscountedRate = (1 - discount) * monthlyRate;

const numExtraDays = numDays % 22;
const priceExtraDays = numExtraDays * dayRate(ratePerHour);

return Math.ceil(numMonths * monthlyDiscountedRate + priceExtraDays);
}
31 changes: 10 additions & 21 deletions exercises/concept/freelancer-rates/freelancer-rates.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,36 +29,25 @@ export function dayRate(ratePerHour) {
throw new Error('Implement the dayRate function');
}

/**
* Calculates the rate per month
*
* @param {number} ratePerHour
* @param {number} discount for example 20% written as 0.2
* @returns {number} the rounded up monthly rate
*/
export function monthRate(ratePerHour, discount) {
throw new Error('Implement the monthRate function');
}

/**
* Calculates the number of days in a budget, rounded down
*
* @param {number} budget the total budget
* @param {number} ratePerHour the rate per hour
* @param {number} discount to apply, example 20% written as 0.2
* @param {number} budget: the total budget
* @param {number} ratePerHour: the rate per hour
* @returns {number} the number of days
*/
export function daysInBudget(budget, ratePerHour, discount) {
export function daysInBudget(budget, ratePerHour) {
throw new Error('Implement the daysInBudget function');
}

/**
* Applies a discount to the value
* Calculates the discounted rate for large projects, rounded up
*
* @param {number} value
* @param {number} percentage for example 20% written as 0.2
* @returns {number} the discounted value
* @param {number} ratePerHour
* @param {number} numDays: number of days the project spans
* @param {number} discount: for example 20% written as 0.2
* @returns {number} the rounded up discounted rate
*/
function applyDiscount(value, percentage) {
throw new Error('Implement the applyDiscount function');
export function priceWithMonthlyDiscount(ratePerHour, numDays, discount) {
throw new Error('Implement the priceWithMonthlyDiscount function');
}
Loading

0 comments on commit b7da090

Please sign in to comment.