Created
April 27, 2019 02:10
-
-
Save haru01/3573f65ea37dd4d10ef7c017df06c506 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface Expression { | |
times(muptiplier: number): Expression; | |
plus(addend: Expression): Expression; | |
reduce(bank: Bank, to: string): Money | |
} | |
class Money implements Expression { | |
private _amount: number | |
private _currency: string | |
constructor(amount: number, currency: string) { | |
this._amount = amount | |
this._currency = currency | |
} | |
currency(): string { | |
return this._currency | |
} | |
amount(): number { | |
return this._amount | |
} | |
plus(other: Expression): Expression { | |
return new Sum(this, other) | |
} | |
times(muptiplier: number): Expression { | |
return new Money(this.amount() * muptiplier, this.currency()) | |
} | |
reduce(bank: Bank, to: string): Money { | |
const rate = bank.rate(this.currency(), to) | |
return new Money(this.amount() / rate, to) | |
} | |
static dollar(amount: number) { | |
return new Money(amount, 'USD') | |
} | |
static franc(amount: number) { | |
return new Money(amount, 'CHF') | |
} | |
} | |
class Sum implements Expression { | |
private _augend: Expression | |
private _addend: Expression | |
constructor(augend: Expression, addend: Expression) { | |
this._augend = augend | |
this._addend = addend | |
} | |
plus(addend: Expression): Expression { | |
return new Sum(this, addend) | |
} | |
times(muptiplier: number): Expression { | |
return new Sum(this._augend.times(muptiplier), this._addend.times(muptiplier)) | |
} | |
reduce(bank: Bank, to: string): Money { | |
const amount = this._augend.reduce(bank, to).amount() + this._addend.reduce(bank, to).amount() | |
return new Money(amount, to) | |
} | |
} | |
class Bank { | |
private _rates | |
constructor() { | |
this._rates = {} | |
} | |
rate(from: string, to: string): number { | |
return this._rates[from + to] || 1 | |
} | |
addRate(from: string, to: string, rate: number) { | |
this._rates[from + to] = rate | |
} | |
reduce(source: Expression, to: string): Money { | |
return source.reduce(this, to) | |
} | |
} | |
it('mupltiplication', () => { | |
const five = Money.dollar(5) | |
expect(five.times(2)).toEqual(Money.dollar(10)) | |
expect(five.times(3)).toEqual(Money.dollar(15)) | |
expect(Money.franc(5).times(3)).toEqual(Money.franc(15)) | |
}) | |
it('equals', () => { | |
expect(Money.dollar(5)).toEqual(Money.dollar(5)) | |
expect(Money.dollar(5)).not.toEqual(Money.dollar(6)) | |
expect(Money.dollar(5)).not.toEqual(Money.franc(5)) | |
}) | |
it('currency', () => { | |
expect(Money.dollar(1).currency()).toBe('USD') | |
expect(Money.franc(1).currency()).toBe('CHF') | |
}) | |
it('simple saddtion', () => { | |
const five = Money.dollar(5) | |
const sum: Expression = five.plus(five) | |
const bank = new Bank() | |
const reduced = bank.reduce(sum, 'USD') | |
expect(reduced).toEqual(Money.dollar(10)) | |
}) | |
it('reduces sum', () => { | |
const sum: Expression = new Sum(Money.dollar(3), Money.dollar(4)) | |
const bank = new Bank() | |
expect(bank.reduce(sum, "USD")).toEqual(Money.dollar(7)) | |
}) | |
it('reduce money', () => { | |
const bank = new Bank() | |
const result = bank.reduce(Money.dollar(1), "USD") | |
expect(result).toEqual(Money.dollar(1)) | |
}) | |
it('reduce money differenct currency', () => { | |
const bank = new Bank() | |
bank.addRate("CHF", "USD", 2) | |
const result = bank.reduce(Money.franc(2), "USD") | |
expect(result).toEqual(Money.dollar(1)) | |
}) | |
it('mix addtion', () => { | |
const fiveBucks: Expression = Money.dollar(5) | |
const tenFrans: Expression = Money.franc(10) | |
const bank = new Bank() | |
bank.addRate("CHF", "USD", 2) | |
const result = bank.reduce(fiveBucks.plus(tenFrans), "USD") | |
expect(result).toEqual(Money.dollar(10)) | |
}) | |
it('sum plus money', () => { | |
const fiveBucks: Expression = Money.dollar(5) | |
const tenFrans: Expression = Money.franc(10) | |
const bank = new Bank() | |
bank.addRate("CHF", "USD", 2) | |
const sum = new Sum(fiveBucks, tenFrans).plus(fiveBucks) | |
const result = bank.reduce(sum, "USD") | |
expect(result).toEqual(Money.dollar(15)) | |
}) | |
it('sum & times', () => { | |
const fiveBucks: Expression = Money.dollar(5) | |
const tenFrans: Expression = Money.franc(10) | |
const bank = new Bank() | |
bank.addRate("CHF", "USD", 2) | |
const sum = new Sum(fiveBucks, tenFrans).times(2) | |
const result = bank.reduce(sum, "USD") | |
expect(result).toEqual(Money.dollar(20)) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment