์šฐ๋ฆฌ๊ฐ€ ํ•˜๊ณ  ์‹ถ์—ˆ๋˜ HTML์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๊ณ„์‚ฐ ๋‹จ๊ณ„์™€ ํฌ๋งทํŒ… ๋‹จ๊ณ„๋ฅผ ๋ถ„๋ฆฌํ•˜๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ•ด๋ณด์ž.

๊ณ„์‚ฐ ๋‹จ๊ณ„์™€ ํฌ๋งทํŒ… ๋‹จ๊ณ„ ๋ถ„๋ฆฌํ•˜๊ธฐ

 
function statement(invoice, plays) {
    let result = "์ฒญ๊ตฌ ๋‚ด์—ญ (๊ณ ๊ฐ๋ช…: ${invoice.customer})\n";
    for (let perf of invoice.performances) {
      result += " ${playFor(perf).name}: ${usd(amountFor(perf))} (${perf.audience}์„)\n";
    }
    result += "์ด์•ก: ${usd(totalAmount())}\n";
    result += "์ ๋ฆฝ ํฌ์ธํŠธ: ${totalVolumeCredits()}์ \n";
    return result;
 
    function totalAmount() {
        let result = 0;
        for (let perf of invoice.performances) {
            result += amountFor(perf);
        }
        return result;
    }
 
    function amountFor(aPerformance) {
        let result = 0;
        switch (playFor(aPerformance).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(`unknown type: ${playFor(aPerformance).type}`);
        }
        return result;
    }
 
    function playFor(aPerformance) {
        return plays[aPerformance.playID];
    }
 
    function usd(aNumber) {
        return new Intl.NumberFormat("en-US",
            { style: "currency", currency: "USD",
            minimumFractionDigits: 2 }).format(aNumber/100);
    }
 
    func totalVolumeCredits() {
        let result = 0;
        for (let perf of invoice.performances) {
            result += volumeCreditsFor(perf);
        }
        return result;
    }
 
    function volumeCreditsFor(aPerformance) {
        let result = 0;
        // add volume credits
        result += Math.max(aPerformance.audience - 30, 0);
        // add extra credit for every ten comedy attendees
        if ("comedy" === playFor(aPerformance).type) result += Math.floor(aPerformance.audience / 5);
        return result;
    }
}
  • ์ง€๊ธˆ๊นŒ์ง€ ์ง„ํ–‰ํ•œ ๊ณผ์ •์€ ๊ตฌ์กฐ๋ฅผ ๋ณด๊ฐ•ํ•˜๋Š”๋ฐ ์ฃผ์•ˆ์ ์„ ๋‘์—ˆ๋‹ค.
  • ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „์— ์ฝ”๋“œ๋ฅผ ๋ฆฌํŒฉํ† ๋ง ํ–ˆ๊ณ ,
  • ์ด์ œ ์ŠคํŽ™์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.
  • statement() ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋ฅผ HTML๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์„ ์ฒ˜๋ฆฌํ•ด๋ณด์ž.
  • HTML ๋ฒ„์ „์„ ๋งŒ๋“ ๋‹ค๊ณ  ํ•ด์„œ statement() ํ•จ์ˆ˜๋ฅผ ๋ณต์‚ฌํ•ด์„œ ๊ตฌํ˜„์„ ๋ณ€๊ฒฝํ•  ์ˆ˜๋Š” ์—†๋‹ค.
  • ๊ณ„์‚ฐ์€ ๋™์ผํ•˜๊ฒŒ ํ•˜๋˜, ํ‘œํ˜„๋งŒ ๋ณ€๊ฒฝ๋˜๊ฒŒ ํ•ด์•ผ ํ•œ๋‹ค.
  • ์ด๋Ÿฐ ๊ฒฝ์šฐ ๋‹จ๊ณ„ ์ชผ๊ฐœ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์ž. ํ•ต์‹ฌ์€ ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ด๋ฅผ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํ‘œํ˜„ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
  • ๋‹จ๊ณ„ ์ชผ๊ฐœ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์–ด๋””๊นŒ์ง€๊ฐ€ ๊ณ„์‚ฐ์ธ์ง€๋ฅผ ์•Œ์•„๋‚ด์–ด ์ถ”์ถœํ•ด์•ผ ํ•œ๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ ํ•จ์ˆ˜ ์ถ”์ถœํ•˜๊ธฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์œ„ ๊ฒฝ์šฐ์—์„œ๋Š” statement() ํ•จ์ˆ˜์˜ ๋ณธ๋ฌธ ์ „์ฒด๋ฅผ ์ถ”์ถœํ•˜์ž.
function statement(invoice, plays) {
    return renderPlainText(invoice, plays);
}
 
function renderPlainText(invoice, plays) {
    let result = "์ฒญ๊ตฌ ๋‚ด์—ญ (๊ณ ๊ฐ๋ช…: ${invoice.customer})\n";
    for (let perf of invoice.performances) {
      result += " ${playFor(perf).name}: ${usd(amountFor(perf))} (${perf.audience}์„)\n";
    }
    result += "์ด์•ก: ${usd(totalAmount())}\n";
    result += "์ ๋ฆฝ ํฌ์ธํŠธ: ${totalVolumeCredits()}์ \n";
    return result;
}
 
...
  • ๋‹ค์‹œ ์ปดํŒŒ์ผ-ํ…Œ์ŠคํŠธ-์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ์ด์ œ ์ค‘๊ฐ„ ๋‹จ๊ณ„ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ํ•  ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ๋„ฃ์–ด๋ณด์ž.
function statement(invoice, plays) {
    const statementData = {};
    return renderPlainText(statementData, invoice, plays);
}
 
function renderPlainText(data, invoice, plays) {
    let result = "์ฒญ๊ตฌ ๋‚ด์—ญ (๊ณ ๊ฐ๋ช…: ${invoice.customer})\n";
    for (let perf of invoice.performances) {
      result += " ${playFor(perf).name}: ${usd(amountFor(perf))} (${perf.audience}์„)\n";
    }
    result += "์ด์•ก: ${usd(totalAmount())}\n";
    result += "์ ๋ฆฝ ํฌ์ธํŠธ: ${totalVolumeCredits()}์ \n";
    return result;
}
  • ์ด์ œ invoice, plays๋ฅผ ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋กœ ์˜ฎ๊ธฐ์ž.
  • invoice๋ถ€ํ„ฐ ์˜ฎ๊ฒจ๋ณด์ž. ์ผ๋‹จ ํ•„์š”ํ•ด๋ณด์ด๋Š” ๊ฑด customer ๋ฟ์ด๋‹ค.
function statement(invoice, plays) {
    const statementData = {};
    statementData.customer = invoice.customer;
    return renderPlainText(statementData, invoice, plays);
}
 
function renderPlainText(data, invoice, plays) {
    let result = "์ฒญ๊ตฌ ๋‚ด์—ญ (๊ณ ๊ฐ๋ช…: ${data.customer})\n";
    for (let perf of invoice.performances) {
      result += " ${playFor(perf).name}: ${usd(amountFor(perf))} (${perf.audience}์„)\n";
    }
    result += "์ด์•ก: ${usd(totalAmount())}\n";
    result += "์ ๋ฆฝ ํฌ์ธํŠธ: ${totalVolumeCredits()}์ \n";
    return result;
}
  • ๋‹ค์‹œ ์ปดํŒŒ์ผ-ํ…Œ์ŠคํŠธ-์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ๊ทธ ๋‹ค์Œ์œผ๋กœ๋Š” performaces๋ฅผ ์˜ฎ๊ฒจ๋ณด์ž.
function statement(invoice, plays) {
    const statementData = {};
    statementData.customer = invoice.customer; // ๋ณ€๊ฒฝ๋จ
    statementData.performances = invoice.performances; // ๋ณ€๊ฒฝ๋จ
    return renderPlainText(statementData, invoice, plays);
}
 
