Repository: na-ji/leaderboard
Pull request #776: feat: add Community Member, Expert Navigator & Life of the Party badges
Author: login: sanderDijkxhoorn
Labels: name: released
Created: 2025-04-04T21:09:53Z | Merged: 2025-04-12T14:48:06Z

Integrating #775 

<img width="1010" alt="image" src="https://github.com/user-attachments/assets/20744eb5-26be-4707-b5ea-51e704290cdc" />
<img width="1225" alt="image" src="https://github.com/user-attachments/assets/6c087270-8830-4b4e-9564-a1a58e7a909c" />

  
 Missing FR translation.


Diff:
diff --git a/public/badges/achievements/Badge_83_0_01.webp b/public/badges/achievements/Badge_83_0_01.webp
new file mode 100644
index 00000000..ce81ccef
Binary files /dev/null and b/public/badges/achievements/Badge_83_0_01.webp differ
diff --git a/public/badges/achievements/Badge_83_1_01.webp b/public/badges/achievements/Badge_83_1_01.webp
new file mode 100644
index 00000000..ace4481d
Binary files /dev/null and b/public/badges/achievements/Badge_83_1_01.webp differ
diff --git a/public/badges/achievements/Badge_83_2_01.webp b/public/badges/achievements/Badge_83_2_01.webp
new file mode 100644
index 00000000..3ca3dad7
Binary files /dev/null and b/public/badges/achievements/Badge_83_2_01.webp differ
diff --git a/public/badges/achievements/Badge_83_3_01.webp b/public/badges/achievements/Badge_83_3_01.webp
new file mode 100644
index 00000000..d49ee2cf
Binary files /dev/null and b/public/badges/achievements/Badge_83_3_01.webp differ
diff --git a/public/badges/achievements/Badge_83_4_01.webp b/public/badges/achievements/Badge_83_4_01.webp
new file mode 100644
index 00000000..e6d0c2f4
Binary files /dev/null and b/public/badges/achievements/Badge_83_4_01.webp differ
diff --git a/public/badges/achievements/Badge_85_0_01.webp b/public/badges/achievements/Badge_85_0_01.webp
new file mode 100644
index 00000000..4d374e0b
Binary files /dev/null and b/public/badges/achievements/Badge_85_0_01.webp differ
diff --git a/public/badges/achievements/Badge_85_1_01.webp b/public/badges/achievements/Badge_85_1_01.webp
new file mode 100644
index 00000000..5bba38b6
Binary files /dev/null and b/public/badges/achievements/Badge_85_1_01.webp differ
diff --git a/public/badges/achievements/Badge_85_2_01.webp b/public/badges/achievements/Badge_85_2_01.webp
new file mode 100644
index 00000000..b0d856d2
Binary files /dev/null and b/public/badges/achievements/Badge_85_2_01.webp differ
diff --git a/public/badges/achievements/Badge_85_3_01.webp b/public/badges/achievements/Badge_85_3_01.webp
new file mode 100644
index 00000000..bc111a06
Binary files /dev/null and b/public/badges/achievements/Badge_85_3_01.webp differ
diff --git a/public/badges/achievements/Badge_85_4_01.webp b/public/badges/achievements/Badge_85_4_01.webp
new file mode 100644
index 00000000..3b21c2d8
Binary files /dev/null and b/public/badges/achievements/Badge_85_4_01.webp differ
diff --git a/server/create-schema.ts b/server/create-schema.ts
index 6937ce6f..e64ac0de 100644
--- a/server/create-schema.ts
+++ b/server/create-schema.ts
@@ -1,8 +1,14 @@
-import { addFriendCodeToHistoryTable, addGen9ToHistoryTable, createTrainerHistoryTable } from './database';
+import {
+  addFriendCodeToHistoryTable,
+  addGen9ToHistoryTable,
+  addRouteTeamAmbassadorBadgesToHistoryTable,
+  createTrainerHistoryTable,
+} from './database';
 
 createTrainerHistoryTable()
   .then(addFriendCodeToHistoryTable)
   .then(addGen9ToHistoryTable)
+  .then(addRouteTeamAmbassadorBadgesToHistoryTable)
   .then(() => {
     process.exit(0);
   })
diff --git a/server/database.ts b/server/database.ts
index b0875783..fb009bba 100644
--- a/server/database.ts
+++ b/server/database.ts
@@ -98,8 +98,8 @@ const schemaCreationQuery = `
 
 const schemaUpdateQuery = `
     INSERT ignore 
