Skip to content
This repository has been archived by the owner on May 25, 2024. It is now read-only.

Commit

Permalink
2.15.0 - [CLOSE: #164, CLOSE: #165, CLOSE: #168, CLOSE: #170, CLOSE: #…
Browse files Browse the repository at this point in the history
…171, CLOSE: #172, CLOSE: #173]
  • Loading branch information
digitalghost-dev committed Jan 29, 2024
1 parent 9de07cc commit 95aac28
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 48 deletions.
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

# Update History

## 2.14.1 | 2024-01-25
## 2.15.0 | 2024-01-28

### Added
* [#165](https://github.com/digitalghost-dev/premier-league/issues/165) - Added each team's club icon to the **Squads** tab when a team is selected from the dropdown menu.
* [#172](https://github.com/digitalghost-dev/premier-league/issues/172) - Added a new **Players Statistics** tab.

### Changed
* [#164](https://github.com/digitalghost-dev/premier-league/issues/164) - Changed the default value `st.selectbox` to `None` in the **Squads** tab.
* [#168](https://github.com/digitalghost-dev/premier-league/issues/168) - Changed the `max_value` for each `st.dataframe` to programatically calaculate based on current max value in the DataFrame under the **League Statistics** section.
* [#171](https://github.com/digitalghost-dev/premier-league/issues/171) - Changed line chart under **Point Progression throughout the Season** section to use plotly instead of Streamlit's built in `st.line_chart` method.

### Removed
* [#170](https://github.com/digitalghost-dev/premier-league/issues/168) - Removed `for` loop that previously generated the sections for **Goalkeepers**, **Defenders**, **Midfielders**, and **Attackers** under the **Squads** tab.
* [#173](https://github.com/digitalghost-dev/premier-league/issues/173) - Removed `st.container` border from **Top 5 Teams** and **Top 5 Scorers** sections.

---

## [2.14.1] | 2024-01-25

### Changed
* [#169](https://github.com/digitalghost-dev/premier-league/issues/154) - Changed the query for `components/connections.py` to reflect table schema changes for the standings `st.dataframe`.
Expand Down Expand Up @@ -420,6 +437,8 @@ Top Teams Tab
Top Players Tab
* Shows the `portrait`, `goals`, `team`, and `nationality` of the current top five goal scorers in the league.

[2.14.1]: https://github.com/digitalghost-dev/premier-league/commit/e4a0ba46fd3dee96544b34b2022140c73a4d2ccd

[2.14.0]: https://github.com/digitalghost-dev/premier-league/commit/62a27e488c3fbc91c585e55e73c91adbe9edf0b8#diff-4dc66906e3c3b7f7a82967d85af564f2d5a6e0bee5829aa5eda607dd9756c87d

[2.13.0]: https://github.com/digitalghost-dev/premier-league/commit/dec0426ca5d3de50e8093874635f5bf01718aaa6
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
<p align="center">
<img src="https://img.shields.io/github/actions/workflow/status/digitalghost-dev/premier-league/ci_streamlit.yaml?style=flat-square&logo=github&label=CI%2FCD"/>
<a href="https://github.com/digitalghost-dev/premier-league/blob/main/CHANGELOG.md">
<img src="https://img.shields.io/badge/Dashboard_Version-2.14.1-FF4B4B?style=flat-square&logo=streamlit"/>
<img src="https://img.shields.io/badge/Dashboard_Version-2.15.0-FF4B4B?style=flat-square&logo=streamlit"/>
</a>
<a href="https://hub.docker.com/repository/docker/digitalghostdev/premier-league/general">
<img src="https://img.shields.io/docker/image-size/digitalghostdev/premier-league/2.14.1?style=flat-square&logo=docker&label=Image%20Size&color=0DB7ED"/>
<img src="https://img.shields.io/docker/image-size/digitalghostdev/premier-league/2.15.0?style=flat-square&logo=docker&label=Image%20Size&color=0DB7ED"/>
</a>
<img src="https://img.shields.io/github/repo-size/digitalghost-dev/premier-league?style=flat-square&label=Repo%20Size&color=DEA584">
</p>
Expand Down Expand Up @@ -69,7 +69,7 @@
3. The prior steps are orchestrated with Cloud Scheduler as a Docker container hosted on Cloud Run as a Job.

#### Pipeline Diagram
![data-pipeline](https://storage.googleapis.com/premier-league/data_pipelines.png)
![data-pipeline](https://storage.googleapis.com/premier_league_bucket/flowcharts/data_pipelines_flowchart.png)

### CI/CD Pipeline
The CI/CD pipeline is focused on building the Streamlit app into a Docker container that is then pushed to Artifact Registry and deployed to Cloud Run as a Service. Different architecutres are buit for different machine types and pushed to Docker Hub.
Expand All @@ -79,7 +79,7 @@ The CI/CD pipeline is focused on building the Streamlit app into a Docker contai
3. The Docker image is then deployed to [Cloud Run](https://cloud.google.com/run/docs/overview/what-is-cloud-run) as a Service.

#### Pipeline Diagram
![cicd_pipeline](https://storage.googleapis.com/premier-league/cicd_pipeline.png)
![cicd_pipeline](https://storage.googleapis.com/premier_league_bucket/flowcharts/cicd_pipeline_flowchart.png)

---

Expand Down
23 changes: 22 additions & 1 deletion components/point_progression_section.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pandas as pd
import plotly.graph_objects as go
import streamlit as st


Expand Down Expand Up @@ -35,4 +36,24 @@ def display(self):
df = self.create_dataframe(team_forms)

st.subheader("Point Progression throughout the Season")
st.line_chart(data=df)

labels = [str(f"{self.standings_df.iloc[i, 3]} - {self.standings_df.iloc[i, 1]} points") for i in range(5)]
colors = ["#1e90ff", "#ff4500", "#ffd700", "#228b22", "#000000"]

fig = go.Figure()

for i in range(5):
fig.add_trace(go.Scatter(x=df.index, y=df.iloc[:, i], name=labels[i], line=dict(color=colors[i], width=2)))

# add markers
fig.update_traces(mode="markers+lines", marker=dict(size=8, line=dict(width=2)))

fig.update_layout(
xaxis_title="Gameweek",
yaxis_title="Points",
legend_title="Team",
legend=dict(yanchor="top", y=0.99, xanchor="left", x=0.01),
height=600,
)

st.plotly_chart(fig, use_container_width=True)
52 changes: 52 additions & 0 deletions components/point_slider_section.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import streamlit as st
import plotly.graph_objects as go


class PointSliderSection:
def __init__(self, standings_df):
self.standings_df = standings_df

def display(self):
st.subheader("Points per Team:")
# Creating the slider.
points = self.standings_df["points"].tolist()
points_selection = st.slider(
"Select a Range of Points:", min_value=min(points), max_value=max(points), value=(min(points), max(points))
)
# Picking colors to use for the bar chart.
colors = [
"indigo",
] * 20
# Making sure the bar chart changes with the slider.
mask = self.standings_df["points"].between(*points_selection)
amount_of_teams = self.standings_df[mask].shape[0]

df_grouped = self.standings_df[mask]
df_grouped = df_grouped.reset_index()
lowest_number = df_grouped["points"].min()
st.markdown(f"Number of teams with {lowest_number} or more points: {amount_of_teams}")
# Creating the bar chart.
points_chart = go.Figure(
data=[
go.Bar(
x=df_grouped["team"],
y=df_grouped["points"],
marker_color=colors,
text=df_grouped["points"],
textposition="auto",
)
]
)
# Rotating x axis lables.
points_chart.update_layout(
xaxis_tickangle=-35,
autosize=False,
margin=dict(
l=0, # left
r=0, # right
b=0, # bottom
t=0, # top
),
)

st.plotly_chart(points_chart, use_container_width=True)
4 changes: 2 additions & 2 deletions components/social_media_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ def __init__(self):
self.social_links = [
{
"url": "https://hub.docker.com/r/digitalghostdev/premier-league/tags",
"icon_url": "https://storage.googleapis.com/premier-league/docker.svg",
"icon_url": "https://storage.googleapis.com/premier_league_bucket/icons/companies/docker.svg",
"alt_text": "Docker",
},
{
"url": "https://github.com/digitalghost-dev/",
"icon_url": "https://storage.googleapis.com/premier-league/github.svg",
"icon_url": "https://storage.googleapis.com/premier_league_bucket/icons/companies/github.svg",
"alt_text": "GitHub",
},
]
Expand Down
2 changes: 1 addition & 1 deletion components/top_scorers_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def generate_scorer_html(self, index):
]

def display(self):
with st.container(border=True):
with st.container():
st.subheader("Top 5 Scorers")
columns = st.columns(5)

Expand Down
2 changes: 1 addition & 1 deletion components/top_teams_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def generate_team_html(self, index):
]

def display(self):
with st.container(border=True):
with st.container():
st.subheader("Top 5 Teams")
columns = st.columns(5)

Expand Down
86 changes: 48 additions & 38 deletions streamlit_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from components.highlights_section import HighlightsSection
from components.league_form_section import LeagueFormsSection
from components.point_progression_section import PointProgressionSection
from components.point_slider_section import PointSliderSection
from components.social_media_section import SocialMediaSection
from components.squads_section import SquadSection
from components.stadiums_map_section import StadiumMapSection
Expand Down Expand Up @@ -73,10 +74,11 @@ def get_suffix(day):
st.write(f"{formatted_date}")

# Tab menu.
tab1, tab2, tab3, tab4, tab5, tab6 = st.tabs(
tab1, tab2, tab3, tab4, tab5, tab6, tab7 = st.tabs(
[
"Standings & Overview",
"Top Teams & Scorers",
"Teams Statistics",
"Players Statistics",
"Fixtures",
"Squads",
"News & Hightlights",
Expand All @@ -93,11 +95,12 @@ def get_suffix(day):
# Average goals scored column.
with col1:
teams_df_average_goals = teams_df.sort_values(by=["average_goals"], ascending=False)
max_average_goals = teams_df_average_goals.iloc[0, 6]

average_goals_df = pd.DataFrame(
{
"Average Goals": [
teams_df_average_goals.iloc[0, 6],
max_average_goals,
teams_df_average_goals.iloc[1, 6],
teams_df_average_goals.iloc[2, 6],
teams_df_average_goals.iloc[3, 6],
Expand All @@ -121,19 +124,20 @@ def get_suffix(day):
help="The Average Goals Scored by Each Team.",
format="%f",
min_value=0,
max_value=8,
max_value=int(round(max_average_goals, 2)) * 2,
),
},
hide_index=True,
)

with col2:
teams_df_penalties_scored = teams_df.sort_values(by=["penalties_scored"], ascending=False)
max_penalties_scored = teams_df_penalties_scored.iloc[0, 4]

penalties_scored_df = pd.DataFrame(
{
"Penalties Scored": [
teams_df_penalties_scored.iloc[0, 4],
max_penalties_scored,
teams_df_penalties_scored.iloc[1, 4],
teams_df_penalties_scored.iloc[2, 4],
teams_df_penalties_scored.iloc[3, 4],
Expand All @@ -157,19 +161,20 @@ def get_suffix(day):
help="The Amount of Penalties Scored by Each Team.",
format="%d",
min_value=0,
max_value=20,
max_value=int(max_penalties_scored) * 2,
),
},
hide_index=True,
)

with col3:
teams_df_win_streak = teams_df.sort_values(by=["win_streak"], ascending=False)
max_win_streak = teams_df_win_streak.iloc[0, 7]

win_streak_df = pd.DataFrame(
{
"Biggest Win Streak": [
teams_df_win_streak.iloc[0, 7],
max_win_streak,
teams_df_win_streak.iloc[1, 7],
teams_df_win_streak.iloc[2, 7],
teams_df_win_streak.iloc[3, 7],
Expand All @@ -193,7 +198,7 @@ def get_suffix(day):
help="The Biggest Win Streak by Each Team.",
format="%d",
min_value=0,
max_value=10,
max_value=int(max_win_streak) * 2,
),
},
hide_index=True,
Expand Down Expand Up @@ -262,56 +267,61 @@ def standings_table() -> DeltaGenerator:
stadium_map_section = StadiumMapSection()
stadium_map_section.display(stadiums_df)

# --------- Statistics Tab ---------
# --------- Team Statistics Tab ---------
# Tab 2 holds the following sections: [Top Teams, Point Progression, Top Scorers, League Forms].
with tab2:
top_teams_section = TopTeamsSection(teams_df)
with st.container():
sections = [
(TopTeamsSection, teams_df, None),
(PointProgressionSection, teams_df, standings_df),
(TopScorersSection, top_scorers_df, None),
(LeagueFormsSection, teams_df, None),
]

first_section = True
for section_class, dataframe_1, dataframe_2 in sections:
if not first_section:
st.subheader("")
else:
first_section = False

if dataframe_2 is not None:
section = section_class(dataframe_1, dataframe_2)
else:
section = section_class(dataframe_1)
section.display()
top_teams_section.display()

# --------- Fixtures Tab ---------
# Tab 3 holds the following sections: [Fixtures].
point_progression_section = PointProgressionSection(teams_df, standings_df)
with st.container():
point_progression_section.display()

point_slider_section = PointSliderSection(standings_df)
with st.container():
point_slider_section.display()

league_forms_section = LeagueFormsSection(teams_df)
with st.container():
league_forms_section.display()

# --------- Player Statistics Tab ---------
# Tab 3 holds the following sections: [Player Statistics].
with tab3:
top_scorers_section = TopScorersSection(top_scorers_df)
with st.container():
top_scorers_section.display()

# --------- Fixtures Tab ---------
# Tab 4 holds the following sections: [Fixtures].
with tab4:
# Fixtures section.
fixtures_section.display()

# --------- Squads Tab ---------
# Tab 4 holds the following sections: [Squads].
with tab4:
# Tab 5 holds the following sections: [Squads].
with tab5:
st.subheader("Team Squads")
st.markdown("**Note:** Double click on the player's photo to expand it.")
squads = SquadSection(squads_df)

col1, _, _ = st.columns(3)
with col1:
option = st.selectbox(
label="**Select a team to view their squad:**",
index=None,
label="Use the dropdown menu to select a team:",
options=squads.teams,
placeholder="Please select a team to view their squad.",
placeholder="Please make a selection",
)
if option:
selected_team_logo = teams_df[teams_df["team"] == option]["logo"].iloc[0]
st.image(selected_team_logo, width=75)
squads.display(option)

# --------- News Tab ---------
# Tab 5 holds the following sections: [News].
with tab5:
# Tab 6 holds the following sections: [News, Highlights].
with tab6:
st.header("Recent News")
col1, col2, col3, col4 = st.columns(4)

Expand Down Expand Up @@ -374,8 +384,8 @@ def standings_table() -> DeltaGenerator:
HighlightsSection(highlights_df).display_second_row()

# --------- About Tab ---------
# Tab 6 holds the following sections: [About].
with tab6:
# Tab 7 holds the following sections: [About].
with tab7:
# About
about_section = AboutSection()
about_section.display()
Expand Down

0 comments on commit 95aac28

Please sign in to comment.