function renderPlainText(data, plays) {
    let result = "์ฒญ๊ตฌ ๋‚ด์—ญ (๊ณ ๊ฐ๋ช…: ${data.customer})\n";
    for (let perf of data.performances) {
      result += " ${playFor(perf).name}: ${usd(amountFor(perf))} (${perf.audience}์„)\n";
    }
    result += "์ด์•ก: ${usd(totalAmount())}\n";
    result += "์ ๋ฆฝ ํฌ์ธํŠธ: ${totalVolumeCredits()}์ \n";
    return result;
 
    ... 
 
    function totalAmount() {
        let result = 0;
        for (let perf of data.performances) { // ๋ณ€๊ฒฝ๋จ
            result += amountFor(perf);
        }
        return result;
    }
 
    function playFor(aPerformance) {
        return plays[aPerformance.playID];
    }
}
  • ๋‹ค์‹œ ์ปดํŒŒ์ผ-ํ…Œ์ŠคํŠธ-์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • playFor(aPerformance) ํ•จ์ˆ˜๋ฅผ ๋ณด์ž.
  • ๊ฒฐ๊ตญ ํ•˜๋Š” ํ–‰์œ„๋Š”, ์–ด๋– ํ•œ ๊ณต์—ฐ์— ๋Œ€ํ•œ ์—ฐ๊ทน ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด๋‹ค.
  • ๊ฐ€์ ธ์˜จ ์ •๋ณด๋Š” result์— ์ถ”๊ฐ€ํ•œ๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ ๊ตณ์ด ์ด๋ ‡๊ฒŒ ํ•  ํ•„์š”์—†์ด, ๋ฐ”๊นฅ์ชฝ์—์„œ data๋ฅผ ๋„ฃ์–ด์ฃผ๋Š” ์‹œ์ ์— play ์ •๋ณด๋„ ์•Œ ์ˆ˜ ์žˆ์œผ๋ฉด ์ข‹์ง€ ์•Š์„๊นŒ?
  • ๋ณด๋‹ค ๋‹จ์ˆœํ•œ ๋ฐฉ์‹์ด๋‹ค.
  • ์ฒ˜๋ฆฌํ•ด๋ณด์ž.
function statement(invoice, plays) {
    const statementData = {};
    statementData.customer = invoice.customer;
    statementData.performances = invoice.performances.map(enrichPerformance); // ๋ณ€๊ฒฝ๋จ
    return renderPlainText(statementData, plays);
 
    function enrichPerformance(aPerformance) {
        const result = Object.assign({}, aPerformance); // ์–•์€ ๋ณต์‚ฌ ์ˆ˜ํ–‰
        return result;
    }
}
  • ๋‹ค์‹œ ์ปดํŒŒ์ผ-ํ…Œ์ŠคํŠธ-์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ํ•˜๋Š” ์ด์œ ๋Š” ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋„˜๊ธด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ์ด์ œ play์ •๋ณด๋ฅผ ๋„ฃ์–ด์ฃผ๋Ÿฌ ๊ฐ€๋ณด์ž.
function statement(invoice, plays) {
    const statementData = {};
    statementData.customer = invoice.customer;
    statementData.performances = invoice.performances.map(enrichPerformance);
    return renderPlainText(statementData, plays);
 
    function enrichPerformance(aPerformance) { 
        const result = Object.assign({}, aPerformance);
        result.play = playFor(result); // play ์ •๋ณด๋ฅผ ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ๋กœ ์˜ฎ๊น€
        return result;
    }
 
    function playFor(aPerformance) { // renderPlainText()์˜ ์ค‘์ฒฉ ํ•จ์ˆ˜์˜€๋‹ค๊ฐ€ statement()์˜ ํ•˜์œ„๋กœ ์˜ฎ๊น€
        return plays[aPerformance.playID];
    }
}
 
function renderPlainText(data, plays) {
    let result = "์ฒญ๊ตฌ ๋‚ด์—ญ (๊ณ ๊ฐ๋ช…: ${data.customer})\n";
    for (let perf of data.performances) {
      result += " ${perf.play.name}: ${usd(amountFor(perf))} (${perf.audience}์„)\n"; // play ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ
    }
    result += "์ด์•ก: ${usd(totalAmount())}\n";
    result += "์ ๋ฆฝ ํฌ์ธํŠธ: ${totalVolumeCredits()}์ \n";
    return result;
 
    function volumeCreditsFor(aPerformance) {
        let result = 0;
        result += Math.max(aPerformance.audience - 30, 0);
        if ("comedy" === aPerformance.play.type) 
            result += Math.floor(aPerformance.audience / 5);
        return result;
    }
 
    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 totalAmount() {
        let result = 0;
        for (let perf of data.performances) {
            result += amountFor(perf);
        }
        return result;
    }
}
  • ๋‹ค์‹œ ์ปดํŒŒ์ผ-ํ…Œ์ŠคํŠธ-์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • amountFor(aPerformance) ์—ญ์‹œ ๊ณต์—ฐ ์ •๋ณด์— ๋กœ์ง์ด ๊ท€์†๋˜๋ฏ€๋กœ, ๊ทธ ์•ˆ์— ์ •๋ณด๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ๋„ฃ์–ด์ฃผ์ž.
  • ๋ณ€๊ฒฝํ•ด๋ณด์ž.
