@claudinho/core 0.8.4 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1053,8 +1053,8 @@ declare function parseTeamSlot(team: Team): SlotRef | null;
1053
1053
 
1054
1054
  /**
1055
1055
  * Resolve the bundled topology against merged knockout matches and standings.
1056
- * Group slots project from live standings once a group has started; winner/loser slots
1057
- * require a confirmed FT result on the source match.
1056
+ * Group slots project from live standings once a group has started; confirmed when
1057
+ * the group is fully played. Winner/loser slots require a confirmed FT result.
1058
1058
  */
1059
1059
  declare function buildBracketView(topology: BracketTopology, matches: Match[], tables: GroupStandings[], standingsDegraded: boolean, liveDegraded: boolean, filterStage?: string, lang?: string): BracketView;
1060
1060
 
package/dist/index.js CHANGED
@@ -295,8 +295,8 @@ var ES = {
295
295
  "bracket.invalidStage": "La fase debe ser una de: R32, R16, QF, SF, 3P, F",
296
296
  "bracket.unknownStage": 'Fase desconocida "{stage}". Usa R32, R16, QF, SF, 3P o F.',
297
297
  "bracket.slot.groupWinner": "Ganador del grupo {group}",
298
- "bracket.slot.groupSecond": "2.\xBA del grupo {group}",
299
- "bracket.slot.third": "3.\xBA ({groups})",
298
+ "bracket.slot.groupSecond": "2\xBA del grupo {group}",
299
+ "bracket.slot.third": "3\xBA ({groups})",
300
300
  "bracket.slot.winner": "Ganador {stage} {n}",
301
301
  "bracket.slot.loser": "Perdedor {stage} {n}",
302
302
  "bracket.slot.tbd": "Por definir",
@@ -3353,6 +3353,18 @@ function hasGroupStarted(group, tables) {
3353
3353
  if (!table?.rows.length) return false;
3354
3354
  return table.rows.some((r) => r.played > 0);
3355
3355
  }
3356
+ function matchesPerTeamInGroup(teamCount) {
3357
+ return Math.max(0, teamCount - 1);
3358
+ }
3359
+ function isGroupStandingsComplete(table) {
3360
+ const n = table?.rows.length ?? 0;
3361
+ if (n < 2) return false;
3362
+ const required = matchesPerTeamInGroup(n);
3363
+ return table.rows.every((r) => r.played >= required);
3364
+ }
3365
+ function isGroupComplete(group, tables) {
3366
+ return isGroupStandingsComplete(tables.find((t2) => t2.group === group));
3367
+ }
3356
3368
  function resolveWinner(match) {
3357
3369
  if (!isFinished(match.status)) return void 0;
3358
3370
  if (match.winnerCode) {
@@ -3388,25 +3400,36 @@ function participant(team, status) {
3388
3400
  function tbd(label) {
3389
3401
  return { label, flag: "\u{1F3F3}\uFE0F", status: "tbd" };
3390
3402
  }
3403
+ function confirmedLiveParticipant(team) {
3404
+ if (!team || team.flag === "\u{1F3F3}\uFE0F") return void 0;
3405
+ return participant(team, "confirmed");
3406
+ }
3391
3407
  function winnerLabel(ctx, stage, index) {
3392
3408
  return t(ctx.lang, "bracket.slot.winner", {
3393
3409
  stage: stageLabelI18n(ctx.lang, stage),
3394
3410
  n: String(index)
3395
3411
  });
3396
3412
  }
3397
- function resolveSlot(ref, ctx) {
3413
+ function resolveSlot(ref, ctx, liveTeam) {
3414
+ const liveParticipant = confirmedLiveParticipant(liveTeam);
3398
3415
  switch (ref.kind) {
3399
3416
  case "seed":
3417
+ if (liveParticipant) return liveParticipant;
3400
3418
  return tbd(ref.label);
3401
3419
  case "group": {
3420
+ if (liveParticipant) return liveParticipant;
3402
3421
  if (!ctx.standingsDegraded && hasGroupStarted(ref.group, ctx.tables)) {
3403
3422
  const team = teamFromStandings(ref.group, ref.position, ctx.tables);
3404
- if (team) return participant(team, "projected");
3423
+ if (team) {
3424
+ const status = isGroupComplete(ref.group, ctx.tables) ? "confirmed" : "projected";
3425
+ return participant(team, status);
3426
+ }
3405
3427
  }
3406
3428
  const label = ref.position === 1 ? t(ctx.lang, "bracket.slot.groupWinner", { group: ref.group }) : t(ctx.lang, "bracket.slot.groupSecond", { group: ref.group });
3407
3429
  return tbd(label);
3408
3430
  }
3409
3431
  case "third":
3432
+ if (liveParticipant) return liveParticipant;
3410
3433
  return tbd(t(ctx.lang, "bracket.slot.third", { groups: ref.groups.join("/") }));
3411
3434
  case "winner": {
3412
3435
  const node = ctx.nodesByKey.get(matchKey(ref.stage, ref.index));
@@ -3415,6 +3438,7 @@ function resolveSlot(ref, ctx) {
3415
3438
  const winner = resolveWinner(match);
3416
3439
  if (winner) return participant(winner, "confirmed");
3417
3440
  }
3441
+ if (liveParticipant) return liveParticipant;
3418
3442
  return tbd(winnerLabel(ctx, ref.stage, ref.index));
3419
3443
  }
3420
3444
  case "loser": {
@@ -3424,6 +3448,7 @@ function resolveSlot(ref, ctx) {
3424
3448
  const loser = resolveLoser(match);
3425
3449
  if (loser) return participant(loser, "confirmed");
3426
3450
  }
3451
+ if (liveParticipant) return liveParticipant;
3427
3452
  return tbd(
3428
3453
  t(ctx.lang, "bracket.slot.loser", {
3429
3454
  stage: stageLabelI18n(ctx.lang, ref.stage),
@@ -3461,8 +3486,8 @@ function buildBracketView(topology, matches, tables, standingsDegraded, liveDegr
3461
3486
  stage: node.stage,
3462
3487
  index: node.index,
3463
3488
  kickoff: match.kickoff,
3464
- home: resolveSlot(node.home, ctx),
3465
- away: resolveSlot(node.away, ctx),
3489
+ home: resolveSlot(node.home, ctx, match.home),
3490
+ away: resolveSlot(node.away, ctx, match.away),
3466
3491
  match
3467
3492
  };
3468
3493
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claudinho/core",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
4
4
  "description": "Domain model, provider adapters (ESPN), standings, bundled schedule, and the read-only Polymarket market-signal sidecar powering Claudinho. Not affiliated with FIFA or Anthropic.",
5
5
  "type": "module",
6
6
  "license": "MIT",