data(*): Improve ordering of forms

This commit is contained in:
Josh Creek
2026-01-17 21:08:21 +00:00
parent f302721119
commit a26f38bca1
4 changed files with 76 additions and 36 deletions
+15 -15
View File
@@ -1,15 +1,15 @@
region region,releaseOrder
Kanto Kanto,1
Johto Johto,2
Hoenn Hoenn,3
Sinnoh Orre,4
Unova Sinnoh,5
Galar Ranch,6
Alola Unova,7
Kalos Kalos,8
Hisui Alola,9
Paldea Go,10
Go Galar,11
Home Home,12
Orre Hisui,13
Ranch Paldea,14
1 region releaseOrder
2 Kanto 1
3 Johto 2
4 Hoenn 3
5 Sinnoh Orre 4
6 Unova Sinnoh 5
7 Galar Ranch 6
8 Alola Unova 7
9 Kalos 8
10 Hisui Alola 9
11 Paldea Go 10
12 Go Galar 11
13 Home 12
14 Orre Hisui 13
15 Ranch Paldea 14
@@ -59,10 +59,14 @@ class CombinedDataRepository {
query = query.contains('gamesToCatchIn', [game]); query = query.contains('gamesToCatchIn', [game]);
} }
// Stable ordering: national dex number, then base form first, then form name. // Stable ordering from the database: national dex, Unown order, base/female/temporal, then form label.
query = query query = query
.order('pokedexNumber', { ascending: true }) .order('pokedexNumber', { ascending: true })
.order('form', { ascending: true, nullsFirst: true }); .order('unownSortOrder', { ascending: true })
.order('formSortBucket', { ascending: true })
.order('formSortRegionOrder', { ascending: true })
.order('formSortRegionalSub', { ascending: true })
.order('formSortLabel', { ascending: true });
return query; return query;
} }
@@ -220,7 +224,6 @@ class CombinedDataRepository {
): Promise<CombinedData[]> { ): Promise<CombinedData[]> {
const from = (page - 1) * limit; const from = (page - 1) * limit;
const to = from + limit - 1; const to = from + limit - 1;
const entries = await this.fetchEntriesByRange(from, to, enableForms, region, game); const entries = await this.fetchEntriesByRange(from, to, enableForms, region, game);
if (!entries || entries.length === 0) { if (!entries || entries.length === 0) {
@@ -16,6 +16,7 @@ $$ LANGUAGE plpgsql;
CREATE TABLE regions ( CREATE TABLE regions (
id BIGSERIAL PRIMARY KEY, id BIGSERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE, name TEXT NOT NULL UNIQUE,
"releaseOrder" INTEGER NOT NULL,
"createdAt" TIMESTAMPTZ DEFAULT NOW(), "createdAt" TIMESTAMPTZ DEFAULT NOW(),
"updatedAt" TIMESTAMPTZ DEFAULT NOW() "updatedAt" TIMESTAMPTZ DEFAULT NOW()
); );
@@ -283,6 +284,7 @@ SELECT
p.form, p.form,
p."canGigantamax", p."canGigantamax",
r.name AS "regionToCatchIn", r.name AS "regionToCatchIn",
r."releaseOrder" AS "regionReleaseOrder",
COALESCE( COALESCE(
ARRAY_AGG(g."displayName" ORDER BY g."displayName") FILTER (WHERE g.id IS NOT NULL), ARRAY_AGG(g."displayName" ORDER BY g."displayName") FILTER (WHERE g.id IS NOT NULL),
ARRAY[]::TEXT[] ARRAY[]::TEXT[]
@@ -291,12 +293,45 @@ SELECT
p."evolutionInformation", p."evolutionInformation",
p."catchInformation", p."catchInformation",
p."createdAt", p."createdAt",
p."updatedAt" p."updatedAt",
CASE
WHEN p.form IS NULL OR lower(p.form) = 'male' THEN 0
WHEN lower(p.form) = 'female' THEN 1
WHEN lower(p.form) LIKE '%alolan%'
OR lower(p.form) LIKE '%galarian%'
OR lower(p.form) LIKE '%hisuian%'
OR lower(p.form) LIKE '%paldean%'
THEN 2
ELSE 3
END AS "formSortBucket",
CASE
WHEN lower(p.form) LIKE '%alolan%'
OR lower(p.form) LIKE '%galarian%'
OR lower(p.form) LIKE '%hisuian%'
OR lower(p.form) LIKE '%paldean%'
THEN r."releaseOrder"
ELSE 0
END AS "formSortRegionOrder",
CASE
WHEN lower(p.form) LIKE 'female-%' THEN 1
ELSE 0
END AS "formSortRegionalSub",
COALESCE(lower(p.form), '') AS "formSortLabel",
CASE
WHEN p.pokemon = 'Unown' THEN
CASE
WHEN p.form = '?' THEN 26
WHEN p.form = '!' THEN 27
WHEN length(p.form) = 1 AND ascii(upper(p.form)) BETWEEN 65 AND 90 THEN ascii(upper(p.form)) - 65
ELSE 28
END
ELSE 0
END AS "unownSortOrder"
FROM pokemon p FROM pokemon p
JOIN regions r ON r.id = p."originRegionId" JOIN regions r ON r.id = p."originRegionId"
LEFT JOIN pokemon_origin_games pog ON pog."pokemonId" = p.id LEFT JOIN pokemon_origin_games pog ON pog."pokemonId" = p.id
LEFT JOIN games g ON g.id = pog."gameId" LEFT JOIN games g ON g.id = pog."gameId"
GROUP BY p.id, r.name; GROUP BY p.id, r.name, r."releaseOrder";
GRANT SELECT ON pokedex_entries TO anon, authenticated; GRANT SELECT ON pokedex_entries TO anon, authenticated;
@@ -1,22 +1,24 @@
-- Seed regions, games, pokemon, and origin game mappings. -- Seed regions, games, pokemon, and origin game mappings.
-- Auto-generated from data/csvs/*.csv -- Auto-generated from data/csvs/*.csv
INSERT INTO regions (name) VALUES INSERT INTO regions (name, "releaseOrder") VALUES
('Kanto'), ('Kanto', 1),
('Johto'), ('Johto', 2),
('Hoenn'), ('Hoenn', 3),
('Sinnoh'), ('Orre', 4),
('Unova'), ('Sinnoh', 5),
('Galar'), ('Ranch', 6),
('Alola'), ('Unova', 7),
('Kalos'), ('Kalos', 8),
('Hisui'), ('Alola', 9),
('Paldea'), ('Go', 10),
('Go'), ('Galar', 11),
('Home'), ('Home', 12),
('Orre'), ('Hisui', 13),
('Ranch') ('Paldea', 14)
ON CONFLICT (name) DO NOTHING; ON CONFLICT (name) DO UPDATE SET
"releaseOrder" = EXCLUDED."releaseOrder",
"updatedAt" = NOW();
INSERT INTO games (id, "displayName", "regionId", region, "releaseYear") VALUES INSERT INTO games (id, "displayName", "regionId", region, "releaseYear") VALUES
('red', 'Red', (SELECT id FROM regions WHERE name = 'Kanto'), 'Kanto', 1996), ('red', 'Red', (SELECT id FROM regions WHERE name = 'Kanto'), 'Kanto', 1996),