๋ง์ฝ์ ์ฐ๊ทน ์ข ๋ฅ๊ฐ ์ถ๊ฐ๋๋ฉด ์ด๋ป๊ฒ ๋ ๊น? ์ด์ ๋คํ์ฑ์ผ๋ก ๋ณ๊ฒฝํ ์์ ์ด๋ค.
๋คํ์ฑ์ ํ์ฉํด ๊ณ์ฐ์ฝ๋ ์ฌ๊ตฌ์ฑํ๊ธฐ
- ์ง๊ธ๊น์ง ๊ตฌ์ฑํ ์ฝ๋๋ฅผ ํ๋ฒ ๋ณด์.
// createStatementData.js
export default function createStatementData(invoice, plays) {
const statementData = {};
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount();
statementData.totalVolumeCredits = totalVolumeCredits();
return statementData;
function enrichPerformance(aPerformance) {
const result = Object.assign({}, aPerformance);
result.play = playFor(result);
result.amount = amountFor(result);
result.volumeCredits = volumeCreditsFor(result);
return result;
}
function playFor(aPerformance) {
return plays[aPerformance.playID];
}
function amountFor(aPerformance) {
let result = 0;
switch (aPerformance.play.type) {
case "tragedy": // ๋น๊ทน
result = 40000;
if (aPerformance.audience > 30) {
result += 1000 * (aPerformance.audience - 30);
}
break;
case "comedy": // ํฌ๊ทน
result = 30000;
if (aPerformance.audience > 20) {
result += 10000 + 500 * (aPerformance.audience - 20);
}
result += 300 * aPerformance.audience;
break;
default:
throw new Error('์ ์ ์๋ ์ฅ๋ฅด: ${aPerformance.play.type}');
}
return result;
}
function volumeCreditsFor(aPerformance) {
let result = 0;
result += Math.max(aPerformance.audience - 30, 0);
if ("comedy" === playFor(aPerformance).type)
result += Math.floor(aPerformance.audience / 5);
return result;
}
function totalAmount(data) {
return data.performances
.reduce((total, p) => total + p.amount, 0);
}
func totalVolumeCredits(data) {
data.performances
.reduce((total, p) => total + p.volumeCredits, 0);
}
}// statement.js
import createStatementData from './createStatementData.js';
function statement(invoice, plays) {
return renderPlainText(createStatementData(invoice, plays));
}
function htmlStatement(invoice, plays) {
return renderHtml(createStatementData(invoice, plays));
}
function renderPlainText(data) {
let result = "์ฒญ๊ตฌ ๋ด์ญ (๊ณ ๊ฐ๋ช
: ${data.customer})\n";
for (let perf of data.performances) {
result += " ${perf.play.name}: ${usd(amountFor(perf))} (${perf.audience}์)\n";
}
result += "์ด์ก: ${usd(data.totalAmount)}\n";
result += "์ ๋ฆฝ ํฌ์ธํธ: ${data.totalVolumeCredits}์ \n";
return result;
}
function renderHtml(data) {
let result = "<h1>์ฒญ๊ตฌ ๋ด์ญ (๊ณ ๊ฐ๋ช
: ${data.customer})</h1>\n";
result += "<table>\n";
result += "<tr><th>์ฐ๊ทน</th><th>์ข์ ์</th><th>๊ธ์ก</th></tr>";
for (let perf of data.performances) {
result += " <tr><td>${perf.play.name}</td><td>(${perf.audience}์)</td>";
result += "<td>${usd(amountFor(perf))}</td></tr>\n";
}
result += "</table>\n";
result += "<p>์ด์ก: <em>${usd(data.totalAmount)}</em></p>\n";
result += "<p>์ ๋ฆฝ ํฌ์ธํธ: <em>${data.totalVolumeCredits}</em>์ </p>\n";
return result;
}
function usd(aNumber) {
return new Intl.NumberFormat("en-US",
{ style: "currency", currency: "USD",
minimumFractionDigits: 2 }).format(aNumber/100);
}- ์ด๋ฒ์๋ ์ฐ๊ทน ์ฅ๋ฅด๋ฅผ ์ถ๊ฐํด๋ณด์.
- ์ฐ๊ทน ์ฅ๋ฅด๋ผ ํจ์ โcomedyโ์ ๊ฐ์ด ํ๊ธฐ๋๊ฑธ ๋งํ๋ค.
- ๊ทธ๋ ๊ฒ ๋๋ฉด
amountFor()ํจ์๋ฅผ ๊ฑด๋ค๊ณ , ์ฌ๊ธฐ์ ์ฒ๋ฆฌํ ์ ๋ฐ์ ์๋ค. switch๋ฌธ์ ์ฌ์ฉํ๊ฒ ๋๊ณ , ํ์ฅ์ด ๋ ์๋ก ๊ณจ์นซ๊ฑฐ๋ฆฌ๊ฐ ๋ ๊ฒ์ด๋ผ๋ ๊ฒ์ ํ์ ํ ์ ์๋ค.- ์ด๋ฅผ ๋ฐฉ์งํ๋ ค๋ฉด ๊ตฌ์กฐ์ ์ธ ์์๋ก ๋ณด์ํด์ผ ํ๋ค. ์ฌ๊ธฐ์ ์ฌ์ฉํ ๋ฐฉ๋ฒ์ ๋คํ์ฑ์ด๋ค.
- ์กฐ๊ฑด๋ถ ๋ก์ง์ ๋คํ์ฑ์ผ๋ก ๋ฐ๊พธ๊ธฐ๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ค.
- ์์ ๊ณ์ธต์ ๊ตฌ์ฑํ์ฌ ๊ฐ๊ฐ์ ์๋ธ ํด๋์ค๊ฐ ๊ตฌ์ฒด์ ์ธ ๊ณ์ฐ ๋ก์ง์ ์ ์ํ ์ ์๋๋ก ํ์.
- ์์ ๋ฆฌํฉํ ๋ง์ ํด๋์๊ธฐ ๋๋ฌธ์
createStatementData.js์๋ง ์ง์คํ๋ฉด ๋๋ค.
// createStatementData.js
export default function createStatementData(invoice, plays) {
const statementData = {};
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount();
statementData.totalVolumeCredits = totalVolumeCredits();
return statementData;
function enrichPerformance(aPerformance) {
const result = Object.assign({}, aPerformance);
result.play = playFor(result);
result.amount = amountFor(result);
result.volumeCredits = volumeCreditsFor(result);
return result;
}
function playFor(aPerformance) {
return plays[aPerformance.playID];
}
function amountFor(aPerformance) {
let result = 0;
switch (aPerformance.play.type) {
case "tragedy": // ๋น๊ทน
result = 40000;
if (aPerformance.audience > 30) {
result += 1000 * (aPerformance.audience - 30);
}
break;
case "comedy": // ํฌ๊ทน
result = 30000;
if (aPerformance.audience > 20) {
result += 10000 + 500 * (aPerformance.audience - 20);
}
result += 300 * aPerformance.audience;
break;
default:
throw new Error('์ ์ ์๋ ์ฅ๋ฅด: ${aPerformance.play.type}');
}
return result;
}
function volumeCreditsFor(aPerformance) {
let result = 0;
result += Math.max(aPerformance.audience - 30, 0);
if ("comedy" === playFor(aPerformance).type)
result += Math.floor(aPerformance.audience / 5);
return result;
}
function totalAmount(data) {
return data.performances
.reduce((total, p) => total + p.amount, 0);
}
func totalVolumeCredits(data) {
data.performances
.reduce((total, p) => total + p.volumeCredits, 0);
}
}๊ณต์ฐ๋ฃ ๊ณ์ฐ๊ธฐ ๋ง๋ค๊ธฐ
- ์์ ์ฝ๋๋ฅผ ๋ณด๋ฉด,
amountFor()ํจ์๊ฐaPerformance๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๋๋ค. - ๊ทธ๋ฆฌ๊ณ ๊ทธ ์์์
type์ ๋ฐ๋ผ ๊ณ์ฐ๋ก์ง์ด ๋ถ๊ธฐ๋๊ณ ์๋ค. volumeCreditsFor()ํจ์๋ ๋ง์ฐฌ๊ฐ์ง๋ค.- ์์ ๋ ํจ์๋ฅผ ์ ์ฉ ํด๋์ค๋ก ์ฎ๊ธฐ์. (
PerformanceCalculator)
// createStatementData.js
class PerformanceCalculator {
constructor(aPerformance) {
this.performance = aPerformance;
}
}
export default function createStatementData(invoice, plays) {
const statementData = {};
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount();
statementData.totalVolumeCredits = totalVolumeCredits();
return statementData;
function enrichPerformance(aPerformance) {
const calculator = new PerformanceCalculator(aPerformance);
const result = Object.assign({}, aPerformance);
result.play = playFor(aPerformance);
result.amount = amountFor(result);
result.volumeCredits = volumeCreditsFor(result);
return result;
}
function playFor(aPerformance) {
return plays[aPerformance.playID];
}
function amountFor(aPerformance) {
let result = 0;
switch (aPerformance.play.type) {
case "tragedy": // ๋น๊ทน
result = 40000;
if (aPerformance.audience > 30) {
result += 1000 * (aPerformance.audience - 30);
}
break;
case "comedy": // ํฌ๊ทน
result = 30000;
if (aPerformance.audience > 20) {
result += 10000 + 500 * (aPerformance.audience - 20);
}
result += 300 * aPerformance.audience;
break;
default:
throw new Error('์ ์ ์๋ ์ฅ๋ฅด: ${aPerformance.play.type}');
}
return result;
}
function volumeCreditsFor(aPerformance) {
let result = 0;
result += Math.max(aPerformance.audience - 30, 0);
if ("comedy" === playFor(aPerformance).type)
result += Math.floor(aPerformance.audience / 5);
return result;
}
function totalAmount(data) {
return data.performances
.reduce((total, p) => total + p.amount, 0);
}
func totalVolumeCredits(data) {
data.performances
.reduce((total, p) => total + p.volumeCredits, 0);
}
}- ์ปดํ์ผ - ํ ์คํธ - ์ปค๋ฐํ๋ค.
- ์ผ๋จ ์ด ๊ณ์ฐ๊ธฐ์์ ๋ชจ๋ ์ ๋ณด๋ฅผ ๊ณ์ฐํ ์ ์๋๋ก ๋ณ๊ฒฝํด๋ณด์.
- ์ฐ๊ทน ๋ ์ฝ๋๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํด ํด๋น ์ ๋ณด๋ฅผ ์ผ๋จ ์์ผ๋ก ๋ฐ์๋ณด์.
// createStatementData.js
class PerformanceCalculator {
constructor(aPerformance, aPlay) { // ๋ณ๊ฒฝ๋จ
this.performance = aPerformance;
this.play = aPlay; // ๋ณ๊ฒฝ๋จ
}
}
export default function createStatementData(invoice, plays) {
const statementData = {};
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount();
statementData.totalVolumeCredits = totalVolumeCredits();
return statementData;
function enrichPerformance(aPerformance) {
const calculator = new PerformanceCalculator(aPerformance, playFor(aPerformance)); // ๋ณ๊ฒฝ๋จ
const result = Object.assign({}, aPerformance);
result.play = calculator.play; // ๋ณ๊ฒฝ๋จ
result.amount = amountFor(result);
result.volumeCredits = volumeCreditsFor(result);
return result;
}
...
}ํจ์๋ค์ ๊ณ์ฐ๊ธฐ๋ก ์ฎ๊ธฐ๊ธฐ
- ์ด ๋ค์์ ๊ณต์ฐ๋ฃ ๊ณ์ฐ ๋ก์ง์ด๋ค.
- ์ฌ๊ธฐ์๋ถํฐ ์์ ์ด ์ข ์ปค์ง๋ค.
- ์ผ๋จ
amountFor()ํจ์๋ฅผ ์ฎ๊ฒจ๋ณด์. - ์์
PerfomanaceCalculatorํด๋์ค ์์์ ์์ ๊ฐ๋ฅํ๋๋ก ํ์.
// createStatementData.js
class PerformanceCalculator {
constructor(aPerformance, aPlay) {
this.performance = aPerformance;
this.play = aPlay;
}
function amount() {
let result = 0;
switch (this.play.type) { // ๋ณ๊ฒฝ๋จ
case "tragedy":
result = 40000;
if (this.performance.audience > 30) { // ๋ณ๊ฒฝ๋จ
result += 1000 * (this.performance.audience - 30); // ๋ณ๊ฒฝ๋จ
}
break;
case "comedy":
result = 30000;
if (this.performance.audience > 20) { // ๋ณ๊ฒฝ๋จ
result += 10000 + 500 * (this.performance.audience - 20); // ๋ณ๊ฒฝ๋จ
}
result += 300 * this.performance.audience; // ๋ณ๊ฒฝ๋จ
break;
default:
throw new Error('์ ์ ์๋ ์ฅ๋ฅด: ${this.play.type}'); // ๋ณ๊ฒฝ๋จ
}
return result;
}
}
export default function createStatementData(invoice, plays) {
const statementData = {};
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount();
statementData.totalVolumeCredits = totalVolumeCredits();
return statementData;
function enrichPerformance(aPerformance) {
const calculator = new PerformanceCalculator(aPerformance, playFor(aPerformance));
const result = Object.assign({}, aPerformance);
result.play = calculator.play;
result.amount = calculator.amount(); // ๋ณ๊ฒฝ๋จ
result.volumeCredits = volumeCreditsFor(result);
return result;
}
function playFor(aPerformance) {
return plays[aPerformance.playID];
}
function volumeCreditsFor(aPerformance) {
let result = 0;
result += Math.max(aPerformance.audience - 30, 0);
if ("comedy" === playFor(aPerformance).type)
result += Math.floor(aPerformance.audience / 5);
return result;
}
function totalAmount(data) {
return data.performances
.reduce((total, p) => total + p.amount, 0);
}
func totalVolumeCredits(data) {
data.performances
.reduce((total, p) => total + p.volumeCredits, 0);
}
...
}amountFor()ํจ์๋ฅผPerformanceCalculatorํด๋์ค๋ก ์ฎ๊ฒผ๋ค.- ๋ค์์ ์ ๋ฆฝ ํฌ์ธํธ ๋ถ๋ถ์ด๋ค.
// createStatementData.js
class PerformanceCalculator {
constructor(aPerformance, aPlay) {
this.performance = aPerformance;
this.play = aPlay;
}
get amount() {
let result = 0;
switch (this.play.type) {
case "tragedy":
result = 40000;
if (this.performance.audience > 30) {
result += 1000 * (this.performance.audience - 30);
}
break;
case "comedy":
result = 30000;
if (this.performance.audience > 20) {
result += 10000 + 500 * (this.performance.audience - 20);
}
result += 300 * this.performance.audience;
break;
default:
throw new Error('์ ์ ์๋ ์ฅ๋ฅด: ${this.play.type}');
}
return result;
}
get volumeCredits() {
let result = 0;
result += Math.max(this.aPerformance.audience - 30, 0); // ๋ณ๊ฒฝ๋จ
if ("comedy" === this.play.type) // ๋ณ๊ฒฝ๋จ
result += Math.floor(this.aPerformance.audience / 5); // ๋ณ๊ฒฝ๋จ
return result;
}
}
export default function createStatementData(invoice, plays) {
const statementData = {};
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount();
statementData.totalVolumeCredits = totalVolumeCredits();
return statementData;
function enrichPerformance(aPerformance) {
const calculator = new PerformanceCalculator(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 totalAmount(data) {
return data.performances
.reduce((total, p) => total + p.amount, 0);
}
function totalVolumeCredits(data) {
data.performances
.reduce((total, p) => total + p.volumeCredits, 0);
}
...
}๊ณต์ฐ๋ฃ ๊ณ์ฐ๊ธฐ๋ฅผ ๋คํ์ฑ ๋ฒ์ ์ผ๋ก ๋ง๋ค๊ธฐ
- ์ด์
PerformanceCalculatorํด๋์ค๋ฅผ ๋คํ์ฑ์ผ๋ก ๋ฐ๊ฟ๋ณด์. - ๊ฐ์ฅ ๋จผ์ ํ ์ผ์
.type๋์ ์๋ธํด๋์ค๋ฅผ ์ฌ์ฉํ๋๋ก ๋ฐ๊พธ๋ ๊ฒ์ด๋ค. (ํ์ ์ฝ๋๋ฅผ ์๋ธํด๋์ค๋ก ๋ฐ๊พธ๊ธฐ) - ์ผ๋จ ํฉํ ๋ฆฌ ํจ์๋ฅผ ๋ง๋ค์.
// createStatementData.js
function createPerformanceCalculator(aPerformance, aPlay) {
switch(aPlay.type) {
case "tragedy":
return new TragedyCalculator(aPerformance, aPlay);
case "comedy":
return new ComedyCalculator(aPerformance, aPlay);
default:
throw new Error('์ ์ ์๋ ์ฅ๋ฅด: ${aPlay.type}');
}
}
class TragedyCalculator(aPerformance, aPlay) {
}
class ComedyCalculator(aPerformance, aPlay) {
}
class PerformanceCalculator {
constructor(aPerformance, aPlay) {
this.performance = aPerformance;
this.play = aPlay;
}
get amount() {
let result = 0;
switch (this.play.type) {
case "tragedy":
result = 40000;
if (this.performance.audience > 30) {
result += 1000 * (this.performance.audience - 30);
}
break;
case "comedy":
result = 30000;
if (this.performance.audience > 20) {
result += 10000 + 500 * (this.performance.audience - 20);
}
result += 300 * this.performance.audience;
break;
default:
throw new Error('์ ์ ์๋ ์ฅ๋ฅด: ${this.play.type}');
}
return result;
}
get volumeCredits() {
let result = 0;
result += Math.max(this.aPerformance.audience - 30, 0); // ๋ณ๊ฒฝ๋จ
if ("comedy" === this.play.type) // ๋ณ๊ฒฝ๋จ
result += Math.floor(this.aPerformance.audience / 5); // ๋ณ๊ฒฝ๋จ
return result;
}
}
export default function createStatementData(invoice, plays) {
const statementData = {};
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount();
statementData.totalVolumeCredits = totalVolumeCredits();
return statementData;
function enrichPerformance(aPerformance) {
const calculator = createPerformanceCalculator(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 totalAmount(data) {
return data.performances
.reduce((total, p) => total + p.amount, 0);
}
function totalVolumeCredits(data) {
data.performances
.reduce((total, p) => total + p.volumeCredits, 0);
}
...
}
- ์ปดํ์ผ - ํ ์คํธ - ์ปค๋ฐํ๋ค.
- ์ด์ ๋คํ์ฑ์ผ๋ก ๋ฐ๊ฟ๋ณด์.
// createStatementData.js
function createPerformanceCalculator(aPerformance, aPlay) {
switch(aPlay.type) {
case "tragedy":
return new TragedyCalculator(aPerformance, aPlay);
case "comedy":
return new ComedyCalculator(aPerformance, aPlay);
default:
throw new Error('์ ์ ์๋ ์ฅ๋ฅด: ${aPlay.type}');
}
}
class TragedyCalculator(aPerformance, aPlay) {
get amount() { // ๋ณ๊ฒฝ๋จ
let result = 40000;
if (this.performance.audience > 30) {
result += 1000 * (this.performance.audience - 30);
}
return result;
}
}
class ComedyCalculator(aPerformance, aPlay) {
get amount() { // ๋ณ๊ฒฝ๋จ
let result = 30000;
if (this.performance.audience > 20) {
result += 10000 + 500 * (this.performance.audience - 20);
}
result += 300 * this.performance.audience;
return result;
}
}
class PerformanceCalculator {
constructor(aPerformance, aPlay) {
this.performance = aPerformance;
this.play = aPlay;
}
get amount() {
throw new Error('์๋ธํด๋์ค์์ ์ฒ๋ฆฌํ๋๋ก ์ค๊ณ๋์์ต๋๋ค.'); // ๋ณ๊ฒฝ๋จ
}
get volumeCredits() {
let result = 0;
result += Math.max(this.aPerformance.audience - 30, 0);
if ("comedy" === this.play.type)
result += Math.floor(this.aPerformance.audience / 5);
return result;
}
}
export default function createStatementData(invoice, plays) {
const statementData = {};
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount();
statementData.totalVolumeCredits = totalVolumeCredits();
return statementData;
function enrichPerformance(aPerformance) {
const calculator = createPerformanceCalculator(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 totalAmount(data) {
return data.performances
.reduce((total, p) => total + p.amount, 0);
}
function totalVolumeCredits(data) {
data.performances
.reduce((total, p) => total + p.volumeCredits, 0);
}
...
}- ์ปดํ์ผ - ํ ์คํธ - ์ปค๋ฐํ๋ค.
- ๋ค์์ผ๋ก๋
volumeCredits()ํจ์๋ฅผ ์ฎ๊ฒจ๋ณด์.
// createStatementData.js
function createPerformanceCalculator(aPerformance, aPlay) {
switch(aPlay.type) {
case "tragedy":
return new TragedyCalculator(aPerformance, aPlay);
case "comedy":
return new ComedyCalculator(aPerformance, aPlay);
default:
throw new Error('์ ์ ์๋ ์ฅ๋ฅด: ${aPlay.type}');
}
}
class TragedyCalculator(aPerformance, aPlay) {
get amount() {
let result = 40000;
if (this.performance.audience > 30) {
result += 1000 * (this.performance.audience - 30);
}
return result;
}
}
class ComedyCalculator(aPerformance, aPlay) {
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() { // ๋ณ๊ฒฝ๋จ
super.volumeCredits + Math.floor(this.aPerformance.audience / 5);
}
}
class PerformanceCalculator {
constructor(aPerformance, aPlay) {
this.performance = aPerformance;
this.play = aPlay;
}
get amount() {
throw new Error('์๋ธํด๋์ค์์ ์ฒ๋ฆฌํ๋๋ก ์ค๊ณ๋์์ต๋๋ค.');
}
get volumeCredits() {
Math.max(this.aPerformance.audience - 30, 0);
}
}
export default function createStatementData(invoice, plays) {
const statementData = {};
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount();
statementData.totalVolumeCredits = totalVolumeCredits();
return statementData;
function enrichPerformance(aPerformance) {
const calculator = createPerformanceCalculator(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 totalAmount(data) {
return data.performances
.reduce((total, p) => total + p.amount, 0);
}
function totalVolumeCredits(data) {
data.performances
.reduce((total, p) => total + p.volumeCredits, 0);
}
...
}