-    INTO ${config.database.leaderboardDatabase}.pogo_leaderboard_trainer_history (date, rpl, name, team, level, xp, battles_won, last_seen, km_walked, caught_pokemon, friendship_id, friend_code, gbl_rank, gbl_rating, event_badges, stops_spun, evolved, hatched, quests, trades, photobombs, purified, grunts_defeated, gym_battles_won, normal_raids_won, legendary_raids_won, trainings_won, berries_fed, hours_defended, best_friends, best_buddies, giovanni_defeated, mega_evos, collections_done, vivillon, showcase_max_size_first_place, unique_stops_spun, unique_mega_evos, unique_raid_bosses, unique_unown, seven_day_streaks, trade_km, raids_with_friends, caught_at_lure, wayfarer_agreements, trainers_referred, raid_achievements, xl_karps, xs_rats, tiny_pokemon_caught, jumbo_pokemon_caught, pikachu_caught, league_great_won, league_ultra_won, league_master_won, dex_gen1, dex_gen2, dex_gen3, dex_gen4, dex_gen5, dex_gen6, dex_gen7, dex_gen8, dex_gen8a, dex_gen9, caught_normal, caught_fighting, caught_flying, caught_poison, caught_ground, caught_rock, caught_bug, caught_ghost, caught_steel, caught_fire, caught_water, caught_grass, caught_electric, caught_psychic, caught_ice, caught_dragon, caught_dark, caught_fairy)
-    SELECT curdate(), 1440, name, team, level, xp, battles_won, last_seen, km_walked, caught_pokemon, friendship_id, friend_code, gbl_rank, gbl_rating, event_badges, stops_spun, evolved, hatched, quests, trades, photobombs, purified, grunts_defeated, gym_battles_won, normal_raids_won, legendary_raids_won, trainings_won, berries_fed, hours_defended, best_friends, best_buddies, giovanni_defeated, mega_evos, collections_done, vivillon, showcase_max_size_first_place, unique_stops_spun, unique_mega_evos, unique_raid_bosses, unique_unown, seven_day_streaks, trade_km, raids_with_friends, caught_at_lure, wayfarer_agreements, trainers_referred, raid_achievements, xl_karps, xs_rats, tiny_pokemon_caught, jumbo_pokemon_caught, pikachu_caught, league_great_won, league_ultra_won, league_master_won, dex_gen1, dex_gen2, dex_gen3, dex_gen4, dex_gen5, dex_gen6, dex_gen7, dex_gen8, dex_gen8a, dex_gen9, caught_normal, caught_fighting, caught_flying, caught_poison, caught_ground, caught_rock, caught_bug, caught_ghost, caught_steel, caught_fire, caught_water, caught_grass, caught_electric, caught_psychic, caught_ice, caught_dragon, caught_dark, caught_fairy
+    INTO ${config.database.leaderboardDatabase}.pogo_leaderboard_trainer_history (date, rpl, name, team, level, xp, battles_won, last_seen, km_walked, caught_pokemon, friendship_id, friend_code, gbl_rank, gbl_rating, event_badges, stops_spun, evolved, hatched, quests, trades, photobombs, purified, grunts_defeated, gym_battles_won, normal_raids_won, legendary_raids_won, trainings_won, berries_fed, hours_defended, best_friends, best_buddies, giovanni_defeated, mega_evos, collections_done, vivillon, showcase_max_size_first_place, event_check_ins, parties_completed, total_route_play, unique_stops_spun, unique_mega_evos, unique_raid_bosses, unique_unown, seven_day_streaks, trade_km, raids_with_friends, caught_at_lure, wayfarer_agreements, trainers_referred, raid_achievements, xl_karps, xs_rats, tiny_pokemon_caught, jumbo_pokemon_caught, pikachu_caught, league_great_won, league_ultra_won, league_master_won, dex_gen1, dex_gen2, dex_gen3, dex_gen4, dex_gen5, dex_gen6, dex_gen7, dex_gen8, dex_gen8a, dex_gen9, caught_normal, caught_fighting, caught_flying, caught_poison, caught_ground, caught_rock, caught_bug, caught_ghost, caught_steel, caught_fire, caught_water, caught_grass, caught_electric, caught_psychic, caught_ice, caught_dragon, caught_dark, caught_fairy)
+    SELECT curdate(), 1440, name, team, level, xp, battles_won, last_seen, km_walked, caught_pokemon, friendship_id, friend_code, gbl_rank, gbl_rating, event_badges, stops_spun, evolved, hatched, quests, trades, photobombs, purified, grunts_defeated, gym_battles_won, normal_raids_won, legendary_raids_won, trainings_won, berries_fed, hours_defended, best_friends, best_buddies, giovanni_defeated, mega_evos, collections_done, vivillon, showcase_max_size_first_place, event_check_ins, parties_completed, total_route_play, unique_stops_spun, unique_mega_evos, unique_raid_bosses, unique_unown, seven_day_streaks, trade_km, raids_with_friends, caught_at_lure, wayfarer_agreements, trainers_referred, raid_achievements, xl_karps, xs_rats, tiny_pokemon_caught, jumbo_pokemon_caught, pikachu_caught, league_great_won, league_ultra_won, league_master_won, dex_gen1, dex_gen2, dex_gen3, dex_gen4, dex_gen5, dex_gen6, dex_gen7, dex_gen8, dex_gen8a, dex_gen9, caught_normal, caught_fighting, caught_flying, caught_poison, caught_ground, caught_rock, caught_bug, caught_ghost, caught_steel, caught_fire, caught_water, caught_grass, caught_electric, caught_psychic, caught_ice, caught_dragon, caught_dark, caught_fairy
     FROM player
     WHERE name <> ''
       AND friendship_id IS NOT NULL
@@ -207,6 +207,13 @@ const addGen9ToHistoryTableQuery = `
       ADD COLUMN IF NOT EXISTS \`showcase_max_size_first_place\` INT(6)  UNSIGNED DEFAULT NULL AFTER \`vivillon\`;
 `;
 
+const addRouteTeamAmbassadorBadgesToHistoryQuery = `
+  ALTER TABLE ${config.database.leaderboardDatabase}.pogo_leaderboard_trainer_history
+    ADD COLUMN IF NOT EXISTS \`total_route_play\`   INT(6) UNSIGNED DEFAULT NULL AFTER \`showcase_max_size_first_place\`,
+    ADD COLUMN IF NOT EXISTS \`parties_completed\`  INT(6) UNSIGNED DEFAULT NULL AFTER \`showcase_max_size_first_place\`,
+    ADD COLUMN IF NOT EXISTS \`event_check_ins\`    INT(6) UNSIGNED DEFAULT NULL AFTER \`showcase_max_size_first_place\`;
+`;
+
 export const createTrainerHistoryTable = async (): Promise<void> => {
   logger.info('Creating leaderboard table if needed');
   await pool.execute(schemaCreationQuery);
@@ -239,3 +246,12 @@ export const addGen9ToHistoryTable = async (): Promise<void> => {
     logger.warn(error);
   }
 };
+
+export const addRouteTeamAmbassadorBadgesToHistoryTable = async (): Promise<void> => {
+  logger.info('Adding new route play, event check-ins and parties completed badges to history if needed');
+  try {
+    await pool.execute(addRouteTeamAmbassadorBadgesToHistoryQuery);
+  } catch (error) {
+    logger.warn(error);
+  }
+};
diff --git a/server/index.ts b/server/index.ts
index b1c91559..1cfdf57d 100644
--- a/server/index.ts
+++ b/server/index.ts
@@ -3,6 +3,7 @@ import { job } from 'cron';
 import {
   addFriendCodeToHistoryTable,
   addGen9ToHistoryTable,
+  addRouteTeamAmbassadorBadgesToHistoryTable,
   createTrainerHistoryTable,
   updateTrainerHistory,
 } from './database';
@@ -25,6 +26,7 @@ async function bootstrap() {
     await createTrainerHistoryTable();
     await addFriendCodeToHistoryTable();
     await addGen9ToHistoryTable();
+    await addRouteTeamAmbassadorBadgesToHistoryTable();
   } catch (err) {
     logger.fatal(err);
   }
