Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Conversation

@smallst
Copy link
Contributor

@smallst smallst commented Dec 12, 2025

fix ENG-2164

Summary by CodeRabbit

  • New Features

    • New direct tournament play route for tournament links.
    • Clan/tournament links are normalized/converted for tournament access.
    • Tournament context (tid/mixed id) now flows through play, spectate, and leaderboard flows.
  • UI

    • Added "Anonymize Tournament" option in tournament settings/forms.
    • Leaderboards and tournament views now honor tournament state (including ended) for correct ranking and display logic.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 12, 2025

Walkthrough

Adds an encrypted mixed-ID tournament flow: new route /play/tournament/:levelID/:mixedID, a public tournamentMixedIdHelper (encrypt/decrypt/convertUrl), schema/UI changes to surface anonymous, and multiple view/template updates to propagate tournament context and tournamentState into leaderboard and play/spectate plumbing.

Changes

Cohort / File(s) Summary
Routing
app/core/Router.js
Added route play/tournament/:levelID/:mixedIDLadderView
Core utility
app/core/utils.js
New exported tournamentMixedIdHelper with secret, hexToBytes/bytesToHex, encrypt/decrypt, and convertUrl; minor optional-chaining refactor for showOzaria
Schema
app/schemas/models/tournament.schema.js
Added boolean anonymous property to TournamentSchema
Templates using tournament links
app/templates/clans/clan-details.pug, app/templates/courses/tournament-tile-mixin.pug, app/templates/play/tournament_home.pug, app/templates/play/ladder/my_matches_tab.pug
Precompute and use converted tournament URLs via tournamentHelper.convertUrl; conditionally append tournament query where applicable
View helper wiring
app/views/clans/ClanDetailsView.js, app/views/courses/CoursesView.js, app/views/courses/TournamentsListModal.js, app/views/ladder/MainTournamentView.js
Initialize this.tournamentHelper = utils.tournamentMixedIdHelper for template/view access
Landing / Page URL transforms
app/views/landing-pages/league-v2/components/GlobalRankings.vue, app/views/landing-pages/league/PageLeagueGlobal.vue
Import and apply tournamentMixedIdHelper.convertUrl() for arena URLs when clan + tournament selected
Ladder panels & leaderboard wiring
app/views/ladder/components/LadderPanel.vue, app/views/ladder/components/Leaderboard.vue, app/views/ladder/components/Leaderboard.js
Use helper to convert clan/tournament ladder URLs; add tournament prop and computed tournamentId; thread tournamentState into leaderboard data
Ladder view & tab logic
app/views/ladder/LadderView.js, app/views/ladder/LadderTabView.js, app/views/ladder/LadderPlayModal.js, app/views/ladder/MyMatchesTabView.js
Parse mixed ID from /play/tournament/… path, decrypt to obtain clanId/tournamentId, set leagueType to clan, propagate tournamentId and tournamentState into TournamentLeaderboard / LeaderboardData; branch on tournamentState === 'ended'
Tournament edit UI
app/views/ladder/components/EditTournamentModal.vue
Renamed template binding anonymizeanonymous (v-model/id/label)
Play / level / spectate plumbing
app/views/play/level/ControlBarView.coffee, app/views/play/level/modal/HeroVictoryModal.js, app/views/play/SpectateView.js, app/views/play/level/PlayLevelView.coffee, app/lib/LevelLoader.coffee
Thread tournament identifier (query tournament / tid) into URLs and LevelLoader via new tId option; convert ladder URLs via helper when appropriate
Class links (Ozaria)
ozaria/site/components/teacher-dashboard/BaseMyClasses/components/ClassLinksComponent.vue
Added tournamentUrl(levelId, tournament) method using utils.tournamentMixedIdHelper.convertUrl() and updated anchor hrefs
Misc templates/views
app/views/courses/TournamentsListModal.js, app/views/ladder/MainTournamentView.js, app/views/clans/ClanDetailsView.js
Wire tournament helper onto view instances for template access

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser
    participant Router as CocoRouter
    participant Utils as tournamentMixedIdHelper
    participant LadderView
    participant TournamentLB as TournamentLeaderboard

    User->>Browser: Click converted tournament ladder link
    Browser->>Router: GET /play/tournament/:levelID/:mixedID
    Router->>LadderView: instantiate(levelID, mixedID)
    LadderView->>Utils: decrypt(mixedID)
    Utils-->>LadderView: { clanId, tournamentId }
    LadderView->>TournamentLB: new TournamentLeaderboard({ league: clanId, tournament: tournamentId, tournamentState })
    TournamentLB->>Browser: fetch leaderboard API (tournament or level)
    Browser-->>TournamentLB: leaderboard response
    TournamentLB-->>LadderView: render data
    LadderView-->>Browser: render ladder page
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Areas to focus:

  • app/core/utils.js — verify bit/byte operations, XOR correctness, hex encoding/decoding, and URL-safety.
  • app/views/ladder/LadderView.js & app/views/ladder/LadderTabView.js — mixed-ID parsing, fallbacks, and correct tournamentState propagation.
  • Leaderboard components (Leaderboard.js, Leaderboard.vue) — ensure data-shape compatibility between tournament vs non-tournament paths.
  • Level/play/spectate plumbing (LevelLoader, Play/Spectate views) — confirm tId is consistently passed and query names match server expectations.

