{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# WEEK 06 MISSION: 매개변수형 이미지 생성기 완성하기\n",
        "\n",
        "5주차의 난수·반복·조건 코드를 `create_poster()` 함수로 묶고, 서로 다른 매개변수 조합 A·B·C로 포스터 세 장을 만듭니다. 세 결과를 한 장의 비교 PNG로 저장하고 마지막 자동 검사에서 `WEEK 06 PARAMETER GENERATOR COMPLETE`를 확인합니다. `.ipynb`와 `.png` 두 파일을 제출하면 남은 시간과 관계없이 바로 귀가할 수 있습니다.\n",
        "\n",
        "빈 노트북에서 긴 함수를 다시 작성하지 않습니다. `EDIT` 표시가 있는 정보, 함수 안의 세 줄, A·B·C 설정값만 수정합니다. `DO NOT EDIT` 영역과 FINAL CHECK는 그대로 둡니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# STEP 0: 준비 셀입니다. 수정하지 말고 실행만 하세요.\n",
        "from pathlib import Path\n",
        "import inspect\n",
        "import random\n",
        "from PIL import Image, ImageDraw\n",
        "from IPython.display import display\n",
        "\n",
        "canvas_width = 600\n",
        "canvas_height = 600\n",
        "min_size = 20\n",
        "max_size = 80\n",
        "margin = 40\n",
        "\n",
        "STARTER_SEED = 73\n",
        "STARTER_SHAPE_COUNT = 48\n",
        "STARTER_MEDIUM_THRESHOLD = 42\n",
        "STARTER_LARGE_THRESHOLD = 64\n",
        "STARTER_PALETTE = [\n",
        "    (235, 241, 250),\n",
        "    (48, 112, 166),\n",
        "    (92, 150, 118),\n",
        "    (230, 83, 72),\n",
        "    (35, 42, 55),\n",
        "]\n",
        "\n",
        "mission_step0_execution = get_ipython().execution_count\n",
        "mission_stage = 0\n",
        "print(\"✅ STEP 0 준비 완료: 다음 셀로 이동하세요.\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## STEP 1: 제출 정보와 생성기 규칙 작성\n",
        "\n",
        "따옴표 안의 세 문자열만 수정합니다. `generator_rule`에는 함수의 공통 규칙, 호출할 때 바꿀 입력, 세 결과의 차이를 한 문장으로 작성합니다.\n",
        "\n",
        "예: `600 × 600 형식과 도형 분기는 유지하고 시드·개수·경계·팔레트를 바꾸어 세 가지 밀도와 색상 변주를 만든다.`"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# STEP 1 / EDIT: 따옴표 안의 내용만 자신의 정보로 바꾸세요.\n",
        "assert mission_stage in (0, 1, 2, 3, 4, 5), \"STEP 0 준비 셀을 먼저 실행하세요.\"\n",
        "student_id = \"학번\"\n",
        "student_name = \"이름 또는 별명\"\n",
        "generator_rule = \"함수의 공통 규칙, 바꿀 입력, 세 결과의 차이를 한 문장으로 작성하세요.\"\n",
        "\n",
        "# DO NOT EDIT: 아래 실행 확인 코드는 수정하지 마세요.\n",
        "output_filename = \"week06_\" + student_id + \"_\" + student_name + \"_generator.png\"\n",
        "mission_step1_execution = get_ipython().execution_count\n",
        "mission_stage = 1\n",
        "print(\"생성기 규칙:\", generator_rule)\n",
        "print(\"저장 파일명:\", output_filename)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## STEP 2: create_poster 함수의 세 줄 완성\n",
        "\n",
        "처음 상태로 실행해도 오류는 나지 않지만, 함수는 시드를 0으로 고정하고 도형을 하나만 만든 뒤 빈 이미지를 돌려줍니다. 아래 함수에서 `EDIT A`, `EDIT B`, `EDIT C`의 세 줄만 다음과 같이 바꿉니다.\n",
        "\n",
        "```python\n",
        "random.seed(seed_number)\n",
        "for shape_number in range(shape_count):\n",
        "return image\n",
        "```\n",
        "\n",
        "함수의 매개변수 목록과 `DO NOT EDIT` 영역은 수정하지 않습니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# STEP 2: create_poster 함수입니다. EDIT A·B·C 세 줄만 수정하세요.\n",
        "assert mission_stage in (1, 2, 3, 4, 5), \"STEP 1 제출 정보 셀을 먼저 실행하세요.\"\n",
        "\n",
        "def create_poster(\n",
        "    seed_number,\n",
        "    shape_count,\n",
        "    medium_threshold,\n",
        "    large_threshold,\n",
        "    palette,\n",
        "):\n",
        "    # DO NOT EDIT: 아래 고정 형식과 팔레트 역할은 유지하세요.\n",
        "    background_color = palette[0]\n",
        "    primary_color = palette[1]\n",
        "    secondary_color = palette[2]\n",
        "    accent_color = palette[3]\n",
        "    outline_color = palette[4]\n",
        "    base_palette = [primary_color, secondary_color, accent_color]\n",
        "\n",
        "    image = Image.new(\n",
        "        \"RGB\",\n",
        "        (canvas_width, canvas_height),\n",
        "        background_color,\n",
        "    )\n",
        "    draw = ImageDraw.Draw(image)\n",
        "\n",
        "    # EDIT A: 고정된 0 대신 seed_number 매개변수를 사용하세요.\n",
        "    random.seed(0)\n",
        "\n",
        "    # EDIT B: 한 번 대신 shape_count만큼 반복하세요.\n",
        "    for shape_number in range(1):\n",
        "        # DO NOT EDIT: 아래 난수 선택과 조건 분기는 유지하세요.\n",
        "        size = random.randint(min_size, max_size)\n",
        "        x = random.randint(\n",
        "            margin,\n",
        "            canvas_width - margin - size,\n",
        "        )\n",
        "        y = random.randint(\n",
        "            margin,\n",
        "            canvas_height - margin - size,\n",
        "        )\n",
        "        base_color = random.choice(base_palette)\n",
        "\n",
        "        if size >= large_threshold:\n",
        "            draw.rectangle(\n",
        "                (x, y, x + size, y + size),\n",
        "                fill=accent_color,\n",
        "                outline=outline_color,\n",
        "                width=3,\n",
        "            )\n",
        "        elif size >= medium_threshold:\n",
        "            draw.ellipse(\n",
        "                (x, y, x + size, y + size),\n",
        "                fill=base_color,\n",
        "            )\n",
        "        else:\n",
        "            draw.ellipse(\n",
        "                (x, y, x + size, y + size),\n",
        "                fill=background_color,\n",
        "                outline=base_color,\n",
        "                width=4,\n",
        "            )\n",
        "\n",
        "    # EDIT C: 새 빈 이미지 대신 위에서 완성한 image를 돌려주세요.\n",
        "    return Image.new(\"RGB\", (canvas_width, canvas_height), background_color)\n",
        "\n",
        "mission_step2_execution = get_ipython().execution_count\n",
        "mission_stage = 2\n",
        "print(\"✅ 함수 정의 실행 완료: 다음 셀에서 A·B·C 입력을 설계하세요.\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## STEP 3: A·B·C 매개변수 조합 설계\n",
        "\n",
        "A는 기준안으로 유지하거나 수정할 수 있습니다. B와 C는 A와 다른 시드와 팔레트를 사용하고, 도형 수 또는 두 조건 기준도 바꿉니다.\n",
        "\n",
        "안전 조건은 다음과 같습니다.\n",
        "\n",
        "- 시드는 서로 다른 0~9999 정수입니다.\n",
        "- 도형 수는 40~80입니다.\n",
        "- `20 < medium < large < 80` 순서를 지킵니다.\n",
        "- 작은·중간·큰 크기 구간을 각각 10 이상 확보합니다.\n",
        "- 각 팔레트에는 서로 다른 RGB 색상 다섯 개가 필요합니다.\n",
        "- B와 C 팔레트는 A에서 각각 세 역할 이상 바꿉니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# STEP 3 / EDIT: B와 C를 중심으로 세 입력 조합을 설계하세요.\n",
        "assert mission_stage in (2, 3, 4, 5), \"STEP 2 함수 정의 셀을 먼저 실행하세요.\"\n",
        "\n",
        "# A / BASELINE\n",
        "seed_a = 73\n",
        "shape_count_a = 48\n",
        "medium_a = 42\n",
        "large_a = 64\n",
        "palette_a = [\n",
        "    (235, 241, 250),\n",
        "    (48, 112, 166),\n",
        "    (92, 150, 118),\n",
        "    (230, 83, 72),\n",
        "    (35, 42, 55),\n",
        "]\n",
        "\n",
        "# B / EDIT: A와 다른 시드·개수·팔레트를 권장합니다.\n",
        "seed_b = 73\n",
        "shape_count_b = 48\n",
        "medium_b = 42\n",
        "large_b = 64\n",
        "palette_b = [\n",
        "    (235, 241, 250),\n",
        "    (48, 112, 166),\n",
        "    (92, 150, 118),\n",
        "    (230, 83, 72),\n",
        "    (35, 42, 55),\n",
        "]\n",
        "\n",
        "# C / EDIT: A·B와 다른 시드·조건 기준·팔레트를 권장합니다.\n",
        "seed_c = 73\n",
        "shape_count_c = 48\n",
        "medium_c = 42\n",
        "large_c = 64\n",
        "palette_c = [\n",
        "    (235, 241, 250),\n",
        "    (48, 112, 166),\n",
        "    (92, 150, 118),\n",
        "    (230, 83, 72),\n",
        "    (35, 42, 55),\n",
        "]\n",
        "\n",
        "# DO NOT EDIT: 아래 설정 묶음과 출력 코드는 유지하세요.\n",
        "variant_a = (seed_a, shape_count_a, medium_a, large_a, palette_a)\n",
        "variant_b = (seed_b, shape_count_b, medium_b, large_b, palette_b)\n",
        "variant_c = (seed_c, shape_count_c, medium_c, large_c, palette_c)\n",
        "print(\"A 설정:\", seed_a, shape_count_a, medium_a, large_a)\n",
        "print(\"B 설정:\", seed_b, shape_count_b, medium_b, large_b)\n",
        "print(\"C 설정:\", seed_c, shape_count_c, medium_c, large_c)\n",
        "mission_step3_execution = get_ipython().execution_count\n",
        "mission_stage = 3"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## STEP 4: 같은 함수를 세 번 호출\n",
        "\n",
        "이 셀은 수정하지 않습니다. STEP 3의 A·B·C 값을 키워드 인자로 전달하고, 함수가 돌려준 세 이미지를 각각 `poster_a`, `poster_b`, `poster_c`에 저장합니다. 세 이미지가 모두 보이면 입력이 함수에 전달된 것입니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# STEP 4: create_poster를 세 번 호출합니다. 이 셀은 수정하지 마세요.\n",
        "assert mission_stage in (3, 4, 5), \"STEP 3 A·B·C 설정 셀을 먼저 실행하세요.\"\n",
        "\n",
        "poster_a = create_poster(\n",
        "    seed_number=seed_a,\n",
        "    shape_count=shape_count_a,\n",
        "    medium_threshold=medium_a,\n",
        "    large_threshold=large_a,\n",
        "    palette=palette_a,\n",
        ")\n",
        "poster_b = create_poster(\n",
        "    seed_number=seed_b,\n",
        "    shape_count=shape_count_b,\n",
        "    medium_threshold=medium_b,\n",
        "    large_threshold=large_b,\n",
        "    palette=palette_b,\n",
        ")\n",
        "poster_c = create_poster(\n",
        "    seed_number=seed_c,\n",
        "    shape_count=shape_count_c,\n",
        "    medium_threshold=medium_c,\n",
        "    large_threshold=large_c,\n",
        "    palette=palette_c,\n",
        ")\n",
        "\n",
        "display(poster_a)\n",
        "display(poster_b)\n",
        "display(poster_c)\n",
        "mission_step4_execution = get_ipython().execution_count\n",
        "mission_stage = 4\n",
        "print(\"✅ A·B·C 함수 호출 완료\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## STEP 5: 세 결과를 한 장의 비교 PNG로 저장\n",
        "\n",
        "이 셀은 수정하지 않습니다. 600 × 600 포스터 세 장을 가로로 배치하고 위쪽에 각 시드와 도형 수를 표시한 1800 × 680 비교 이미지를 만듭니다. 최종 설정을 바꾸었다면 STEP 3부터 STEP 5까지 다시 실행합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# STEP 5: 비교 PNG를 생성하고 저장합니다. 이 셀은 수정하지 마세요.\n",
        "assert mission_stage == 4, \"STEP 4의 세 함수 호출을 먼저 실행하세요.\"\n",
        "comparison_sheet = Image.new(\"RGB\", (1800, 680), (35, 42, 55))\n",
        "sheet_draw = ImageDraw.Draw(comparison_sheet)\n",
        "sheet_draw.text((30, 30), f\"A  seed={seed_a}  count={shape_count_a}\", fill=(255, 255, 255))\n",
        "sheet_draw.text((630, 30), f\"B  seed={seed_b}  count={shape_count_b}\", fill=(255, 255, 255))\n",
        "sheet_draw.text((1230, 30), f\"C  seed={seed_c}  count={shape_count_c}\", fill=(255, 255, 255))\n",
        "comparison_sheet.paste(poster_a, (0, 80))\n",
        "comparison_sheet.paste(poster_b, (600, 80))\n",
        "comparison_sheet.paste(poster_c, (1200, 80))\n",
        "comparison_sheet.save(output_filename)\n",
        "with Image.open(output_filename) as opened_sheet:\n",
        "    saved_sheet = opened_sheet.copy()\n",
        "display(saved_sheet)\n",
        "mission_step5_execution = get_ipython().execution_count\n",
        "mission_stage = 5\n",
        "print(\"✅ 비교 PNG 저장 완료:\", output_filename)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## FINAL CHECK: 새 세션 전체 실행으로 완료 증명\n",
        "\n",
        "완성했다면 **런타임 → 세션 다시 시작**을 선택한 뒤 **런타임 → 모두 실행**을 선택합니다. 마지막 셀에 `WEEK 06 PARAMETER GENERATOR COMPLETE`가 나타나면 `.ipynb`와 비교 `.png` 두 파일을 제출하고 바로 귀가할 수 있습니다.\n",
        "\n",
        "자동 검사는 디자인 취향을 채점하지 않습니다. 함수의 다섯 매개변수, 세 줄의 연결, A·B·C 입력 차이, 팔레트 안전성, 같은 입력의 재현, 세 이미지의 차이, 비교 PNG, 전체 실행 순서만 확인합니다."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# FINAL CHECK: 이 셀의 코드는 수정하지 마세요.\n",
        "mission_final_execution = get_ipython().execution_count\n",
        "\n",
        "assert type(student_id) is str and student_id.strip() not in (\"\", \"학번\"), \"STEP 1의 student_id를 자신의 학번으로 바꾸세요.\"\n",
        "assert type(student_name) is str and student_name.strip() not in (\"\", \"이름 또는 별명\"), \"STEP 1의 student_name을 이름 또는 별명으로 바꾸세요.\"\n",
        "assert all(character not in student_id + student_name for character in (\"/\", \"\\\\\")), \"학번과 이름에는 / 또는 \\\\ 문자를 사용할 수 없습니다.\"\n",
        "assert type(generator_rule) is str and len(generator_rule.strip()) >= 25 and generator_rule != \"함수의 공통 규칙, 바꿀 입력, 세 결과의 차이를 한 문장으로 작성하세요.\", \"generator_rule에 생성기 규칙을 25자 이상 작성하세요.\"\n",
        "expected_output_filename = \"week06_\" + student_id + \"_\" + student_name + \"_generator.png\"\n",
        "assert output_filename == expected_output_filename, \"STEP 1을 다시 실행해 출력 파일명을 현재 제출 정보와 맞추세요.\"\n",
        "\n",
        "expected_parameter_names = (\"seed_number\", \"shape_count\", \"medium_threshold\", \"large_threshold\", \"palette\")\n",
        "actual_parameter_names = tuple(inspect.signature(create_poster).parameters)\n",
        "assert actual_parameter_names == expected_parameter_names, \"create_poster 함수의 다섯 매개변수 이름과 순서를 유지하세요.\"\n",
        "assert (canvas_width, canvas_height, min_size, max_size, margin) == (600, 600, 20, 80, 40), \"캔버스·크기·여백의 고정값을 수정하지 마세요.\"\n",
        "\n",
        "def valid_palette(palette):\n",
        "    return (\n",
        "        type(palette) is list\n",
        "        and len(palette) == 5\n",
        "        and all(type(color) is tuple and len(color) == 3 for color in palette)\n",
        "        and all(type(channel) is int and 0 <= channel <= 255 for color in palette for channel in color)\n",
        "        and len(set(palette)) == 5\n",
        "    )\n",
        "\n",
        "variants = (variant_a, variant_b, variant_c)\n",
        "for label, variant in zip((\"A\", \"B\", \"C\"), variants):\n",
        "    seed_value, count_value, medium_value, large_value, palette_value = variant\n",
        "    assert type(seed_value) is int and 0 <= seed_value <= 9999, f\"{label}의 시드는 0~9999 정수여야 합니다.\"\n",
        "    assert type(count_value) is int and 40 <= count_value <= 80, f\"{label}의 도형 수는 40~80 정수여야 합니다.\"\n",
        "    assert type(medium_value) is int and type(large_value) is int, f\"{label}의 두 조건 기준은 정수여야 합니다.\"\n",
        "    assert min_size < medium_value < large_value < max_size, f\"{label}에서 20 < medium < large < 80 순서를 확인하세요.\"\n",
        "    assert medium_value - min_size >= 10 and large_value - medium_value >= 10 and max_size - large_value >= 10, f\"{label}의 작은·중간·큰 구간을 각각 10 이상 확보하세요.\"\n",
        "    assert valid_palette(palette_value), f\"{label} 팔레트를 서로 다른 RGB 다섯 색으로 작성하세요.\"\n",
        "\n",
        "assert len({seed_a, seed_b, seed_c}) == 3, \"A·B·C에 서로 다른 시드를 사용하세요.\"\n",
        "changed_palette_b = sum(color_a != color_b for color_a, color_b in zip(palette_a, palette_b))\n",
        "changed_palette_c = sum(color_a != color_c for color_a, color_c in zip(palette_a, palette_c))\n",
        "assert changed_palette_b >= 3 and changed_palette_c >= 3, \"B와 C 팔레트는 A에서 각각 세 역할 이상 바꾸세요.\"\n",
        "assert palette_b != palette_c, \"B와 C에도 서로 다른 팔레트를 사용하세요.\"\n",
        "comparable_variants = [\n",
        "    (seed, count, medium, large, tuple(palette))\n",
        "    for seed, count, medium, large, palette in variants\n",
        "]\n",
        "for first_index, second_index in ((0, 1), (0, 2), (1, 2)):\n",
        "    difference_count = sum(\n",
        "        first_value != second_value\n",
        "        for first_value, second_value in zip(\n",
        "            comparable_variants[first_index],\n",
        "            comparable_variants[second_index],\n",
        "        )\n",
        "    )\n",
        "    assert difference_count >= 2, \"A·B·C의 각 조합은 입력 역할을 두 가지 이상 다르게 설계하세요.\"\n",
        "\n",
        "def build_expected_poster(seed_number, shape_count, medium_threshold, large_threshold, palette):\n",
        "    background_color = palette[0]\n",
        "    primary_color = palette[1]\n",
        "    secondary_color = palette[2]\n",
        "    accent_color = palette[3]\n",
        "    outline_color = palette[4]\n",
        "    base_palette = [primary_color, secondary_color, accent_color]\n",
        "    checker_random = random.Random(seed_number)\n",
        "    expected_image = Image.new(\"RGB\", (canvas_width, canvas_height), background_color)\n",
        "    expected_draw = ImageDraw.Draw(expected_image)\n",
        "    for shape_number in range(shape_count):\n",
        "        size = checker_random.randint(min_size, max_size)\n",
        "        x = checker_random.randint(margin, canvas_width - margin - size)\n",
        "        y = checker_random.randint(margin, canvas_height - margin - size)\n",
        "        base_color = checker_random.choice(base_palette)\n",
        "        if size >= large_threshold:\n",
        "            expected_draw.rectangle((x, y, x + size, y + size), fill=accent_color, outline=outline_color, width=3)\n",
        "        elif size >= medium_threshold:\n",
        "            expected_draw.ellipse((x, y, x + size, y + size), fill=base_color)\n",
        "        else:\n",
        "            expected_draw.ellipse((x, y, x + size, y + size), fill=background_color, outline=base_color, width=4)\n",
        "    return expected_image\n",
        "\n",
        "posters = (poster_a, poster_b, poster_c)\n",
        "for label, poster, variant in zip((\"A\", \"B\", \"C\"), posters, variants):\n",
        "    assert isinstance(poster, Image.Image), f\"{label}가 이미지가 아닙니다. 함수 마지막을 return image로 바꾸세요.\"\n",
        "    assert poster.mode == \"RGB\" and poster.size == (600, 600), f\"{label}는 600 × 600 RGB 이미지여야 합니다.\"\n",
        "    expected_poster = build_expected_poster(*variant)\n",
        "    assert poster.tobytes() == expected_poster.tobytes(), \"create_poster 함수 안의 seed·shape_count·return 세 줄을 안내대로 바꾸세요.\"\n",
        "    visible_colors = poster.getcolors(maxcolors=canvas_width * canvas_height)\n",
        "    assert visible_colors is not None and len(visible_colors) >= 4, f\"{label}에서 배경과 여러 도형 색상이 보여야 합니다.\"\n",
        "\n",
        "poster_a_again = create_poster(*variant_a)\n",
        "assert poster_a.tobytes() == poster_a_again.tobytes(), \"같은 A 입력으로 같은 이미지를 다시 만들 수 있어야 합니다.\"\n",
        "assert len({poster.tobytes() for poster in posters}) == 3, \"A·B·C가 서로 다른 이미지가 되도록 입력 조합을 수정하세요.\"\n",
        "\n",
        "assert isinstance(comparison_sheet, Image.Image) and comparison_sheet.mode == \"RGB\" and comparison_sheet.size == (1800, 680), \"1800 × 680 RGB 비교 이미지를 다시 만드세요.\"\n",
        "assert comparison_sheet.crop((0, 80, 600, 680)).tobytes() == poster_a.tobytes(), \"비교 이미지의 A 영역을 수정하지 마세요.\"\n",
        "assert comparison_sheet.crop((600, 80, 1200, 680)).tobytes() == poster_b.tobytes(), \"비교 이미지의 B 영역을 수정하지 마세요.\"\n",
        "assert comparison_sheet.crop((1200, 80, 1800, 680)).tobytes() == poster_c.tobytes(), \"비교 이미지의 C 영역을 수정하지 마세요.\"\n",
        "assert Path(output_filename).is_file(), \"STEP 5를 실행해 비교 PNG를 저장하세요.\"\n",
        "with Image.open(output_filename) as checked_file:\n",
        "    assert checked_file.format == \"PNG\", \"비교 이미지의 저장 형식을 PNG로 유지하세요.\"\n",
        "    assert checked_file.mode == \"RGB\" and checked_file.size == comparison_sheet.size, \"저장된 비교 PNG의 모드와 크기를 확인하세요.\"\n",
        "    assert checked_file.tobytes() == comparison_sheet.tobytes(), \"A·B·C를 수정한 뒤 STEP 5 저장 셀을 다시 실행하세요.\"\n",
        "\n",
        "assert mission_stage == 5, \"STEP 0부터 STEP 5까지 순서대로 실행하세요.\"\n",
        "assert (mission_step0_execution, mission_step1_execution, mission_step2_execution, mission_step3_execution, mission_step4_execution, mission_step5_execution, mission_final_execution) == (1, 2, 3, 4, 5, 6, 7), \"세션을 다시 시작한 뒤 위에서 아래로 모두 실행하세요.\"\n",
        "\n",
        "print(\"✅ 제출 정보와 생성기 규칙 문장 검사 통과\")\n",
        "print(\"✅ create_poster 다섯 매개변수 검사 통과\")\n",
        "print(\"✅ seed·shape_count·return 연결 검사 통과\")\n",
        "print(\"✅ A·B·C 입력 조합과 팔레트 검사 통과\")\n",
        "print(\"✅ 세 이미지의 재현성과 차이 검사 통과\")\n",
        "print(\"✅ 1800 × 680 비교 PNG 저장 검사 통과\")\n",
        "print(\"✅ 새 런타임 전체 실행 검사 통과\")\n",
        "print(\"🎉 WEEK 06 PARAMETER GENERATOR COMPLETE\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 선택 확장\n",
        "\n",
        "필수 미션을 제출한 뒤 더 실험하고 싶은 경우에만 진행합니다. 추가 점수는 없습니다.\n",
        "\n",
        "- A와 같은 팔레트에서 시드만 바꾼 D를 만들어 배치 차이를 비교합니다.\n",
        "- 같은 시드와 팔레트에서 도형 수만 바꾸어 밀도 차이를 비교합니다.\n",
        "- 같은 시드에서 두 조건 기준만 바꾸어 강조 사각형의 수를 비교합니다.\n",
        "- 함수의 고정 여백과 캔버스는 유지한 채 새로운 팔레트 하나를 설계합니다."
      ]
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
