Skip to content

Latest commit

ย 

History

History
333 lines (290 loc) ยท 12.5 KB

ch01.md

File metadata and controls

333 lines (290 loc) ยท 12.5 KB

๋ฆฌํŒฉํ„ฐ๋ง: ์ฒซ ๋ฒˆ์งธ ์˜ˆ์‹œ

1.1

๋ฆฌํŒฉํ† ๋ง ์ „ ์˜ˆ์ œ ์ฝ”๋“œ

import INVOICE from "../invoices.json";
import PLAYS from "../plays.json";

function statement(invoice, plays) {
  let totalAmount = 0;
  let volumeCredits = 0;
  let result = `์ฒญ๊ตฌ ๋‚ด์—ญ(๊ณ ๊ฐ๋ช…: ${invoice.customer})\n`;
  const format = new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "USD",
    minimumFractionDigits: 2
  }).format;

  for (let perf of invoice.performances) {
    const play = plays[perf.playID]; // object {name, type}
    let thisAmount = 0;
    switch (play.type) {
      case "tragedy": //๋น„๊ทน
        thisAmount = 40000;
        if (perf.audience > 30) thisAmount += 1000 * (perf.audience - 30);
        break;
      case "comedy": //ํฌ๊ทน
        thisAmount = 30000;
        if (perf.audience > 20) thisAmount += 1000 + 500 * (perf.audience - 20);
        thisAmount += 300 * perf.audience;
        break;
      default:
        throw new Error(`์•Œ ์ˆ˜ ์—†๋Š” ์žฅ๋ฅด: ${play.type}`);
    }
    // ํฌ์ธํŠธ๋ฅผ ์ ๋ฆฝํ•œ๋‹ค.
    volumeCredits += Math.max(perf.audience - 30, 0);
    // ํฌ๊ทน ๊ด€๊ฐ 5๋ช…๋งˆ๋‹ค ์ถ”๊ฐ€ ํฌ์ธํŠธ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
    if ("comedy" === play.type) volumeCredits += Math.floor(perf.audience / 5);

    // ์ฒญ๊ตฌ ๋‚ด์—ญ์„ ์ถœ๋ ฅํ•œ๋‹ค.
    result += `${play.name}: ${format(thisAmount / 100)} (${
      perf.audience
    }์„)\n`;
    totalAmount += thisAmount;
  }
  result += `์ด์•ก: ${format(totalAmount / 100)}\n`;
  result += `์ ๋ฆฝ ํฌ์ธํŠธ: ${volumeCredits}์ \n`;
  return result;
}

statement(INVOICE[0], PLAYS);

1.2

์ €์ž์˜ ์†Œ๊ฐ?

  1. ์ด ์ฝ”๋“œ ์ž์ฒด๋กœ๋Š”, ํ”„๋กœ๊ทธ๋žจ์ด ์งง์•„ ํŠน๋ณ„ํžˆ ์• ์จ ์ดํ•ดํ•ด์•ผ ํ•  ๊ตฌ์กฐ๊ฐ€ ์—†๋‹ค.

  2. ํ•˜์ง€๋งŒ, ์ด๋Ÿฐ ์ฝ”๋“œ๊ฐ€ ์ˆ˜๋ฐฑ ์ค„ ์งœ๋ฆฌ์˜ ํ”„๋กœ๊ทธ๋žจ์˜ ์ผ๋ถ€๋ผ๋ฉด ๊ฐ„๋‹จํ•œ ์ธ๋ผ์ธ ํ•จ์ˆ˜ ํ•˜๋‚˜๋ผ๋„ ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ์‰ฝ์ง€ ์•Š๋‹ค.

  3. ํ”„๋กœ๊ทธ๋žจ์ด ์ž˜ ์ž‘๋™ํ•˜๋Š” ์ƒํ™ฉ์—์„œ, ๊ทธ์ € ์ฝ”๋“œ๊ฐ€ '์ง€์ €๋ถ„ํ•˜๋‹ค' ํ•˜๋‹ค๊ณ  ๋ถˆํ‰ํ•˜๋Š” ๊ฒƒ์€ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ตฌ์กฐ๋ฅผ ์ง€๋‚˜์น˜๊ฒŒ ๋ฏธ์ ์ธ ๊ธฐ์ค€์œผ๋กœ ํŒ๋‹จํ•œ๋‹ค๋Š” ์˜๊ฒฌ๋„ ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ, ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๋ ค๋ฉด ์‚ฌ๋žŒ์ด ๊ฐœ์ž…๋˜๊ณ  ๋˜ ์‚ฌ๋žŒ์€ ์ฝ”๋“œ์˜ ๋ฏธ์  ์ƒํƒœ์— ๋ฏผ๊ฐํ•˜๋‹ค.