Possibly related PRs

Suggested reviewers

  • mrfinch

Poem

🐰 I hid the keys inside a hop,

Mixed IDs stitched — no need to stop.
XOR and hex, a secret song,
Clans and ladders hop along.
A rabbit cheers: the links belong.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Yuqiang/anonymouse in tournament' is vague and does not clearly convey the main changes. It appears to reference the developer's branch name rather than describing what the PR accomplishes. Use a descriptive title that summarizes the main change, such as 'Add tournament anonymization and mixed ID URL routing' or 'Implement tournament anonymization and encrypted ID handling'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch yuqiang/anonymouse-in-tournament

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bbdbf22 and 4e10f53.

📒 Files selected for processing (6)
  • app/core/Router.js (1 hunks)
  • app/core/utils.js (3 hunks)
  • app/lib/LevelLoader.coffee (3 hunks)
  • app/views/courses/CoursesView.js (1 hunks)
  • app/views/ladder/LadderView.js (2 hunks)
  • app/views/landing-pages/league/PageLeagueGlobal.vue (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • app/core/Router.js
  • app/views/courses/CoursesView.js
  • app/lib/LevelLoader.coffee
  • app/views/landing-pages/league/PageLeagueGlobal.vue
  • app/views/ladder/LadderView.js
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: mrfinch
Repo: codecombat/codecombat PR: 8170
File: app/templates/courses/tournament-tile-mixin.pug:14-16
Timestamp: 2025-12-15T10:29:04.692Z
Learning: In CodeCombat repository, tournamentHelper (utils.tournamentMixedIdHelper) should be initialized universally in all views that render tournament-related templates, not conditionally based on utils.isCodeCombat, to prevent runtime errors in non-CodeCombat deployments.
📚 Learning: 2025-12-15T10:29:04.692Z
Learnt from: mrfinch
Repo: codecombat/codecombat PR: 8170
File: app/templates/courses/tournament-tile-mixin.pug:14-16
Timestamp: 2025-12-15T10:29:04.692Z
Learning: In CodeCombat repository, tournamentHelper (utils.tournamentMixedIdHelper) should be initialized universally in all views that render tournament-related templates, not conditionally based on utils.isCodeCombat, to prevent runtime errors in non-CodeCombat deployments.

Applied to files:

  • app/core/utils.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: ESLint CI
  • GitHub Check: Node.js CI (20.19.2)
🔇 Additional comments (3)
app/core/utils.js (3)

22-22: LGTM - Optional chaining addresses the previous review concern.

The use of window?.location?.pathname?.includes('ozaria') safely guards against undefined window in non-browser environments (Node.js tests, SSR).


1806-1849: Validation improvements look good.

The input validation in hexToBytes, encrypt, and decrypt along with the modulo fix for XOR operations (keyBytes[i % keyBytes.length]) properly address the concerns from the previous review. The helper is now robust against malformed inputs.


2029-2029: Export is correct.

The tournamentMixedIdHelper is properly added to module.exports for use across the codebase.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • ENG-2164: Authentication required, not authenticated - You need to authenticate to access this operation.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
app/views/ladder/components/Leaderboard.js (2)

227-257: Add bounds checks before dereferencing leaderboard rows (ended path especially).

leaderboards[lkey][+rank] can be out-of-range (bad UI event payload / race during refresh), and ended path expects levelSession to exist. Suggest:

- this.spectateTargets.humans = leaderboards[lkey][+rank].get('levelSession');
+ const row0 = leaderboards[lkey]?.[+rank]
+ if (!row0) return
+ this.spectateTargets.humans = row0.get('levelSession')

(similar for ogres and non-ended _id branch).


259-276: Admin “click player name” modal: ensure sessionId exists before fetching.

If an ended-tournament row is missing levelSession, new LevelSession({ _id: sessionId }) will fetch /db/level.session/undefined-like URLs. Quick guard:

 const sessionId = this.tournamentState === 'ended' ? leaderboards[id].get('levelSession') : leaderboards[id].get('_id')
+if (!sessionId) return
app/views/ladder/LadderTabView.js (1)

462-488: Guard invariant: tournamentState === 'ended' requires tournamentId.

Without this, ended-state fetches can hit /db/tournament/undefined/.... Suggest:

 constructor (level, team, session, limit, league, tournamentId, ageBracket, myTournamentSubmission, tournamentState) {
   super()
   ...
   this.tournamentId = tournamentId
   this.tournamentState = tournamentState
+  if (this.tournamentState === 'ended' && !this.tournamentId) {
+    throw new Error('tournamentId is required when tournamentState is ended')
+  }
   ...
 }
🧹 Nitpick comments (1)
app/views/ladder/components/Leaderboard.js (1)

36-78: Good propagation of tournamentState; consider defaulting to avoid accidental “not ended”.

If options.tournamentState is missing, the view falls into the non-ended path (likely fine), but it may be safer to default explicitly:

-({ league: this.league, tournament: this.tournament, tournamentState: this.tournamentState, leagueType: this.leagueType, course: this.course } = options)
+({ league: this.league, tournament: this.tournament, tournamentState: this.tournamentState = null, leagueType: this.leagueType, course: this.course } = options)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8150651 and c222167.

📒 Files selected for processing (20)
  • app/core/Router.js (1 hunks)
  • app/core/utils.js (3 hunks)
  • app/schemas/models/tournament.schema.js (1 hunks)
  • app/templates/clans/clan-details.pug (1 hunks)
  • app/templates/courses/tournament-tile-mixin.pug (1 hunks)
  • app/templates/play/tournament_home.pug (1 hunks)
  • app/views/clans/ClanDetailsView.js (1 hunks)
  • app/views/courses/CoursesView.js (1 hunks)
  • app/views/courses/TournamentsListModal.js (2 hunks)
  • app/views/ladder/LadderTabView.js (6 hunks)
  • app/views/ladder/LadderView.js (2 hunks)
  • app/views/ladder/MainTournamentView.js (2 hunks)
  • app/views/ladder/components/EditTournamentModal.vue (1 hunks)
  • app/views/ladder/components/LadderPanel.vue (2 hunks)
  • app/views/ladder/components/Leaderboard.js (6 hunks)
  • app/views/landing-pages/league-v2/components/GlobalRankings.vue (2 hunks)
  • app/views/landing-pages/league/PageLeagueGlobal.vue (5 hunks)
  • app/views/play/level/ControlBarView.coffee (1 hunks)
  • app/views/play/level/modal/HeroVictoryModal.js (1 hunks)
  • ozaria/site/components/teacher-dashboard/BaseMyClasses/components/ClassLinksComponent.vue (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
app/views/clans/ClanDetailsView.js (2)
app/views/ladder/LadderView.js (2)
  • utils (24-24)
  • utils (78-78)
app/core/Router.js (1)
  • utils (34-34)
app/views/courses/TournamentsListModal.js (1)
app/views/ladder/LadderView.js (6)
  • utils (24-24)
  • utils (78-78)
  • require (20-20)
  • require (21-21)
  • require (25-25)
  • require (26-26)
app/views/ladder/LadderView.js (1)
app/core/utils.js (2)
  • clanId (1847-1847)
  • tournamentId (1848-1848)
🪛 Gitleaks (8.30.0)
app/core/utils.js

[high] 1807-1807: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: ESLint CI
  • GitHub Check: Node.js CI (20.19.2)
🔇 Additional comments (16)
app/schemas/models/tournament.schema.js (1)

43-43: LGTM!

The addition of the anonymous field to the tournament schema is straightforward and correctly structured. The field is appropriately optional and includes clear title and description metadata.

app/core/Router.js (1)

369-369: LGTM!

The new tournament route with mixed ID parameter is correctly added and follows the established routing pattern. The route integrates well with the existing ladder routes.

app/views/clans/ClanDetailsView.js (1)

73-73: LGTM!

The initialization of tournamentHelper is correctly placed in the constructor and follows the pattern used consistently across other views in this PR.

app/views/courses/TournamentsListModal.js (1)

13-13: LGTM!

The import and initialization of tournamentHelper are correctly implemented and follow the established pattern across the codebase.

Also applies to: 29-29

app/templates/play/tournament_home.pug (1)

25-28: LGTM!

The URL transformation using tournamentHelper.convertUrl is correctly implemented. The change properly computes the tournament URL and applies it to the anchor element.

app/views/ladder/MainTournamentView.js (1)

21-21: LGTM!

The import and initialization of tournamentHelper follow the established pattern and are correctly placed in the constructor.

Also applies to: 72-72

app/views/ladder/components/LadderPanel.vue (1)

89-89: LGTM!

The import of utils and the conditional application of convertUrl are correctly implemented. The logic appropriately applies URL transformation only when both clan and tournament context exist, which aligns with the mixed ID obfuscation feature.

Also applies to: 154-167

app/views/courses/CoursesView.js (1)

136-136: LGTM!

The initialization of tournamentHelper is appropriately scoped to CodeCombat only and correctly placed within the existing tournament-related initialization block.

app/views/play/level/modal/HeroVictoryModal.js (1)

529-531: LGTM! Tournament URL conversion is correctly applied.

The URL transformation logic is sound: the tournament query parameter is appended first, then the URL is converted via tournamentMixedIdHelper.convertUrl(), and finally the fragment identifier is added. This ensures the conversion operates on the complete tournament URL.

app/views/ladder/components/EditTournamentModal.vue (1)

122-127: LGTM! Field rename is consistent.

The rename from anonymize to anonymous is applied consistently across the id attribute, v-model binding, and label's for attribute. This aligns with the tournament schema change.

ozaria/site/components/teacher-dashboard/BaseMyClasses/components/ClassLinksComponent.vue (1)

932-935: LGTM! Tournament URL generation is correctly implemented.

The tournamentUrl method properly encapsulates the URL construction and conversion logic using utils.tournamentMixedIdHelper.convertUrl(). Good separation of concerns.

app/views/landing-pages/league-v2/components/GlobalRankings.vue (1)

137-139: LGTM! Correct usage of tournament URL helper.

The URL conversion is correctly applied using tournamentMixedIdHelper.convertUrl(url) when both clan and tournament are present.

app/views/play/level/ControlBarView.coffee (1)

146-155: The encrypt/decrypt implementation is properly implemented but uses obfuscation, not cryptographic encryption.

The code correctly implements a symmetric encrypt/decrypt pair using XOR with a hardcoded secret key:

  • ControlBarView.coffee line 155 calls encrypt(leagueID, tournamentId) and passes the result to homeViewArgs
  • LadderView.js line 78 calls decrypt(mixedID) to recover clanId and tournamentId
  • Router.js line 369 correctly maps the /play/tournament/:levelID/:mixedID route to LadderView

The approach is not cryptographic encryption but client-side obfuscation (XOR with hardcoded key exposed in source). This is acceptable for the use case since this is for URL structuring and view argument passing, not authentication or sensitive data protection. The implementation is correct and consistent throughout the flow.

app/core/utils.js (1)

1888-2017: Exporting tournamentMixedIdHelper is fine—verify it’s not used as a real secret.

Given the helper is exported broadly, ensure downstream code treats this strictly as URL obfuscation (not access control), and that server endpoints still enforce authorization based on the resolved clan/tournament IDs.

app/views/ladder/components/Leaderboard.js (1)

175-212: Ended vs non-ended row mapping looks consistent.

The switched branching to this.tournamentState === 'ended' matches the different row shapes (wins/losses/win-rate vs score/when).

app/views/ladder/LadderTabView.js (1)

490-558: Ended-state branching for collections/URLs is coherent.

Switching to TournamentLeaderboardCollection and the tournament rankings endpoints when tournamentState === 'ended' aligns the data model with the UI changes.

app/core/utils.js Outdated Show resolved Hide resolved
app/core/utils.js Show resolved Hide resolved
app/views/ladder/LadderView.js Show resolved Hide resolved
app/views/ladder/LadderView.js Show resolved Hide resolved
Copy link
Contributor

@mrfinch mrfinch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also resove AI bot comments?

})
}