diff --git a/src/features/leaderboard/api/periodLeaderboard.ts b/src/features/leaderboard/api/periodLeaderboard.ts
index f25b5c62..e50e82f2 100644
--- a/src/features/leaderboard/api/periodLeaderboard.ts
+++ b/src/features/leaderboard/api/periodLeaderboard.ts
@@ -39,6 +39,9 @@ const periodLeaderboardQuery = `
          trainer.collections_done - trainer_history.collections_done                     AS collections_done,
          trainer.vivillon - IFNULL(trainer_history.vivillon, 0)                          AS vivillon,
          trainer.showcase_max_size_first_place - IFNULL(trainer_history.showcase_max_size_first_place, 0) AS showcase_max_size_first_place,
+         trainer.event_check_ins - IFNULL(trainer_history.event_check_ins, 0)            AS event_check_ins,
+         trainer.parties_completed - IFNULL(trainer_history.parties_completed, 0)        AS parties_completed,
+         trainer.total_route_play - IFNULL(trainer_history.total_route_play, 0)          AS total_route_play,
          trainer.unique_stops_spun - trainer_history.unique_stops_spun                   AS unique_stops_spun,
          trainer.unique_mega_evos - trainer_history.unique_mega_evos                     AS unique_mega_evos,
          trainer.unique_raid_bosses - trainer_history.unique_raid_bosses                 AS unique_raid_bosses,
diff --git a/src/features/leaderboard/components/columnDefinitions/miscellaneousLeaderboardColumns.ts b/src/features/leaderboard/components/columnDefinitions/miscellaneousLeaderboardColumns.ts
index a95dc0b0..750f5986 100644
--- a/src/features/leaderboard/components/columnDefinitions/miscellaneousLeaderboardColumns.ts
+++ b/src/features/leaderboard/components/columnDefinitions/miscellaneousLeaderboardColumns.ts
@@ -17,6 +17,21 @@ export const miscellaneousLeaderboardColumns: ColumnsType = [
     minWidth: 120,
     type: 'number',
   },
+  {
+    field: 'event_check_ins',
+    minWidth: 120,
+    type: 'number',
+  },
+  {
+    field: 'parties_completed',
+    minWidth: 120,
+    type: 'number',
+  },
+  {
+    field: 'total_route_play',
+    minWidth: 120,
+    type: 'number',
+  },
   {
     field: 'collections_done',
     minWidth: 120,
diff --git a/src/features/leaderboard/lang/columnHeaderTranslations.ts b/src/features/leaderboard/lang/columnHeaderTranslations.ts
index 396dd55a..d14b5f52 100644
--- a/src/features/leaderboard/lang/columnHeaderTranslations.ts
+++ b/src/features/leaderboard/lang/columnHeaderTranslations.ts
@@ -256,6 +256,21 @@ export const columnHeaderTranslations = defineMessages({
     defaultMessage: 'Showcase',
     description: 'Leaderboard showcase column header',
   },
+  event_check_ins: {
+    id: 'leaderboard_header.event_check_ins',
+    defaultMessage: 'Event check-ins',
+    description: 'Leaderboard event check-ins column header',
+  },
+  parties_completed: {
+    id: 'leaderboard_header.parties_completed',
+    defaultMessage: 'Parties completed',
+    description: 'Leaderboard parties completed column header',
+  },
+  total_route_play: {
+    id: 'leaderboard_header.total_route_play',
+    defaultMessage: 'Route play',
+    description: 'Leaderboard route play column header',
+  },
   tiny_pokemon_caught: {
     id: 'leaderboard_header.tiny_pokemon_caught',
     defaultMessage: 'Tiny',
diff --git a/src/features/profile/utils/badgeToAssetId.ts b/src/features/profile/utils/badgeToAssetId.ts
index 1938cb34..16bb2d43 100644
--- a/src/features/profile/utils/badgeToAssetId.ts
+++ b/src/features/profile/utils/badgeToAssetId.ts
@@ -53,6 +53,9 @@ export const badgeToAssetId: Partial<Record<Badge, string | number>> = {
   [Badge.COLLECTIONS_DONE]: '1002',
   [Badge.VIVILLON]: 1003,
   [Badge.SHOWCASE_MAX_SIZE_FIRST_PLACE]: 1004,
+  [Badge.EVENT_CHECK_INS]: 85,
+  [Badge.PARTIES_COMPLETED]: 83,
+  [Badge.TOTAL_ROUTE_PLAY]: 77,
   [Badge.CAUGHT_NORMAL]: 18,
   [Badge.CAUGHT_FIGHTING]: 19,
   [Badge.CAUGHT_FLYING]: 20,
diff --git a/src/features/profile/utils/badgeToTierRequirements.ts b/src/features/profile/utils/badgeToTierRequirements.ts
index 01e4336d..58966689 100644
--- a/src/features/profile/utils/badgeToTierRequirements.ts
+++ b/src/features/profile/utils/badgeToTierRequirements.ts
@@ -53,6 +53,9 @@ export const badgeToTierRequirements: Record<Badge, [number, number, number, num
   [Badge.COLLECTIONS_DONE]: [0, 0, 0, 0],
   [Badge.VIVILLON]: [1, 5, 10, 18],
   [Badge.SHOWCASE_MAX_SIZE_FIRST_PLACE]: [1, 10, 50, 100],
+  [Badge.EVENT_CHECK_INS]: [1, 20, 50, 100],
+  [Badge.PARTIES_COMPLETED]: [10, 50, 100, 200],
+  [Badge.TOTAL_ROUTE_PLAY]: [10, 50, 200, 600],
   [Badge.CAUGHT_NORMAL]: [10, 50, 200, 2500],
   [Badge.CAUGHT_FIGHTING]: [10, 50, 200, 2500],
   [Badge.CAUGHT_FLYING]: [10, 50, 200, 2500],
diff --git a/src/features/profile/utils/badgeTranslations.ts b/src/features/profile/utils/badgeTranslations.ts
index 7cd460b5..26c3f1a4 100644
--- a/src/features/profile/utils/badgeTranslations.ts
+++ b/src/features/profile/utils/badgeTranslations.ts
@@ -193,6 +193,21 @@ export const badgeTranslations = defineMessages({
     defaultMessage: 'Showcase Star',
     description: 'Badge SHOWCASE_MAX_SIZE_FIRST_PLACE',
   },
+  [Badge.EVENT_CHECK_INS]: {
+    id: 'badge_event_check_ins',
+    defaultMessage: 'Community Member',
+    description: 'Badge EVENT_CHECK_INS',
+  },
+  [Badge.PARTIES_COMPLETED]: {
+    id: 'badge_parties_completed',
+    defaultMessage: 'Life of the Party',
+    description: 'Badge PARTIES_COMPLETED',
+  },
+  [Badge.TOTAL_ROUTE_PLAY]: {
+    id: 'badge_total_route_play',
+    defaultMessage: 'Expert Navigator',
+    description: 'Badge TOTAL_ROUTE_PLAY',
+  },
   [Badge.PIKACHU_CAUGHT]: {
     id: 'badge_pikachu_caught',
     defaultMessage: 'Pikachu caught',
diff --git a/src/i18n/lang/de.json b/src/i18n/lang/de.json
index 9769ce7e..5fafa195 100644
--- a/src/i18n/lang/de.json
+++ b/src/i18n/lang/de.json
@@ -155,6 +155,18 @@
     "defaultMessage": "Showcase-Star",
     "description": "Badge SHOWCASE_MAX_SIZE_FIRST_PLACE"
   },
+  "badge_event_check_ins": {
+    "defaultMessage": "Community-Mitglied",
+    "description": "Badge EVENT_CHECK_INS"
+  },
+  "badge_parties_completed": {
+    "defaultMessage": "Teamwork",
+    "description": "Badge PARTIES_COMPLETED"
+  },
+  "badge_total_route_play": {
+    "defaultMessage": "Profi-Navigator",
+    "description": "Badge TOTAL_ROUTE_PLAY"
+  },
   "badge_stops_spun": {
     "defaultMessage": "Backpacker",
     "description": "Badge STOPS_SPUN"
diff --git a/src/i18n/lang/en.json b/src/i18n/lang/en.json
index 8326ab56..d442034f 100644
--- a/src/i18n/lang/en.json
+++ b/src/i18n/lang/en.json
@@ -155,6 +155,18 @@
     "defaultMessage": "Showcase Star",
     "description": "Badge SHOWCASE_MAX_SIZE_FIRST_PLACE"
   },
+  "badge_event_check_ins": {
+    "defaultMessage": "Community Member",
+    "description": "Badge EVENT_CHECK_INS"
+  },
+  "badge_parties_completed": {
+    "defaultMessage": "Life of the Party",
+    "description": "Badge PARTIES_COMPLETED"
+  },
+  "badge_total_route_play": {
+    "defaultMessage": "Expert Navigator",
+    "description": "Badge TOTAL_ROUTE_PLAY"
+  },
   "badge_stops_spun": {
     "defaultMessage": "Stops spun",
     "description": "Badge STOPS_SPUN"
diff --git a/src/types/badge.ts b/src/types/badge.ts
index 3ac22de1..495f6790 100644
--- a/src/types/badge.ts
+++ b/src/types/badge.ts
@@ -22,6 +22,9 @@ export enum Badge {
   COLLECTIONS_DONE = 'collections_done',
   VIVILLON = 'vivillon',
   SHOWCASE_MAX_SIZE_FIRST_PLACE = 'showcase_max_size_first_place',
+  EVENT_CHECK_INS = 'event_check_ins',
+  PARTIES_COMPLETED = 'parties_completed',
+  TOTAL_ROUTE_PLAY = 'total_route_play',
   UNIQUE_STOPS_SPUN = 'unique_stops_spun',
   UNIQUE_MEGA_EVOS = 'unique_mega_evos',
   UNIQUE_RAID_BOSSES = 'unique_raid_bosses',
diff --git a/src/types/trainer.ts b/src/types/trainer.ts
index 8e8f05e7..a04178f2 100644
--- a/src/types/trainer.ts
+++ b/src/types/trainer.ts
@@ -34,6 +34,9 @@ export interface Trainer {
   collections_done?: number;
   vivillon?: number;
   showcase_max_size_first_place?: number;
+  event_check_ins?: number;
+  parties_completed?: number;
+  total_route_play?: number;
   unique_stops_spun?: number;
   unique_mega_evos?: number;
   unique_raid_bosses?: number;
diff --git a/src/utils/fixtures.ts b/src/utils/fixtures.ts
index e2046f26..62ed7ef7 100644
--- a/src/utils/fixtures.ts
+++ b/src/utils/fixtures.ts
@@ -48,6 +48,9 @@ export const trainer = {
   jumbo_pokemon_caught: 456,
   vivillon: 15,
   showcase_max_size_first_place: 30,
+  event_check_ins: 32,
+  parties_completed: 39,
+  total_route_play: 239,
   league_great_won: 369,
   league_ultra_won: 337,
   league_master_won: 1025,
diff --git a/trainer.sql b/trainer.sql
index 987d70f9..fa91edc0 100644
--- a/trainer.sql
+++ b/trainer.sql
@@ -34,6 +34,9 @@ CREATE TABLE IF NOT EXISTS `player`
     `collections_done`     smallint(3) UNSIGNED DEFAULT NULL,
     `vivillon`             tinyint(2) UNSIGNED  DEFAULT NULL,
     `showcase_max_size_first_place` int(6) UNSIGNED  DEFAULT NULL,
+    `event_check_ins`      int(6) UNSIGNED      DEFAULT NULL,
+    `parties_completed`    int(6) UNSIGNED      DEFAULT NULL,
+    `total_route_play`     int(6) UNSIGNED      DEFAULT NULL,
     `unique_stops_spun`    int(6) UNSIGNED      DEFAULT NULL,
     `unique_mega_evos`     int(3) UNSIGNED      DEFAULT NULL,
     `unique_raid_bosses`   int(4) UNSIGNED      DEFAULT NULL,


Reviews:
user: login: Fabio1988
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T11:53:28Z
user: login: sanderDijkxhoorn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T12:08:23Z
user: login: Fabio1988
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T12:09:53Z
user: login: Fabio1988
body: Works as expected, thanks :) 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T12:22:53Z
user: login: na-ji
state: APPROVED
author_association: OWNER
submitted_at: 2025-04-12T14:47:41Z

Review comments:
diff_hunk: @@ -207,6 +207,13 @@ const addGen9ToHistoryTableQuery = `
       ADD COLUMN IF NOT EXISTS \`showcase_max_size_first_place\` INT(6)  UNSIGNED DEFAULT NULL AFTER \`vivillon\`;
 `;
 