์ฆ‰ ์„ค๊ณ„๊ฐ€ ๋‚˜์œ ์‹œ์Šคํ…œ์€ ์ˆ˜์ •ํ•˜๊ธฐ ์–ด๋ ต๋‹ค. -> ์›ํ•˜๋Š” ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•˜์—ฌ ์ˆ˜์ •ํ•ด์•ผ ํ•  ๋ถ€๋ถ„์„ ์ฐพ๊ณ , ๊ธฐ์กด ์ฝ”๋“œ์™€ ์ž˜ ๋งž๋ฌผ๋ ค ์ž‘๋™ํ•˜๊ฒŒ ํ•  ๋ฐฉ๋ฒ•์„ ์ฐพ๊ธฐ ์–ด๋ ต๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์‹ค์ˆ˜์™€ ๋ฒ„๊ทธ์˜ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ ์—ญ์‹œ ๋†’์•„์ง„๋‹ค.

๋”ฐ๋ผ์„œ, ์ˆ˜๋ฐฑ ์ค„ ์งœ๋ฆฌ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ

๋จผ์ € ํ”„๋กœ๊ทธ๋žจ์˜ ์ž‘๋™ ๋ฐฉ์‹์„ ์ž˜ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋ฅผ ์—ฌ๋Ÿฌ ํ•จ์ˆ˜์™€ ํ”„๋กœ๊ทธ๋žจ ์š”์†Œ๋กœ ์žฌ๊ตฌ์„ฑํ•ด์•ผํ•œ๋‹ค. ํ”„๋กœ๊ทธ๋žจ์˜ ๊ตฌ์กฐ๊ฐ€ ๋นˆ์•ฝํ•˜๋‹ค๋ฉด, ๋Œ€์ฒด๋กœ ๊ตฌ์กฐ๋ถ€ํ„ฐ ๋ฐ”๋กœ์žก์•„์•ผ ์ž‘์—…์ด ์ˆ˜์›”ํ•ด์ง„๋‹ค.

