Created
December 4, 2018 08:49
-
-
Save tmitz/853f8e2b005aa92786ebe057e6d05405 to your computer and use it in GitHub Desktop.
Refactoring
This file contains hidden or 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
export default function createStatementData(invoice, plays) { | |
const result = {}; | |
result.customer = invoice.customer; | |
result.performances = invoice.performances.map(enrichPerformance); | |
result.totalAmount = totalAmount(result); | |
result.totalVolumeCredits = totalVolumeCredits(result); | |
return result; | |
function enrichPerformance(aPerformance) { | |
const calculator = createPerformanceCaluculator(aPerformance, playFor(aPerformance)); | |
const result = Object.assign({}, aPerformance); | |
result.play = calculator.play; | |
result.amount = calculator.amount; | |
result.volumeCredits = calculator.volumeCredits; | |
return result; | |
} | |
function playFor(aPerformance) { | |
return plays[aPerformance.playID]; | |
} | |
function totalVolumeCredits(data) { | |
return data.performances.reduce((total, p) => total + p.volumeCredits, 0); | |
} | |
function totalAmount(data) { | |
return data.performances.reduce((total, p) => total + p.amount, 0); | |
} | |
} | |
function createPerformanceCaluculator(aPerformance, aPlay) { | |
switch (aPlay.type) { | |
case 'tragedy': | |
return new TragedyCalculator(aPerformance, aPlay); | |
case 'comedy': | |
return new ComedyCalculator(aPerformance, aPlay); | |
default: | |
throw new Error(`unknown type: ${aPlay.type}`); | |
} | |
} | |
class PerformanceCalculator { | |
constructor(aPerformance, aPlay) { | |
this.performance = aPerformance; | |
this.play = aPlay; | |
} | |
get amount() { | |
throw new Error('subclass responsibility.'); | |
} | |
get volumeCredits() { | |
return Math.max(this.performance.audience - 30, 0); | |
} | |
} | |
class TragedyCalculator extends PerformanceCalculator { | |
get amount() { | |
let result = 40000; | |
if (this.performance.audience > 30) { | |
result += 1000 * (this.performance.audience - 30); | |
} | |
return result; | |
} | |
} | |
class ComedyCalculator extends PerformanceCalculator { | |
get amount() { | |
let result = 30000; | |
if (this.performance.audience > 20) { | |
result += 10000 + 500 * (this.performance.audience - 20); | |
} | |
result += 300 * this.performance.audience; | |
return result; | |
} | |
get volumeCredits() { | |
return super.volumeCredits + Math.floor(this.performance.audience / 5); | |
} | |
} |
This file contains hidden or 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
import createStatementData from './createStatementData.js'; | |
function statement(invoice, plays) { | |
return renderPlainText(createStatementData(invoice, plays)); | |
} | |
function renderPlainText(data) { | |
let result = `Statement for ${data.customer}\n`; | |
for (const perf of data.performances) { | |
// print line for this order | |
result += ` ${perf.play.name}: ${usd(perf.amount)} (${perf.audience} seats)\n`; | |
} | |
result += `Amount owed is ${usd(data.totalAmount)}\n`; | |
result += `You earned ${data.totalVolumeCredits} credits\n`; | |
return result; | |
} | |
function htmlStatement(invoice, plays) { | |
return renderHtml(createStatementData(invoice, plays)); | |
} | |
function renderHtml(data) { | |
let result = `<h1>Statement for ${data.customer}</h1>\n`; | |
result += `<table>\n`; | |
result += `<tr><th>play</th><th>seats</th><th>cost</th></tr>`; | |
for (let perf of data.performances) { | |
result += ` <tr><td>${perf.play.name}</td><td>${perf.audience}</td>`; | |
result += `<td>${usd(perf.amount)}</td></tr>\n`; | |
} | |
result += `</table>\n`; | |
result += `<p>Amount owed is <em>${usd(data.totalAmount)}</em></p>\n`; | |
result += `<p>You earned <em>${data.totalVolumeCredits}</em> credits</p>\n`; | |
return result; | |
} | |
function usd(aNumber) { | |
return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', minimumFractionDigits: 2 }).format( | |
aNumber / 100 | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment