{ "cells": [ { "cell_type": "code", "execution_count": 90, "id": "5c77481b", "metadata": {}, "outputs": [], "source": [ "# Requirements\n", "import numpy as np\n", "import pandas as pd\n", "import io\n", "import json\n", "\n", "\n", "# In this notebook, I take the ideas from experiments-1, and we use the quest levels to discover zones instead of using hard coded zone names. " ] }, { "cell_type": "code", "execution_count": 91, "id": "d0b3427f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total quests for level bracket 1-3: 77\n", " Tirisfal Glades: 15 quests\n", " Mulgore: 11 quests\n", " Durotar: 20 quests\n", " Warlock: 4 quests\n", " Warrior: 5 quests\n", " Hunter: 4 quests\n", " Rogue: 4 quests\n", " Shaman: 4 quests\n", " Priest: 2 quests\n", " Mage: 3 quests\n", " Druid: 2 quests\n", " Blackrock Depths: 1 quests\n", " Uncategorized: 23 quests\n", " Darkmoon Faire: 1 quests\n", " Winter Veil: 4 quests\n", " Paladin: 2 quests\n", " Zephras Isle: 13 quests\n", "Total quests for level bracket 4-6: 126\n", " Tirisfal Glades: 32 quests\n", " Mulgore: 32 quests\n", " Durotar: 35 quests\n", " Shaman: 8 quests\n", " Warlock: 2 quests\n", " Priest: 4 quests\n", " Paladin: 2 quests\n", " Uncategorized: 72 quests\n", " Zephras Isle: 30 quests\n", "Total quests for level bracket 7-9: 85\n", " Undercity: 4 quests\n", " Tirisfal Glades: 16 quests\n", " Mulgore: 17 quests\n", " Thunder Bluff: 3 quests\n", " Durotar: 19 quests\n", " Miscellaneous: 1 quests\n", " Uncategorized: 30 quests\n", " Zephras Isle: 30 quests\n", "Total quests for level bracket 10-12: 216\n", " Tirisfal Glades: 45 quests\n", " Silverpine Forest: 17 quests\n", " Thunder Bluff: 30 quests\n", " Mulgore: 29 quests\n", " Durotar: 38 quests\n", " The Barrens: 25 quests\n", " Loch Modan: 1 quests\n", " Warlock: 6 quests\n", " Warrior: 10 quests\n", " Shaman: 11 quests\n", " Rogue: 2 quests\n", " Mage: 4 quests\n", " Priest: 12 quests\n", " Orgrimmar: 29 quests\n", " Druid: 11 quests\n", " Hunter: 19 quests\n", " Winter Veil: 1 quests\n", " Miscellaneous: 2 quests\n", " Paladin: 13 quests\n", " Uncategorized: 29 quests\n", " Zephras Isle: 41 quests\n", "Total quests for level bracket 13-15: 79\n", " Silverpine Forest: 13 quests\n", " Thunder Bluff: 7 quests\n", " Tirisfal Glades: 4 quests\n", " Mulgore: 4 quests\n", " Durotar: 6 quests\n", " The Barrens: 31 quests\n", " Undercity: 11 quests\n", " Shaman: 3 quests\n", " Rogue: 6 quests\n", " Mage: 3 quests\n", " Priest: 3 quests\n", " Ragefire Chasm: 1 quests\n", " Orgrimmar: 13 quests\n", " Druid: 5 quests\n", " Uncategorized: 7 quests\n", " Zephras Isle: 7 quests\n", "Total quests for level bracket 16-18: 76\n", " Druid: 4 quests\n", " Westfall: 5 quests\n", " Silverpine Forest: 14 quests\n", " The Barrens: 35 quests\n", " Herbalism: 1 quests\n", " Wailing Caverns: 6 quests\n", " Stonetalon Mountains: 7 quests\n", " Thunder Bluff: 10 quests\n", " Mage: 1 quests\n", " Rogue: 6 quests\n", " Ragefire Chasm: 5 quests\n", " Orgrimmar: 9 quests\n", " Undercity: 10 quests\n", " Zephras Isle: 0 quests\n", "Total quests for level bracket 19-21: 116\n", " Westfall: 2 quests\n", " Orgrimmar: 21 quests\n", " Silverpine Forest: 5 quests\n", " Hillsbrad Foothills: 3 quests\n", " Thunder Bluff: 9 quests\n", " The Barrens: 46 quests\n", " Shaman: 5 quests\n", " Stonetalon Mountains: 11 quests\n", " Warlock: 15 quests\n", " Wailing Caverns: 1 quests\n", " Warrior: 3 quests\n", " Rogue: 4 quests\n", " Priest: 6 quests\n", " Ashenvale: 7 quests\n", " Warsong Gulch: 2 quests\n", " Winter Veil: 1 quests\n", " Miscellaneous: 1 quests\n", " Uncategorized: 16 quests\n", " Mage: 1 quests\n", " Ruins of Lordaeron: 4 quests\n", " Undercity: 36 quests\n", " Druid: 8 quests\n", " Zephras Isle: 0 quests\n" ] } ], "source": [ "path = rf\"D:\\Project\\Py\\WowheadScraper\\quest_analyzer\\resources\\quests.jsonl\"\n", "df = pd.read_json(path, lines=True)\n", "\n", "if df is None:\n", " raise Exception(\"DataFrame is None. Failed to read the CSV file.\")\n", "\n", "df.describe()\n", "\n", "horde_only_quests = df[(df[\"side\"] == \"Horde\") | (df[\"side\"] == \"Both\")]\n", "\n", "def strip_bracket_string(bracket_string):\n", " # Split the string by \": \" and take the second part\n", " parts = bracket_string.split(\": \")\n", " if len(parts) > 1:\n", " return parts[1]\n", " return bracket_string # Return the original string if it doesn't contain \": \"\n", "\n", "def locations_contains_zone(row, zone_name):\n", " locations = row.get(\"locations\")\n", " if not isinstance(locations, list):\n", " return False\n", " for location in locations:\n", " if location.get(\"role\") == \"start\" and zone_name in location[\"zone\"]:\n", " return True\n", " if location.get(\"role\") == \"end\" and zone_name in location[\"zone\"]:\n", " return True\n", " return False\n", "\n", "def get_quests_by_zone(_df: pd.DataFrame, zone_name: str) -> pd.DataFrame:\n", " location_mask = _df.apply(lambda row: locations_contains_zone(row, zone_name), axis=1)\n", " category_mask = (_df[\"category\"] == zone_name) | (_df[\"category2\"] == zone_name)\n", " return _df[location_mask | category_mask]\n", "\n", "def get_quests_by_level_bracket(_df: pd.DataFrame, min_level: int, max_level: int) -> pd.DataFrame:\n", " return _df[(_df[\"level\"] >= min_level) & (_df[\"level\"] <= max_level)]\n", "\n", "# Now, our brackets are going to be every three levels instead of 10. Let's use loops to make things\n", "# a little more efficient.\n", "index_prefix = 1\n", "brackets = {}\n", "for i in range(1, 21, 3):\n", " min_level = i\n", " max_level = i + 2\n", " bracket_quests = get_quests_by_level_bracket(horde_only_quests, min_level, max_level)\n", " print(f\"Total quests for level bracket {min_level}-{max_level}: {len(bracket_quests)}\")\n", "\n", " bracket_zones = bracket_quests[[\"category\", \"category2\"]].drop_duplicates().to_dict(orient='records')\n", " bracket_zones.append({\"category\": \"Zephras Isle\", \"category2\": \"Unknown\"}) # Add a placeholder for unknown zones\n", " \n", " \n", " for zone in bracket_zones:\n", " zone_name = zone.get(\"category\") or zone.get(\"category2\")\n", " if zone_name:\n", " zone_quests = get_quests_by_zone(bracket_quests, zone_name)\n", " print(f\" {zone_name}: {len(zone_quests)} quests\")\n", " brackets[(zone_name, f\"{index_prefix}: {min_level}-{max_level}\")] = zone_quests \n", " index_prefix += 1\n", "\n" ] }, { "cell_type": "code", "execution_count": 92, "id": "e826b3eb", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
| \n", " | zone | \n", "bracket | \n", "quests | \n", "total_xp | \n", "avg_xp | \n", "
|---|---|---|---|---|---|
| 0 | \n", "Ashenvale | \n", "7: 19-21 | \n", "7 | \n", "2150 | \n", "307.0 | \n", "
| 1 | \n", "Blackrock Depths | \n", "1: 1-3 | \n", "1 | \n", "0 | \n", "0.0 | \n", "
| 2 | \n", "Darkmoon Faire | \n", "1: 1-3 | \n", "1 | \n", "0 | \n", "0.0 | \n", "
| 3 | \n", "Druid | \n", "1: 1-3 | \n", "2 | \n", "125 | \n", "62.0 | \n", "
| 4 | \n", "Druid | \n", "4: 10-12 | \n", "11 | \n", "4540 | \n", "413.0 | \n", "
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| 103 | \n", "Zephras Isle | \n", "3: 7-9 | \n", "30 | \n", "15090 | \n", "503.0 | \n", "
| 104 | \n", "Zephras Isle | \n", "4: 10-12 | \n", "41 | \n", "25465 | \n", "621.0 | \n", "
| 105 | \n", "Zephras Isle | \n", "5: 13-15 | \n", "7 | \n", "3045 | \n", "435.0 | \n", "
| 106 | \n", "Zephras Isle | \n", "6: 16-18 | \n", "0 | \n", "0 | \n", "NaN | \n", "
| 107 | \n", "Zephras Isle | \n", "7: 19-21 | \n", "0 | \n", "0 | \n", "NaN | \n", "
108 rows × 5 columns
\n", "| \n", " | \n", " | quests | \n", "with_objective | \n", "total_xp | \n", "total_to_objective | \n", "total_from_objective | \n", "total_travel | \n", "avg_travel | \n", "xp_per_travel | \n", "
|---|---|---|---|---|---|---|---|---|---|
| zone | \n", "bracket | \n", "\n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " | \n", " |
| Ashenvale | \n", "7: 19-21 | \n", "7 | \n", "3 | \n", "2150 | \n", "86.2 | \n", "86.2 | \n", "172.4 | \n", "43.1 | \n", "12.5 | \n", "
| Blackrock Depths | \n", "1: 1-3 | \n", "1 | \n", "0 | \n", "0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "NaN | \n", "NaN | \n", "
| Darkmoon Faire | \n", "1: 1-3 | \n", "1 | \n", "0 | \n", "0 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "NaN | \n", "NaN | \n", "
| Druid | \n", "1: 1-3 | \n", "2 | \n", "0 | \n", "125 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "NaN | \n", "inf | \n", "
| 4: 10-12 | \n", "11 | \n", "0 | \n", "4540 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "NaN | \n", "inf | \n", "|
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| Zephras Isle | \n", "1: 1-3 | \n", "13 | \n", "4 | \n", "1475 | \n", "14.5 | \n", "14.5 | \n", "42.2 | \n", "3.2 | \n", "35.0 | \n", "
| 2: 4-6 | \n", "30 | \n", "9 | \n", "8780 | \n", "62.6 | \n", "62.6 | \n", "251.4 | \n", "8.4 | \n", "34.9 | \n", "|
| 3: 7-9 | \n", "30 | \n", "17 | \n", "15090 | \n", "182.4 | \n", "183.2 | \n", "501.8 | \n", "16.7 | \n", "30.1 | \n", "|
| 4: 10-12 | \n", "41 | \n", "20 | \n", "25465 | \n", "251.0 | \n", "186.7 | \n", "646.0 | \n", "16.1 | \n", "39.4 | \n", "|
| 5: 13-15 | \n", "7 | \n", "3 | \n", "3045 | \n", "23.1 | \n", "23.1 | \n", "54.0 | \n", "10.8 | \n", "56.4 | \n", "
106 rows × 8 columns
\n", "| \n", " | \n", " | \n", " | center_x | \n", "center_y | \n", "quests | \n", "total_xp | \n", "avg_to_objective | \n", "avg_from_objective | \n", "
|---|---|---|---|---|---|---|---|---|
| zone | \n", "bracket | \n", "objective_hotspot | \n", "\n", " | \n", " | \n", " | \n", " | \n", " | \n", " |
| Ashenvale | \n", "7: 19-21 | \n", "0 | \n", "52.7 | \n", "48.0 | \n", "3 | \n", "1450 | \n", "28.7 | \n", "28.7 | \n", "
| Durotar | \n", "1: 1-3 | \n", "0 | \n", "42.9 | \n", "65.1 | \n", "2 | \n", "420 | \n", "3.6 | \n", "3.6 | \n", "
| 2: 4-6 | \n", "0 | \n", "45.6 | \n", "56.6 | \n", "8 | \n", "3310 | \n", "11.0 | \n", "10.4 | \n", "|
| 3: 7-9 | \n", "0 | \n", "58.7 | \n", "65.4 | \n", "6 | \n", "3990 | \n", "16.0 | \n", "16.0 | \n", "|
| 4: 10-12 | \n", "0 | \n", "67.5 | \n", "84.8 | \n", "2 | \n", "1680 | \n", "15.3 | \n", "15.3 | \n", "|
| 1 | \n", "47.3 | \n", "27.9 | \n", "11 | \n", "9260 | \n", "15.2 | \n", "15.2 | \n", "||
| Mulgore | \n", "1: 1-3 | \n", "0 | \n", "46.5 | \n", "84.4 | \n", "2 | \n", "420 | \n", "7.5 | \n", "7.5 | \n", "
| 2: 4-6 | \n", "0 | \n", "45.8 | \n", "57.9 | \n", "3 | \n", "1355 | \n", "8.5 | \n", "8.5 | \n", "|
| 1 | \n", "60.7 | \n", "79.1 | \n", "4 | \n", "1830 | \n", "17.7 | \n", "16.5 | \n", "||
| 3: 7-9 | \n", "0 | \n", "49.7 | \n", "56.3 | \n", "7 | \n", "4840 | \n", "9.6 | \n", "9.6 | \n", "|
| 4: 10-12 | \n", "0 | \n", "59.4 | \n", "45.5 | \n", "5 | \n", "4370 | \n", "17.5 | \n", "17.7 | \n", "|
| 1 | \n", "54.6 | \n", "26.5 | \n", "2 | \n", "1470 | \n", "19.5 | \n", "4.2 | \n", "||
| Orgrimmar | \n", "4: 10-12 | \n", "0 | \n", "50.9 | \n", "57.4 | \n", "3 | \n", "2025 | \n", "22.2 | \n", "22.2 | \n", "
| 5: 13-15 | \n", "0 | \n", "43.8 | \n", "52.4 | \n", "2 | \n", "1605 | \n", "10.3 | \n", "10.3 | \n", "|
| 7: 19-21 | \n", "0 | \n", "49.7 | \n", "50.1 | \n", "2 | \n", "2300 | \n", "4.8 | \n", "4.8 | \n", "|
| Silverpine Forest | \n", "4: 10-12 | \n", "0 | \n", "54.0 | \n", "27.1 | \n", "5 | \n", "3310 | \n", "12.6 | \n", "13.9 | \n", "
| 5: 13-15 | \n", "0 | \n", "50.9 | \n", "34.5 | \n", "3 | \n", "3010 | \n", "13.5 | \n", "13.5 | \n", "|
| 1 | \n", "46.0 | \n", "72.8 | \n", "1 | \n", "1350 | \n", "33.0 | \n", "33.0 | \n", "||
| 6: 16-18 | \n", "0 | \n", "68.8 | \n", "28.6 | \n", "2 | \n", "3300 | \n", "28.5 | \n", "27.2 | \n", "|
| 1 | \n", "56.2 | \n", "69.4 | \n", "2 | \n", "2300 | \n", "32.3 | \n", "32.3 | \n", "||
| 7: 19-21 | \n", "0 | \n", "55.8 | \n", "76.7 | \n", "3 | \n", "4350 | \n", "38.9 | \n", "38.9 | \n", "|
| Stonetalon Mountains | \n", "6: 16-18 | \n", "0 | \n", "71.3 | \n", "88.9 | \n", "3 | \n", "4050 | \n", "29.0 | \n", "29.0 | \n", "
| 7: 19-21 | \n", "0 | \n", "56.2 | \n", "77.9 | \n", "3 | \n", "4650 | \n", "20.3 | \n", "22.4 | \n", "|
| 1 | \n", "66.4 | \n", "52.3 | \n", "2 | \n", "3100 | \n", "12.8 | \n", "12.8 | \n", "||
| The Barrens | \n", "4: 10-12 | \n", "0 | \n", "52.7 | \n", "27.1 | \n", "2 | \n", "1820 | \n", "4.0 | \n", "4.0 | \n", "
| 5: 13-15 | \n", "0 | \n", "52.8 | \n", "42.0 | \n", "5 | \n", "4990 | \n", "10.9 | \n", "10.9 | \n", "|
| 1 | \n", "50.6 | \n", "19.4 | \n", "7 | \n", "6540 | \n", "7.4 | \n", "7.4 | \n", "||
| 6: 16-18 | \n", "0 | \n", "49.8 | \n", "16.5 | \n", "9 | \n", "11230 | \n", "12.0 | \n", "12.0 | \n", "|
| 1 | \n", "53.0 | \n", "43.4 | \n", "10 | \n", "12600 | \n", "12.2 | \n", "12.3 | \n", "||
| 7: 19-21 | \n", "0 | \n", "49.6 | \n", "51.8 | \n", "17 | \n", "17450 | \n", "10.6 | \n", "10.7 | \n", "|
| 1 | \n", "43.8 | \n", "22.3 | \n", "3 | \n", "5950 | \n", "9.6 | \n", "9.6 | \n", "||
| Thunder Bluff | \n", "4: 10-12 | \n", "0 | \n", "25.1 | \n", "33.4 | \n", "2 | \n", "1300 | \n", "24.4 | \n", "24.4 | \n", "
| Tirisfal Glades | \n", "1: 1-3 | \n", "0 | \n", "50.1 | \n", "50.3 | \n", "1 | \n", "170 | \n", "24.8 | \n", "24.8 | \n", "
| 1 | \n", "32.7 | \n", "62.8 | \n", "4 | \n", "695 | \n", "3.9 | \n", "3.9 | \n", "||
| 2: 4-6 | \n", "0 | \n", "51.7 | \n", "54.4 | \n", "2 | \n", "810 | \n", "8.1 | \n", "8.1 | \n", "|
| 1 | \n", "61.5 | \n", "50.2 | \n", "3 | \n", "900 | \n", "14.7 | \n", "3.9 | \n", "||
| 2 | \n", "35.8 | \n", "66.8 | \n", "3 | \n", "1475 | \n", "4.9 | \n", "4.9 | \n", "||
| 3 | \n", "26.5 | \n", "60.8 | \n", "3 | \n", "890 | \n", "7.2 | \n", "7.2 | \n", "||
| 3: 7-9 | \n", "0 | \n", "51.8 | \n", "48.6 | \n", "7 | \n", "5170 | \n", "14.9 | \n", "14.9 | \n", "|
| 4: 10-12 | \n", "0 | \n", "15.5 | \n", "57.4 | \n", "4 | \n", "3140 | \n", "13.7 | \n", "13.8 | \n", "|
| 1 | \n", "67.2 | \n", "47.6 | \n", "12 | \n", "8790 | \n", "15.4 | \n", "18.1 | \n", "||
| 5: 13-15 | \n", "0 | \n", "48.3 | \n", "44.2 | \n", "3 | \n", "2730 | \n", "24.1 | \n", "24.1 | \n", "|
| Westfall | \n", "7: 19-21 | \n", "0 | \n", "32.4 | \n", "62.9 | \n", "2 | \n", "3000 | \n", "23.2 | \n", "23.2 | \n", "
| Zephras Isle | \n", "1: 1-3 | \n", "0 | \n", "46.0 | \n", "27.2 | \n", "3 | \n", "565 | \n", "4.2 | \n", "4.2 | \n", "
| 1 | \n", "47.2 | \n", "19.8 | \n", "1 | \n", "250 | \n", "2.0 | \n", "2.0 | \n", "||
| 2: 4-6 | \n", "0 | \n", "45.6 | \n", "46.0 | \n", "6 | \n", "1890 | \n", "8.2 | \n", "8.2 | \n", "|
| 1 | \n", "37.3 | \n", "28.4 | \n", "3 | \n", "1475 | \n", "4.5 | \n", "4.5 | \n", "||
| 3: 7-9 | \n", "0 | \n", "49.4 | \n", "61.2 | \n", "17 | \n", "9945 | \n", "10.7 | \n", "10.8 | \n", "|
| 4: 10-12 | \n", "0 | \n", "61.3 | \n", "41.2 | \n", "8 | \n", "6840 | \n", "16.4 | \n", "14.1 | \n", "|
| 1 | \n", "60.0 | \n", "69.3 | \n", "12 | \n", "8220 | \n", "10.0 | \n", "6.2 | \n", "||
| 5: 13-15 | \n", "0 | \n", "58.0 | \n", "41.0 | \n", "3 | \n", "1820 | \n", "7.7 | \n", "7.7 | \n", "