1.1์—์„œ ์–ด๋–ค ์‹์œผ๋กœ ์ˆ˜์ •ํ•˜๋ฉด ์ข‹์„๊นŒ?

  1. ์ฒญ๊ตฌ ๋‚ด์—ญ์„ HTML๋กœ ์ถœ๋ ฅํ•˜๋Š” ๊ธฐ๋Šฅ
  • ์ฒญ๊ตฌ ๊ฒฐ๊ณผ์— ๋ฌธ์ž์—ด์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฌธ์žฅ ๊ฐ๊ฐ์„ ์กฐ๊ฑด๋ฌธ์œผ๋กœ ๊ฐ์‹ธ์•ผํ•จ
    • ์ด ๊ฒฝ์šฐ ๋Œ€๋ถ€๋ถ„ ์ด ํ•จ์ˆ˜์˜ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค์–ด ๋ณต์‚ฌ๋ณธ์—์„œ HTML์„ ์ถœ๋ ฅํ•˜๋Š” ์‹์œผ๋กœ ์ฒ˜๋ฆฌ
    • ์ฒญ๊ตฌ์„œ ์ž‘์„ฑ ๋กœ์ง์ด ๋ณ€๊ฒฝ๋  ๋•Œ ๋งˆ๋‹ค ๊ธฐ์กด ํ•จ์ˆ˜์™€ HTML ๋ฒ„์ „ ํ•จ์ˆ˜ ๋ชจ๋‘ ์ˆ˜์ •, ํ•ญ์‹œ ์ผ๊ด€๋˜๊ฒŒ ์ˆ˜์ •ํ–ˆ๋Š”์ง€ ์—ญ์‹œ ํ™•์ธ
    • ๋ฐฐ์šฐ๋“ค์€ ๋” ๋งŽ์€ ์žฅ๋ฅด๋ฅผ ์—ฐ๊ธฐํ•˜๊ณ  ์‹ถ์–ด ํ•˜๋Š”๋ฐ, ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ์€ ๊ณต์—ฐ๋ฃŒ์™€ ์ ๋ฆฝ ํฌ์ธํŠธ ๊ณ„์‚ฐ๋ฒ•์— ์˜ํ–ฅ์„ ์ค€๋‹ค. ๋”ฐ๋ผ์„œ ์—ฐ๊ทน ์žฅ๋ฅด์™€ ๊ณต์—ฐ๋ฃŒ ์ •์ฑ…์ด ๋ณ€๊ฒฝ๋  ๋•Œ ๋งˆ๋‹ค statement() ํ•จ์ˆ˜๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ด๋ฅผ ๋ณต์‚ฌํ•ด์„œ htmlStatement()๋ฅผ ๋งŒ๋“ ๋‹ค๋ฉด ๋ชจ๋“  ์ˆ˜์ •์ด ๋‘ ํ•จ์ˆ˜ ๊ฐ๊ฐ์— ์ผ๊ด€์„ฑ์„ ๊ฐ€์ ธ์•ผํ•œ๋‹ค.

๋ฆฌํŒฉํ† ๋ง์ด ํ•„์š”ํ•œ ์ด์œ 

์œ„์™€ ๊ฐ™์ด ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ๋ฐœ์ƒํ•  ๋•Œ ์‹ค์ˆ˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค

1.3 ๋ฆฌํŒฉํ„ฐ๋ง์˜ ์ฒซ ๋‹จ๊ณ„

1) ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ

๋ฆฌํŒฉํ„ฐ๋ง์—์„œ ํ…Œ์ŠคํŠธ์˜ ์—ญํ• ์€ ๊ต‰์žฅํžˆ ์ค‘์š”ํ•˜๋‹ค. ๋ฆฌํŒฉํ„ฐ๋ง ํ•˜๊ธฐ ์ „์— ์ œ๋Œ€๋กœ ๋œ ํ…Œ์ŠคํŠธ ๋ถ€ํ„ฐ ๋งˆ๋ จํ•˜๊ณ , ํ…Œ์ŠคํŠธ๋Š” ๋ฐ˜๋“œ์‹œ ์ž๊ฐ€์ง„๋‹จ์ด ๊ฐ€๋Šฅํ•ด์•ผํ•œ๋‹ค. ์›ํ•˜๋Š” ๋‚ด์šฉ์„ ์†Œ์Šค์ฝ”๋“œ์™€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์–‘์ชฝ์— ์ ์–ด๋‘๋ฉด ๋‘ ๋ฒˆ ๋‹ค ๋˜‘๊ฐ™์ด ์‹ค์ˆ˜ํ•˜์ง€ ์•Š๋Š” ํ•œ ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ…Œ์ŠคํŠธ ์ž‘์„ฑ ์‹œ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด์ง€๋ผ๋„ ์‹ ๊ฒฝ ์จ์„œ ๋งŒ๋“ค์–ด๋‘๋ฉด ๋””๋ฒ„๊น… ์‹œ๊ฐ„์ด ๊ฐ์†Œํ•œ๋‹ค.

2) ๋‹จ๊ณ„๋ณ„ ์ ์ธต์  ์ˆ˜์ •

๋ฆฌํŒฉํ„ฐ๋ง ์‹œ ์ž‘์€ ๋‹จ๊ณ„๋กœ ๋‚˜๋‰˜์–ด ์ง„ํ–‰ํ•ด์•ผํ•œ๋‹ค. ์ค‘๊ฐ„์— ์‹ค์ˆ˜ํ•˜๋”๋ผ๋„ ๋ฒ„๊ทธ๋ฅผ ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

