@onlyworlds/sdk 4.75.0 → 4.76.1
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/AGENTS.md +1 -1
- package/CHANGELOG.md +17 -0
- package/SCHEMA.md +1 -1
- package/dist/index.d.ts +10 -3
- package/dist/index.js +76 -18
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# For AI agents using @onlyworlds/sdk
|
|
2
2
|
|
|
3
|
-
**Current as of**: SDK **4.x** · schema-dist **v0.33.0-dist.
|
|
3
|
+
**Current as of**: SDK **4.x** · schema-dist **v0.33.0-dist.69** (canonical 00.33.00).
|
|
4
4
|
This line is asserted by `codegen:check` in CI — if the pin moves and this file is not
|
|
5
5
|
re-read against it, the check fails rather than letting this document rot quietly.
|
|
6
6
|
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,23 @@ earlier history lives in git log only.
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [4.76.1] - 2026-10-25
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **Schema repinned to schema-dist v0.33.0-dist.69** (from dist.68; same canonical 00.33.00). The calendar fixture's `v2-except-chain-gregorian` case gains 12 steps, the days around Leap Day in 1900, 2000 and 2100 (no Leap Day in 1900 and 2100, one in 2000), each checked against LegendKeeper's own reading; a reader whose days ignore `except` while its year count keeps it misreads only these. The test replays all 64 cases, now 198 steps. The script that generates the amendment's cases (`scripts/calendar-fixture-cases.mjs`) adds those century days and keeps the case's earlier sampled steps as published; its 14 cases equal the published ones. No generated type changed.
|
|
13
|
+
|
|
14
|
+
## [4.76.0] - 2026-10-25
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Calendar version 2: a leap rule with exceptions and an offset** (the calendar profile's amendment, schema-dist v0.33.0-dist.68). An intercalary entry with `every_years` may carry `except`, divisors that flip the rule in order (`every_years: 4, except: [100, 400]`: every 4, not every 100, yet every 400), and `offset`, added to the year index before the rule (1 for a calendar with no year 0). Gregorian is `every_years: 4, except: [100, 400], offset: 1`. A value that uses either key is `version: 2`; `readCalendarConfig` reads versions 1 and 2, reads the two keys only under version 2, and refuses an `except` that is not strictly ascending with each entry a multiple of the one before (the first of `every_years`), or an `offset` that is not a whole number. `validateCalendarConfig` names each of these, and the keys under version 1. Year arithmetic stays closed-form. `intercalaryInYear(cfg, entry, year)` says whether an intercalary day falls in a year.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **An era with no `end` runs to the next up era's start**, skipping down eras, whatever the list order. An up era listed before a down era with the same pivot no longer ends where it begins: with eras `After` (up, from 0) and `Before` (down, pivot 0), step 5 reads `6 AF`, where it read `5` with no era.
|
|
23
|
+
- **Schema repinned to schema-dist v0.33.0-dist.68** (from dist.66; same canonical 00.33.00). The calendar fixture's 64 cases are replayed by a test, which no test did before; the import map profile (serial 67) is vendored with the distribution and not read by this package. No generated type changed.
|
|
24
|
+
|
|
8
25
|
## [4.75.0] - 2026-10-25
|
|
9
26
|
|
|
10
27
|
### Changed
|
package/SCHEMA.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OnlyWorlds Schema Reference
|
|
2
2
|
|
|
3
|
-
**Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.33.0-dist.
|
|
3
|
+
**Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.33.0-dist.69** — canonical schema **00.33.00**, published 2026-10-25.
|
|
4
4
|
|
|
5
5
|
GENERATED from the canonical schema YAML — do not hand-edit (regenerate: `python codegen/generate_types.py`).
|
|
6
6
|
Written for both humans and AI agents reading this package locally.
|
package/dist/index.d.ts
CHANGED
|
@@ -5030,8 +5030,13 @@ interface CalendarIntercalary {
|
|
|
5030
5030
|
name: string;
|
|
5031
5031
|
/** 0 = before month 1; k = after month k. Requires months. */
|
|
5032
5032
|
after_month: number;
|
|
5033
|
-
/** Present only in years where floorMod(absYear, N) === 0 (the leap rule). */
|
|
5033
|
+
/** Present only in years where floorMod(absYear + offset, N) === 0 (the leap rule). */
|
|
5034
5034
|
every_years?: number;
|
|
5035
|
+
/** Version 2: divisors that flip the rule in order, each a multiple of the one before
|
|
5036
|
+
* (`every_years: 4, except: [100, 400]`: every 4, not every 100, yet every 400). */
|
|
5037
|
+
except?: number[];
|
|
5038
|
+
/** Version 2: the rule reads year absYear + offset (default 0; 1 for a calendar with no year 0). */
|
|
5039
|
+
offset?: number;
|
|
5035
5040
|
/** Counts in the free-running week (default true). The Shire lock = opting
|
|
5036
5041
|
* exactly Mid-year's Day + Overlithe out (364 = 52 × 7). */
|
|
5037
5042
|
in_week?: boolean;
|
|
@@ -5089,8 +5094,10 @@ declare function validateCalendarConfig(cfg: CalendarConfig): string[];
|
|
|
5089
5094
|
* back to bare numbers, never a broken axis.
|
|
5090
5095
|
*/
|
|
5091
5096
|
declare function readCalendarConfig(value: unknown): CalendarConfig | null;
|
|
5092
|
-
/** True when absolute year y contains
|
|
5097
|
+
/** True when absolute year y contains a leap entry with period N (the version-1 rule). */
|
|
5093
5098
|
declare function isLeapYear(y: number, N: number): boolean;
|
|
5099
|
+
/** True when the intercalary day falls in absolute year y: always without `every_years`, else by its rule. */
|
|
5100
|
+
declare function intercalaryInYear(cfg: CalendarConfig, ic: CalendarIntercalary, y: number): boolean;
|
|
5094
5101
|
/** First step of absolute year y. yearStart(0) === 0 by construction. */
|
|
5095
5102
|
declare function yearStartStep(cfg: CalendarConfig, y: number): number;
|
|
5096
5103
|
/** Length in steps of absolute year y. */
|
|
@@ -5549,4 +5556,4 @@ declare class TokenResource {
|
|
|
5549
5556
|
getEncryptionInfo(): Promise<EncryptionInfo>;
|
|
5550
5557
|
}
|
|
5551
5558
|
|
|
5552
|
-
export { AGENT_DOORS, ASK_LIMITS, type AccessKeyResponse, CALENDAR_FIELD, CALENDAR_SUPERTYPE, type CalendarConfig, type CalendarEra, type CalendarIntercalary, type CalendarMonths, type CalendarWeek, ELEMENT_FAMILIES, ELEMENT_ICONS, ELEMENT_LABELS, ELEMENT_SECTIONS, ELEMENT_TYPES, type ElementFamily, type ElementType, type EncryptionInfo, type EraDomain, FAMILY_COLORS, FAMILY_ORDER, FIELD_ACRONYMS, FIELD_SCHEMA, FILE_EXTENSIONS, type FieldInfo, type FieldType, GameTier, type ListParams, ONLYWORLDS_VERSION, type OwAccountWorld, type OwAgentJoined, type OwAllowance, OwApiError, type OwAskAnswer, type OwAskContext, type OwAskContextOptions, type OwAskLeftOut, type OwAuthErrorCode, type OwBulkItem, type OwBulkItemResult, type OwBulkResponse, type OwCalendarElement, type OwChange, type OwChangeDelete, type OwChangeUpsert, type OwChangesPage, type OwClientConfig, type OwCreateAccountWorldInput, type OwCreatedAccountWorld, type OwCreatedWorldLink, type OwDeleteReason, type OwDraught, type OwDraughtCompact, type OwDraughtComponent, type OwDraughtItem, type OwDraughtPolicy, type OwElement, type OwElementBase, type OwErrorBody, type OwFileAddedBy, type OwFileDownload, type OwFileKind, type OwFileRow, type OwFileTicket, type OwFrontDoor, type OwHiddenRow, type OwJoinPreview, type OwJoined, type OwJoinedMembership, type OwKeyKind, type OwLinkEdit, type OwLookupElement, type OwLookupHit, type OwLookupLink, type OwLookupOptions, type OwLookupReason, type OwMe, type OwMediaTicket, type OwMember, type OwMemberRole, type OwMintedKey, type OwNamesMap, OwNetworkError, type OwPage, type OwPhotoOptions, type OwPhotoPlan, type OwPlayerJoined, OwPreconditionFailedError, type OwPreparedPhoto, type OwProposal, type OwProposalAccepted, type OwProposalConflict, type OwProposalList, type OwProposalQuery, type OwProposalState, type OwProposeInput, type OwProposed, OwProposedError, type OwProposedNewElement, type OwReadWorldFile, type OwReadWorldFileOptions, type OwRemovalTicket, type OwRemovedImage, type OwRenderOptions, type OwResyncReason, type OwReviewInput, type OwReviewed, type OwSeat, type OwSeatCreated, type OwSignInBegin, type OwSignInBegun, type OwSignInComplete, OwSignInError, type OwSignInReason, type OwSignInResult, type OwSignInStorage, type OwSignedIn, type OwSortAddToRow, type OwSortAnswer, type OwSortAskRow, type OwSortLinkRow, type OwSortMakeRow, type OwSortNote, type OwSortRef, type OwSortRow, OwStaleProposalError, type OwUploadedFile, type OwUploadedImage, OwV2Client, type OwWordPair, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldFileRow, type OwWorldFiles, type OwWorldIndex, type OwWorldLink, type OwWorldMeta, type OwWorldOrigin, type OwWorldProducer, type OwWorldProposalList, type OwWorldProposalQuery, type OwWorldProposalRow, type OwWorldPublicPage, type OwWorldSource, type OwWriteDoor, type OwWriteWorldFileOptions, type OwWriteWorldFileReport, PHOTO_MAX_BYTES, PHOTO_TYPES, PUBLIC_FIELDS, type ParseError, type ParseOptions, type ParseResult, REVIEW_PROPOSED_LABEL, ROOM_PAIRS, type RevokeAllSessionsResponse, type RevokeSessionResponse, SPATIAL_TYPES, type SectionInfo, type StepBreakdown, type TokenConsumeParams, type TokenConsumeResponse, TokenResource, type TokenStatus, type TokenTransport, WORLD_FILE_MAX_BYTES, WORLD_FILE_MAX_ENTRIES, WORLD_FILE_MEDIA_TYPE, type WorldCalendar, absYearForEraYear, absoluteYear, approxYearLength, base64url, breakdownStep, buildAskContext, buildWorldIndex, detectKeyKind, displayYear, elementColor, eraForStep, errorFromResponse, familyOf, fieldLabel, fileKindOf, floorDiv, floorMod, formatDuration, formatMidLabel, formatStep, formatYearLabel, getElementIcon, getElementLabel, isAgentDoor, isDemoKey, isKnownOf, isLeapYear, isParseError, isRoomElement, kindCanWrite, lookupWorld, monthStartSteps, nfc, parseDate, parseErrorEnvelope, pinExpectation, pkceChallenge, planPhoto, preparePhoto, readCalendarConfig, readCalendarValue, readWorldFile, renderElement, resolveCalendarLens, resolveEraDomains, simpleCaseFold, typeWord, validateCalendarConfig, weekdayForStep, worldCalendars, writeWorldFile, yearLength, yearStartStep };
|
|
5559
|
+
export { AGENT_DOORS, ASK_LIMITS, type AccessKeyResponse, CALENDAR_FIELD, CALENDAR_SUPERTYPE, type CalendarConfig, type CalendarEra, type CalendarIntercalary, type CalendarMonths, type CalendarWeek, ELEMENT_FAMILIES, ELEMENT_ICONS, ELEMENT_LABELS, ELEMENT_SECTIONS, ELEMENT_TYPES, type ElementFamily, type ElementType, type EncryptionInfo, type EraDomain, FAMILY_COLORS, FAMILY_ORDER, FIELD_ACRONYMS, FIELD_SCHEMA, FILE_EXTENSIONS, type FieldInfo, type FieldType, GameTier, type ListParams, ONLYWORLDS_VERSION, type OwAccountWorld, type OwAgentJoined, type OwAllowance, OwApiError, type OwAskAnswer, type OwAskContext, type OwAskContextOptions, type OwAskLeftOut, type OwAuthErrorCode, type OwBulkItem, type OwBulkItemResult, type OwBulkResponse, type OwCalendarElement, type OwChange, type OwChangeDelete, type OwChangeUpsert, type OwChangesPage, type OwClientConfig, type OwCreateAccountWorldInput, type OwCreatedAccountWorld, type OwCreatedWorldLink, type OwDeleteReason, type OwDraught, type OwDraughtCompact, type OwDraughtComponent, type OwDraughtItem, type OwDraughtPolicy, type OwElement, type OwElementBase, type OwErrorBody, type OwFileAddedBy, type OwFileDownload, type OwFileKind, type OwFileRow, type OwFileTicket, type OwFrontDoor, type OwHiddenRow, type OwJoinPreview, type OwJoined, type OwJoinedMembership, type OwKeyKind, type OwLinkEdit, type OwLookupElement, type OwLookupHit, type OwLookupLink, type OwLookupOptions, type OwLookupReason, type OwMe, type OwMediaTicket, type OwMember, type OwMemberRole, type OwMintedKey, type OwNamesMap, OwNetworkError, type OwPage, type OwPhotoOptions, type OwPhotoPlan, type OwPlayerJoined, OwPreconditionFailedError, type OwPreparedPhoto, type OwProposal, type OwProposalAccepted, type OwProposalConflict, type OwProposalList, type OwProposalQuery, type OwProposalState, type OwProposeInput, type OwProposed, OwProposedError, type OwProposedNewElement, type OwReadWorldFile, type OwReadWorldFileOptions, type OwRemovalTicket, type OwRemovedImage, type OwRenderOptions, type OwResyncReason, type OwReviewInput, type OwReviewed, type OwSeat, type OwSeatCreated, type OwSignInBegin, type OwSignInBegun, type OwSignInComplete, OwSignInError, type OwSignInReason, type OwSignInResult, type OwSignInStorage, type OwSignedIn, type OwSortAddToRow, type OwSortAnswer, type OwSortAskRow, type OwSortLinkRow, type OwSortMakeRow, type OwSortNote, type OwSortRef, type OwSortRow, OwStaleProposalError, type OwUploadedFile, type OwUploadedImage, OwV2Client, type OwWordPair, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldFileRow, type OwWorldFiles, type OwWorldIndex, type OwWorldLink, type OwWorldMeta, type OwWorldOrigin, type OwWorldProducer, type OwWorldProposalList, type OwWorldProposalQuery, type OwWorldProposalRow, type OwWorldPublicPage, type OwWorldSource, type OwWriteDoor, type OwWriteWorldFileOptions, type OwWriteWorldFileReport, PHOTO_MAX_BYTES, PHOTO_TYPES, PUBLIC_FIELDS, type ParseError, type ParseOptions, type ParseResult, REVIEW_PROPOSED_LABEL, ROOM_PAIRS, type RevokeAllSessionsResponse, type RevokeSessionResponse, SPATIAL_TYPES, type SectionInfo, type StepBreakdown, type TokenConsumeParams, type TokenConsumeResponse, TokenResource, type TokenStatus, type TokenTransport, WORLD_FILE_MAX_BYTES, WORLD_FILE_MAX_ENTRIES, WORLD_FILE_MEDIA_TYPE, type WorldCalendar, absYearForEraYear, absoluteYear, approxYearLength, base64url, breakdownStep, buildAskContext, buildWorldIndex, detectKeyKind, displayYear, elementColor, eraForStep, errorFromResponse, familyOf, fieldLabel, fileKindOf, floorDiv, floorMod, formatDuration, formatMidLabel, formatStep, formatYearLabel, getElementIcon, getElementLabel, intercalaryInYear, isAgentDoor, isDemoKey, isKnownOf, isLeapYear, isParseError, isRoomElement, kindCanWrite, lookupWorld, monthStartSteps, nfc, parseDate, parseErrorEnvelope, pinExpectation, pkceChallenge, planPhoto, preparePhoto, readCalendarConfig, readCalendarValue, readWorldFile, renderElement, resolveCalendarLens, resolveEraDomains, simpleCaseFold, typeWord, validateCalendarConfig, weekdayForStep, worldCalendars, writeWorldFile, yearLength, yearStartStep };
|
package/dist/index.js
CHANGED
|
@@ -4287,7 +4287,7 @@ function floorMod(a, b) {
|
|
|
4287
4287
|
}
|
|
4288
4288
|
function validateCalendarConfig(cfg) {
|
|
4289
4289
|
const errors = [];
|
|
4290
|
-
if (cfg.version !== 1) errors.push(`Unsupported calendar version: ${cfg.version}`);
|
|
4290
|
+
if (cfg.version !== 1 && cfg.version !== 2) errors.push(`Unsupported calendar version: ${cfg.version}`);
|
|
4291
4291
|
if (!cfg.grain || typeof cfg.grain !== "string") errors.push("Grain is required");
|
|
4292
4292
|
const months = cfg.bundles?.months;
|
|
4293
4293
|
if (months) {
|
|
@@ -4317,6 +4317,11 @@ function validateCalendarConfig(cfg) {
|
|
|
4317
4317
|
if (ic.every_years != null && (!Number.isInteger(ic.every_years) || ic.every_years < 1)) {
|
|
4318
4318
|
errors.push(`Festival day "${ic.name}": every N yrs must be a whole number, 1 or more`);
|
|
4319
4319
|
}
|
|
4320
|
+
const rule = leapRuleProblem(ic);
|
|
4321
|
+
if (rule) errors.push(`Festival day "${ic.name}": ${rule}`);
|
|
4322
|
+
if (cfg.version === 1 && (ic.except != null || ic.offset != null)) {
|
|
4323
|
+
errors.push(`Festival day "${ic.name}": except and offset need calendar version 2`);
|
|
4324
|
+
}
|
|
4320
4325
|
}
|
|
4321
4326
|
const eras = cfg.eras ?? [];
|
|
4322
4327
|
for (const era of eras) {
|
|
@@ -4345,7 +4350,7 @@ function validateCalendarConfig(cfg) {
|
|
|
4345
4350
|
function readCalendarConfig(value) {
|
|
4346
4351
|
if (typeof value !== "object" || value === null) return null;
|
|
4347
4352
|
const cfg = value;
|
|
4348
|
-
if (cfg.version !== 1 || typeof cfg.grain !== "string") return null;
|
|
4353
|
+
if (cfg.version !== 1 && cfg.version !== 2 || typeof cfg.grain !== "string") return null;
|
|
4349
4354
|
const months = cfg.bundles?.months;
|
|
4350
4355
|
if (months && (!Array.isArray(months.names) || !Array.isArray(months.lengths) || months.names.length !== months.lengths.length || months.names.length === 0 || !months.names.every(isString))) return null;
|
|
4351
4356
|
if (cfg.eras != null && !Array.isArray(cfg.eras)) return null;
|
|
@@ -4357,48 +4362,100 @@ function readCalendarConfig(value) {
|
|
|
4357
4362
|
const week = cfg.bundles?.week;
|
|
4358
4363
|
if (week != null && (!isPositiveInt(week.length) || !Array.isArray(week.names) || !week.names.every(isString))) return null;
|
|
4359
4364
|
if (cfg.intercalary?.some((i) => i.every_years != null && !isPositiveInt(i.every_years))) return null;
|
|
4365
|
+
if (cfg.version === 2 && cfg.intercalary?.some((i) => leapRuleProblem(i) != null)) return null;
|
|
4360
4366
|
return cfg;
|
|
4361
4367
|
}
|
|
4368
|
+
function leapRuleProblem(ic) {
|
|
4369
|
+
const ex = ic.except;
|
|
4370
|
+
const off = ic.offset;
|
|
4371
|
+
if (ex == null && off == null) return null;
|
|
4372
|
+
if (ic.every_years == null) return "except and offset need every_years";
|
|
4373
|
+
if (off != null && !Number.isSafeInteger(off)) return "offset must be a whole number";
|
|
4374
|
+
if (ex != null) {
|
|
4375
|
+
if (!Array.isArray(ex)) return "except must be a list";
|
|
4376
|
+
let prev = ic.every_years;
|
|
4377
|
+
for (const d of ex) {
|
|
4378
|
+
if (!isPositiveInt(d) || d <= prev || d % prev !== 0) {
|
|
4379
|
+
return "each except must be a multiple of the number before it, and larger";
|
|
4380
|
+
}
|
|
4381
|
+
prev = d;
|
|
4382
|
+
}
|
|
4383
|
+
}
|
|
4384
|
+
return null;
|
|
4385
|
+
}
|
|
4362
4386
|
function isString(s) {
|
|
4363
4387
|
return typeof s === "string";
|
|
4364
4388
|
}
|
|
4365
4389
|
function isPositiveInt(n) {
|
|
4366
4390
|
return Number.isSafeInteger(n) && n >= 1;
|
|
4367
4391
|
}
|
|
4392
|
+
function leapRule(cfg, ic) {
|
|
4393
|
+
const v2 = cfg.version === 2;
|
|
4394
|
+
return { n: ic.every_years, except: v2 && ic.except || [], offset: v2 && ic.offset || 0 };
|
|
4395
|
+
}
|
|
4396
|
+
function leapRules(cfg, inter) {
|
|
4397
|
+
return inter.filter((i) => i.every_years != null).map((i) => leapRule(cfg, i));
|
|
4398
|
+
}
|
|
4368
4399
|
function yearShape(cfg) {
|
|
4369
4400
|
const months = cfg.bundles?.months;
|
|
4370
4401
|
const inter = cfg.intercalary ?? [];
|
|
4371
|
-
const
|
|
4402
|
+
const rules = leapRules(cfg, inter);
|
|
4372
4403
|
if (months) {
|
|
4373
4404
|
const base = months.lengths.reduce((a, b) => a + b, 0) + inter.filter((i) => i.every_years == null).length;
|
|
4374
|
-
return { baseLen: base,
|
|
4405
|
+
return { baseLen: base, rules };
|
|
4375
4406
|
}
|
|
4376
|
-
return { baseLen: cfg.bundles?.year?.steps ?? 1,
|
|
4407
|
+
return { baseLen: cfg.bundles?.year?.steps ?? 1, rules };
|
|
4408
|
+
}
|
|
4409
|
+
function ruleHolds(r, y) {
|
|
4410
|
+
const Y = y + r.offset;
|
|
4411
|
+
let on = floorMod(Y, r.n) === 0;
|
|
4412
|
+
for (const d of r.except) if (floorMod(Y, d) === 0) on = !on;
|
|
4413
|
+
return on;
|
|
4377
4414
|
}
|
|
4378
|
-
function
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4415
|
+
function multiplesIn(a, b, m, offset) {
|
|
4416
|
+
return floorDiv(b - 1 + offset, m) - floorDiv(a - 1 + offset, m);
|
|
4417
|
+
}
|
|
4418
|
+
function leapYearsBefore(y, r) {
|
|
4419
|
+
const [a, b, sign] = y >= 0 ? [0, y, 1] : [y, 0, -1];
|
|
4420
|
+
let count = multiplesIn(a, b, r.n, r.offset);
|
|
4421
|
+
let s = -1;
|
|
4422
|
+
for (const d of r.except) {
|
|
4423
|
+
count += s * multiplesIn(a, b, d, r.offset);
|
|
4424
|
+
s = -s;
|
|
4425
|
+
}
|
|
4426
|
+
return sign * count;
|
|
4382
4427
|
}
|
|
4383
4428
|
function isLeapYear(y, N) {
|
|
4384
4429
|
return floorMod(y, N) === 0;
|
|
4385
4430
|
}
|
|
4431
|
+
function intercalaryInYear(cfg, ic, y) {
|
|
4432
|
+
return ic.every_years == null || ruleHolds(leapRule(cfg, ic), y);
|
|
4433
|
+
}
|
|
4386
4434
|
function yearStartStep(cfg, y) {
|
|
4387
4435
|
const shape = yearShape(cfg);
|
|
4388
4436
|
let start = y * shape.baseLen;
|
|
4389
|
-
for (const
|
|
4437
|
+
for (const r of shape.rules) start += leapYearsBefore(y, r);
|
|
4390
4438
|
return start;
|
|
4391
4439
|
}
|
|
4392
4440
|
function yearLength(cfg, y) {
|
|
4393
4441
|
const shape = yearShape(cfg);
|
|
4394
4442
|
let len = shape.baseLen;
|
|
4395
|
-
for (const
|
|
4443
|
+
for (const r of shape.rules) if (ruleHolds(r, y)) len += 1;
|
|
4396
4444
|
return len;
|
|
4397
4445
|
}
|
|
4446
|
+
function meanLeap(r) {
|
|
4447
|
+
let m = 1 / r.n;
|
|
4448
|
+
let s = -1;
|
|
4449
|
+
for (const d of r.except) {
|
|
4450
|
+
m += s / d;
|
|
4451
|
+
s = -s;
|
|
4452
|
+
}
|
|
4453
|
+
return m;
|
|
4454
|
+
}
|
|
4398
4455
|
var MAX_YEAR_CORRECTION = 1e4;
|
|
4399
4456
|
function absoluteYear(cfg, step) {
|
|
4400
4457
|
const shape = yearShape(cfg);
|
|
4401
|
-
const meanLen = shape.
|
|
4458
|
+
const meanLen = shape.rules.reduce((a, r) => a + meanLeap(r), shape.baseLen);
|
|
4402
4459
|
let y = floorDiv(step, meanLen);
|
|
4403
4460
|
if (!Number.isFinite(y)) return y;
|
|
4404
4461
|
for (let i = 0; i < MAX_YEAR_CORRECTION && step < yearStartStep(cfg, y); i++) y -= 1;
|
|
@@ -4413,8 +4470,8 @@ function resolveEraDomains(eras) {
|
|
|
4413
4470
|
if ((era.direction ?? "up") === "down") {
|
|
4414
4471
|
out.push({ era, lo: era.end ?? -Infinity, hi: era.start });
|
|
4415
4472
|
} else {
|
|
4416
|
-
const
|
|
4417
|
-
out.push({ era, lo: era.start, hi: era.end ??
|
|
4473
|
+
const nextUp = sorted.slice(i + 1).find((e) => (e.direction ?? "up") === "up");
|
|
4474
|
+
out.push({ era, lo: era.start, hi: era.end ?? nextUp?.start ?? Infinity });
|
|
4418
4475
|
}
|
|
4419
4476
|
}
|
|
4420
4477
|
return out;
|
|
@@ -4442,7 +4499,7 @@ function yearSlots(cfg, y) {
|
|
|
4442
4499
|
const months = cfg.bundles?.months;
|
|
4443
4500
|
if (!months) return [];
|
|
4444
4501
|
const inter = cfg.intercalary ?? [];
|
|
4445
|
-
const active = (ic) =>
|
|
4502
|
+
const active = (ic) => intercalaryInYear(cfg, ic, y);
|
|
4446
4503
|
const slots = [];
|
|
4447
4504
|
const push = (afterMonth) => {
|
|
4448
4505
|
for (const ic of inter) if (ic.after_month === afterMonth && active(ic)) slots.push({ kind: "intercalary", intercalary: ic });
|
|
@@ -4458,7 +4515,7 @@ function skippedWeekDaysPerYear(cfg) {
|
|
|
4458
4515
|
const inter = (cfg.intercalary ?? []).filter((i) => i.in_week === false);
|
|
4459
4516
|
return {
|
|
4460
4517
|
base: inter.filter((i) => i.every_years == null).length,
|
|
4461
|
-
|
|
4518
|
+
rules: leapRules(cfg, inter)
|
|
4462
4519
|
};
|
|
4463
4520
|
}
|
|
4464
4521
|
function weekdayForStep(cfg, step, pre) {
|
|
@@ -4473,7 +4530,7 @@ function weekdayForStep(cfg, step, pre) {
|
|
|
4473
4530
|
const skipped = skippedWeekDaysPerYear(cfg);
|
|
4474
4531
|
const y = pos.absYear;
|
|
4475
4532
|
let skippedBeforeYear = y * skipped.base;
|
|
4476
|
-
for (const
|
|
4533
|
+
for (const r of skipped.rules) skippedBeforeYear += leapYearsBefore(y, r);
|
|
4477
4534
|
let skippedInYear = 0;
|
|
4478
4535
|
if (pos.slots) {
|
|
4479
4536
|
for (let i = 0; i < pos.offset; i++) {
|
|
@@ -4565,7 +4622,7 @@ function monthStartSteps(cfg, y) {
|
|
|
4565
4622
|
const months = cfg.bundles?.months;
|
|
4566
4623
|
if (!months) return [];
|
|
4567
4624
|
const inter = cfg.intercalary ?? [];
|
|
4568
|
-
const active = (ic) =>
|
|
4625
|
+
const active = (ic) => intercalaryInYear(cfg, ic, y);
|
|
4569
4626
|
const out = [];
|
|
4570
4627
|
let offset = inter.filter((i) => i.after_month === 0 && active(i)).length;
|
|
4571
4628
|
const start = yearStartStep(cfg, y);
|
|
@@ -4983,6 +5040,7 @@ export {
|
|
|
4983
5040
|
formatYearLabel,
|
|
4984
5041
|
getElementIcon,
|
|
4985
5042
|
getElementLabel,
|
|
5043
|
+
intercalaryInYear,
|
|
4986
5044
|
isAgentDoor,
|
|
4987
5045
|
isDemoKey,
|
|
4988
5046
|
isKnownOf,
|