{ "cells": [ { "cell_type": "code", "execution_count": 1, "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": 2, "id": "d0b3427f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total quests for level bracket 1-3: 90\n", " Elwynn Forest: 21 quests\n", " Dun Morogh: 19 quests\n", " Stormwind City: 5 quests\n", " Teldrassil: 12 quests\n", " Darkshore: 2 quests\n", " Warrior: 6 quests\n", " Paladin: 2 quests\n", " Rogue: 5 quests\n", " Priest: 4 quests\n", " Mage: 3 quests\n", " Warlock: 2 quests\n", " Hunter: 3 quests\n", " Druid: 2 quests\n", " Uncategorized: 24 quests\n", " Blackrock Depths: 1 quests\n", " Darkmoon Faire: 1 quests\n", " Winter Veil: 4 quests\n", " Ironforge: 5 quests\n", " Shaman: 1 quests\n", " Zephras Isle: 13 quests\n", "Total quests for level bracket 4-6: 130\n", " Elwynn Forest: 34 quests\n", " Dun Morogh: 32 quests\n", " Teldrassil: 33 quests\n", " Warlock: 2 quests\n", " Priest: 6 quests\n", " Miscellaneous: 1 quests\n", " Uncategorized: 70 quests\n", " Shaman: 4 quests\n", " Anvilmar: 1 quests\n", " Zephras Isle: 27 quests\n", "Total quests for level bracket 7-9: 88\n", " Elwynn Forest: 21 quests\n", " Westfall: 1 quests\n", " Dun Morogh: 20 quests\n", " Cooking: 2 quests\n", " Teldrassil: 20 quests\n", " Durotar: 1 quests\n", " Alchemy: 1 quests\n", " Uncategorized: 25 quests\n", " Zephras Isle: 25 quests\n", "Total quests for level bracket 10-12: 252\n", " Elwynn Forest: 37 quests\n", " Westfall: 13 quests\n", " Loch Modan: 13 quests\n", " Dun Morogh: 36 quests\n", " Teldrassil: 38 quests\n", " Durotar: 1 quests\n", " Darkshore: 13 quests\n", " Blacksmithing: 1 quests\n", " Fishing: 2 quests\n", " Warrior: 17 quests\n", " Paladin: 13 quests\n", " Warlock: 4 quests\n", " Mage: 6 quests\n", " Cooking: 1 quests\n", " Rogue: 7 quests\n", " Darnassus: 33 quests\n", " Priest: 28 quests\n", " Druid: 11 quests\n", " Hunter: 23 quests\n", " Deeprun Tram: 2 quests\n", " Ironforge: 37 quests\n", " Kharanos: 1 quests\n", " Winter Veil: 1 quests\n", " Miscellaneous: 2 quests\n", " Uncategorized: 34 quests\n", " Shaman: 3 quests\n", " Stormwind City: 41 quests\n", " Zephras Isle: 44 quests\n", "Total quests for level bracket 13-15: 119\n", " Westfall: 16 quests\n", " Redridge Mountains: 10 quests\n", " Loch Modan: 19 quests\n", " Stormwind City: 21 quests\n", " Darnassus: 3 quests\n", " The Barrens: 7 quests\n", " Darkshore: 25 quests\n", " Paladin: 12 quests\n", " Mage: 3 quests\n", " Ironforge: 13 quests\n", " Priest: 7 quests\n", " Druid: 5 quests\n", " Uncategorized: 8 quests\n", " Shaman: 4 quests\n", " Dun Morogh: 7 quests\n", " The Hall of Thanes: 2 quests\n", " Zephras Isle: 8 quests\n", "Total quests for level bracket 16-18: 98\n", " Westfall: 20 quests\n", " Druid: 4 quests\n", " Redridge Mountains: 14 quests\n", " Loch Modan: 14 quests\n", " The Deadmines: 3 quests\n", " The Barrens: 10 quests\n", " Herbalism: 1 quests\n", " Darkshore: 24 quests\n", " Wailing Caverns: 3 quests\n", " Ashenvale: 5 quests\n", " Leatherworking: 1 quests\n", " Blacksmithing: 1 quests\n", " Mage: 1 quests\n", " Rogue: 6 quests\n", " The Hall of Thanes: 1 quests\n", " Stormwind City: 18 quests\n", " Dun Morogh: 3 quests\n", " Zephras Isle: 0 quests\n", "Total quests for level bracket 19-21: 133\n", " Duskwood: 6 quests\n", " Redridge Mountains: 10 quests\n", " Westfall: 3 quests\n", " The Deadmines: 2 quests\n", " Loch Modan: 9 quests\n", " Wetlands: 8 quests\n", " Darkshore: 20 quests\n", " Ashenvale: 16 quests\n", " The Barrens: 8 quests\n", " Stonetalon Mountains: 12 quests\n", " Dustwallow Marsh: 1 quests\n", " Wailing Caverns: 1 quests\n", " Paladin: 4 quests\n", " Warrior: 1 quests\n", " Warlock: 6 quests\n", " Rogue: 5 quests\n", " Priest: 13 quests\n", " Warsong Gulch: 2 quests\n", " Winter Veil: 1 quests\n", " Miscellaneous: 1 quests\n", " Uncategorized: 14 quests\n", " Shaman: 2 quests\n", " Ruins of Lordaeron: 1 quests\n", " Mage: 1 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", "Alliance_only_quests = df[(df[\"side\"] == \"Alliance\") | (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(Alliance_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": 3, "id": "e826b3eb", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
| \n", " | zone | \n", "bracket | \n", "quests | \n", "total_xp | \n", "avg_xp | \n", "
|---|---|---|---|---|---|
| 0 | \n", "Alchemy | \n", "3: 7-9 | \n", "1 | \n", "700 | \n", "700.0 | \n", "
| 1 | \n", "Anvilmar | \n", "2: 4-6 | \n", "1 | \n", "405 | \n", "405.0 | \n", "
| 2 | \n", "Ashenvale | \n", "6: 16-18 | \n", "5 | \n", "4910 | \n", "982.0 | \n", "
| 3 | \n", "Ashenvale | \n", "7: 19-21 | \n", "16 | \n", "17250 | \n", "1078.0 | \n", "
| 4 | \n", "Blackrock Depths | \n", "1: 1-3 | \n", "1 | \n", "0 | \n", "0.0 | \n", "
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| 123 | \n", "Zephras Isle | \n", "3: 7-9 | \n", "25 | \n", "11665 | \n", "467.0 | \n", "
| 124 | \n", "Zephras Isle | \n", "4: 10-12 | \n", "44 | \n", "26290 | \n", "598.0 | \n", "
| 125 | \n", "Zephras Isle | \n", "5: 13-15 | \n", "8 | \n", "3590 | \n", "449.0 | \n", "
| 126 | \n", "Zephras Isle | \n", "6: 16-18 | \n", "0 | \n", "0 | \n", "NaN | \n", "
| 127 | \n", "Zephras Isle | \n", "7: 19-21 | \n", "0 | \n", "0 | \n", "NaN | \n", "
128 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", " |
| Alchemy | \n", "3: 7-9 | \n", "1 | \n", "0 | \n", "700 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "NaN | \n", "inf | \n", "
| Anvilmar | \n", "2: 4-6 | \n", "1 | \n", "0 | \n", "405 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "NaN | \n", "inf | \n", "
| Ashenvale | \n", "6: 16-18 | \n", "5 | \n", "0 | \n", "4910 | \n", "0.0 | \n", "0.0 | \n", "0.0 | \n", "NaN | \n", "inf | \n", "
| 7: 19-21 | \n", "16 | \n", "4 | \n", "17250 | \n", "43.5 | \n", "73.4 | \n", "169.3 | \n", "14.1 | \n", "101.9 | \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", "
| ... | \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", "41.9 | \n", "3.2 | \n", "35.2 | \n", "
| 2: 4-6 | \n", "27 | \n", "8 | \n", "8110 | \n", "35.7 | \n", "35.7 | \n", "184.0 | \n", "6.8 | \n", "44.1 | \n", "|
| 3: 7-9 | \n", "25 | \n", "14 | \n", "11665 | \n", "113.7 | \n", "114.6 | \n", "346.7 | \n", "13.9 | \n", "33.6 | \n", "|
| 4: 10-12 | \n", "44 | \n", "20 | \n", "26290 | \n", "224.1 | \n", "187.1 | \n", "623.8 | \n", "14.5 | \n", "42.1 | \n", "|
| 5: 13-15 | \n", "8 | \n", "4 | \n", "3590 | \n", "64.7 | \n", "64.7 | \n", "132.8 | \n", "22.1 | \n", "27.0 | \n", "
126 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", "21.9 | \n", "29.8 | \n", "4 | \n", "5900 | \n", "10.9 | \n", "18.4 | \n", "
| Darkshore | \n", "4: 10-12 | \n", "0 | \n", "43.0 | \n", "60.0 | \n", "3 | \n", "2730 | \n", "14.3 | \n", "14.3 | \n", "
| 1 | \n", "42.2 | \n", "40.2 | \n", "3 | \n", "2900 | \n", "4.1 | \n", "9.6 | \n", "||
| 5: 13-15 | \n", "0 | \n", "47.6 | \n", "40.0 | \n", "2 | \n", "1650 | \n", "7.1 | \n", "7.1 | \n", "|
| 1 | \n", "42.7 | \n", "56.5 | \n", "4 | \n", "3790 | \n", "18.9 | \n", "20.2 | \n", "||
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| Zephras Isle | \n", "3: 7-9 | \n", "1 | \n", "50.4 | \n", "76.9 | \n", "5 | \n", "2735 | \n", "4.8 | \n", "4.8 | \n", "
| 4: 10-12 | \n", "0 | \n", "62.0 | \n", "35.1 | \n", "5 | \n", "4430 | \n", "12.5 | \n", "12.5 | \n", "|
| 1 | \n", "59.0 | \n", "65.0 | \n", "15 | \n", "10315 | \n", "10.8 | \n", "8.3 | \n", "||
| 5: 13-15 | \n", "0 | \n", "61.7 | \n", "51.9 | \n", "1 | \n", "910 | \n", "15.1 | \n", "15.1 | \n", "|
| 1 | \n", "57.1 | \n", "36.6 | \n", "3 | \n", "1820 | \n", "16.6 | \n", "16.6 | \n", "
72 rows × 6 columns
\n", "