+const addNewBadgesToHistoryTableQuery = `
path: server/database.ts
user: login: Fabio1988
body: Wondering if we should rename this to be more precise, as we might add another new badges for sure 😄

`addRouteTeamAmbassadorBadgesToHistory`
created_at: 2025-04-11T11:53:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -207,6 +207,13 @@ const addGen9ToHistoryTableQuery = `
       ADD COLUMN IF NOT EXISTS \`showcase_max_size_first_place\` INT(6)  UNSIGNED DEFAULT NULL AFTER \`vivillon\`;
 `;
 
+const addNewBadgesToHistoryTableQuery = `
path: server/database.ts
user: login: sanderDijkxhoorn
body: Yes, good idea. I pushed a new commit(s). 
created_at: 2025-04-11T12:08:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -207,6 +207,13 @@ const addGen9ToHistoryTableQuery = `
       ADD COLUMN IF NOT EXISTS \`showcase_max_size_first_place\` INT(6)  UNSIGNED DEFAULT NULL AFTER \`vivillon\`;
 `;
 
+const addNewBadgesToHistoryTableQuery = `
path: server/database.ts
user: login: Fabio1988
body: thanks :) 
created_at: 2025-04-11T12:09:53Z
author_association: CONTRIBUTOR

PR comments:
user: login: Fabio1988
created_at: 2025-04-11T11:54:08Z
body: Thanks a lot for the contribution :)
author_association: CONTRIBUTOR
user: login: relativeci[bot]
created_at: 2025-04-12T14:02:05Z
body: ## [#1240](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr?utm_source=github&utm_campaign=pr-report&utm_content=title "Bundle Size — 2.01MiB (0%).") Bundle Size — 2.01MiB (0%).
d2b93e0(current) vs 391d691 **[main#1239](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1239-yr7j7K2Nb8XrUiKmM9WE?utm_source=github&utm_content=report-header&utm_campaign=pr-report "View baseline job report")**(baseline)
<details>
<summary><strong>Bundle metrics</strong>&nbsp;&nbsp;<code>no changes</code></summary>
<br>


|            |       Current<br />[#1240](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr?utm_source=github&utm_content=summary&utm_campaign=pr-report "View bundle analysis report") |      Baseline<br />[#1239](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1239-yr7j7K2Nb8XrUiKmM9WE?utm_source=github&utm_content=summary&utm_campaign=pr-report "View baseline bundle analysis report") |
|:--|--:|--:|
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[Initial JS](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/assets?ba=%7B%22filters%22%3A%22et.entrypoint-0_et.initial-1_et.chunk-0_et.asset-0_ft.CSS-0_ft.JS-1_ft.IMG-0_ft.MEDIA-0_ft.FONT-0_ft.HTML-0_ft.OTHER-0%22%7D&utm_source=github&utm_content=summary&utm_campaign=pr-report "View initial JS assets")</span> | <span>`1.87MiB`</span> | <span>`1.87MiB`</span> |
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[Initial CSS](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/assets?ba=%7B%22filters%22%3A%22et.entrypoint-0_et.initial-1_et.chunk-0_et.asset-0_ft.CSS-1_ft.JS-0_ft.IMG-0_ft.MEDIA-0_ft.FONT-0_ft.HTML-0_ft.OTHER-0%22%7D&utm_source=github&utm_content=summary&utm_campaign=pr-report "View initial CSS assets")</span> | <span>`53.14KiB`</span> | <span>`53.14KiB`</span> |
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[Cache Invalidation](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/assets?ba=%7B%22filters%22%3A%22changed-1%22%7D&utm_source=github&utm_content=summary&utm_campaign=pr-report "View changed assets")</span> | <span>`0.04%`</span> | <span>`0.04%`</span> |
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[Chunks](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/assets?ba=%7B%22filters%22%3A%22et.entrypoint-0_et.initial-0_et.chunk-1_et.asset-0%22%7D&utm_source=github&utm_content=summary&utm_campaign=pr-report "View chunks")</span> | <span>`15`</span> | <span>`15`</span> |
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[Assets](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/assets?ba=%7B%22filters%22%3A%22changed-0%22%7D&utm_source=github&utm_content=summary&utm_campaign=pr-report "View assets")</span> | <span>`24`</span> | <span>`24`</span> |
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[Modules](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/modules?bm=%7B%22metric%22%3A%22totalSize%22%2C%22filters%22%3A%22changed-0%22%7D&utm_source=github&utm_content=summary&utm_campaign=pr-report "View modules")</span> | <span>`626`</span> | <span>`626`</span> |
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[Duplicate Modules](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/modules?bm=%7B%22metric%22%3A%22duplicateSize%22%2C%22filters%22%3A%22changed-0_md-1%22%7D&utm_source=github&utm_content=summary&utm_campaign=pr-report "View duplicate modules")</span> | <span>`2`</span> | <span>`2`</span> |
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[Duplicate Code](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/modules?bm=%7B%22metric%22%3A%22duplicateSize%22%2C%22filters%22%3A%22changed-0_md-1%22%7D&utm_source=github&utm_content=summary&utm_campaign=pr-report "View duplicate modules")</span> | <span>`0.02%`</span> | <span>`0.02%`</span> |
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[Packages](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/packages?bp=%7B%22filters%22%3A%22changed-0%22%7D&utm_source=github&utm_content=summary&utm_campaign=pr-report "View packages")</span> | <span>`27`</span> | <span>`27`</span> |
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[Duplicate Packages](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/packages?bp=%7B%22filters%22%3A%22duplicate-1%22%7D&utm_source=github&utm_content=summary&utm_campaign=pr-report "View duplicate packages")</span> | <span>`0`</span> | <span>`0`</span> |
</details>


<details>
<summary><strong>Bundle size by type</strong>&nbsp;&nbsp;<code>no changes</code></summary>
<br>


|            |       Current<br />[#1240](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr?utm_source=github&utm_content=totals&utm_campaign=pr-report "View bundle analysis report") |      Baseline<br />[#1239](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1239-yr7j7K2Nb8XrUiKmM9WE?utm_source=github&utm_content=totals&utm_campaign=pr-report "View baseline bundle analysis report") |
|:--|--:|--:|
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[JS](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/assets?ba=%7B%22filters%22%3A%22ft.CSS-0_ft.JS-1_ft.IMG-0_ft.MEDIA-0_ft.FONT-0_ft.HTML-0_ft.OTHER-0%22%7D&utm_source=github&utm_content=totals&utm_campaign=pr-report "View JS assets")</span> | <span>`1.96MiB`</span> | <span>`1.96MiB`</span> |
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[CSS](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/assets?ba=%7B%22filters%22%3A%22ft.CSS-1_ft.JS-0_ft.IMG-0_ft.MEDIA-0_ft.FONT-0_ft.HTML-0_ft.OTHER-0%22%7D&utm_source=github&utm_content=totals&utm_campaign=pr-report "View CSS assets")</span> | <span>`53.14KiB`</span> | <span>`53.14KiB`</span> |
| <span><img src="https://raw.githubusercontent.com/relative-ci/relative-ci-github-app-assets/v0.0.4/reports/circle-gray.svg?sanitize=true" width="8" alt="No change" align="center">&nbsp;&nbsp;[Other](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr/assets?ba=%7B%22filters%22%3A%22ft.CSS-0_ft.JS-0_ft.IMG-0_ft.MEDIA-0_ft.FONT-0_ft.HTML-0_ft.OTHER-1%22%7D&utm_source=github&utm_content=totals&utm_campaign=pr-report "View Other assets")</span> | <span>`1.97KiB`</span> | <span>`1.97KiB`</span> |
</details>


[Bundle analysis report](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/jobs/1240-WvOHxMrf1r1usJ8GEsYr?utm_source=github&utm_content=report-footer&utm_campaign=pr-report) [Branch **main**](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE/tree/main?utm_source=github&utm_content=report-footer&utm_campaign=pr-report) [Project dashboard](https://app.relative-ci.com/projects/UEtAHtbLSninBQKuz5nE?utm_source=github&utm_content=report-footer&utm_campaign=pr-report)---<sup>Generated by [RelativeCI](https://relative-ci.com/?utm_source=github&utm_content=report-footer&utm_campaign=pr-report) [Documentation](https://relative-ci.com/documentation?utm_source=github&utm_content=report-footer&utm_campaign=pr-report) [Report issue](https://github.com/relative-ci/roadmap/issues)</sup>
<!--RELATIVE_CI_PROJECT_NAME="leaderboard"-->
author_association: NONE
user: login: na-ji
created_at: 2025-04-12T14:48:03Z
body: Thanks!
author_association: OWNER
user: login: na-ji
created_at: 2025-04-12T14:52:09Z
body: :tada: This PR is included in version 7.3.0 :tada:

The release is available on [GitHub release](https://github.com/na-ji/leaderboard/releases/tag/v7.3.0)

Your **[semantic-release](https://github.com/semantic-release/semantic-release)** bot :package::rocket:
author_association: OWNER