const tournamentMixedIdHelper = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you explain how this is secure? I don't understand how encrypt / decrpyt function present in client can help.

Where did u get the logic from? Can you put a reference to it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not for secure but for obfuscation

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
app/views/ladder/LadderView.js (2)

68-82: Handle invalid mixedID safely to prevent view crashes.

The utils.tournamentMixedIdHelper.decrypt(mixedID) call on line 78 can throw or return invalid data when given malformed input. Wrap the decrypt operation in a try/catch block to handle errors gracefully:

 if (currentPath.includes('/play/tournament/')) {
   const mixedID = leagueTypeOrMixedId
-  const { clanId, tournamentId } = utils.tournamentMixedIdHelper.decrypt(mixedID)
-  this.leagueType = 'clan'
-  this.leagueID = clanId
-  this.tournamentId = tournamentId
+  try {
+    const { clanId, tournamentId } = utils.tournamentMixedIdHelper.decrypt(mixedID)
+    this.leagueType = 'clan'
+    this.leagueID = clanId
+    this.tournamentId = tournamentId
+  } catch (e) {
+    console.warn('Invalid tournament mixedID:', mixedID, e)
+    // Fall back to treating leagueTypeOrMixedId as leagueType
+  }
 }

329-335: Use this.leagueType instead of hardcoding 'clan' for ended tournaments.

