Skip to content
Merged

1.9.0 #253

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
ac99f12
initial streamlit app
digitalghost-dev Feb 14, 2026
4254812
uv init
digitalghost-dev Feb 14, 2026
f047681
adding paths to ignore
digitalghost-dev Feb 14, 2026
c53c725
pinning all dependencies
digitalghost-dev Feb 19, 2026
4339a9a
updating version numbers
digitalghost-dev Feb 19, 2026
03253c8
adding `country_codes`, `standings`, and ` tournaments` sources (#247)
digitalghost-dev Feb 19, 2026
347df7d
replacing `st-supabase-connection` with official `supabase` library (…
digitalghost-dev Feb 24, 2026
57c0613
initial `selectbox` and `dataframe` layout (#249)
digitalghost-dev Feb 24, 2026
6034fe1
adding header (#249)
digitalghost-dev Feb 27, 2026
cadb7ea
Merge branch 'main' into 1.9.0
digitalghost-dev Feb 27, 2026
8a8fa44
adding initial tournament metrics layout (#249)
digitalghost-dev Feb 27, 2026
dd6e392
adding flag representing tournament location, updating standings data…
digitalghost-dev Mar 1, 2026
4bdab47
adding winning deck column and event logo (#249)
digitalghost-dev Mar 3, 2026
8a92b02
adding paths to ignore
digitalghost-dev Mar 5, 2026
1bd03e1
adding additional columns
digitalghost-dev Mar 5, 2026
ab60c3f
adding map of all events during current season (#249)
digitalghost-dev Mar 6, 2026
ee8b2f2
splitting into two tabs (#249)
digitalghost-dev Mar 6, 2026
686c548
splitting into two tabs (#249)
digitalghost-dev Mar 6, 2026
7e121c5
adding box plot (#249)
digitalghost-dev Mar 11, 2026
7755f97
moving player country stats into a class for better organization (#249)
digitalghost-dev Mar 11, 2026
484c7fe
moving raw standings section to class (#249)
digitalghost-dev Mar 11, 2026
5445dab
applying ruff formatting
digitalghost-dev Mar 11, 2026
e7f8117
adding initial deck stats section (#249)
digitalghost-dev Mar 12, 2026
47d8b4c
updating deck stats section (#249)
digitalghost-dev Mar 14, 2026
a5c0464
adding tournament locations section to a class (#249)
digitalghost-dev Mar 16, 2026
32424bc
moving to styling for shared list designs (#252)
digitalghost-dev Mar 17, 2026
08fe34c
adding main entry point for `tcg` command (#247)
digitalghost-dev Mar 17, 2026
70b18a0
update card package to reference `item` and `itemDelegate` from styli…
digitalghost-dev Mar 17, 2026
9e2aedc
initial tournament list page (#247)
digitalghost-dev Mar 18, 2026
6b0c484
initial dashboard/tabs page (#247)
digitalghost-dev Mar 18, 2026
05be4ea
increasing list height (#247)
digitalghost-dev Mar 18, 2026
e7707fb
initial entry point for `tcg` command (#247)
digitalghost-dev Mar 18, 2026
768960c
updating comments
digitalghost-dev Mar 18, 2026
ef50694
adding option to return back to previous screen (#247)
digitalghost-dev Mar 18, 2026
25d0e2e
fixing naming conventions and typos (#247)
digitalghost-dev Mar 18, 2026
f2c6485
fixing `Exported function with the unexported return type` warning (#…
digitalghost-dev Mar 18, 2026
7cbac74
adding countries as first content in the lipgloss tab screen (#247)
digitalghost-dev Mar 18, 2026
653be13
updating tests
digitalghost-dev Mar 19, 2026
342c674
initial overview tab content (#247)
digitalghost-dev Mar 19, 2026
13af63e
moving tab content to own files (#247)
digitalghost-dev Mar 19, 2026
fdd0c0b
updating tests
digitalghost-dev Mar 19, 2026
e8fa71b
renaming files (#247)
digitalghost-dev Mar 19, 2026
2d64227
splitting tab content into separate files (#247)
digitalghost-dev Mar 19, 2026
f9e56e6
protecting against division by 0 (#247)
digitalghost-dev Mar 19, 2026
aefec4c
store structured tournament data instead of parsing display string (#…
digitalghost-dev Mar 19, 2026
73bfcaf
updating function references (#247)
digitalghost-dev Mar 19, 2026
cf311ac
sorting tournaments in descending order (#247)
digitalghost-dev Mar 20, 2026
8129cba
guarantee at least 1 block for any non-zero count (#247)
digitalghost-dev Mar 20, 2026
0e54566
adding 2 columns for standings table (#247)
digitalghost-dev Mar 20, 2026
c031a06
updating function names (#247)
digitalghost-dev Mar 22, 2026
3a7d3bf
updating tests
digitalghost-dev Mar 22, 2026
ece7a6b
initial standings tab content (#247)
digitalghost-dev Mar 22, 2026
17c0118
moving bar chart for countries and decks to own file (#247)
digitalghost-dev Mar 22, 2026
9f9e529
moving list designs to `styling` package (#252)
digitalghost-dev Mar 22, 2026
1bca58b
replace global `supabaseConn` with dependency injection (#247)
digitalghost-dev Mar 22, 2026
76e623b
updating tests
digitalghost-dev Mar 22, 2026
456cc0f
adding golden files to test `tcg` command output (#247)
digitalghost-dev Mar 22, 2026
a53d25d
extract `runTcgLoop` to enable unit testing of loop logic (#247)
digitalghost-dev Mar 23, 2026
d26422a
containerizing Streamlit app (#249)
digitalghost-dev Mar 23, 2026
11d061b
adding `standings` table as a source
digitalghost-dev Mar 23, 2026
805c1b6
fixing `golangci-lint` errors
digitalghost-dev Mar 24, 2026
f3f872a
updating tests
digitalghost-dev Mar 24, 2026
201875e
adding `--web` flag to `tcg` command (#249)
digitalghost-dev Mar 24, 2026
2fa4eca
adding entry point for `tcg` command (#247)
digitalghost-dev Mar 24, 2026
6ed281f
adding `COPY` step for `.config` file (#249)
digitalghost-dev Mar 24, 2026
f78a53f
updating link to Streamlit app (#249)
digitalghost-dev Mar 24, 2026
57741c2
applying `go fmt` changes
digitalghost-dev Mar 24, 2026
1a752b4
fixing `golangci-lint` errors
digitalghost-dev Mar 24, 2026
60b96d6
printing out warning if current environment can't open a browser (#249)
digitalghost-dev Mar 25, 2026
21bd085
updating version number
digitalghost-dev Mar 25, 2026
ebbbf02
fixing `gosec` error
digitalghost-dev Mar 25, 2026
0cc3a08
updating demo gifs to use CloudFront cdn links
digitalghost-dev Mar 25, 2026
6acc673
updating roadmap
digitalghost-dev Mar 25, 2026
d98983c
updating dependencies
digitalghost-dev Mar 25, 2026
5cc734b
fixing `pyrefly` issues
digitalghost-dev Mar 25, 2026
95ef484
guarding against non-ASCII ISO codes (#247)
digitalghost-dev Mar 25, 2026
50f19a4
adding description (#249)
digitalghost-dev Mar 25, 2026
144f679
pinning to specific version
digitalghost-dev Mar 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ on:
- main

env:
VERSION_NUMBER: 'v1.8.11'
VERSION_NUMBER: 'v1.9.0'
DOCKERHUB_REGISTRY_NAME: 'digitalghostdev/poke-cli'
AWS_REGION: 'us-west-2'

Expand All @@ -50,7 +50,7 @@ jobs:
uses: actions/checkout@v6

- name: Run Gosec Security Scanner
uses: securego/gosec@v2.22.11
uses: securego/gosec@v2.25.0
with:
args: '-no-fail -fmt sarif -out results.sarif ./...'

Expand Down
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ go.work.sum
# env file
.env

# web
web/.venv
web/.streamlit/secrets.toml
web/.coverage

# Python
card_data/.venv
__pycache__/
Expand Down Expand Up @@ -56,7 +61,6 @@ card_data/infrastructure/supabase/access-token

card_data/.tmp*/**


card_data/pipelines/poke_cli_dbt/.user.yml
/card_data/supabase/
/card_data/sample_scripts/
Expand Down
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ builds:
- windows
- darwin
ldflags:
- -s -w -X main.version=v1.8.11
- -s -w -X main.version=v1.9.0

archives:
- formats: [ 'zip' ]
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ RUN go mod download

COPY . .

RUN go build -ldflags "-X main.version=v1.8.11" -o poke-cli .
RUN go build -ldflags "-X main.version=v1.9.0" -o poke-cli .

# build 2
FROM --platform=$BUILDPLATFORM alpine:3.23
Expand Down
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<img width="425" src="poke-cli.png" alt="pokemon-logo"/>
<h4></h4>
<img src="https://img.shields.io/github/v/release/digitalghost-dev/poke-cli?style=flat-square&logo=git&logoColor=FFCC00&label=Release%20Version&labelColor=EEE&color=FFCC00" alt="version-label">
<img src="https://img.shields.io/docker/image-size/digitalghostdev/poke-cli/v1.8.11?arch=arm64&style=flat-square&logo=docker&logoColor=FFCC00&labelColor=EEE&color=FFCC00" alt="docker-image-size">
<img src="https://img.shields.io/docker/image-size/digitalghostdev/poke-cli/v1.9.0?arch=arm64&style=flat-square&logo=docker&logoColor=FFCC00&labelColor=EEE&color=FFCC00" alt="docker-image-size">
<img src="https://img.shields.io/github/actions/workflow/status/digitalghost-dev/poke-cli/ci.yml?branch=main&style=flat-square&logo=github&logoColor=FFCC00&label=CI&labelColor=EEE&color=FFCC00" alt="ci-status-badge">
</div>
<div align="center">
Expand All @@ -27,11 +27,11 @@ View the [documentation](https://docs.poke-cli.com) on the data infrastructure i
## Demo
### Video Game Data

![demo-vg](https://poke-cli-s3-bucket.s3.us-west-2.amazonaws.com/demo-v1.6.0.gif)
![demo-vg](https://dc8hq8aq7pr04.cloudfront.net/demo-v1.6.0.gif)

### Trading Card Game Data

![demo-tcg](https://poke-cli-s3-bucket.s3.us-west-2.amazonaws.com/poke-cli-card-v1.8.8.gif)
![demo-tcg](https://dc8hq8aq7pr04.cloudfront.net/poke-cli-card-v1.8.8.gif)

---

Expand Down Expand Up @@ -99,11 +99,11 @@ Cloudsmith is a fully cloud-based service that lets you easily create, store, an
3. Choose how to interact with the container:
* Run a single command and exit:
```bash
docker run --rm -it digitalghostdev/poke-cli:v1.8.11 <command> [subcommand] [flag]
docker run --rm -it digitalghostdev/poke-cli:v1.9.0 <command> [subcommand] [flag]
```
* Enter the container and use its shell:
```bash
docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.8.11 -c "cd /app && exec sh"
docker run --rm -it --name poke-cli --entrypoint /bin/sh digitalghostdev/poke-cli:v1.9.0 -c "cd /app && exec sh"
# placed into the /app directory, run the program with './poke-cli'
# example: ./poke-cli ability swift-swim
```
Expand All @@ -118,7 +118,7 @@ Cloudsmith is a fully cloud-based service that lets you easily create, store, an
6. Run the tool!

> [!IMPORTANT]
> For macOS, you may have to allow the executable to run as it is not signed. Head to System Settings > Privacy & Security > scroll down and allow the executable to run.
> For macOS, you may have to allow the executable to run as it is not signed. Head to System Settings > Privacy & Security > scroll down and allow executable to run.

<details>

Expand Down Expand Up @@ -174,6 +174,7 @@ By running `poke-cli [-h | --help]`, it'll display information on how to use the
│ pokemon Get details about a Pokémon │
│ search Search for a resource │
│ speed Calculate the speed of a Pokémon in battle │
│ tcg Get details about TCG tournaments │
│ types Get details about a typing │
│ │
│ hint: when calling a resource with a space, use a hyphen │
Expand All @@ -197,7 +198,7 @@ Below is a list of the planned/completed commands and flags:
- [x] add mega evolution data
- [x] add scarlet & violet data
- [x] add sword & shield data
- [ ] add sun & moon data
- [x] add sun & moon data
- [ ] add x & y data
- [x] `item`: get data about an item.
- [x] `move`: get data about a move.
Expand All @@ -216,6 +217,7 @@ Below is a list of the planned/completed commands and flags:
- [x] `move`
- [x] `pokemon`
- [x] `speed`: compare speed stats between two Pokémon.
- [x] `tcg`: get data about TCG tournaments.
- [x] `types`: get data about a specific typing.

---
Expand Down
24 changes: 18 additions & 6 deletions card_data/pipelines/defs/extract/limitless/extract_standings.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import dagster as dg
import polars as pl
import requests
from bs4 import BeautifulSoup
from bs4 import BeautifulSoup, Tag

def seasons(year: int) -> list[dict]:
url = "https://labs.limitlesstcg.com/"
r = requests.get(url)
soup = BeautifulSoup(r.content, 'html.parser')

season_header = soup.find("h2", string=lambda x: x and f"{year}" in x)
season_header = soup.find("h2", string=lambda x: bool(x and f"{year}" in x))
if not isinstance(season_header, Tag):
return []
tournament_list = season_header.find_next_sibling("ul")
if not isinstance(tournament_list, Tag):
return []

tournaments = []
for a in tournament_list.find_all("a", href=True):
if not isinstance(a, Tag):
continue
parts = list(a.stripped_strings)
tournaments.append({
"name": parts[0],
Expand All @@ -31,23 +37,29 @@ def build_standings(tournament: dict) -> pl.DataFrame | None:

table = soup.find("table", class_="data-table striped")

if table:
if isinstance(table, Tag):
headers = ['Rank', 'Name', 'Country', 'Points', 'Record', 'OPW%', 'OOPW%', 'Deck', 'Decklist', 'Unknown']

rows = []
tbody = table.find('tbody')
if not isinstance(tbody, Tag):
return None

for tr in tbody.find_all('tr'):
if not isinstance(tr, Tag):
continue
cells = tr.find_all('td')

if len(cells) == 1:
continue

row_data = []
for i, td in enumerate(cells):
if not isinstance(td, Tag):
continue
if i == 2:
img = td.find('img')
if img:
if isinstance(img, Tag):
country = img.get('alt') or img.get('title') or ''
row_data.append(country)
else:
Expand All @@ -56,15 +68,15 @@ def build_standings(tournament: dict) -> pl.DataFrame | None:
elif i == 7: # Deck column
pokemon_imgs = td.find_all('img', class_='pokemon')
if pokemon_imgs:
pokemon_names = [img.get('alt', '') for img in pokemon_imgs if img.get('alt')]
pokemon_names = [str(img.get('alt', '')) for img in pokemon_imgs if isinstance(img, Tag) and img.get('alt')]
pokemon_string = '/'.join(pokemon_names)
row_data.append(pokemon_string)
else:
row_data.append('')

elif i == 8: # Decklist column
link = td.find('a')
if link:
if isinstance(link, Tag):
decklist_url = link.get('href', '')
row_data.append(f"https://labs.limitlesstcg.com{decklist_url}" if decklist_url else '')
else:
Expand Down
1 change: 1 addition & 0 deletions card_data/pipelines/defs/transform/transform_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def get_asset_key(self, dbt_resource_props):
"sets": "data_quality_checks_on_sets",
"cards": "load_card_data",
"pricing_data": "data_quality_checks_on_pricing",
"standings": "load_standings_data",
}
if name in source_mapping:
return dg.AssetKey([source_mapping[name]])
Expand Down
2 changes: 1 addition & 1 deletion card_data/pipelines/poke_cli_dbt/dbt_project.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: 'poke_cli_dbt'
version: '1.8.11'
version: '1.9.0'

profile: 'poke_cli_dbt'

Expand Down
53 changes: 51 additions & 2 deletions card_data/pipelines/poke_cli_dbt/models/sources.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,62 @@ sources:
description: "Third attack energy cost"

- name: standings
description: "Tournament standings data"
description: "Player standings data for tournaments"
columns:
- name: rank
description: "Player rank in the tournament"
- name: name
description: "Player name"
- name: points
description: "Player points"
- name: record
description: "Player win/loss record"
- name: opp_win_percent
description: "Opponent win percentage"
- name: opp_opp_win_percent
description: "Opponent's opponent win percentage"
- name: deck
description: "Deck name used by player"
- name: decklist
description: "Decklist URL"
- name: country
description: "Player country code"
- name: tournament_id
description: "Foreign key to tournaments"

- name: tournaments
description: "Tournament metadata"
columns:
- name: tournament_id
description: "Unique tournament identifier"
- name: location
description: "Tournament location"
- name: start_date
description: "Tournament start date"
- name: end_date
description: "Tournament end date"
- name: type
description: "Tournament type"
- name: player_quantity
description: "Number of players in the tournament"
- name: text_date
description: "Tournament date in text format"
- name: country_code
description: "Country ISO code"
- name: logo
description: "Tournament type logo URL"
- name: latitude
description: "Tournament city latitude"
- name: longitude
description: "Tournament city longitude"

- name: country_codes
description: "Country code to country name mapping"
description: "Country code to country name mapping with geographic centroids"
columns:
- name: code
description: "ISO country code"
- name: country_name
description: "Full country name"

- name: pricing_data
description: "Card pricing data"
Expand Down
8 changes: 7 additions & 1 deletion card_data/pipelines/poke_cli_dbt/models/standings.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,20 @@ SELECT
s.deck,
s.decklist,
c.country_name AS player_country,
LOWER(c.code) AS country_code,
t.location,
t.country_code AS iso_code,
t.latitude AS tournament_latitude,
t.longitude AS tournament_longitude,
t.logo,
t.start_date,
t.end_date,
t.text_date,
t.type,
t.player_quantity
FROM
{{ source('staging', 'standings') }} AS s
INNER JOIN {{ source('staging', 'tournaments') }} AS t
ON s.tournament_id = t.tournament_id
INNER JOIN {{ source('staging', 'country_codes') }} AS c
LEFT JOIN {{ source('staging', 'country_codes') }} AS c
ON s.country = c.code
42 changes: 21 additions & 21 deletions card_data/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
[project]
name = "card-data"
version = "1.8.11"
version = "1.9.0"
description = "File directory to store all data related processes for the Pokémon TCG."
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"aws-secretsmanager-caching>=1.1.3",
"beautifulsoup4>=4.13.5",
"dagster>=1.11.3",
"dagster-dbt>=0.27.3",
"dagster-dg-cli>=1.11.3",
"aws-secretsmanager-caching==1.1.3",
"beautifulsoup4==4.13.5",
"dagster==1.12.7",
"dagster-dbt==0.28.7",
"dagster-dg-cli==1.12.7",
"dagster-postgres==0.28.7",
"dagster-webserver==1.12.7",
"dbt-core>=1.10.8",
"dbt-postgres>=1.9.0",
"pandas>=2.3.1",
"polars>=1.31.0",
"psycopg2-binary>=2.9.10",
"pyarrow>=20.0.0",
"pydantic>=2.11.7",
"requests>=2.32.4",
"soda-core-postgres>=3.5.5",
"sqlalchemy>=2.0.41",
"termcolor>=3.1.0",
"dbt-core==1.10.8",
"dbt-postgres==1.9.0",
"pandas==2.3.1",
"polars==1.31.0",
"psycopg2-binary==2.9.10",
"pyarrow==20.0.0",
"pydantic==2.11.7",
"requests==2.32.4",
"soda-core-postgres==3.5.5",
"sqlalchemy==2.0.41",
"termcolor==3.1.0",
]

[dependency-groups]
dev = [
"dagster-webserver==1.12.7",
"dagster-dg-cli",
"dagster-dbt>=0.27.3",
"dagster-dbt==0.28.7",
"dagster-postgres==0.28.7",
"pytest>=9.0.2",
"pytest-codspeed>=4.2.0",
"responses>=0.25.8",
"pytest==9.0.2",
"pytest-codspeed==4.2.0",
"responses==0.25.8",
]

[tool.dg]
Expand Down
Loading
Loading