Skip to content

Instantly share code, notes, and snippets.

@haru01
Created April 27, 2019 02:10
Show Gist options
  • Save haru01/3573f65ea37dd4d10ef7c017df06c506 to your computer and use it in GitHub Desktop.
Save haru01/3573f65ea37dd4d10ef7c017df06c506 to your computer and use it in GitHub Desktop.
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