# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# %matplotlib inline

# +
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.model_selection import StratifiedKFold
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import LinearSVC
from sklearn.svm import SVC
from sklearn.metrics import f1_score
from sklearn.metrics import make_scorer
from sklearn.metrics import accuracy_score
from sklearn.ensemble import AdaBoostClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.linear_model import LinearRegression

# +
# Vanilla WoW ninjaloot predictor
# Sources:
# database source - https://github.com/classicdb/database/tree/classic/Full_DB
# labels source - https://www.youtube.com/watch?v=6PY3W404Ca4

# +
# Loading the data
# -

items = pd.read_csv('data/vanilla_wow_items.csv', sep = ";")

items.head()

items.shape

# +
# This dataframe doesn't have labels so we need to create our own based on common knowledge and personal experience...
# -

most_commonly_ninjad = ["'Shadowfang'","'Assassin\'s Blade'", "'Corpsemaker'", "'The Rockpounder'", "'Blackstone Ring'",
                        "'Hand of Justice'", "'Ironfoe'", "'Savage Gladiator Chain'", "'Cape of the Black Baron'",
                        "'Deathcharger\'s Reins'", "'Recipe: Flask of Distilled Wisdom'", "'Recipe: Flask of the Titans'",
                        "'Recipe: Flask of Supreme Power'", "'Righteous Orb'", "'Pattern: Truefaith Vestments'",
                        "'Tarnished Elven Ring'", "'Rod of the Ogre Magi'", "'Foror\'s Compendium of Dragon Slaying'",
                        "'Dark Rune'", "'Pattern: Robe of the Void'", "'Felstriker'", "'Dal\'Rend\'s Sacred Charge'",
                        "'Dal\'Rend\'s Tribal Guardian'", "'Truestrike Shoulders'", "'Briarwood Reed'",
                        "'Pristine Hide of the Beast'", "'Ace of Beasts'", "'Alcor\'s Sunrazor'", "'Edgemaster\'s Handguards'",
                        "'Freezing Band'", "'Krol Blade'", "'Stockade Pauldrons'", "'Pristine Black Diamond'"]
items['ninjalooted'] = np.where(items['name'].isin(most_commonly_ninjad), 1, 0)

# We see that almost all items are not worth ninjalooting
items['ninjalooted'].value_counts(normalize=True) * 100

items_attributes = items.drop('ninjalooted', axis = 1)
items_labels = items.ninjalooted

# +
# Exploring the data
# While making the csv file out of an sql, I noted a couple of attributes that might be interesting
# -

interesting_attributes = items_attributes[['name', 'class', "subclass", "Quality", "BuyPrice", "SellPrice", "InventoryType",
                                           "ItemLevel", "RequiredLevel", "RequiredSkill",
                                           "dmg_min1", "dmg_max1", "bonding", "MaxDurability"]]

interesting_attributes.loc[interesting_attributes['name'].isin(most_commonly_ninjad)]

interesting_attributes.loc[interesting_attributes['name'].isin(most_commonly_ninjad)].describe()

interesting_attributes.describe()

# +
# From the descriptions we can see our sought after items have a 
# higher mean Quality, ItemLevel, min/max damage and buy/sell price.
# I think the models we will train have to take those attributes into consideration

# +
# Preparing the data for training
# -

interesting_attributes = interesting_attributes.drop('name', axis = 1)
really_interesting_attributes = interesting_attributes.drop(['InventoryType', 'MaxDurability'], axis = 1)

scaler = MinMaxScaler(feature_range = (-1, 1))
interesting_attributes = scaler.fit_transform(interesting_attributes)
really_interesting_attributes = scaler.fit_transform(really_interesting_attributes)

item_attributes_train, item_attributes_test, item_labels_train, item_labels_test = train_test_split(
    interesting_attributes, items_labels, train_size = 0.7, test_size = 0.3, stratify = items_labels)

k_fold = StratifiedKFold(n_splits = 5)
k_fold = k_fold.get_n_splits(item_attributes_train, item_labels_train)

# +
# Training the models

# +
# Decision Tree
# -

decision_tree_model = DecisionTreeClassifier()
decision_tree_model.fit(item_attributes_train, item_labels_train)
decision_tree_baseline_score = decision_tree_model.score(item_attributes_test, item_labels_test)
decision_tree_baseline_score

# +
# The scoring method for our baseline decision tree is useless due to the data being highly imbalanced
# -

item_labels_pred = decision_tree_model.predict(item_attributes_test)
decision_tree_f1_score = f1_score(item_labels_pred, item_labels_test)
decision_tree_f1_score

# +
# Random Forest
# -

random_forest_model = RandomForestClassifier()
random_forest_model.fit(item_attributes_train, item_labels_train)
random_forest_baseline_score = random_forest_model.score(item_attributes_test, item_labels_test)
random_forest_baseline_score

item_labels_pred = random_forest_model.predict(item_attributes_test)
random_forest_f1_score = f1_score(item_labels_pred, item_labels_test)
random_forest_f1_score

# +
# Both trees fair equally poorly

# +
# AdaBoost
# -

tree = DecisionTreeClassifier()
ada = AdaBoostClassifier(base_estimator = tree, n_estimators = 100, learning_rate = 0.1)
ada.fit(item_attributes_train, item_labels_train)
train_pred = accuracy_score(item_labels_train, ada.predict(item_attributes_train))
test_pred = accuracy_score(item_labels_test, ada.predict(item_attributes_test))
item_labels_pred = ada.predict(item_attributes_test)
adaBoost_f1_score = f1_score(item_labels_pred, item_labels_test)
print(train_pred, test_pred, adaBoost_f1_score)

# +
# Unfortunately none of the classifiers show good results.
# I have tried the regression and svm algorithms but they have yielded simular results.
# In conclusion the phrase garbage in, garbage out cannot be more true. I'm very sorry.

StarcoderdataJupyterScriptsDedupFiltered