Pair
Реалізувати класи Time (“години.хвилини”) та Money (“гривні.копійки”), які містять методи збільшення/зменшення величин на 1 та додавання двох величин. Згенерувати поступово випадковим чином пар (час, гроші), де час – тривалість виконання роботи, а гроші – вартість однієї хвилини роботи працівників. Обчислити витрати на виконання кожної із робіт.
Рішення:
'use strict'
function getRandomInteger(min, max) {
return min + Math.floor(Math.random() * (max - min + 1))
}
// =======================================================================
class LimitedNumber {
#number
/**
* @param {number} number
* @param {number} minNumber
* @param {number} maxNumber
*/
constructor(number, minNumber, maxNumber) {
if (minNumber >= maxNumber)
throw new RangeError("Max can't be lesser or equal min.")
this.minNumber = minNumber
this.maxNumber = maxNumber
this.offset = maxNumber - minNumber
this.number = number
}
get number() {
return this.#number
}
set number(newValue) {
if (typeof newValue !== 'number' || Number.isNaN(newValue))
throw new TypeError('Invalid number.')
const wrapperValue =
((newValue - this.minNumber) % this.offset) + this.minNumber
this.#number =
wrapperValue < this.minNumber ? wrapperValue + this.offset : wrapperValue
}
toString() {
return `Number ${this.number} ∈ [${this.minNumber}, ${this.maxNumber})`
}
}
// ---
const n1 = new LimitedNumber(0, -10, 10)
n1.number = 10
console.debug(String(n1))
// =======================================================================
class Pair {
limitHigh
limitLow
#high
#low
/**
* @param {number} high
* @param {number} low
* @param {number} limitHigh
* @param {number} limitLow
*/
constructor(high, low, limitHigh, limitLow) {
this.limitHigh = limitHigh
this.limitLow = limitLow
this.#high = new LimitedNumber(high, 0, limitHigh)
this.#low = new LimitedNumber(low, 0, limitLow)
}
get low() {
return this.#low.number
}
set low(v) {
this.#low.number = v
}
get high() {
return this.#high.number
}
set high(v) {
this.#high.number = v
}
increase() {
this.low++ //? can't use prefix increment for private fields
if (this.low === 0) this.high++
}
decrease() {
if (this.low-- === 0) this.high--
}
/**
* @param {number} high
* @param {number} low
*/
add(high, low) {
this.high += high
this.low += low
}
toString() {
return `${this.high} - ${this.low}`
}
valueOf() {
return this.low + this.high * this.limitLow
}
}
class Time extends Pair {
/**
* @param {number} h
* @param {number} m
*/
constructor(h, m) {
super(h, m, 24, 60)
}
get h() {
return this.high
}
set h(v) {
this.high = v
}
get m() {
return this.low
}
set m(v) {
this.low = v
}
toString() {
return `${String(this.high).padStart(2, '0')}:${String(this.low).padStart(2, '0')}`
}
}
// ---
const t1 = new Time(23 + 24, 59 + 60)
console.debug(String(t1))
t1.increase()
console.debug(String(t1))
t1.decrease()
console.debug(String(t1))
// =======================================================================
class Money extends Pair {
/**
* @param {number} grn
* @param {number} coins
*/
constructor(grn, coins) {
super(grn, coins, Infinity, 100)
}
get grn() {
return this.high
}
set grn(v) {
this.high = v
}
get coins() {
return this.low
}
set coins(v) {
this.low = v
}
decrease() {
super.decrease()
if (this.grn === Infinity) throw new Error("Money can't be negative.")
}
toString() {
return `${this.high}.${String(this.low).padStart(2, '0')} UAH`
}
}
// ---
const m1 = new Money(0, 99)
console.debug(String(m1))
m1.increase()
console.debug(String(m1))
m1.decrease()
console.debug(String(m1))
m1.add(2, 1)
console.debug(String(m1))
// =======================================================================
class Job {
durationHours
costPerMinute
title
/**
* @param {number} hours
* @param {number} minutes
* @param {number} grn
* @param {number} coins
* @param {string} title
*/
constructor(hours, minutes, grn, coins, title = '') {
this.durationHours = new Time(hours, minutes)
this.costPerMinute = new Money(grn, coins)
this.title = title
}
get totalCost() {
const totalCostInCoins =
Number(this.durationHours) * Number(this.costPerMinute)
const cost = new Money(
Math.floor(totalCostInCoins / 100),
totalCostInCoins % 100,
)
return cost
}
toString() {
return `🧾 Робота ${this.title}\n⏱ Тривалість: ${this.durationHours}\n💰 Вартість за хвилину: ${this.costPerMinute}\n💯 Загальна вартість: ${this.totalCost}.`
}
}
// ---
const w1 = new Job(1, 35, 10, 45, 'таксі')
console.debug(String(w1))
// =======================================================================
const jobList = Array.from(
{length: 5},
(_, i) =>
new Job(
getRandomInteger(0, 23),
getRandomInteger(0, 59),
getRandomInteger(0, 200),
getRandomInteger(0, 99),
`№${i + 1}`,
),
)
for (const job of jobList) {
console.log(String(job))
}
