{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7556b349",
   "metadata": {},
   "source": [
    "# 🏦 Citadelle Bank: Python Fraud Investigation\n",
    "\n",
    "Citadelle Bank has detected unusual activity in its systems. Your team has been asked to inspect account movements, login attempts, account statuses, risk scores, and transaction records.\n",
    "\n",
    "Each completed mission unlocks one part of a recovered message. Complete all five missions to reveal the instruction left by the security team.\n",
    "\n",
    "---\n",
    "\n",
    "## Concepts practised\n",
    "\n",
    "- `for` loops\n",
    "- `while` loops\n",
    "- lists and dictionaries\n",
    "- conditions with `if`, `elif`, and `else`\n",
    "- simple functions and `return`\n",
    "- a guided introduction to pandas DataFrames\n",
    "- strings, slicing, and password reconstruction"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "83ddfe47",
   "metadata": {},
   "source": [
    "## How to use this notebook\n",
    "\n",
    "Work from top to bottom.\n",
    "\n",
    "1. Read the explanation above each code cell.\n",
    "2. Edit only the sections marked **TODO**.\n",
    "3. Run the exercise cell.\n",
    "4. Run the check cell immediately underneath it.\n",
    "5. A correct solution prints **MISSION UNLOCKED ✓**.\n",
    "6. Do not edit the bank data or checking tools.\n",
    "7. After all five missions are unlocked, run the **Recovered message** cell.\n",
    "8. Only then move to the **Reveal the password** section.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d2bddf5",
   "metadata": {},
   "source": [
    "## Investigation tools — do not edit\n",
    "\n",
    "This cell imports the required libraries and prepares the mission checker.\n",
    "\n",
    "`pandas` is used only in Mission 5. A DataFrame is a table with rows and columns, similar to a spreadsheet."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "5dddb20b",
   "metadata": {},
   "outputs": [],
   "source": [
    "import base64\n",
    "\n",
    "try:\n",
    "    import pandas as pd\n",
    "    PANDAS_AVAILABLE = True\n",
    "except ImportError:\n",
    "    pd = None\n",
    "    PANDAS_AVAILABLE = False\n",
    "    print(\"pandas is not installed. Ask your teacher for help before Mission 5.\")\n",
    "\n",
    "SEALED_FRAGMENTS = {\n",
    "    1: \"Q29sbGVjdCB0aGUgYW5zd2Vycw==\",\n",
    "    2: \"ZnJvbSBhbGwgZml2ZSBjaGFyYWRlcw==\",\n",
    "    3: \"YW5kIGNyZWF0ZQ==\",\n",
    "    4: \"dGhlIG5leHQgY29kZQ==\",\n",
    "    5: \"dG8gcmV2ZWFsIHRoZSBwYXNzd29yZC4=\",\n",
    "}\n",
    "\n",
    "mission_status = {1: False, 2: False, 3: False, 4: False, 5: False}\n",
    "\n",
    "\n",
    "def decode_fragment(stage_number):\n",
    "    encoded_text = SEALED_FRAGMENTS[stage_number]\n",
    "    return base64.b64decode(encoded_text).decode(\"utf-8\")\n",
    "\n",
    "\n",
    "def check_mission(stage_number, result, expected):\n",
    "    if result == expected:\n",
    "        mission_status[stage_number] = True\n",
    "        print(f\"MISSION {stage_number} UNLOCKED ✓\")\n",
    "    else:\n",
    "        mission_status[stage_number] = False\n",
    "        print(f\"MISSION {stage_number} NOT YET UNLOCKED\")\n",
    "        print(\"Your result:\", repr(result))\n",
    "        print(\"Read the instructions and try again.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9817cb90",
   "metadata": {},
   "source": [
    "# Mission 1 — Reconcile an account\n",
    "\n",
    "A bank account starts with a balance of **€500**. Every number in `movements` represents money entering or leaving the account:\n",
    "\n",
    "- a positive number is money entering;\n",
    "- a negative number is money leaving.\n",
    "\n",
    "Complete `calculate_final_balance()` so that it visits every movement and updates the balance.\n",
    "\n",
    "### Example\n",
    "\n",
    "```python\n",
    "starting_balance = 100\n",
    "movements = [20, -5]\n",
    "```\n",
    "\n",
    "The final balance is `115`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e58f921b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def calculate_final_balance(starting_balance, movements):\n",
    "    balance = starting_balance\n",
    "\n",
    "    # TODO 1\n",
    "    # Use a for loop to visit each movement.\n",
    "    # Add each movement to balance.\n",
    "\n",
    "\n",
    "    return balance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4070fd9f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MISSION 1 NOT YET UNLOCKED\n",
      "Your result: 500\n",
      "Read the instructions and try again.\n"
     ]
    }
   ],
   "source": [
    "ACCOUNT_MOVEMENTS = [120, -40, 250, -30]\n",
    "\n",
    "mission_1_result = calculate_final_balance(500, ACCOUNT_MOVEMENTS)\n",
    "check_mission(1, mission_1_result, 800)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e1fece5",
   "metadata": {},
   "source": [
    "# Mission 2 — Inspect login attempts\n",
    "\n",
    "The security log contains `False` for a failed login and `True` for a successful login.\n",
    "\n",
    "Your function must count how many attempts were checked before access was granted. It must stop when it reaches the first `True`.\n",
    "\n",
    "For this log:\n",
    "\n",
    "```python\n",
    "[False, False, False, True, False]\n",
    "```\n",
    "\n",
    "the function checks four attempts. It does not need to inspect the final `False`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1c08663e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def attempts_until_success(attempts):\n",
    "    index = 0\n",
    "    attempts_checked = 0\n",
    "    access_granted = False\n",
    "\n",
    "    # TODO 2\n",
    "    # Continue while access has not been granted\n",
    "    # AND index is still inside the list.\n",
    "    #\n",
    "    # During each loop:\n",
    "    # 1. Read attempts[index] and store it in access_granted.\n",
    "    # 2. Increase attempts_checked by 1.\n",
    "    # 3. Increase index by 1.\n",
    "\n",
    "\n",
    "    return attempts_checked"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "fdaabead",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MISSION 2 NOT YET UNLOCKED\n",
      "Your result: 0\n",
      "Read the instructions and try again.\n"
     ]
    }
   ],
   "source": [
    "LOGIN_ATTEMPTS = [False, False, False, True, False]\n",
    "\n",
    "mission_2_result = attempts_until_success(LOGIN_ATTEMPTS)\n",
    "check_mission(2, mission_2_result, 4)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e2d3e0a",
   "metadata": {},
   "source": [
    "# Mission 3 — Audit account statuses\n",
    "\n",
    "\n",
    "The bank stores each account status in a dictionary:\n",
    "\n",
    "```python\n",
    "{\n",
    "    \"AC-101\": \"active\",\n",
    "    \"AC-102\": \"frozen\"\n",
    "}\n",
    "```\n",
    "\n",
    "The account number is the **key** and its status is the **value**.\n",
    "\n",
    "Complete the function so that it counts how many accounts have the exact status `\"frozen\"`.\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "7ac94df8",
   "metadata": {},
   "outputs": [],
   "source": [
    "def count_frozen_accounts(account_statuses):\n",
    "    frozen_count = 0\n",
    "\n",
    "    # TODO 3\n",
    "    # Loop through the dictionary.\n",
    "    # Read the status linked to each account number.\n",
    "    # Increase frozen_count when the status equals \"frozen\".\n",
    "\n",
    "\n",
    "    return frozen_count"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "588de82b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MISSION 3 NOT YET UNLOCKED\n",
      "Your result: 0\n",
      "Read the instructions and try again.\n"
     ]
    }
   ],
   "source": [
    "ACCOUNT_STATUSES = {\n",
    "    \"AC-101\": \"active\",\n",
    "    \"AC-102\": \"frozen\",\n",
    "    \"AC-103\": \"active\",\n",
    "    \"AC-104\": \"frozen\",\n",
    "    \"AC-105\": \"closed\",\n",
    "}\n",
    "\n",
    "mission_3_result = count_frozen_accounts(ACCOUNT_STATUSES)\n",
    "check_mission(3, mission_3_result, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "483706b6",
   "metadata": {},
   "source": [
    "# Mission 4 — Classify fraud risk\n",
    "\n",
    "Create a risk score with this formula:\n",
    "\n",
    "```text\n",
    "risk_score =\n",
    "    failed_logins × 5\n",
    "    + (100 − device_trust_score)\n",
    "    + ip_risk_score\n",
    "```\n",
    "\n",
    "Then return:\n",
    "\n",
    "- `\"critical\"` when the score is **200 or more**;\n",
    "- `\"review\"` when the score is **120 or more**;\n",
    "- `\"normal\"` otherwise.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d34df577",
   "metadata": {},
   "outputs": [],
   "source": [
    "def classify_risk(failed_logins, device_trust_score, ip_risk_score):\n",
    "\n",
    "    # TODO 4A\n",
    "    # Calculate risk_score using the formula above.\n",
    "\n",
    "\n",
    "    # TODO 4B\n",
    "    # Use if / elif / else and return the correct word.\n",
    "\n",
    "\n",
    "    return None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "9914afb1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MISSION 4 NOT YET UNLOCKED\n",
      "Your result: None\n",
      "Read the instructions and try again.\n"
     ]
    }
   ],
   "source": [
    "mission_4_result = classify_risk(\n",
    "    failed_logins=9,\n",
    "    device_trust_score=8,\n",
    "    ip_risk_score=97,\n",
    ")\n",
    "\n",
    "check_mission(4, mission_4_result, \"critical\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bb8d9513",
   "metadata": {},
   "source": [
    "# Mission 5 — Find the suspicious transaction\n",
    "\n",
    "### Concept: pandas DataFrame\n",
    "\n",
    "A **DataFrame** is a table in Python. It contains rows and named columns, like a spreadsheet.\n",
    "\n",
    "The example below creates a small table and keeps only accounts with a balance above €1,000."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6b7a1be9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Complete example table:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>balance</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Alex</td>\n",
       "      <td>500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Sam</td>\n",
       "      <td>1400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Maya</td>\n",
       "      <td>900</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   name  balance\n",
       "0  Alex      500\n",
       "1   Sam     1400\n",
       "2  Maya      900"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Filtered table:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>balance</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Sam</td>\n",
       "      <td>1400</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  name  balance\n",
       "1  Sam     1400"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "if PANDAS_AVAILABLE:\n",
    "    example_df = pd.DataFrame({\n",
    "        \"name\": [\"Alex\", \"Sam\", \"Maya\"],\n",
    "        \"balance\": [500, 1400, 900],\n",
    "    })\n",
    "\n",
    "    print(\"Complete example table:\")\n",
    "    display(example_df)\n",
    "\n",
    "    rich_accounts = example_df[example_df[\"balance\"] > 1000]\n",
    "\n",
    "    print(\"Filtered table:\")\n",
    "    display(rich_accounts)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7406c06e",
   "metadata": {},
   "source": [
    "## Combining several pandas conditions\n",
    "\n",
    "Normal Python conditions often use `and` and `or`. For pandas filters, use:\n",
    "\n",
    "- `&` for **and**;\n",
    "- `|` for **or**.\n",
    "\n",
    "Put brackets around every condition:\n",
    "\n",
    "```python\n",
    "filtered = dataframe[\n",
    "    (dataframe[\"score\"] > 50)\n",
    "    & (dataframe[\"status\"] == \"open\")\n",
    "]\n",
    "```\n",
    "\n",
    "Your task is to find the one transaction matching **all three rules**:\n",
    "\n",
    "1. `failed_login_count` is at least `8`;\n",
    "2. `device_trust_score` is below `15`;\n",
    "3. `ip_risk_score` is above `90`.\n",
    "\n",
    "Return its `transaction_id`.\n",
    "\n",
    "After filtering, the first matching ID can be read with:\n",
    "\n",
    "```python\n",
    "filtered.iloc[0][\"transaction_id\"]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "1bab2697",
   "metadata": {},
   "outputs": [],
   "source": [
    "def find_suspicious_transaction(transactions):\n",
    "    if not PANDAS_AVAILABLE:\n",
    "        return \"PANDAS_NOT_INSTALLED\"\n",
    "\n",
    "    # TODO 5A\n",
    "    # Filter the DataFrame using all three conditions.\n",
    "\n",
    "\n",
    "    # TODO 5B\n",
    "    # Return the transaction_id from the first matching row.\n",
    "\n",
    "\n",
    "    return None"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a1f4fd6",
   "metadata": {},
   "source": [
    "## Bank transaction data — do not edit\n",
    "\n",
    "Run this cell to build the DataFrame used by Mission 5."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "0a1f6d63",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>transaction_id</th>\n",
       "      <th>amount</th>\n",
       "      <th>country</th>\n",
       "      <th>failed_login_count</th>\n",
       "      <th>device_trust_score</th>\n",
       "      <th>ip_risk_score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>TX-1041</td>\n",
       "      <td>8200</td>\n",
       "      <td>GB</td>\n",
       "      <td>1</td>\n",
       "      <td>82</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>TX-1042</td>\n",
       "      <td>14950</td>\n",
       "      <td>AE</td>\n",
       "      <td>5</td>\n",
       "      <td>22</td>\n",
       "      <td>76</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>TX-1043</td>\n",
       "      <td>42000</td>\n",
       "      <td>RO</td>\n",
       "      <td>9</td>\n",
       "      <td>8</td>\n",
       "      <td>97</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>TX-1047</td>\n",
       "      <td>6600</td>\n",
       "      <td>NG</td>\n",
       "      <td>7</td>\n",
       "      <td>31</td>\n",
       "      <td>84</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  transaction_id  amount country  failed_login_count  device_trust_score  \\\n",
       "0        TX-1041    8200      GB                   1                  82   \n",
       "1        TX-1042   14950      AE                   5                  22   \n",
       "2        TX-1043   42000      RO                   9                   8   \n",
       "3        TX-1047    6600      NG                   7                  31   \n",
       "\n",
       "   ip_risk_score  \n",
       "0             18  \n",
       "1             76  \n",
       "2             97  \n",
       "3             84  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "TRANSACTION_RECORDS = [\n",
    "    {\n",
    "        \"transaction_id\": \"TX-1041\",\n",
    "        \"amount\": 8200,\n",
    "        \"country\": \"GB\",\n",
    "        \"failed_login_count\": 1,\n",
    "        \"device_trust_score\": 82,\n",
    "        \"ip_risk_score\": 18,\n",
    "    },\n",
    "    {\n",
    "        \"transaction_id\": \"TX-1042\",\n",
    "        \"amount\": 14950,\n",
    "        \"country\": \"AE\",\n",
    "        \"failed_login_count\": 5,\n",
    "        \"device_trust_score\": 22,\n",
    "        \"ip_risk_score\": 76,\n",
    "    },\n",
    "    {\n",
    "        \"transaction_id\": \"TX-1043\",\n",
    "        \"amount\": 42000,\n",
    "        \"country\": \"RO\",\n",
    "        \"failed_login_count\": 9,\n",
    "        \"device_trust_score\": 8,\n",
    "        \"ip_risk_score\": 97,\n",
    "    },\n",
    "    {\n",
    "        \"transaction_id\": \"TX-1047\",\n",
    "        \"amount\": 6600,\n",
    "        \"country\": \"NG\",\n",
    "        \"failed_login_count\": 7,\n",
    "        \"device_trust_score\": 31,\n",
    "        \"ip_risk_score\": 84,\n",
    "    },\n",
    "]\n",
    "\n",
    "if PANDAS_AVAILABLE:\n",
    "    transaction_df = pd.DataFrame(TRANSACTION_RECORDS)\n",
    "    display(transaction_df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "96f5dffb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MISSION 5 NOT YET UNLOCKED\n",
      "Your result: None\n",
      "Read the instructions and try again.\n"
     ]
    }
   ],
   "source": [
    "if PANDAS_AVAILABLE:\n",
    "    mission_5_result = find_suspicious_transaction(transaction_df)\n",
    "else:\n",
    "    mission_5_result = \"PANDAS_NOT_INSTALLED\"\n",
    "\n",
    "check_mission(5, mission_5_result, \"TX-1043\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b6de2108",
   "metadata": {},
   "source": [
    "# Investigation checkpoint\n",
    "\n",
    "Run the cell below after completing all five missions.\n",
    "\n",
    "The recovered instruction remains sealed until every mission is correct. If a mission is still incomplete, the cell tells you which ones need more work."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "288512e1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The message is still sealed.\n",
      "Incomplete missions: [1, 2, 3, 4, 5]\n",
      "Correct those missions and rerun their check cells.\n"
     ]
    }
   ],
   "source": [
    "incomplete_missions = []\n",
    "\n",
    "for mission_number in mission_status:\n",
    "    if not mission_status[mission_number]:\n",
    "        incomplete_missions.append(mission_number)\n",
    "\n",
    "if len(incomplete_missions) == 0:\n",
    "    message_parts = []\n",
    "\n",
    "    for stage_number in range(1, 6):\n",
    "        message_parts.append(decode_fragment(stage_number))\n",
    "\n",
    "    recovered_message = \" \".join(message_parts)\n",
    "\n",
    "    print(\"=\" * 72)\n",
    "    print(\"RECOVERED MESSAGE\")\n",
    "    print(\"=\" * 72)\n",
    "    print(recovered_message)\n",
    "else:\n",
    "    print(\"The message is still sealed.\")\n",
    "    print(\"Incomplete missions:\", incomplete_missions)\n",
    "    print(\"Correct those missions and rerun their check cells.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9640ab4a",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "# Part 2 — Reveal the administrator password\n",
    "\n",
    "Only continue after you recover the message from the previous exercises.\n",
    "\n",
    "Enter the answers below. Use the spelling validated by your teacher, without extra spaces or punctuation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "052a7d6c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Replace each empty string with the validated answer to that charade.\n",
    "\n",
    "# TODO: what term does this describe?\n",
    "WEBSITE_CHARADE_ANSWER = \"___\"\n",
    "\n",
    "# TODO: what term does this describe?\n",
    "IMAGE_CHARADE_ANSWER = \"___\"\n",
    "\n",
    "# TODO: what term does this describe?\n",
    "DNS_CHARADE_ANSWER = \"___\"\n",
    "\n",
    "# TODO: what term does this describe?\n",
    "CHATBOT_CHARADE_ANSWER = \"___\"\n",
    "\n",
    "NOTEBOOK_CHARADE = \"I am a fraudulent message designed to trick people into revealing passwords or sensitive information.\"\n",
    "# TODO: what term does this describe?\n",
    "NOTEBOOK_CHARADE_ANSWER = \"___\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c67bce8",
   "metadata": {},
   "source": [
    "## Rearranging the words\n",
    "\n",
    "You should now have five answers stored in:\n",
    "\n",
    "- `WEBSITE_CHARADE_ANSWER`\n",
    "- `IMAGE_CHARADE_ANSWER`\n",
    "- `DNS_CHARADE_ANSWER`\n",
    "- `NOTEBOOK_CHARADE_ANSWER`\n",
    "- `CHATBOT_CHARADE_ANSWER`\n",
    "\n",
    "Write the code following these steps **in order** to recover the password. \n",
    "\n",
    "1. Take `WEBSITE_CHARADE_ANSWER` and reverse it.\n",
    "2. Join `IMAGE_CHARADE_ANSWER` and `DNS_CHARADE_ANSWER` together (in that order), then keep only the **first 5 characters** of the result.\n",
    "3. Take `NOTEBOOK_CHARADE_ANSWER`, convert it to lowercase, then reverse it.\n",
    "4. Take `CHATBOT_CHARADE_ANSWER`, keep only the **first 4 letters**, and convert them to uppercase.\n",
    "5. Join the results of steps 1–4 together with nothing in between, then convert the whole thing to lowercase. That's your administrator password.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "854c9b7e",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'password' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mNameError\u001b[39m                                 Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[16]\u001b[39m\u001b[32m, line 17\u001b[39m\n\u001b[32m      1\u001b[39m \u001b[38;5;66;03m# Step 1: reverse WEBSITE_CHARADE_ANSWER\u001b[39;00m\n\u001b[32m      2\u001b[39m \n\u001b[32m      3\u001b[39m \n\u001b[32m   (...)\u001b[39m\u001b[32m     13\u001b[39m \u001b[38;5;66;03m# Step 5: join steps 1-4 together with nothing in between, then lowercase the whole thing\u001b[39;00m\n\u001b[32m     14\u001b[39m \u001b[38;5;66;03m# Store the final result in a variable called password\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m17\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[33m\"\u001b[39m\u001b[33mADMINISTRATOR PASSWORD:\u001b[39m\u001b[33m\"\u001b[39m, \u001b[43mpassword\u001b[49m)\n",
      "\u001b[31mNameError\u001b[39m: name 'password' is not defined"
     ]
    }
   ],
   "source": [
    "# Step 1: reverse WEBSITE_CHARADE_ANSWER\n",
    "\n",
    "\n",
    "# Step 2: join IMAGE_CHARADE_ANSWER and DNS_CHARADE_ANSWER, then keep only the first 5 characters\n",
    "\n",
    "\n",
    "# Step 3: lowercase NOTEBOOK_CHARADE_ANSWER, then reverse it\n",
    "\n",
    "\n",
    "# Step 4: keep the first 4 letters of CHATBOT_CHARADE_ANSWER, then uppercase them\n",
    "\n",
    "\n",
    "# Step 5: join steps 1-4 together with nothing in between, then lowercase the whole thing\n",
    "# Store the final result in a variable called password\n",
    "\n",
    "\n",
    "print(\"ADMINISTRATOR PASSWORD:\", password)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4d74522",
   "metadata": {},
   "source": [
    "## Case closed\n",
    "\n",
    "If your five charade answers were correct and your steps were followed exactly, you now have the administrator password. Every tool you used to get here — lists, dictionaries, functions, loops, and pandas — came straight out of what you've already learned.\n",
    "\n",
    "Good work, investigator."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
