Conversation
| 1. `Custom.run` calls `LegacyTeamCard.run(Custom.config)` (where `Custom.config` is a table of per-wiki overrides — see Section 7). | ||
| 2. `Legacy.run` retrieves all stashed args via `Template.retrieveReturnValues('LegacyTeamCard')`. | ||
| 3. First entry = header (from `columns start`); remaining entries = cards (from each `TeamCard`). | ||
| 4. Header is mapped into TP top-level args (`minimumplayers`, `store`, `date`); per-card `import=false` is set on each opponent. |
There was a problem hiding this comment.
Top level date should not be needed (doesn't exist), only opponent level date?
| Wiki templates (on-wiki, edited at deploy): | ||
| Template:TeamCard columns start → invoke Module:Template fn=stashArgs namespace=LegacyTeamCard | ||
| Template:TeamCard → invoke Module:Template fn=stashArgs namespace=LegacyTeamCard | ||
| Template:TeamCard columns end → invoke Module:TeamCard/Legacy/Custom fn=run |
There was a problem hiding this comment.
Technically one more tempalte that we need to care about at deploy. The toogle pplayers button
| 6. The wrapper sets the `team` / `teamRR` global page vars from the first non-TBD card (preserving an old TC behavior that TP's `setPageVars` doesn't cover). | ||
| 7. The collected TP args are passed into a render path equivalent to `TeamParticipantsController.fromTemplate`, which itself calls `TeamParticipantsRepository.save` (storing in a TC-compatible shape) and `TeamParticipantsRepository.setPageVars` (defining the per-team / per-player wiki vars). | ||
|
|
||
| ## Section 1 — Module layout & wiki templates |
There was a problem hiding this comment.
Do we need to care about TeamPartipantGroups (mapping the old Team Card manual groupings into the new one)?
| | `Template:TeamCard columns start` | `<div class="template-box">…<#vardefine>` | `{{#invoke:Lua\|invoke\|module=Template\|fn=stashArgs\|namespace=LegacyTeamCard}}` | | ||
| | `Template:TeamCard` | `{{#invoke:Lua\|invoke\|module=TeamCard\|fn=draw\|...}}` | `{{#invoke:Lua\|invoke\|module=Template\|fn=stashArgs\|namespace=LegacyTeamCard}}` | |
There was a problem hiding this comment.
Just FYI, may need to insert an empty div or something similiar inorder for MW parser to be happy, otherwise it may insert
for each call
There was a problem hiding this comment.
yes you need to insert empty div for mw not to add a ton of linebreaks
| | TC header param | TP top-level arg | Notes | | ||
| |---|---|---| | ||
| | `defaultRowNumber` | `minimumplayers` | Closest semantic match. | | ||
| | `disable_storage`/`nostorage` (header-level) | `store = false` (top-level) | Honored only when set on the header, since TP's `store` is top-level. Per-card occurrences are ignored (out-of-scope). | |
There was a problem hiding this comment.
Never set on the heading in TC afaik
|
|
||
| Hardcoded by the wrapper: | ||
| - `import = false` is set **per card** (not at header level — TP reads `import` off each Opponent), so old pages use explicit rosters. | ||
| - `store` defaults to true (TP's default) unless the header disabled storage. TP's `Repository.save` produces records with the same `objectName` shape as old TC and the same legacy participant fields via `Opponent.toLegacyParticipantData`. |
There was a problem hiding this comment.
store doesn't need to be hardcoded tby the wrapper. The existing logic will take care o whther r not it's needed. Hardcoding would force it to store even if SaveLpdb=false from wiki vars.
| Hardcoded by the wrapper: | ||
| - `import = false` is set **per card** (not at header level — TP reads `import` off each Opponent), so old pages use explicit rosters. | ||
| - `store` defaults to true (TP's default) unless the header disabled storage. TP's `Repository.save` produces records with the same `objectName` shape as old TC and the same legacy participant fields via `Opponent.toLegacyParticipantData`. | ||
| - `date` — passed through if set on header, else TP's tournament-date default applies. |
There was a problem hiding this comment.
Don't think that date needs to be set by the wrapper (doesn't exist on this level afik in TC). TP handles fallbacks
| - `store` defaults to true (TP's default) unless the header disabled storage. TP's `Repository.save` produces records with the same `objectName` shape as old TC and the same legacy participant fields via `Opponent.toLegacyParticipantData`. | ||
| - `date` — passed through if set on header, else TP's tournament-date default applies. | ||
|
|
||
| Before invoking the TP render, the wrapper also sets two global page vars from the first non-TBD card (matching old TC behavior): `team` (resolved team name at `tournament_date`) and `teamRR` (redirect-resolved name). TP's `setPageVars` does the per-team `<TeamName>_pN` style vars itself, so those are not duplicated here. |
There was a problem hiding this comment.
What? Is this needed? Not sure
|
|
||
| Before invoking the TP render, the wrapper also sets two global page vars from the first non-TBD card (matching old TC behavior): `team` (resolved team name at `tournament_date`) and `teamRR` (redirect-resolved name). TP's `setPageVars` does the per-team `<TeamName>_pN` style vars itself, so those are not duplicated here. | ||
|
|
||
| If the first stash entry contains a `team` key (i.e. it looks like a card, not a header — defensive case for pages where `columns start` is missing or malformed), treat all entries as cards and synthesize an empty header. |
There was a problem hiding this comment.
Spit out a warning or tracking category if this happens. The "columns end" template might be missing then too
| |---|---|---| | ||
| | `link` (or fallback to `team`) | positional `[1]` (template) | TC's `team` is the display name, `link` is the team template. The wrapper uses `args.link or args.team` for the TP template arg. | | ||
| | `team` (display name) | dropped | TP derives display from the team template; no separate display override. | | ||
| | `team2`/`team3` set | TP `contenders` (list of team templates) | Maps to TP's `contenders` parsing path: opponent becomes TBD with `potentialQualifiers` populated from each team template (`Opponent.readOpponentArgs({type=team, template=…})`). `link2`/`link3` are used as templates if present. | |
There was a problem hiding this comment.
Don't forget about team when using team2, team3 for contenders
| | `image1`/`imagedark1`/`imagesize` | dropped | TP gets logos from team templates. Image override (#7295) was reverted (#7449). | | ||
| | `flag` (header flag) | dropped | No TP equivalent. | |
There was a problem hiding this comment.
| | `image1`/`imagedark1`/`imagesize` | dropped | TP gets logos from team templates. Image override (#7295) was reverted (#7449). | | |
| | `flag` (header flag) | dropped | No TP equivalent. | | |
| | `image1`/`imagedark1`/`imagesize` | dropped | Not relevant, using team templates | | |
| | `flag` (header flag) | dropped | Not relevant | |
| | `notes` | appended to `notes` list as `{text=notes, highlighted=false}` | | | ||
| | `inotes` | appended to `notes` list as `{text=inotes, highlighted=false}` | If both `notes` and `inotes` are set, both entries are added to the TP `notes` list. | |
There was a problem hiding this comment.
The text parameter is wrong I think? The text should be the onctent of the note or inote, not a hardcoded string.
There was a problem hiding this comment.
| | `notes` | appended to `notes` list as `{text=notes, highlighted=false}` | | | |
| | `inotes` | appended to `notes` list as `{text=inotes, highlighted=false}` | If both `notes` and `inotes` are set, both entries are added to the TP `notes` list. | | |
| | `notes` | appended to `notes` list as `{[1] = value, highlighted=false}` | | | |
| | `inotes` | appended to `notes` list as `{[1] = value, highlighted=false}` | If both `notes` and `inotes` are set, both entries are added to the TP `notes` list. | |
It's this right?
| | `pNdnp` (truthy) | `played = false` | `dnp` wins over `played`/`result` if both set. | | ||
| | `pNplayed` / `pNresult` | `played` (boolean) | | |
There was a problem hiding this comment.
Verify functionality when in combination with certain config parameters. They can interact weirdly, especially with, e.g., subs.
| | `c1` (default) | `role = head coach` | First coach is head coach. Override via per-wiki `coachRoles` config (Section 7). | | ||
| | `c2..cN` (default) | `role = coach` | Override via per-wiki `coachRoles` config. | |
There was a problem hiding this comment.
Don't assume this. Any coach without a role should be assumed to be the role "Coach".
|
|
||
| **Coach mapping** (per `cN`, `scN`, `fcN`, `t2cN`, `t3cN`): | ||
|
|
||
| | TC param | TP `Person` field | Notes | |
There was a problem hiding this comment.
I think cNpos needs to be mapped as well
|
|
||
| | Key | Type | Default | Purpose | | ||
| |---|---|---|---| | ||
| | `coachRoles` | `string[]` | `{'head coach', 'coach'}` | Role assigned to `cN` by index — `coachRoles[1]` → `c1`, `coachRoles[2]` → `c2`, with `'coach'` for any further coaches beyond the array length. | |
There was a problem hiding this comment.
Don't think this is needed. Map by cNpos. Default to coach
| | Key | Type | Default | Purpose | | ||
| |---|---|---|---| | ||
| | `coachRoles` | `string[]` | `{'head coach', 'coach'}` | Role assigned to `cN` by index — `coachRoles[1]` → `c1`, `coachRoles[2]` → `c2`, with `'coach'` for any further coaches beyond the array length. | | ||
| | `positionMapping` | `table<string, string>` | `{}` (identity / TP-RoleUtil-only) | Maps TC `pNpos` values to TP `role` values when the wiki uses non-standard position labels (e.g. dota2 might map `1` → `'carry'`). When empty, `pNpos` is passed through as-is and `RoleUtil.readRoleArgs` normalizes it. | |
There was a problem hiding this comment.
Should be normalized later anyway. Probably not needed
| | `playerParamMap` | `table<string, string>` | `{}` | Optional per-wiki rename of TC player suffixes to TP person fields (e.g. `{ ['pNheroes'] = 'extradata.heroes' }`) for wiki-specific input. Empty default; rarely needed. | | ||
| | `coachParamMap` | `table<string, string>` | `{}` | Same shape as `playerParamMap`, applied to `cN`/`scN`/`fcN` etc. | | ||
| | `cardParamMap` | `table<string, string>` | `{}` | Per-wiki rename of TC card-level params to TP opponent fields. | |
There was a problem hiding this comment.
Not sure if theres are needed outside of dota. I think only dota need a forced number mapping
| | `playerParamMap` | `table<string, string>` | `{}` | Optional per-wiki rename of TC player suffixes to TP person fields (e.g. `{ ['pNheroes'] = 'extradata.heroes' }`) for wiki-specific input. Empty default; rarely needed. | | ||
| | `coachParamMap` | `table<string, string>` | `{}` | Same shape as `playerParamMap`, applied to `cN`/`scN`/`fcN` etc. | | ||
| | `cardParamMap` | `table<string, string>` | `{}` | Per-wiki rename of TC card-level params to TP opponent fields. | | ||
|
|
There was a problem hiding this comment.
Missing config for the very important for biz logic property
subdnpdefault
hjpalpha
left a comment
There was a problem hiding this comment.
this wrapper is not applicable for sc, sc2, sg
|
|
||
| ## Out of scope | ||
|
|
||
| - Per-wiki bot-edit work to insert `{{TeamCard columns start}}` / `{{TeamCard columns end}}` around naked `{{TeamCard}}` runs. The wrapper assumes columns markers are always present. |
There was a problem hiding this comment.
maybe a bot run with
"\{\{[bB]ox\s*\|\s*start[^\}]*\}\}\s*\{\{[tT]eamCard" "{{TeamCard columns start}}\n{{TeamCard"
"\{\{[bB]ox\s*\|\s*break[^\}]*\}\}\s*\{\{[tT]eamCard" "{{TeamCard"
"\{\{[tT]eamCard([^\}]*)\}\}\s*\{\{[bB]ox\s*\|\s*end\}\}" "{{TeamCard\1}}\n{{TeamCard columns end}}"
prior?
There was a problem hiding this comment.
note for myself - prep bot run on sc (<2k), sc2 (~300), sg (<100):
pwb replace -lang:starcraft2 -transcludes:TeamCard -regex -summary:"prep for conversion" "\{\{[bB]ox\s*\|\s*start[^\}]*\}\}\s*\{\{[tT]eamCard" "{{TeamList\n|{{TeamCard" "\{\{[bB]ox\s*\|\s*break[^\}]*\}\}\s*\{\{[tT]eamCard" "|{{TeamCard" "\{\{[tT]eamCard([^\}]*)\}\}\s*\{\{[bB]ox\s*\|\s*end\}\}" "|{{TeamCard\1}}\n}}"
allows the wrapper in place apply to be a simple template adjust + purge run
(for subst inner ones need to be converted to use json (with subst) plus the outer one using the conversion wrapper which generates the wiki code)
Summary
docs/superpowers/specs/2026-05-06-teamcard-legacy-wrapper-design.md.How did you test this change?
n/a — spec only, no code changes.