@claudinho/core 0.9.1 → 0.9.3
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 +42 -3
- package/dist/index.js +18 -3
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -385,9 +385,48 @@ declare function nextFixtureForTeam(code: string, opts?: {
|
|
|
385
385
|
from?: Date;
|
|
386
386
|
fixtures?: Match[];
|
|
387
387
|
}): Match | undefined;
|
|
388
|
-
/**
|
|
388
|
+
/**
|
|
389
|
+
* A group/regular fixture is potentially live from kickoff until ~kickoff + 140
|
|
390
|
+
* min (90' + half-time + stoppage).
|
|
391
|
+
*/
|
|
389
392
|
declare const LIVE_WINDOW_MS: number;
|
|
390
|
-
/**
|
|
393
|
+
/**
|
|
394
|
+
* Extra allowance for knockout matches, which can go to extra time (+30') and a
|
|
395
|
+
* penalty shootout, running to ~kickoff + 190 min — well past LIVE_WINDOW_MS.
|
|
396
|
+
* Without it the statusline refresher stops polling at kickoff+140min and the
|
|
397
|
+
* cache goes stale mid-match, so a knockout tie still level after 90' (in ET or
|
|
398
|
+
* penalties) silently drops off the statusline while it's still being played.
|
|
399
|
+
* Numerically matches the slack `marketFixtureForTeam` already applies (live.ts).
|
|
400
|
+
*/
|
|
401
|
+
declare const KNOCKOUT_EXTRA_TIME_MS: number;
|
|
402
|
+
/** Live-window length for a fixture — longer for knockout (extra time + penalties). */
|
|
403
|
+
declare function liveWindowMsFor(m: Match): number;
|
|
404
|
+
/**
|
|
405
|
+
* True once EVERY bundled fixture's (stage-aware) live window has ELAPSED —
|
|
406
|
+
* derived from the bundled schedule rather than a hardcoded date (same reasoning
|
|
407
|
+
* as the derived knockout window: the `CLAUDINHO_COMPETITION` seam must not carry
|
|
408
|
+
* a dead calendar).
|
|
409
|
+
*
|
|
410
|
+
* Named for exactly what it measures. This is a TIME predicate, not proof that
|
|
411
|
+
* every match was played: the bundled schedule is a **resultless skeleton** (every
|
|
412
|
+
* fixture ships `SCHEDULED` by design), so status can't inform it — a POSTPONED or
|
|
413
|
+
* abandoned fixture still reads as elapsed once its window passes. That is
|
|
414
|
+
* acceptable for the only use it has (turning a spent schedule into a sign-off),
|
|
415
|
+
* and it's why this is not called `isTournamentComplete`. **Make it status-aware
|
|
416
|
+
* against the live overlay before reusing it for anything that asserts results.**
|
|
417
|
+
*
|
|
418
|
+
* Deliberately a GLOBAL condition, independent of any team filter: an eliminated
|
|
419
|
+
* team mid-tournament has no next fixture either, and must NOT read as "over".
|
|
420
|
+
* Every other empty case still fails closed to the neutral `⚽ —`.
|
|
421
|
+
*
|
|
422
|
+
* Callers must additionally confirm the bundled schedule even applies — it
|
|
423
|
+
* describes the DEFAULT competition, so `CLAUDINHO_COMPETITION` pointing elsewhere
|
|
424
|
+
* makes this answer meaningless (see the `DEFAULT_COMPETITION` gates in the CLI).
|
|
425
|
+
*
|
|
426
|
+
* Empty fixture list → false: "we know nothing" is not "it's over".
|
|
427
|
+
*/
|
|
428
|
+
declare function isTournamentWindowOver(now?: number, fixtures?: Match[]): boolean;
|
|
429
|
+
/** Fixtures whose (stage-aware) live window contains `now` (cheap, static — no network). */
|
|
391
430
|
declare function fixturesInLiveWindow(now?: number, fixtures?: Match[]): Match[];
|
|
392
431
|
/**
|
|
393
432
|
* The team's in-play fixture when one is inside its live window, else the next
|
|
@@ -1279,4 +1318,4 @@ declare function formatShareBracket(input: ShareBracketInput, options?: ShareBra
|
|
|
1279
1318
|
/** Compact one-line-per-match bracket for narrow share contexts. */
|
|
1280
1319
|
declare function formatBracketCompactLine(mv: BracketMatchView, opts?: BracketFormatOpts): string;
|
|
1281
1320
|
|
|
1282
|
-
export { BRACKET_STAGE_ORDER, type BracketFormatOpts, type BracketMatchNode, type BracketMatchView, type BracketResult, type BracketTopology, type BracketView, type BuildSignalInput, DEFAULT_COMPETITION, DEFAULT_FLAVOR, DEFAULT_MAX_AGE_MS, EspnAdapter, type EspnAdapterOptions, FEED_TEXT_MAX, FLAVOR_LEVELS, FakeMarketProvider, type FakeMarketProviderOptions, type FavoriteStrength, type FlavorLevel, type FormatOpts, type GroupStandings, KNOWN_SOURCES, type KnockoutFixturesResult, LIVE_WINDOW_MS, type Lang, type LedgerRow, type LiveResult, type MapContext, type MarketFavorite, type MarketMapping, type MarketMappingTable, type MarketOutcome, type MarketOutcomeKind, type MarketProvider, type MarketSignal, type MarketSignalOptions, type MarketSignalsResult, type Match, type MatchByIdResult, type MatchEvent, type NextFixtureResult, type Outcome, PolymarketProvider, type PolymarketProviderOptions, type ProviderAdapter, type ProviderCapabilities, ProviderError, type ProviderErrorKind, type PunditPick, type ResolvedParticipant, SHARE_DISCLAIMER, SHARE_HASHTAG, type ShareBracketInput, type ShareBracketOptions, type ShareSnippetInput, type ShareSnippetOptions, type ShareStyle, type ShareTableInput, type SlotRef, type Stage, type StandingRow, type StandingsResult, type Status, type Team, type TeamInfo, type TeamLookup, allFixtures, allTeams, asFlavorLevel, buildBracketTopology, buildBracketView, buildMarketSignal, byKickoff, competitionBase, computeStandings, countdown, currentOrNextFixtureForTeam, deriveFavorite, displayWidth, favoriteStrength, fixturesByDate, fixturesByGroup, fixturesByTeam, fixturesInLiveWindow, flagEmoji, formatBracketCompactLine, formatBracketList, formatBracketMatchLine, formatBracketTree, formatDate, formatKickoff, formatShareBracket, formatShareSnippet, formatShareTable, formatTime, getBracket, getKnockoutFixtures, getLiveMatches, getMarketSignal, getMarketSignals, getMatchById, getMatchesForDate, getNextFixtureForTeam, getStandings, groups, hasSaneDistribution, isFinished, isFlavorLevel, isLive, isReliableMarketSignal, isResolvedNation, isStaleSignal, isValidDate, isValidTimeZone, knockoutWindow, liveSourceLabel, loadBracketTopology, localDate, lookupTeam, makeAdapter, makeMarketProvider, mapEspnEvent, mapsCleanly, marketAttributionText, marketBlock, marketFavoriteText, marketFixtureForTeam, marketLine, marketProbabilityText, marketRelevant, marketSignalRendersFor, marketSourceLabel, matchFlavor, matchKey, matchLocation, mergeLive, nationToFlag, nationToRegion, nextFixtureForTeam, normalizeLang, normalizeOutcomes, outcomeFromScore, padVisible, parseStandings, parseTeamSlot, resolveCompetition, resolveMarketSource, resolveTz, sanitizeBundledFixture, sanitizeFeedText, sanitizeMatchStrings, scoreline, stageLabel, stageLabelI18n, t };
|
|
1321
|
+
export { BRACKET_STAGE_ORDER, type BracketFormatOpts, type BracketMatchNode, type BracketMatchView, type BracketResult, type BracketTopology, type BracketView, type BuildSignalInput, DEFAULT_COMPETITION, DEFAULT_FLAVOR, DEFAULT_MAX_AGE_MS, EspnAdapter, type EspnAdapterOptions, FEED_TEXT_MAX, FLAVOR_LEVELS, FakeMarketProvider, type FakeMarketProviderOptions, type FavoriteStrength, type FlavorLevel, type FormatOpts, type GroupStandings, KNOCKOUT_EXTRA_TIME_MS, KNOWN_SOURCES, type KnockoutFixturesResult, LIVE_WINDOW_MS, type Lang, type LedgerRow, type LiveResult, type MapContext, type MarketFavorite, type MarketMapping, type MarketMappingTable, type MarketOutcome, type MarketOutcomeKind, type MarketProvider, type MarketSignal, type MarketSignalOptions, type MarketSignalsResult, type Match, type MatchByIdResult, type MatchEvent, type NextFixtureResult, type Outcome, PolymarketProvider, type PolymarketProviderOptions, type ProviderAdapter, type ProviderCapabilities, ProviderError, type ProviderErrorKind, type PunditPick, type ResolvedParticipant, SHARE_DISCLAIMER, SHARE_HASHTAG, type ShareBracketInput, type ShareBracketOptions, type ShareSnippetInput, type ShareSnippetOptions, type ShareStyle, type ShareTableInput, type SlotRef, type Stage, type StandingRow, type StandingsResult, type Status, type Team, type TeamInfo, type TeamLookup, allFixtures, allTeams, asFlavorLevel, buildBracketTopology, buildBracketView, buildMarketSignal, byKickoff, competitionBase, computeStandings, countdown, currentOrNextFixtureForTeam, deriveFavorite, displayWidth, favoriteStrength, fixturesByDate, fixturesByGroup, fixturesByTeam, fixturesInLiveWindow, flagEmoji, formatBracketCompactLine, formatBracketList, formatBracketMatchLine, formatBracketTree, formatDate, formatKickoff, formatShareBracket, formatShareSnippet, formatShareTable, formatTime, getBracket, getKnockoutFixtures, getLiveMatches, getMarketSignal, getMarketSignals, getMatchById, getMatchesForDate, getNextFixtureForTeam, getStandings, groups, hasSaneDistribution, isFinished, isFlavorLevel, isLive, isReliableMarketSignal, isResolvedNation, isStaleSignal, isTournamentWindowOver, isValidDate, isValidTimeZone, knockoutWindow, liveSourceLabel, liveWindowMsFor, loadBracketTopology, localDate, lookupTeam, makeAdapter, makeMarketProvider, mapEspnEvent, mapsCleanly, marketAttributionText, marketBlock, marketFavoriteText, marketFixtureForTeam, marketLine, marketProbabilityText, marketRelevant, marketSignalRendersFor, marketSourceLabel, matchFlavor, matchKey, matchLocation, mergeLive, nationToFlag, nationToRegion, nextFixtureForTeam, normalizeLang, normalizeOutcomes, outcomeFromScore, padVisible, parseStandings, parseTeamSlot, resolveCompetition, resolveMarketSource, resolveTz, sanitizeBundledFixture, sanitizeFeedText, sanitizeMatchStrings, scoreline, stageLabel, stageLabelI18n, t };
|
package/dist/index.js
CHANGED
|
@@ -2941,10 +2941,22 @@ function nextFixtureForTeam(code, opts = {}) {
|
|
|
2941
2941
|
);
|
|
2942
2942
|
}
|
|
2943
2943
|
var LIVE_WINDOW_MS = 140 * 6e4;
|
|
2944
|
+
var KNOCKOUT_EXTRA_TIME_MS = 60 * 6e4;
|
|
2945
|
+
function liveWindowMsFor(m) {
|
|
2946
|
+
return m.stage === "GROUP" || m.stage === "FRIENDLY" ? LIVE_WINDOW_MS : LIVE_WINDOW_MS + KNOCKOUT_EXTRA_TIME_MS;
|
|
2947
|
+
}
|
|
2948
|
+
function isTournamentWindowOver(now = Date.now(), fixtures = SCHEDULE) {
|
|
2949
|
+
if (fixtures.length === 0) return false;
|
|
2950
|
+
return fixtures.every((m) => {
|
|
2951
|
+
const k = Date.parse(m.kickoff);
|
|
2952
|
+
if (Number.isNaN(k)) return false;
|
|
2953
|
+
return now > k + liveWindowMsFor(m);
|
|
2954
|
+
});
|
|
2955
|
+
}
|
|
2944
2956
|
function fixturesInLiveWindow(now = Date.now(), fixtures = SCHEDULE) {
|
|
2945
2957
|
return fixtures.filter((m) => {
|
|
2946
2958
|
const k = Date.parse(m.kickoff);
|
|
2947
|
-
return now >= k && now <= k +
|
|
2959
|
+
return now >= k && now <= k + liveWindowMsFor(m);
|
|
2948
2960
|
}).sort(byKickoff);
|
|
2949
2961
|
}
|
|
2950
2962
|
function currentOrNextFixtureForTeam(code, opts = {}) {
|
|
@@ -2952,7 +2964,7 @@ function currentOrNextFixtureForTeam(code, opts = {}) {
|
|
|
2952
2964
|
const nowMs = from.getTime();
|
|
2953
2965
|
const inPlay = fixturesByTeam(code, opts.fixtures ?? SCHEDULE).find((m) => {
|
|
2954
2966
|
const k = Date.parse(m.kickoff);
|
|
2955
|
-
return nowMs >= k && nowMs <= k +
|
|
2967
|
+
return nowMs >= k && nowMs <= k + liveWindowMsFor(m);
|
|
2956
2968
|
});
|
|
2957
2969
|
return inPlay ?? nextFixtureForTeam(code, opts);
|
|
2958
2970
|
}
|
|
@@ -3086,7 +3098,7 @@ function rosterAtZero(matches) {
|
|
|
3086
3098
|
var ESPN_SOCCER = "https://site.api.espn.com/apis/site/v2/sports/soccer";
|
|
3087
3099
|
var DEFAULT_COMPETITION = "fifa.world";
|
|
3088
3100
|
var DEFAULT_BASE = `${ESPN_SOCCER}/${DEFAULT_COMPETITION}`;
|
|
3089
|
-
var USER_AGENT = `claudinho/${"0.9.
|
|
3101
|
+
var USER_AGENT = `claudinho/${"0.9.3"} (+https://github.com/arturogarrido/claudinho)`;
|
|
3090
3102
|
var MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
|
|
3091
3103
|
function competitionBase(slug) {
|
|
3092
3104
|
return `${ESPN_SOCCER}/${slug}`;
|
|
@@ -5206,6 +5218,7 @@ export {
|
|
|
5206
5218
|
FEED_TEXT_MAX,
|
|
5207
5219
|
FLAVOR_LEVELS,
|
|
5208
5220
|
FakeMarketProvider,
|
|
5221
|
+
KNOCKOUT_EXTRA_TIME_MS,
|
|
5209
5222
|
KNOWN_SOURCES,
|
|
5210
5223
|
LIVE_WINDOW_MS,
|
|
5211
5224
|
PolymarketProvider,
|
|
@@ -5258,10 +5271,12 @@ export {
|
|
|
5258
5271
|
isReliableMarketSignal,
|
|
5259
5272
|
isResolvedNation,
|
|
5260
5273
|
isStaleSignal,
|
|
5274
|
+
isTournamentWindowOver,
|
|
5261
5275
|
isValidDate,
|
|
5262
5276
|
isValidTimeZone,
|
|
5263
5277
|
knockoutWindow,
|
|
5264
5278
|
liveSourceLabel,
|
|
5279
|
+
liveWindowMsFor,
|
|
5265
5280
|
loadBracketTopology,
|
|
5266
5281
|
localDate,
|
|
5267
5282
|
lookupTeam,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claudinho/core",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.3",
|
|
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",
|
|
@@ -53,12 +53,12 @@
|
|
|
53
53
|
"agent"
|
|
54
54
|
],
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@types/node": "^22.20.
|
|
57
|
-
"@vitest/coverage-v8": "^4.1.
|
|
56
|
+
"@types/node": "^22.20.1",
|
|
57
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
58
58
|
"tsup": "^8.0.0",
|
|
59
|
-
"tsx": "^4.23.
|
|
59
|
+
"tsx": "^4.23.1",
|
|
60
60
|
"typescript": "^5.7.0",
|
|
61
|
-
"vitest": "^4.1.
|
|
61
|
+
"vitest": "^4.1.10"
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
64
|
"build": "tsup",
|