import INVOICE from "../../invoices.json";
import PLAYS from "../../plays.json";

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 usd(aNumber) {
    return new Intl.NumberFormat("en-US", {
      style: "currency",
      currency: "USD",
      minimumFractionDigits: 2
    }).format(aNumber / 100);
  }

  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 totalVolumeCredits() {
    let volumeCredits = 0;
    for (let perf of invoice.performances) {
      volumeCredits += volumeCreditsFor(perf);
    }
    return volumeCredits;

  }
  function totalAmount() {
    let result = 0;
    for (let perf of invoice.performances) {
      result += amountFor(perf);
    }
    return result;
  }

  function playFor(aPerformance) {
    return plays[aPerformance.playID];
  }

  // play๋Š” aPerformance์—์„œ ์˜ค๋Š” ๊ฐ’์ด๋ผ์„œ ์ œ๊ฑฐ
  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 += 1000 + 500 * (aPerformance.audience - 20);
        result += 300 * aPerformance.audience;
        break;
      default:
        throw new Error(`์•Œ ์ˆ˜ ์—†๋Š” ์žฅ๋ฅด: ${playFor(aPerformance).type}`);
    }
    return result;
  }
}

console.log(statement(INVOICE[0], PLAYS));
  1. ํ•จ์ˆ˜ ์ถ”์ถœ
  2. ๋ณ€์ˆ˜๋ช… ๋ณ€๊ฒฝ
  3. ๋ณ€์ˆ˜ ์ธ๋ผ์ธ์œผ๋กœ ๋ณ€๊ฒฝ
  4. ๋ฐ˜๋ณต๋ฌธ ์ชผ๊ฐœ๊ธฐ

๋ณ€์ˆ˜๋ช…

  1. ์ ‘๋‘์–ด๋กœ ํƒ€์ž… ํ‘œํ˜„ํ•˜๊ธฐ
  2. ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ํƒ€์ž…์ด ๋šœ๋ ทํ•˜์ง€ ์•Š์„ ๋• ๋ถ€์ •๊ด€์‚ฌ(a/an) ๋ถ™์ด๊ธฐ
  3. ์บ”ํŠธ๋ฐฑ ์ฐธ๊ณ 

์ข‹์€ ์ฝ”๋“œ๋Š” ํ•˜๋Š”์ผ์ด ๋ช…ํ™•ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚˜๋Š” ์ฝ”๋“œ์ด๊ณ , ๋ณ€์ˆ˜ ์ด๋ฆ„์€ ์ด์— ํฐ ์—ญํ• ์„ ํ•œ๋‹ค.

์ถ”์ถœํ•œ ํ•จ์ˆ˜์—๋Š” ๊ทธ ์ฝ”๋“œ๊ฐ€ ํ•˜๋Š” ์ผ์„ ์„ค๋ช…ํ•˜๋Š” ์ด๋ฆ„์„ ์ง“๋Š”๋‹ค.

  1. ๋‹ค์Œ๋ฒˆ์— ์ฝ”๋“œ๋ฅผ ๋ณผ ๋•Œ ๋‹ค์‹œ ๋ถ„์„ํ•˜์ง€ ์•Š์•„๋„, ์ฝ”๋“œ ์ž์ฒด๋งŒ ๋ณด๊ณ ๋„ ๋ฌด์—‡์„ ํ•˜๋Š” ๊ฒƒ์ธ์ง€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์‚ฌ๋žŒ์ด ์ดํ•ดํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.

  1. ์ž„์‹œ๋ณ€์ˆ˜๋ฅผ ์งˆ์˜ํ•จ์ˆ˜๋กœ ๋ฐ”๊พธ์ž
  • ๊ธด ํ•จ์ˆ˜๋ฅผ ์ชผ๊ฐค ๋•Œ ๋งˆ๋‹ค ๋ณ€์ˆ˜๋ฅผ ์ตœ๋Œ€ํ•œ ์ œ๊ฑฐํ•œ๋‹ค.
    • ์ง€์—ญ ๋ณ€์ˆ˜๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ์ถ”์ถœ ์ž‘์—…์ด ํ›จ์”ฌ ์‰ฌ์›Œ์ง„๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค. (์œ ํšจ๋ฒ”์œ„ ์‹ ๊ฒฝ์„ ์“ฐ์ง€ ์•Š์•„๋„ ๋จ)
  1. ๋ณ€์ˆ˜ ์ธ๋ผ์ธํ•˜๊ธฐ
  2. ํ•จ์ˆ˜๋ช… ๋ฐ”๊พธ๊ธฐ ์ธ๋ผ์ธํ•˜๊ธฐ
  • ์ด๋ฆ„์ง“๊ธฐ๋Š” ์ค‘์š”ํ•˜๋ฉด์„œ๋„ ์‰ฝ์ง€ ์•Š์€ ์ž‘์—…์ด๋‹ค.
  • ์ด๋ฆ„์ด ์ข‹์œผ๋ฉด ํ•จ์ˆ˜ ๋ณธ๋ฌธ์„ ์ฝ์ง€ ์•Š์•„๋„ ๋ฌด์Šจ ์ผ์„ ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
  1. ๋ฌธ์žฅ ์Šฌ๋ผ์ด๋“œํ•˜๊ธฐ

