-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fd9e194
commit f585ddb
Showing
22 changed files
with
31,280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[[source]] | ||
url = "https://pypi.org/simple" | ||
verify_ssl = true | ||
name = "pypi" | ||
|
||
[packages] | ||
flask = "==2.0.1" | ||
python-decouple = "==3.3" | ||
flask-restful = "==0.3.9" | ||
pandas = "==1.3.0" | ||
plotly = "==5.1.0" | ||
|
||
[dev-packages] | ||
|
||
[requires] | ||
python_version = "3.9" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Backend | ||
|
||
## Project setup | ||
|
||
### Install requirements | ||
``` | ||
pip install -r requirements.pip | ||
``` | ||
|
||
### Run locally | ||
``` | ||
FLASK_APP=src/app.py flask run -h localhost -p 5000 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# | ||
# These requirements were autogenerated by pipenv | ||
# To regenerate from the project's Pipfile, run: | ||
# | ||
# pipenv lock --requirements | ||
# | ||
|
||
-i https://pypi.org/simple | ||
aniso8601==9.0.1 | ||
click==8.0.1; python_version >= '3.6' | ||
flask-restful==0.3.9 | ||
flask==2.0.1 | ||
itsdangerous==2.0.1; python_version >= '3.6' | ||
jinja2==3.0.1; python_version >= '3.6' | ||
markupsafe==2.0.1; python_version >= '3.6' | ||
numpy==1.21.1; python_version >= '3.7' | ||
pandas==1.3.0 | ||
plotly==5.1.0 | ||
python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' | ||
python-decouple==3.3 | ||
pytz==2021.1 | ||
six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' | ||
tenacity==8.0.1; python_version >= '3.6' | ||
werkzeug==2.0.1; python_version >= '3.6' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from flask_restful import Api as RestAPI | ||
|
||
from api.healthcheck.resources import HealthyCheckResource | ||
from api import reports | ||
|
||
|
||
class API(RestAPI): | ||
|
||
def init_app(self, app): | ||
super().init_app(app) | ||
app.after_request(self.add_cors_headers) | ||
|
||
@staticmethod | ||
def add_cors_headers(response): | ||
""" | ||
Enable support for CORS Headers. | ||
""" | ||
response.headers.add('Access-Control-Allow-Origin', '*') | ||
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization') | ||
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE') | ||
return response | ||
|
||
|
||
api = API() | ||
|
||
# Charts | ||
api.add_resource( | ||
reports.GenresByUserScoreAVGChartResource, | ||
'/genres-by-user-score-avg') | ||
|
||
api.add_resource( | ||
reports.PlatformsByUserScoreAVGChartResource, | ||
'/platforms-by-user-score-avg') | ||
|
||
api.add_resource( | ||
reports.GameReleasePercentByPlatformInTheYearsChartResource, | ||
'/game-release-percent-by-platform-in-the-years') | ||
|
||
# Infra | ||
api.add_resource(HealthyCheckResource, '/healthy') |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from flask_restful import Resource | ||
from werkzeug import Response | ||
|
||
|
||
class HealthyCheckResource(Resource): | ||
|
||
def get(self): | ||
return Response('OK', content_type='text/plain') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from api.reports.game_release_percent_by_platform_in_the_years import \ | ||
GameReleasePercentByPlatformInTheYearsChartResource | ||
from api.reports.genres_by_user_score_avg_chart import GenresByUserScoreAVGChartResource | ||
from api.reports.platforms_by_user_score_avg_chart import PlatformsByUserScoreAVGChartResource |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import pandas as pd | ||
from flask import current_app | ||
|
||
|
||
def get_data(): | ||
""" | ||
Load dataset and prepare for reports. | ||
""" | ||
path = current_app.config['BASE_DIR'] / 'data/games.csv' | ||
|
||
# load dataset. | ||
df = pd.read_csv(path) | ||
|
||
# convert date column into python timestamps | ||
df['date'] = pd.to_datetime(df['date'], format='%B %d, %Y') | ||
df['year'] = df['date'].apply(lambda x: x.year) | ||
|
||
# convert user score into float | ||
df['userscore'] = pd.to_numeric(df['userscore'], errors='coerce') | ||
|
||
# strip platforms text | ||
df['platforms'] = df['platforms'] \ | ||
.apply(str.strip) \ | ||
.apply(lambda x: x.replace('\n', '')) \ | ||
.apply(lambda x: x.replace(' ', '')) | ||
|
||
# drop invalid values | ||
df = df.dropna() | ||
|
||
return df |
67 changes: 67 additions & 0 deletions
67
backend/src/api/reports/game_release_percent_by_platform_in_the_years.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import datetime | ||
|
||
import plotly.graph_objects as go | ||
from flask import request | ||
|
||
from api.reports.data import get_data | ||
from commons import parser | ||
from commons.resources import PlotlyChartResource | ||
|
||
|
||
class GameReleasePercentByPlatformInTheYearsChartResource(PlotlyChartResource): | ||
|
||
def get(self): | ||
# load data | ||
df = get_data() | ||
|
||
all_genres = list(df['genre'].unique()) | ||
|
||
# filters | ||
current_year = datetime.datetime.now().year | ||
start_year = parser.parse(request.args.get('start_year'), cast=int, default=current_year - 5) | ||
end_year = parser.parse(request.args.get('end_year'), cast=int, default=current_year) | ||
genres = parser.parse(request.args.get('genres'), cast=parser.csv(), default=[]) or all_genres[:5] | ||
years = list(df['year'].unique()) | ||
|
||
# filter by year | ||
df = df[(df['year'] >= start_year) & (df['year'] <= end_year)] | ||
|
||
df = df[['genre', 'year']] \ | ||
.groupby(['genre', 'year'], as_index=False) \ | ||
.size() | ||
|
||
# calc release percent size | ||
df['p'] = df.apply(lambda x: x[2] / df[(df['year'] == x[1])]['size'].sum(), axis=1) | ||
|
||
# filter genres | ||
df = df[(df['genre'].isin(genres))] | ||
|
||
# build the chart | ||
traces = [go.Scatter( | ||
name=genre, | ||
x=data['year'], | ||
y=data['p'], | ||
mode='markers+lines' | ||
) for genre, data in map(lambda x: (x, df[(df['genre'] == x)]), genres)] | ||
|
||
fig = go.Figure(data=traces) | ||
|
||
fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='#f7f7f7') | ||
fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='#f7f7f7') | ||
fig.update_layout( | ||
xaxis_title='Year', | ||
yaxis_title='% of Realeases', | ||
yaxis_tickformat='1%', | ||
plot_bgcolor='#FFFFFF' | ||
) | ||
|
||
return { | ||
'properties': { | ||
'start_year': start_year, | ||
'end_year': end_year, | ||
'years': years, | ||
'selected_genres': genres, | ||
'genres': all_genres | ||
}, | ||
'chart': fig.to_dict() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import plotly.graph_objects as go | ||
from flask import request | ||
|
||
from api.reports.data import get_data | ||
from commons import parser | ||
from commons.resources import PlotlyChartResource | ||
|
||
|
||
class GenresByUserScoreAVGChartResource(PlotlyChartResource): | ||
|
||
def get(self): | ||
# load data | ||
df = get_data() | ||
|
||
# filters | ||
top = parser.parse(request.args.get('top'), cast=int, default=5) | ||
total = len(df['platforms'].unique()) | ||
|
||
# calc the mean grouped by platforms. | ||
df = df[['genre', 'userscore']] \ | ||
.groupby(['genre'], as_index=False) \ | ||
.mean()[:top] \ | ||
.sort_values('userscore', ascending=True, ignore_index=True) | ||
|
||
# build the figure. | ||
fig = go.Figure() \ | ||
.add_trace(go.Bar( | ||
x=df['userscore'], | ||
y=df['genre'], | ||
text=df['userscore'], | ||
orientation='h', | ||
hovertemplate='%{y}: %{x:.2f}<extra></extra>', | ||
marker=dict(color='#000') | ||
)) | ||
|
||
fig.update_traces(texttemplate='%{text:.2f}', textposition='outside') | ||
fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='#f7f7f7') | ||
fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='#f7f7f7') | ||
fig.update_layout( | ||
xaxis_title='Avg. Userscore', | ||
yaxis_title='Genre', | ||
bargap=0.3, | ||
plot_bgcolor='#FFFFFF', | ||
margin=dict(t=40, r=20, b=20, l=50) | ||
) | ||
|
||
return { | ||
'properties': { | ||
'top': top, | ||
'total': total | ||
}, | ||
'chart': fig.to_dict() | ||
} |
53 changes: 53 additions & 0 deletions
53
backend/src/api/reports/platforms_by_user_score_avg_chart.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import plotly.graph_objects as go | ||
from flask import request | ||
|
||
from api.reports.data import get_data | ||
from commons import parser | ||
from commons.resources import PlotlyChartResource | ||
|
||
|
||
class PlatformsByUserScoreAVGChartResource(PlotlyChartResource): | ||
|
||
def get(self): | ||
# load data | ||
df = get_data() | ||
|
||
# filters | ||
top = parser.parse(request.args.get('top'), cast=int, default=10) | ||
total = len(df['platforms'].unique()) | ||
|
||
# calc the mean grouped by platforms. | ||
df = df[['platforms', 'userscore']] \ | ||
.groupby(['platforms'], as_index=False) \ | ||
.mean()[:top] \ | ||
.sort_values('userscore', ascending=True, ignore_index=True) | ||
|
||
# build the figure. | ||
fig = go.Figure() \ | ||
.add_trace(go.Bar( | ||
x=df['userscore'], | ||
y=df['platforms'], | ||
text=df['userscore'], | ||
orientation='h', | ||
hovertemplate='%{y}: %{x:.2f}<extra></extra>', | ||
marker=dict(color='#000') | ||
)) | ||
|
||
fig.update_traces(texttemplate='%{text:.2f}', textposition='outside') | ||
fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='#f7f7f7') | ||
fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='#f7f7f7') | ||
fig.update_layout( | ||
xaxis_title='Avg. Userscore', | ||
yaxis_title='Platform', | ||
bargap=0.3, | ||
plot_bgcolor='#FFFFFF', | ||
margin=dict(t=40, r=20, b=20, l=50) | ||
) | ||
|
||
return { | ||
'properties': { | ||
'top': top, | ||
'total': total, | ||
}, | ||
'chart': fig.to_dict() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import os | ||
import pathlib | ||
|
||
|
||
from flask import Flask | ||
|
||
from api import api | ||
|
||
PROJECT_ROOT = pathlib.Path(__file__).resolve().parent | ||
|
||
# set default settings file. | ||
os.environ.setdefault('FLASK_SETTINGS_FILE', str(PROJECT_ROOT / 'settings/development.py')) | ||
|
||
|
||
def create_app(config_file=None, settings_override=None): | ||
app = Flask(__name__) | ||
|
||
if config_file: | ||
# apply settings from config file, if defined. | ||
app.config.from_pyfile(config_file) | ||
|
||
else: | ||
# otherwise load settings from environment variable. | ||
app.config.from_envvar('FLASK_SETTINGS_FILE') | ||
|
||
if settings_override: | ||
# apply settings override if necessary. | ||
app.config.update(settings_override) | ||
|
||
# Load app modules. | ||
api.init_app(app) | ||
|
||
return app |
Empty file.
Oops, something went wrong.