Line 333 hardcodes leagueType: 'clan' even though this.leagueType is available and may be 'course' for course-based tournaments. The non-ended branches (lines 342) correctly pass this.leagueType. Use the instance property to ensure correct behavior:

 this.insertSubView(this.ladderTab = new TournamentLeaderboard({
   league: this.league,
   tournament: this.tournamentId,
   tournamentState: 'ended',
-  leagueType: 'clan',
+  leagueType: this.leagueType,
   myTournamentSubmission: this.myTournamentSubmission,
 }, this.level, this.sessions))
🧹 Nitpick comments (2)
app/views/play/level/PlayLevelView.coffee (1)

147-147: Consider validating the tournament parameter.

The tournament query parameter is read without validation. While the main encoding concern is in LevelLoader (see comments on app/lib/LevelLoader.coffee), consider adding basic validation here to catch malformed values early.

app/views/play/SpectateView.js (1)

86-86: Query parameter naming inconsistency across views.

SpectateView reads the tid query parameter, while PlayLevelView (line 147) reads tournament. Both pass the value as tId to LevelLoader. If this naming difference is intentional (e.g., different URL conventions for spectate vs play modes), consider documenting it. Otherwise, standardizing to a single parameter name would improve consistency.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c222167 and bbdbf22.

📒 Files selected for processing (10)
  • app/lib/LevelLoader.coffee (3 hunks)
  • app/templates/play/ladder/my_matches_tab.pug (2 hunks)
  • app/views/ladder/LadderPlayModal.js (1 hunks)
  • app/views/ladder/LadderView.js (2 hunks)
  • app/views/ladder/MyMatchesTabView.js (1 hunks)
  • app/views/ladder/components/Leaderboard.js (7 hunks)
  • app/views/ladder/components/Leaderboard.vue (3 hunks)
  • app/views/play/SpectateView.js (2 hunks)
  • app/views/play/level/ControlBarView.coffee (1 hunks)
  • app/views/play/level/PlayLevelView.coffee (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/views/play/level/ControlBarView.coffee
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: mrfinch
Repo: codecombat/codecombat PR: 8170
File: app/templates/courses/tournament-tile-mixin.pug:14-16
Timestamp: 2025-12-15T10:29:04.692Z
Learning: In CodeCombat repository, tournamentHelper (utils.tournamentMixedIdHelper) should be initialized universally in all views that render tournament-related templates, not conditionally based on utils.isCodeCombat, to prevent runtime errors in non-CodeCombat deployments.
📚 Learning: 2025-12-15T10:29:04.692Z
Learnt from: mrfinch
Repo: codecombat/codecombat PR: 8170
File: app/templates/courses/tournament-tile-mixin.pug:14-16
Timestamp: 2025-12-15T10:29:04.692Z
Learning: In CodeCombat repository, tournamentHelper (utils.tournamentMixedIdHelper) should be initialized universally in all views that render tournament-related templates, not conditionally based on utils.isCodeCombat, to prevent runtime errors in non-CodeCombat deployments.

Applied to files:

  • app/views/play/level/PlayLevelView.coffee
  • app/views/ladder/components/Leaderboard.vue
  • app/views/ladder/LadderView.js
📚 Learning: 2025-12-15T10:28:56.606Z
Learnt from: mrfinch
Repo: codecombat/codecombat PR: 8170
File: app/templates/courses/tournament-tile-mixin.pug:14-16
Timestamp: 2025-12-15T10:28:56.606Z
Learning: In CodeCombat, ensure tournamentHelper (utils.tournamentMixedIdHelper) is initialized in all views that render tournament-related templates, not only when utils.isCodeCombat is true. This prevents runtime errors in non-CodeCombat deployments. Apply this change to all pug templates that render tournament components (e.g., tournament tiles, lists) under app/templates. Verify by scanning for initialization points and confirm no conditional bypasses affect deployment.

Applied to files:

  • app/templates/play/ladder/my_matches_tab.pug
🧬 Code graph analysis (1)
app/views/ladder/LadderView.js (1)
app/core/utils.js (2)
  • clanId (1847-1847)
  • tournamentId (1848-1848)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: ESLint CI
  • GitHub Check: Node.js CI (20.19.2)
🔇 Additional comments (14)
app/views/ladder/components/Leaderboard.vue (3)

50-53: LGTM: Tournament prop definition is correct.

The new tournament prop follows Vue conventions and integrates cleanly with the existing props structure.


63-68: LGTM: Clean computed property implementation.

The tournamentId computed property correctly filters tournament context to arena score types, centralizing the conditional logic and keeping URL construction code clean.


248-250: LGTM: Tournament parameter correctly added to fight URLs.

The conditional URL construction follows the existing pattern for league parameters and appropriately scopes tournament inclusion to clan leagues with arena score types.

app/views/ladder/LadderPlayModal.js (1)

145-147: No issues identified. The code correctly handles tournament as a string ID and league as an object with .id property, which reflects their different data structures in the application.

app/templates/play/ladder/my_matches_tab.pug (2)

59-72: LGTM! Tournament context properly propagated to spectate URLs.

The extraction of tid from view.options.tournament and its conditional inclusion in the spectate URL is correctly implemented and consistent with the existing league parameter handling.


80-87: LGTM! Play URLs correctly handle league types and tournament context.

The conditional logic properly constructs the play URL based on leagueType, appending appropriate parameters for clan leagues, course leagues, and tournaments.

app/views/ladder/components/Leaderboard.js (3)

40-43: LGTM! Constructor properly initializes tournamentState.

The destructuring of tournamentState from options and its assignment to this.tournamentState correctly sets up the state-based branching used throughout the file. The continued use of this.tournament for ID-based checks (like line 43) is appropriate.


62-79: LGTM! TournamentState-based branching improves clarity.

The replacement of this.tournament checks with explicit this.tournamentState comparisons makes the conditional logic clearer. The different data shapes for ended vs. active tournaments (wins/losses/win-rate vs. score/submitDate) are appropriate for their respective use cases.

Also applies to: 181-211


229-229: LGTM! Consistent tournamentState usage throughout.

The tournamentState parameter is correctly passed to LeaderboardData (line 229) and used consistently in conditional logic throughout the file for session ID selection, player ID extraction, and tournament submission handling.

Also applies to: 247-247, 263-263, 269-269, 272-272

app/views/ladder/LadderView.js (2)

340-348: LGTM! Active tournament leaderboard correctly configured.

The TournamentLeaderboard instantiation for active tournaments properly uses this.leagueType (line 342) and passes all necessary context including tournamentState, course, and the updateSpectateList callback.


352-352: LGTM! Tournament context properly passed to MyMatchesTabView.

The tournament parameter is correctly passed to MyMatchesTabView, enabling the template to access view.options.tournament (as seen in the my_matches_tab.pug changes).

app/views/ladder/MyMatchesTabView.js (1)

175-177: Tournament context propagation is properly implemented.

The change correctly adds tournament-specific handling to the user names request. The pattern difference you noted is actually correct: this.options.league is an object (requiring .id accessor) while this.options.tournament receives this.tournamentId, which is already an ID string. Both approaches are consistent with how the options are initialized in LadderView.

app/views/play/level/PlayLevelView.coffee (1)

191-191: LGTM - Parameter correctly passed to LevelLoader.

The tournamentId is appropriately passed as tId to LevelLoader options, enabling tournament-aware session loading.

app/views/play/SpectateView.js (1)

135-135: LGTM - Parameter correctly passed to LevelLoader.

The tId value is appropriately threaded through to LevelLoader for tournament-aware spectate session loading.

app/lib/LevelLoader.coffee Show resolved Hide resolved
app/lib/LevelLoader.coffee Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.