ํ•ญ์‹œ ์ฝ”๋“œ๋ฅผ ์ž‘์—… ์‹œ์ž‘ ์ „๋ณด๋‹ค ๊ฑด๊ฐ•ํ•˜๊ฒŒ ๋งŒ๋“ค์–ด๋†“๊ณ  ๋– ๋‚˜์•ผํ•œ๋‹ค.

import INVOICE from "../../invoices.json";
import PLAYS from "../../plays.json";
import createStatementData from "./createStatementData.js";

function statement(invoice, plays) {
  // ๊ฐ€๋ณ€๋ฐ์ดํ„ฐ๋กœ ๋„˜๊ธฐ๋ฉด ๊ธˆ๋ฐฉ ์ƒํ•˜๊ธฐ๋•Œ๋ฌธ์— ์ตœ๋Œ€ํ•œ ๋ถˆ๋ณ€์œผ๋กœ ๋„˜๊ธด๋‹ค. (๊ตฟ)
  return renderPlainText(createStatementData(invoice, plays));
}

function renderPlainText(data, plays) {
  let result = `์ฒญ๊ตฌ ๋‚ด์—ญ(๊ณ ๊ฐ๋ช…: ${data.customer})\n`;
  for (let perf of data.performances) {
    // ์ฒญ๊ตฌ ๋‚ด์—ญ์„ ์ถœ๋ ฅํ•œ๋‹ค.
    result += `${perf.play.name}: ${usd(perf.amount)} (${perf.audience}์„)\n`;
  }
  result += `์ด์•ก: ${usd(data.totalAmount)}\n`;
  result += `์ ๋ฆฝ ํฌ์ธํŠธ: ${data.totalVolumeCredits}์ \n`;
  return result;
}

function htmlStatement(invoice, plays) {
  return renderHtml(createStatementData(invoice, plays));
}

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(perf.amount)}</td></tr>\n`;
  }
  result += `</table>\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);
}

document.getElementById("app2").innerText = statement(INVOICE[0], PLAYS);
document.getElementById("app").innerHTML = htmlStatement(INVOICE[0], PLAYS);
  1. ๋‹จ๊ณ„ ์ชผ๊ฐœ๊ธฐ
  2. ํ•จ์ˆ˜ ์˜ฎ๊ธฐ๊ธฐ
  3. ๋ฐ˜๋ณต๋ฌธ -> ํŒŒ์ดํ”„๋ผ์ธ
  4. ๊ฐ„๊ฒฐํ•จ ๋ณด๋‹จ ๋ช…๋ฃŒํ•จ์ด ์ค‘์š”ํ•˜๋‹ค. ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋Š” ๋ช…๋ฃŒํ•จ์ด ์ง„ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ์†Œํ”„ํŠธ์›จ์–ด์˜ ์ •์ˆ˜๋‹ค.

