Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare freelancer-rates analyzer #121

Merged
merged 7 commits into from
Nov 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"targets": {
"node": "current"
}

}
],
"@babel/preset-typescript"
Expand Down
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.20.0

- Replace generic ExemplarAnalyzer for `freelancer-rates` with specific analyzer stub

## 0.19.0

- Add analyzer for `concept/annalyns-infiltration`
Expand All @@ -11,7 +15,7 @@

## 0.17.1

- Change the way autoloads work so they are more predicatable
- Change the way autoload work so they are more predictable

## 0.17.0

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@exercism/javascript-analyzer",
"version": "0.19.0",
"version": "0.20.0",
"description": "Exercism analyzer for javascript",
"repository": "https://github.com/exercism/javascript-analyzer",
"author": "Derk-Jan Karrenbeld <[email protected]>",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,43 +13,52 @@ import { PublicApi } from '../../PublicApi'
import { parameterName } from '../../utils/extract_parameter'

export const DAY_RATE = 'dayRate'
export const MONTH_RATE = 'monthRate'
export const MONTH_RATE = 'priceWithMonthlyDiscount'
export const DAYS_IN_BUDGET = 'daysInBudget'

class DayRate extends PublicApi {
public get ratePerHourParameter(): string {
return this.parameter
}

// return ratePerHour * 8;
// return 8 * ratePerHour;
// return ratePerHour * HOURS_IN_DAY;
// return HOURS_IN_DAY * ratePerHour;
}

class MonthRate extends PublicApi {
public get ratePerHourParameter(): string {
class DaysInBudget extends PublicApi {
public get budgetParameter(): string {
return this.parameter
}

public readonly discountParameter: string
public readonly ratePerHourParameter: string

constructor(implementation: ExtractedFunction) {
super(implementation)

this.discountParameter = parameterName(this.implementation.params[1])
this.ratePerHourParameter = parameterName(this.implementation.params[1])
}

// return Math.floor(budget / dayRate(ratePerHour));
}

class DaysInBudget extends PublicApi {
public get budgetParameter(): string {
class MonthRate extends PublicApi {
public get ratePerHourParameter(): string {
return this.parameter
}

public readonly ratePerHourParameter: string
public readonly daysParameter: string
public readonly discountParameter: string

constructor(implementation: ExtractedFunction) {
super(implementation)

this.ratePerHourParameter = parameterName(this.implementation.params[1])
this.daysParameter = parameterName(this.implementation.params[1])
this.discountParameter = parameterName(this.implementation.params[2])
}

// Expect ceil
}

export class FreelancerRatesSolution {
Expand Down
12 changes: 8 additions & 4 deletions src/analyzers/utils/extract_parameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ type VariableDeclarator = TSESTree.VariableDeclarator
type DestructuringPattern = TSESTree.DestructuringPattern

export function parameterName(
parameter: Parameter | VariableDeclarator,
parameter: Parameter | VariableDeclarator | undefined,
fallback = '<unknown>'
): string {
if (parameter === undefined) {
return '<undefined>'
}

switch (parameter.type) {
case AST_NODE_TYPES.VariableDeclarator: {
return parameterName(parameter.id)
Expand Down Expand Up @@ -85,7 +89,7 @@ function objectLiteralElementName(
return fallback

case AST_NODE_TYPES.Property:
return properyNameName(element.key, fallback)
return propertyName(element.key, fallback)

// Don't support nested names for now
// case AST_NODE_TYPES.RestElement:
Expand All @@ -97,7 +101,7 @@ function objectLiteralElementName(
}
}

function properyNameName(key: PropertyName, fallback = '<unknown>'): string {
function propertyName(key: PropertyName, fallback = '<unknown>'): string {
switch (key.type) {
case AST_NODE_TYPES.Identifier:
return key.name
Expand All @@ -109,7 +113,7 @@ function properyNameName(key: PropertyName, fallback = '<unknown>'): string {
// case AST_NODE_TYPES.SpreadElement:
return fallback
case AST_NODE_TYPES.MemberExpression:
return properyNameName(key.property, fallback)
return propertyName(key.property, fallback)
case AST_NODE_TYPES.ArrowFunctionExpression:
case AST_NODE_TYPES.AssignmentExpression:
case AST_NODE_TYPES.BinaryExpression:
Expand Down
43 changes: 18 additions & 25 deletions test/fixtures/freelancer-rates/exemplar/.meta/exemplar.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,43 +25,36 @@
* @param {number} ratePerHour
* @returns {number} the rate per day
*/
export function dayRate(ratePerHour) {
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);
}
43 changes: 18 additions & 25 deletions test/fixtures/freelancer-rates/exemplar/freelancer-rates.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,43 +25,36 @@
* @param {number} ratePerHour
* @returns {number} the rate per day
*/
export function dayRate(ratePerHour) {
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);
}