function statement(invoice, plays) {
    const statementData = {};
    statementData.customer = invoice.customer;
    statementData.performances = invoice.performances.map(enrichPerformance);
    return renderPlainText(statementData, plays);
 
    function enrichPerformance(aPerformance) { 
        const result = Object.assign({}, aPerformance);
        result.play = playFor(result);
        result.amount = amountFor(result); // ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ์— amount ์ •๋ณด๋ฅผ ์ €์žฅ
        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 renderPlainText(data, plays) {
    let result = "์ฒญ๊ตฌ ๋‚ด์—ญ (๊ณ ๊ฐ๋ช…: ${data.customer})\n";
    for (let perf of data.performances) {
      result += " ${perf.play.name}: ${usd(amountFor(perf))} (${perf.audience}์„)\n"; // play ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ
    }
    result += "์ด์•ก: ${usd(totalAmount())}\n";
    result += "์ ๋ฆฝ ํฌ์ธํŠธ: ${totalVolumeCredits()}์ \n";
    return result;
 
    function usd(aNumber) {
        return new Intl.NumberFormat("en-US",
            { style: "currency", currency: "USD",
            minimumFractionDigits: 2 }).format(aNumber/100);
    }
 
    function totalAmount() {
        let result = 0;
        for (let perf of data.performances) {
            result += perf.amount; // ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ
        }
        return result;
    }
 
    func totalVolumeCredits() {
        let result = 0;
        for (let perf of data.performances) { // ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ
            result += volumeCreditsFor(perf);
        }
        return result;
    }
 
    function volumeCreditsFor(aPerformance) {
        let result = 0;
        // add volume credits
        result += Math.max(aPerformance.audience - 30, 0);
        // add extra credit for every ten comedy attendees
        if ("comedy" === playFor(aPerformance).type) result += Math.floor(aPerformance.audience / 5);
        return result;
    }
 
}
  • ์ปดํŒŒ์ผ-ํ…Œ์ŠคํŠธ-์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ์ด์ œ ์ ๋ฆฝ ํฌ์ธํŠธ ๊ณ„์‚ฐ ๋ถ€๋ถ„์„ ์˜ฎ๊ธฐ์ž.
function statement(invoice, plays) {
    const statementData = {};
    statementData.customer = invoice.customer;
    statementData.performances = invoice.performances.map(enrichPerformance);
    return renderPlainText(statementData, plays);
 
    function enrichPerformance(aPerformance) { 
        const result = Object.assign({}, aPerformance);
        result.play = playFor(result);
        result.amount = amountFor(result); 
        result.volumeCredits = volumeCreditsFor(result); // ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ์— volumeCredits ์ •๋ณด๋ฅผ ์ €์žฅ
        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 renderPlainText(data, plays) {
    let result = "์ฒญ๊ตฌ ๋‚ด์—ญ (๊ณ ๊ฐ๋ช…: ${data.customer})\n";
    for (let perf of data.performances) {
      result += " ${perf.play.name}: ${usd(amountFor(perf))} (${perf.audience}์„)\n";
    }
    result += "์ด์•ก: ${usd(totalAmount())}\n";
    result += "์ ๋ฆฝ ํฌ์ธํŠธ: ${totalVolumeCredits()}์ \n";
    return result;
 
    function usd(aNumber) {
        return new Intl.NumberFormat("en-US",
            { style: "currency", currency: "USD",
            minimumFractionDigits: 2 }).format(aNumber/100);
    }
 
    function totalAmount() {
        let result = 0;
        for (let perf of data.performances) {
            result += perf.amount; 
        }
        return result;
    }
 
    func totalVolumeCredits() {
        let result = 0;
        for (let perf of data.performances) {
            result += perf.volumeCredits; // ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ
        }
        return result;
    }
}
  • ์ปดํŒŒ์ผ-ํ…Œ์ŠคํŠธ-์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ๋งˆ์ง€๋ง‰์œผ๋กœ ์ดํ•ฉ(์ ๋ฆฝ ํฌ์ธํŠธ, amount)์„ ๊ตฌํ•˜๋Š” ๋ถ€๋ถ„์„ ์˜ฎ๊ธฐ์ž.
function statement(invoice, plays) {
    const statementData = {};
    statementData.customer = invoice.customer;
    statementData.performances = invoice.performances.map(enrichPerformance);
    statementData.totalAmount = totalAmount(); // ์ดํ•ฉ์„ ๊ตฌํ•˜๋Š” ๋ถ€๋ถ„์„ ์˜ฎ๊น€
    statementData.totalVolumeCredits = totalVolumeCredits(); // ์ดํ•ฉ์„ ๊ตฌํ•˜๋Š” ๋ถ€๋ถ„์„ ์˜ฎ๊น€
    return renderPlainText(statementData, plays);
 
    function enrichPerformance(aPerformance) { 
        const result = Object.assign({}, aPerformance);
        result.play = playFor(result);
        result.amount = amountFor(result); 
        result.volumeCredits = volumeCreditsFor(result); // ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ์— volumeCredits ์ •๋ณด๋ฅผ ์ €์žฅ
        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) {
        let result = 0;
        for (let perf of data.performances) {
            result += perf.amount; 
        }
        return result;
    }
 
    func totalVolumeCredits(data) {
        let result = 0;
        for (let perf of data.performances) {
            result += perf.volumeCredits; // ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝ
        }
        return result;
    }
 
}
 
function renderPlainText(data, plays) {
    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 usd(aNumber) {
        return new Intl.NumberFormat("en-US",
            { style: "currency", currency: "USD",
            minimumFractionDigits: 2 }).format(aNumber/100);
    }
 
}
  • ์ปดํŒŒ์ผ-ํ…Œ์ŠคํŠธ-์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ์ด๋ ‡๊ฒŒ๊นŒ์ง€ ํ•˜๋‹ˆ, ๋ฐ˜๋ณต๋ฌธ์„ ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ๋ฐ”๊พธ๊ธฐ๊นŒ์ง€ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๊ฐ€ ๋˜์—ˆ๋‹ค.
function statement(invoice, plays) {
    const statementData = {};
    statementData.customer = invoice.customer;
    statementData.performances = invoice.performances.map(enrichPerformance);
    statementData.totalAmount = totalAmount();
    statementData.totalVolumeCredits = totalVolumeCredits();
    return renderPlainText(statementData, plays);
 
    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);  // ๋ฐ˜๋ณต๋ฌธ์„ ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ๋ฐ”๊พธ๊ธฐ
    }
 
}
 
function renderPlainText(data, plays) {
    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 usd(aNumber) {
        return new Intl.NumberFormat("en-US",
            { style: "currency", currency: "USD",
            minimumFractionDigits: 2 }).format(aNumber/100);
    }
 
}
  • ์ปดํŒŒ์ผ-ํ…Œ์ŠคํŠธ-์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ๋‹ค์Œ์œผ๋กœ๋Š” statementData๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ถ€๋ถ„์„ ๋ถ„๋ฆฌํ•˜์ž.
function statement(invoice, plays) {
    return renderPlainText(createStatementData(invoice, plays));
 
    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); 
    }
 
}
 
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 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 usd(aNumber) {
        return new Intl.NumberFormat("en-US",
            { style: "currency", currency: "USD",
            minimumFractionDigits: 2 }).format(aNumber/100);
    }
 
}
  • ์ปดํŒŒ์ผ-ํ…Œ์ŠคํŠธ-์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ์ด์ œ ํŒŒ์ผ๊นŒ์ง€ ๋ถ„๋ฆฌํ•ด๋ณด์ž.
// statement.js
 
import createStatementData from './createStatementData.js';
 
function statement(invoice, plays) {
    return renderPlainText(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 usd(aNumber) {
        return new Intl.NumberFormat("en-US",
            { style: "currency", currency: "USD",
            minimumFractionDigits: 2 }).format(aNumber/100);
    }
}
 
// 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); 
    }
}
  • ์ปดํŒŒ์ผ-ํ…Œ์ŠคํŠธ-์ปค๋ฐ‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  • ์ด์ œ HTML ๋ฒ„์ „์„ ์ž‘์„ฑํ•ด๋ณด์ž.
// 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);
}

Reference