mirror of
https://github.com/karl0ss/football-manager-squad-and-recruitment.git
synced 2025-05-29 00:45:08 +01:00
added position calculator with logic, added pre-commit linting, updated requirements and readme, added attribute rating for position calculator
This commit is contained in:
parent
4eefd5f29f
commit
574cb795d8
46
.pre-commit-config.yaml
Normal file
46
.pre-commit-config.yaml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.4.0
|
||||||
|
hooks:
|
||||||
|
- id: check-added-large-files
|
||||||
|
args: [--maxkb=2500]
|
||||||
|
- id: check-ast
|
||||||
|
- id: check-case-conflict
|
||||||
|
- id: check-docstring-first
|
||||||
|
- id: check-json
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: check-toml
|
||||||
|
- id: check-yaml
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: name-tests-test
|
||||||
|
args: [--pytest-test-first]
|
||||||
|
# - id: no-commit-to-branch
|
||||||
|
# args: [--branch, main]
|
||||||
|
- repo: https://github.com/pycqa/isort
|
||||||
|
rev: 5.12.0
|
||||||
|
hooks:
|
||||||
|
- id: isort
|
||||||
|
name: isort (python)
|
||||||
|
args: ["--profile", "black"]
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-yapf
|
||||||
|
rev: v0.32.0
|
||||||
|
hooks:
|
||||||
|
- id: yapf
|
||||||
|
additional_dependencies: [toml]
|
||||||
|
args: [--style "google" ]
|
||||||
|
- repo: https://github.com/psf/black
|
||||||
|
rev: 23.1.0
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
|
args: [--line-length, '180']
|
||||||
|
- repo: https://github.com/PyCQA/flake8
|
||||||
|
rev: 6.0.0
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
||||||
|
args: [--docstring-convention, google, --max-line-length, '180', --ignore, 'D100,D101,D102,D103,D104']
|
||||||
|
additional_dependencies: [flake8-bugbear, flake8-docstrings, pydocstyle==6.1.1]
|
||||||
|
- repo: https://github.com/pycqa/bandit
|
||||||
|
rev: 1.7.4
|
||||||
|
hooks:
|
||||||
|
- id: bandit
|
||||||
|
args: [--skip, B608]
|
13
README.md
13
README.md
@ -1,9 +1,16 @@
|
|||||||
# Football Manager player role evaluation
|
# Football Manager player role evaluation
|
||||||
Python code to evaluate Player attributes in Football Manager against roles based on role weightings. Work in progress.
|
Python code to evaluate Player attributes in Football Manager against roles based on role weightings. Work in progress. Inspired by squirrel_plays_FOF's video [FM24 player recruitment using python](https://www.youtube.com/watch?v=hnAuOakqR90)
|
||||||
|
|
||||||
Inspired by squirrel_plays_FOF's video [FM24 player recruitment using python](https://www.youtube.com/watch?v=hnAuOakqR90)
|
This is split into two scripts; position_score_calculator.py which calculates score based on positions ([Inspired by Mark on fm-arena](https://fm-arena.com/thread/1949-fm22-positional-filters-what-are-the-best-attributes-for-each-position/)) and role_score_calculator.py which caculates scores based on roles (this is missing plenty of roles at the moment!).
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
position_score_calculator.py:
|
||||||
```
|
```
|
||||||
python3 position_score_calculator.py --input-filepath "squad.html" --output-filepath "squad_output.html" --roles gk fb dm w iw
|
python3 role_score_calculator.py --input-filepath "squad.html" --output-filepath "squad_output.html" --roles gk fb dm w iw
|
||||||
|
```
|
||||||
|
|
||||||
|
role_score_calculator.py:
|
||||||
|
```
|
||||||
|
python3 position_score_calculator.py --input-filepath "squad.html" --output-filepath "squad_output.html"
|
||||||
```
|
```
|
BIN
attribute_ratings.xlsx
Normal file
BIN
attribute_ratings.xlsx
Normal file
Binary file not shown.
@ -1,91 +1,35 @@
|
|||||||
import pandas as pd
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
# Define Player attributes
|
import pandas as pd
|
||||||
# TODO: Add roles.
|
|
||||||
gk = {
|
|
||||||
"role_name": "gk",
|
|
||||||
"primary_multiplier": 5,
|
|
||||||
"primary_attributes": ["Agi", "Ref"],
|
|
||||||
"secondary_multiplier": 3,
|
|
||||||
"secondary_attributes": ["1v1", "Ant", "Cmd", "Cnt", "Kic", "Pos"],
|
|
||||||
"tertiary_multiplier": 1,
|
|
||||||
"tertiary_attributes": ["Acc", "Aer", "Cmp", "Dec", "Fir", "Han", "Pas", "Thr", "Vis"]
|
|
||||||
}
|
|
||||||
|
|
||||||
fb = {
|
|
||||||
"role_name": "fb",
|
|
||||||
"primary_multiplier": 5,
|
|
||||||
"primary_attributes": ["Wor", "Acc", "Pac", "Sta"],
|
|
||||||
"secondary_multiplier": 3,
|
|
||||||
"secondary_attributes": ["Cro", "Dri", "Mar", "OtB", "Tck", "Tea"],
|
|
||||||
"tertiary_multiplier": 1,
|
|
||||||
"tertiary_attributes": ["Agi", "Ant", "Cnt", "Dec", "Fir", "Pas", "Pos", "Tec"]
|
|
||||||
}
|
|
||||||
|
|
||||||
cd = {
|
def load_xlsx_data_to_dataframe(filepath: str) -> pd.DataFrame:
|
||||||
"role_name": "cd",
|
"""Read XLSX file into a Dataframe.
|
||||||
"primary_multiplier": 3,
|
|
||||||
"primary_attributes": ["Cmp", "Hea", "Jum", "Mar", "Pas", "Pos", "Str", "Tck", "Pac"],
|
|
||||||
"secondary_multiplier": 1,
|
|
||||||
"secondary_attributes": ["Agg", "Ant", "Bra", "Cnt", "Dec", "Fir", "Tec", "Vis"]
|
|
||||||
}
|
|
||||||
|
|
||||||
dm = {
|
|
||||||
"role_name": "dm",
|
|
||||||
"primary_multiplier": 5,
|
|
||||||
"primary_attributes": ["Wor", "Pac", "Sta", "Pas"],
|
|
||||||
"secondary_multiplier": 3,
|
|
||||||
"secondary_attributes": ["Tck", "Ant", "Cnt", "Pos", "Bal", "Agi"],
|
|
||||||
"tertiary_multiplier": 1,
|
|
||||||
"tertiary_attributes": ["Tea", "Fir", "Mar", "Agg", "Cmp", "Dec", "Str"]
|
|
||||||
}
|
|
||||||
|
|
||||||
b2b = {
|
|
||||||
"role_name": "b2b",
|
|
||||||
"primary_multiplier": 5,
|
|
||||||
"primary_attributes": ["Pas", "Wor", "Sta"],
|
|
||||||
"secondary_multiplier": 3,
|
|
||||||
"secondary_attributes": ["Tck", "OtB", "Tea", "Vis", "Str", "Dec", "Pos", "Pac"],
|
|
||||||
"tertiary_multiplier": 1,
|
|
||||||
"tertiary_attributes": ["Agg", "Ant", "Fin", "Lon", "Cmp", "Acc", "Bal", "Fir", "Dri", "Tec"]
|
|
||||||
}
|
|
||||||
|
|
||||||
w = {
|
|
||||||
"role_name": "w",
|
|
||||||
"primary_multiplier": 3,
|
|
||||||
"primary_attributes": ["Acc", "Cro", "Dri", "OtB", "Pac", "Tec"],
|
|
||||||
"secondary_multiplier": 1,
|
|
||||||
"secondary_attributes": ["Agi", "Fir", "Pas", "Sta", "Wor"],
|
|
||||||
}
|
|
||||||
|
|
||||||
iw = {
|
|
||||||
"role_name": "iw",
|
|
||||||
"primary_multiplier": 5,
|
|
||||||
"primary_attributes": ["Acc", "Pac", "Wor"],
|
|
||||||
"secondary_multiplier": 3,
|
|
||||||
"secondary_attributes": ["Dri", "Pas", "Tec", "OtB"],
|
|
||||||
"tertiary_multiplier": 1,
|
|
||||||
"tertiary_attributes": ["Cro", "Fir", "Cmp", "Dec", "Vis", "Agi", "Sta"]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
filepath -- path to xlsx file
|
||||||
|
"""
|
||||||
|
df = pd.read_excel(filepath, engine="openpyxl", nrows=12)
|
||||||
|
return df
|
||||||
|
|
||||||
|
|
||||||
def load_html_data_to_dataframe(filepath: str) -> pd.DataFrame:
|
def load_html_data_to_dataframe(filepath: str) -> pd.DataFrame:
|
||||||
"""Read HTML file exported by FM into a Dataframe
|
"""Read HTML file exported by FM into a Dataframe.
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
filepath -- path to fm player html file
|
filepath -- path to fm player html file
|
||||||
"""
|
"""
|
||||||
player_df = pd.read_html(filepath, header=0, encoding="utf-8", keep_default_na=False)[0]
|
df = pd.read_html(filepath, header=0, encoding="utf-8", keep_default_na=False)[0]
|
||||||
# Clean Dataframe to get rid of unknown values and ability ranges (takes the lowest value)
|
# Clean Dataframe to get rid of unknown values and ability ranges (takes the lowest value)
|
||||||
# This casts to a string to be able to split, so we have to cast back to an int later.
|
# This casts to a string to be able to split, so we have to cast back to an int later.
|
||||||
player_df = player_df.replace("-", 0)
|
df = df.replace("-", 0)
|
||||||
player_df = player_df.map(lambda x: str(x).split("-")[0])
|
df = df.map(lambda x: str(x).split("-")[0])
|
||||||
return player_df
|
return df
|
||||||
|
|
||||||
|
|
||||||
def export_html_from_dataframe(player_df: pd.DataFrame, filepath: str) -> str:
|
def export_html_from_dataframe(player_df: pd.DataFrame, filepath: str) -> str:
|
||||||
"""Export Dataframe as html with jQuery Data Tables
|
"""Export Dataframe as html with jQuery Data Tables.
|
||||||
|
|
||||||
Taken from: https://www.thepythoncode.com/article/convert-pandas-dataframe-to-html-table-python.
|
Taken from: https://www.thepythoncode.com/article/convert-pandas-dataframe-to-html-table-python.
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
@ -115,71 +59,43 @@ def export_html_from_dataframe(player_df: pd.DataFrame, filepath: str) -> str:
|
|||||||
"""
|
"""
|
||||||
open(filepath, "w", encoding="utf-8").write(html)
|
open(filepath, "w", encoding="utf-8").write(html)
|
||||||
|
|
||||||
# TODO: Do I even want this?
|
|
||||||
def calc_composite_scores(player_df: pd.DataFrame) -> pd.DataFrame:
|
def calc_role_scores(player_df: pd.DataFrame, attribute_df: pd.DataFrame) -> pd.DataFrame:
|
||||||
"""Calculate Speed, Workrate and Set Piece scores
|
"""Calculate Player position scores based on selected attribute weightings.
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
player_df: Dataframe of Players and Attributes
|
player_df: Dataframe of Players and their Attributes
|
||||||
|
attribute_df: Dataframe of Attributes and their Weightings
|
||||||
"""
|
"""
|
||||||
player_df['Spd'] = ( player_df['Pac'] + player_df['Acc'] ) / 2
|
for _, weightings in attribute_df.iterrows():
|
||||||
player_df['Work'] = ( player_df['Wor'] + player_df['Sta'] ) / 2
|
role = weightings["Ratings Weights"]
|
||||||
player_df['SetP'] = ( player_df['Jum'] + player_df['Bra'] ) / 2
|
player_df[role] = 0
|
||||||
|
for attribute in weightings.index[1:]:
|
||||||
|
weighting = weightings[attribute]
|
||||||
|
try:
|
||||||
|
player_df[role] += round(pd.to_numeric(player_df[attribute]) * weighting / 20, 2)
|
||||||
|
except Exception as e: # Used to Nat being used twice (Nationality and Natural Fitness)
|
||||||
|
print(e)
|
||||||
|
continue
|
||||||
return player_df
|
return player_df
|
||||||
|
|
||||||
def sum_attributes(player_df: pd.DataFrame, role: str, attribute_type: str, attributes: [str]) -> pd.DataFrame:
|
|
||||||
"""Create a new Column containing the sum of provided attribute columns
|
|
||||||
|
|
||||||
Keyword arguments:
|
|
||||||
player_df: Dataframe of Players and Attributes
|
|
||||||
role: Name of role to be used as additional column in dataframe
|
|
||||||
attribute_type: Type of Attribute [Primary, Secondary, Tertiary]
|
|
||||||
attributes: List of Attributes to Sum
|
|
||||||
"""
|
|
||||||
player_df[f'{role}_{attribute_type}'] = 0
|
|
||||||
for attribute in attributes:
|
|
||||||
player_df[f'{role}_{attribute_type}'] += pd.to_numeric(player_df[attribute])
|
|
||||||
player_df[f'{role}_{attribute_type}'] = round(player_df[f'{role}_{attribute_type}'] / len(attributes), 2)
|
|
||||||
return player_df
|
|
||||||
|
|
||||||
def calc_role_scores(player_df: pd.DataFrame, role: dict) -> pd.DataFrame:
|
|
||||||
"""Calculate Player Role scores based on selected attributes.
|
|
||||||
|
|
||||||
Keyword arguments:
|
|
||||||
player_df: Dataframe of Players and Attributes
|
|
||||||
role: Dictionary containing role name, role attributes and role attribute weightings
|
|
||||||
"""
|
|
||||||
player_df = sum_attributes(player_df, role["role_name"], "primary", role["primary_attributes"])
|
|
||||||
player_df = sum_attributes(player_df, role["role_name"], "secondary", role["secondary_attributes"])
|
|
||||||
if "tertiary_attributes" in role:
|
|
||||||
print("here")
|
|
||||||
player_df = sum_attributes(player_df, role["role_name"], "tertiary", role["tertiary_attributes"])
|
|
||||||
divisor = role["primary_multiplier"] + role["secondary_multiplier"] + role["tertiary_multiplier"]
|
|
||||||
player_df[f'{role["role_name"]}'] = round((((player_df[f'{role["role_name"]}_primary'] * 5) + (player_df[f'{role["role_name"]}_secondary'] * 3) + (player_df[f'{role["role_name"]}_tertiary'] * 1)) / divisor ), 2)
|
|
||||||
return player_df
|
|
||||||
|
|
||||||
def calc_role_scores_for_tactic_roles(player_df: pd.DataFrame, tactic_roles: [dict]):
|
|
||||||
for role in tactic_roles:
|
|
||||||
player_df = calc_role_scores(player_df, role)
|
|
||||||
return player_df
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Parse Input args
|
# Parse Input args
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("-i", "--input-filepath", type=str, help="Path to Input Html file")
|
parser.add_argument("-i", "--input-filepath", type=str, help="Path to Input Html file")
|
||||||
parser.add_argument("-o", "--output-filepath", type=str, help="Path to Export resultant Html file")
|
parser.add_argument("-o", "--output-filepath", type=str, help="Path to Export resultant Html file")
|
||||||
parser.add_argument("-r", "--roles", nargs='+', type=str, help="Space seperated list of roles for Evaluation")
|
parser.add_argument("-a", "--attribute-filepath", type=str, help="Path to Attribute XLSX file", default="./attribute_ratings.xlsx")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
input_filepath = args.input_filepath
|
input_filepath = args.input_filepath
|
||||||
output_filepath = args.output_filepath
|
output_filepath = args.output_filepath
|
||||||
roles = args.roles
|
attribute_filepath = args.attribute_filepath
|
||||||
|
|
||||||
# Take Role arg and convert to list of role dictionaries
|
# Inport data, calculate scores for role,
|
||||||
tactic_roles = []
|
attribute_df = load_xlsx_data_to_dataframe(attribute_filepath)
|
||||||
for role in roles:
|
|
||||||
tactic_roles.append(globals()[role])
|
|
||||||
|
|
||||||
# Inport data, calculate scores for role, export results as html
|
|
||||||
player_df = load_html_data_to_dataframe(input_filepath)
|
player_df = load_html_data_to_dataframe(input_filepath)
|
||||||
player_df = calc_role_scores_for_tactic_roles(player_df, tactic_roles)
|
player_df = calc_role_scores(player_df, attribute_df)
|
||||||
|
# trim attributes from final output
|
||||||
|
player_df = player_df.drop(player_df.columns[15:-11], axis=1)
|
||||||
|
# export results as html
|
||||||
export_html_from_dataframe(player_df, output_filepath)
|
export_html_from_dataframe(player_df, output_filepath)
|
||||||
|
@ -1,2 +1,5 @@
|
|||||||
pandas
|
pandas
|
||||||
|
numpy
|
||||||
lxml
|
lxml
|
||||||
|
openpyxl
|
||||||
|
pre-commit
|
||||||
|
192
role_score_calculator.py
Normal file
192
role_score_calculator.py
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
# Define Player attributes
|
||||||
|
# TODO: Add roles.
|
||||||
|
gk = {
|
||||||
|
"role_name": "gk",
|
||||||
|
"primary_multiplier": 5,
|
||||||
|
"primary_attributes": ["Agi", "Ref"],
|
||||||
|
"secondary_multiplier": 3,
|
||||||
|
"secondary_attributes": ["1v1", "Ant", "Cmd", "Cnt", "Kic", "Pos"],
|
||||||
|
"tertiary_multiplier": 1,
|
||||||
|
"tertiary_attributes": ["Acc", "Aer", "Cmp", "Dec", "Fir", "Han", "Pas", "Thr", "Vis"],
|
||||||
|
}
|
||||||
|
|
||||||
|
fb = {
|
||||||
|
"role_name": "fb",
|
||||||
|
"primary_multiplier": 5,
|
||||||
|
"primary_attributes": ["Wor", "Acc", "Pac", "Sta"],
|
||||||
|
"secondary_multiplier": 3,
|
||||||
|
"secondary_attributes": ["Cro", "Dri", "Mar", "OtB", "Tck", "Tea"],
|
||||||
|
"tertiary_multiplier": 1,
|
||||||
|
"tertiary_attributes": ["Agi", "Ant", "Cnt", "Dec", "Fir", "Pas", "Pos", "Tec"],
|
||||||
|
}
|
||||||
|
|
||||||
|
cd = {
|
||||||
|
"role_name": "cd",
|
||||||
|
"primary_multiplier": 3,
|
||||||
|
"primary_attributes": ["Cmp", "Hea", "Jum", "Mar", "Pas", "Pos", "Str", "Tck", "Pac"],
|
||||||
|
"secondary_multiplier": 1,
|
||||||
|
"secondary_attributes": ["Agg", "Ant", "Bra", "Cnt", "Dec", "Fir", "Tec", "Vis"],
|
||||||
|
}
|
||||||
|
|
||||||
|
dm = {
|
||||||
|
"role_name": "dm",
|
||||||
|
"primary_multiplier": 5,
|
||||||
|
"primary_attributes": ["Wor", "Pac", "Sta", "Pas"],
|
||||||
|
"secondary_multiplier": 3,
|
||||||
|
"secondary_attributes": ["Tck", "Ant", "Cnt", "Pos", "Bal", "Agi"],
|
||||||
|
"tertiary_multiplier": 1,
|
||||||
|
"tertiary_attributes": ["Tea", "Fir", "Mar", "Agg", "Cmp", "Dec", "Str"],
|
||||||
|
}
|
||||||
|
|
||||||
|
b2b = {
|
||||||
|
"role_name": "b2b",
|
||||||
|
"primary_multiplier": 5,
|
||||||
|
"primary_attributes": ["Pas", "Wor", "Sta"],
|
||||||
|
"secondary_multiplier": 3,
|
||||||
|
"secondary_attributes": ["Tck", "OtB", "Tea", "Vis", "Str", "Dec", "Pos", "Pac"],
|
||||||
|
"tertiary_multiplier": 1,
|
||||||
|
"tertiary_attributes": ["Agg", "Ant", "Fin", "Lon", "Cmp", "Acc", "Bal", "Fir", "Dri", "Tec"],
|
||||||
|
}
|
||||||
|
|
||||||
|
w = {
|
||||||
|
"role_name": "w",
|
||||||
|
"primary_multiplier": 3,
|
||||||
|
"primary_attributes": ["Acc", "Cro", "Dri", "OtB", "Pac", "Tec"],
|
||||||
|
"secondary_multiplier": 1,
|
||||||
|
"secondary_attributes": ["Agi", "Fir", "Pas", "Sta", "Wor"],
|
||||||
|
}
|
||||||
|
|
||||||
|
iw = {
|
||||||
|
"role_name": "iw",
|
||||||
|
"primary_multiplier": 5,
|
||||||
|
"primary_attributes": ["Acc", "Pac", "Wor"],
|
||||||
|
"secondary_multiplier": 3,
|
||||||
|
"secondary_attributes": ["Dri", "Pas", "Tec", "OtB"],
|
||||||
|
"tertiary_multiplier": 1,
|
||||||
|
"tertiary_attributes": ["Cro", "Fir", "Cmp", "Dec", "Vis", "Agi", "Sta"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def load_html_data_to_dataframe(filepath: str) -> pd.DataFrame:
|
||||||
|
"""Read HTML file exported by FM into a Dataframe.
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
filepath -- path to fm player html file
|
||||||
|
"""
|
||||||
|
player_df = pd.read_html(filepath, header=0, encoding="utf-8", keep_default_na=False)[0]
|
||||||
|
# Clean Dataframe to get rid of unknown values and ability ranges (takes the lowest value)
|
||||||
|
# This casts to a string to be able to split, so we have to cast back to an int later.
|
||||||
|
player_df = player_df.replace("-", 0)
|
||||||
|
player_df = player_df.map(lambda x: str(x).split("-")[0])
|
||||||
|
return player_df
|
||||||
|
|
||||||
|
|
||||||
|
def export_html_from_dataframe(player_df: pd.DataFrame, filepath: str) -> str:
|
||||||
|
"""Export Dataframe as html with jQuery Data Tables. Taken from: https://www.thepythoncode.com/article/convert-pandas-dataframe-to-html-table-python.
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
filepath -- path to fm player html file
|
||||||
|
"""
|
||||||
|
table_html = player_df.to_html(table_id="table", index=False)
|
||||||
|
html = f"""
|
||||||
|
<html>
|
||||||
|
<header>
|
||||||
|
<link href="https://cdn.datatables.net/1.11.5/css/jquery.dataTables.min.css" rel="stylesheet">
|
||||||
|
</header>
|
||||||
|
<body>
|
||||||
|
{table_html}
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js" integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous"></script>
|
||||||
|
<script type="text/javascript" src="https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.js"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready( function () {{
|
||||||
|
$('#table').DataTable({{
|
||||||
|
paging: false,
|
||||||
|
order: [[12, 'desc']],
|
||||||
|
// scrollY: 400,
|
||||||
|
}});
|
||||||
|
}});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
open(filepath, "w", encoding="utf-8").write(html)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: Do I even want this?
|
||||||
|
def calc_composite_scores(player_df: pd.DataFrame) -> pd.DataFrame:
|
||||||
|
"""Calculate Speed, Workrate and Set Piece scores.
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
player_df: Dataframe of Players and Attributes
|
||||||
|
"""
|
||||||
|
player_df["Spd"] = (player_df["Pac"] + player_df["Acc"]) / 2
|
||||||
|
player_df["Work"] = (player_df["Wor"] + player_df["Sta"]) / 2
|
||||||
|
player_df["SetP"] = (player_df["Jum"] + player_df["Bra"]) / 2
|
||||||
|
return player_df
|
||||||
|
|
||||||
|
|
||||||
|
def sum_attributes(player_df: pd.DataFrame, role: str, attribute_type: str, attributes: [str]) -> pd.DataFrame:
|
||||||
|
"""Create a new Column containing the sum of provided attribute columns.
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
player_df: Dataframe of Players and Attributes
|
||||||
|
role: Name of role to be used as additional column in dataframe
|
||||||
|
attribute_type: Type of Attribute [Primary, Secondary, Tertiary]
|
||||||
|
attributes: List of Attributes to Sum
|
||||||
|
"""
|
||||||
|
player_df[f"{role}_{attribute_type}"] = 0
|
||||||
|
for attribute in attributes:
|
||||||
|
player_df[f"{role}_{attribute_type}"] += pd.to_numeric(player_df[attribute])
|
||||||
|
player_df[f"{role}_{attribute_type}"] = round(player_df[f"{role}_{attribute_type}"] / len(attributes), 2)
|
||||||
|
return player_df
|
||||||
|
|
||||||
|
|
||||||
|
def calc_role_scores(player_df: pd.DataFrame, role: dict) -> pd.DataFrame:
|
||||||
|
"""Calculate Player Role scores based on selected attributes.
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
player_df: Dataframe of Players and Attributes
|
||||||
|
role: Dictionary containing role name, role attributes and role attribute weightings
|
||||||
|
"""
|
||||||
|
player_df = sum_attributes(player_df, role["role_name"], "primary", role["primary_attributes"])
|
||||||
|
player_df = sum_attributes(player_df, role["role_name"], "secondary", role["secondary_attributes"])
|
||||||
|
if "tertiary_attributes" in role:
|
||||||
|
print("here")
|
||||||
|
player_df = sum_attributes(player_df, role["role_name"], "tertiary", role["tertiary_attributes"])
|
||||||
|
divisor = role["primary_multiplier"] + role["secondary_multiplier"] + role["tertiary_multiplier"]
|
||||||
|
player_df[f'{role["role_name"]}'] = round(
|
||||||
|
(((player_df[f'{role["role_name"]}_primary'] * 5) + (player_df[f'{role["role_name"]}_secondary'] * 3) + (player_df[f'{role["role_name"]}_tertiary'] * 1)) / divisor), 2
|
||||||
|
)
|
||||||
|
return player_df
|
||||||
|
|
||||||
|
|
||||||
|
def calc_role_scores_for_tactic_roles(player_df: pd.DataFrame, tactic_roles: [dict]):
|
||||||
|
for role in tactic_roles:
|
||||||
|
player_df = calc_role_scores(player_df, role)
|
||||||
|
return player_df
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Parse Input args
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("-i", "--input-filepath", type=str, help="Path to Input Html file")
|
||||||
|
parser.add_argument("-o", "--output-filepath", type=str, help="Path to Export resultant Html file")
|
||||||
|
parser.add_argument("-r", "--roles", nargs="+", type=str, help="Space seperated list of roles for Evaluation")
|
||||||
|
args = parser.parse_args()
|
||||||
|
input_filepath = args.input_filepath
|
||||||
|
output_filepath = args.output_filepath
|
||||||
|
roles = args.roles
|
||||||
|
|
||||||
|
# Take Role arg and convert to list of role dictionaries
|
||||||
|
tactic_roles = []
|
||||||
|
for role in roles:
|
||||||
|
tactic_roles.append(globals()[role])
|
||||||
|
|
||||||
|
# Inport data, calculate scores for role, export results as html
|
||||||
|
player_df = load_html_data_to_dataframe(input_filepath)
|
||||||
|
player_df = calc_role_scores_for_tactic_roles(player_df, tactic_roles)
|
||||||
|
export_html_from_dataframe(player_df, output_filepath)
|
Loading…
x
Reference in New Issue
Block a user