๋‹คํ˜•์„ฑ์„ ํ™œ์šฉํ•˜์—ฌ ๊ณ„์‚ฐ ์ฝ”๋“œ ์žฌ๊ตฌ์„ฑ

์ข‹์€ ์ฝ”๋“œ๋ฅผ ๊ฐ€๋Š ํ•˜๋Š” ๊ฐ€์žฅ ํ™•์‹คํ•œ ๋ฐฉ๋ฒ•์€ ์–ผ๋งˆ๋‚˜ ์ˆ˜์ •ํ•˜๊ธฐ ์‰ฌ์šด๊ฐ€ ์ด๋‹ค.

class PerformanceCalculator {
  constructor(aPerformance, aPlay) {
    this.performance = aPerformance;
    this.play = aPlay;
  }

  get amount() {
    throw new Error("์„œ๋ธŒํด๋ž˜์Šค์—์„œ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์„ค๊ณ„");
  }

  get volumeCredits() {
    throw new Error("์„œ๋ธŒํด๋ž˜์Šค์—์„œ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์„ค๊ณ„");
  }
}

class TragedyCalculator extends PerformanceCalculator {
  get amount() {
    let result = 40000;
    if (this.performance.audience > 30)
      result += 1000 * (this.performance.audience - 30);
    return result;
  }
  get volumeCredits() {
    return Math.max(this.performance.audience - 30, 0);
  }
}
class ComedyCalculator extends PerformanceCalculator {
  get amount() {
    let result = 30000;
    if (this.performance.audience > 20)
      result += 1000 + 500 * (this.performance.audience - 20);
    result += 300 * this.performance.audience;

    return result;
  }
  get volumeCredits() {
    return Math.floor(this.performance.audience / 5);
  }
}

export default function createStatementData(invoice, plays) {
  const statementData = {};
  statementData.customer = invoice.customer; // ๊ณ ๊ฐ๋ฐ์ดํ„ฐ๋ฅผ ์ค‘๊ฐ„ ๋ฐ์ดํ„ฐ๋กœ ์˜ฎ๊น€
  statementData.performances = invoice.performances.map(enrichPerformance);
  statementData.totalAmount = totalAmount(statementData);
  statementData.totalVolumeCredits = totalVolumeCredits(statementData);
  return statementData;

  function enrichPerformance(aPerformance) {
    // ๊ฐ๊ฐ ๊ณต์—ฐ๋ณ„๋กœ ์ด๋ฆ„, ์ด๊ธˆ์•ก, ์ดํฌ์ธํŠธ๋“ค์„ ์ƒˆ๋กœํ• ๋‹น
    const calculator = createPerformanceCalculator(
      aPerformance,
      playFor(aPerformance)
    );
    const result = Object.assign({}, aPerformance);
    result.play = playFor(result);
    result.amount = calculator.amount;
    result.volumeCredits = calculator.volumeCredits;
    return result; // ์–•์€๋ณต์‚ฌ
  }

  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}`);
    }
  }
  // ํƒ€์ž… (tragedy, comedy)
  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);
  }
}

์กฐ๊ฑด๋ถ€ ๋กœ์ง์„ ๋‹คํ˜•์„ฑ์œผ๋กœ ๋ณ€๊ฒฝํ•˜์ž

  1. ์ฝ”๋“œ๋Š” ๋ช…ํ™•ํ•ด์•ผํ•˜๊ณ 
  2. ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด์•ผํ•  ์ƒํ™ฉ์ด ๋˜๋ฉด ๊ณ ์ณ์•ผ ํ•  ๊ณณ์„ ์‰ฝ๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๊ณ , ์˜ค๋ฅ˜๊ฐ€ ์—†์ด ๋น ๋ฅธ ์ˆ˜์ •์ด ๊ฐ€๋Šฅํ•ด์•ผํ•œ๋‹ค.
  3. ๊ฑด๊ฐ•ํ•œ ์ฝ”๋“œ๋ฒ ์ด์Šค๋Š” ์ƒ์‚ฐ์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•œ๋‹ค.