function addDays
addDays(day: DayKey, by: number): DayKey
The day by days after (or, negative, before) a day.
@johnmorrisdotca/tane 1.1.1 · 2 entry points · 67 exports
@johnmorrisdotca/taneaddDays below chance checkBlocks CLI_MAX_COUNT cliLanguage CliResult CliSurroundings counted CountedRandom CSV_COLUMNS dailySeed dayKey DayKey dayOfSeed daysBetween daySeed deriveSeed distinctBelow drawSeed DrawSeedOptions fillIn float fork freshSeed fromJSON fromText hashSeed inBlock int isDayKey isSeed Language languageOf MAX_CSV_ROWS mulberry32 nextDayStart normal pick Random randomAt runCli sample SAVE_FORMAT savedStream SavedStream SEED_MOST SeedBlock seededRandom seedFrom shuffle shuffled stateAt step Step StreamPosition STRINGS TaneStrings toCSV toJSON toText VERSION weightedIndex weightedPick
addDays(day: DayKey, by: number): DayKey
The day by days after (or, negative, before) a day.
below(random: Random, n: number): number
An integer in [0, n): one draw.
chance(random: Random, p: number): boolean
True with probability p, from 0 (never) to 1 (always): one draw.
checkBlocks(blocks: readonly SeedBlock[], most?: number): SeedBlock[]
The blocks in ascending order, checked: whole numbers, inside 1 to most, none overlapping another. Throws a RangeError naming the first fault.
CLI_MAX_COUNT: 10000
The most numbers one run prints.
cliLanguage(flag: string | undefined, env?: Record<string, string | undefined>, locale?: string): Language
The language the command line speaks: --lang, or the environment's, or the system's; Japanese for ja…, English for anything else.
type CliResult = { /** 0 when all went well, 1 when what was asked for could not be done, 2 when the command itself was wrong. */ code: 0 | 1 | 2; /** For standard output. */ out: string; /** For standard error. */ err: string; };
What the command line came to.
type CliSurroundings = { /** The environment, for the language (`LC_ALL`, `LC_MESSAGES`, `LANG`) and `NO_COLOR`. */ env?: Record<string, string | undefined>; /** Standard input, when `--stdin` asks for it: one item to a line. */ stdin?: string; /** Whether the output is a terminal that shows colour. `NO_COLOR` and `--no-color` still turn it off. */ colour?: boolean; /** The system's language where the environment na…
What the command line is run in. All of it is optional.
counted(seed: number, draws?: number): CountedRandom
A seeded stream that counts its own draws, so that it can be written down at any moment and picked up later: const random = counted(42), draw from it as from any stream, then keep random.position(). The numbers are those of mulberry32(seed), draw for draw.
type CountedRandom = Random & { /** The seed it was made from, as an unsigned 32-bit integer. */ readonly seed: number; /** How many numbers have been drawn from the seed so far, counting any it started after. */ readonly draws: number; /** Where it is now, as plain data to keep. */ position(): StreamPosition; };
A stream that knows where it is: call it for the next number, as any Random; read seed and draws, or take its position().
CSV_COLUMNS: readonly ["draw", "value", "state"]
The columns of the CSV, in order.
dailySeed(at: Date, timeZone?: string): number
Today's seed, the date as a number: 2026-09-30 is 20260930. UTC unless a zone is named.
dayKey(at: Date, timeZone?: string): DayKey
The day a moment falls on, in UTC or in the named IANA time zone.
type DayKey = string;
A calendar date, YYYY-MM-DD.
dayOfSeed(seed: number, block: SeedBlock): DayKey | null
The day a seed names inside a block, or null for a seed that names none. The inverse of daySeed.
daysBetween(from: DayKey, to: DayKey): number
How many days to is after from: negative when it is before.
daySeed(day: DayKey, block: SeedBlock): number
A day's seed inside a block kept for it: the block's first seed plus the date as a number. With a block from 1,000,000,000, 2026-10-03 is 1,020,261,003: still readable, and never a seed drawn at random if the block is reserved when drawing (drawSeed).
deriveSeed(seed: number, ...labels: readonly (string | number)[]): number
A seed of its own for one part of something seeded: deriveSeed(game, "deck") and deriveSeed(game, "dice") are two unrelated streams from one game's seed, and adding a third part later moves neither. Labels may be text or integers and are read in order, so deriveSeed(s, "round", 3) is round 3's. Returns an unsigned 32-bit integer.
distinctBelow(random: Random, count: number, limit: number): number[]
count different integers below limit, in the order drawn, by drawing again whenever a number comes up twice. The draw count therefore depends on the luck of the stream; prefer sample for new code, and keep this where a stored seed already depends on it.
drawSeed(random: Random, options?: DrawSeedOptions): number
A seed from 1 to most, any of them as likely as another, skipping every reserved block: one draw. The draw is spread over the seeds that are left and then stepped over each block below it, so no seed is ever likelier than another and no draw is wasted.
type DrawSeedOptions = { /** The largest seed to draw. `SEED_MOST` unless said. */ readonly most?: number; /** Blocks a drawn seed never lands in. They must not overlap. */ readonly reserved?: readonly SeedBlock[]; };
Where a drawn seed may land.
fillIn(template: string, values: Record<string, string | number>): string
Put values into a string's braces: fillIn("Seed {seed}", { seed: 42 }) is "Seed 42". A brace with no value is left as it is.
float(random: Random, min: number, max: number): number
A number in [min, max): one draw.
fork(random: Random): Random
A new, independent stream split off another: it takes one draw from random and seeds a fresh generator from it. Use it to hand a part of the work its own stream, so drawing more there never shifts what comes after. For a sub-stream named by a label rather than by order, use deriveSeed.
freshSeed(options?: DrawSeedOptions): number
A new seed for something nobody asked for by number, drawn from Math.random.
fromJSON(text: string): StreamPosition | null
A position from JSON that toJSON wrote. Nothing in it is trusted: the seed and the draws must be whole numbers in range, the algorithm (when named) must be mulberry32, and the state (when given) must be the one that seed and those draws come to. Null when the text is not JSON, is not a position, does not add up, or is of a later format than this version reads.
fromText(text: string): StreamPosition | null
A position from a line toText wrote, with any space around it. Null for anything else, or for a later format.
hashSeed(text: string): number
A seed from any text: hashSeed("room-7") is the same unsigned 32-bit integer everywhere. FNV-1a over the UTF-16 code units, then MurmurHash3's finaliser, so "a" and "b" land far apart. Use it to seed from a name, a room code or a date string.
inBlock(seed: number, block: SeedBlock): boolean
Whether a seed falls inside a block.
int(random: Random, min: number, max: number): number
An integer from min to max, both included: one draw.
isDayKey(text: string): boolean
Whether a text is a real date written YYYY-MM-DD: 2026-02-30 is not.
isSeed(value: unknown, most?: number): value is number
Whether a value read from outside (an address, a request body) is a seed: an integer from 1 to most.
type Language = "en" | "ja";
The languages Tane speaks.
languageOf(tag: string | null | undefined): Language
The language a tag such as ja-JP or en_US.UTF-8 names: Japanese for anything that starts ja, English otherwise.
MAX_CSV_ROWS: 100000
The most rows toCSV writes at once.
mulberry32(seed: number): Random
A seeded stream: mulberry32(42) returns the same numbers every time it is made. The seed is read as an unsigned 32-bit integer, so any integer works and 2^32 + 1 is the same seed as 1.
nextDayStart(at: Date, timeZone?: string): Date
The first moment of the day after the one at falls on, in that zone: when a daily seed next changes. Found by searching the next 27 hours for the millisecond the date turns, so daylight saving and half-hour zones need no special case.
normal(random: Random, mean?: number, spread?: number): number
A number from a normal distribution (Box–Muller): two draws.
pick<T>(random: Random, items: readonly T[]): T
One item of a list, each as likely as the next: one draw. Throws on an empty list.
type Random = () => number;
A number in [0, 1), like Math.random, from a stream a seed fixes.
randomAt(seed: number, draws?: number): Random
A stream that starts draws numbers into seed's: randomAt(42, 7)() is the eighth number of mulberry32(42), reached without drawing the first seven. Use it to pick a stream up from a stored position.
runCli(args: readonly string[], around?: CliSurroundings): CliResult
Run the command line. See tane --help for what it takes. One seed serves the whole run, so the same command prints the same lines on every machine.
sample<T>(random: Random, items: readonly T[], count: number): T[]
count items of a list, no item twice, in the order drawn: a partial Fisher–Yates, one draw each. Asking for more than the list holds gives the whole list, shuffled.
SAVE_FORMAT: 1
The shape of the JSON and the text this package writes. It goes up only when a reader of the old shape would be wrong about the new one.
savedStream(position: StreamPosition): SavedStream
A position as the object toJSON writes: the format, the seed, the draws and the state they come to.
type SavedStream = { /** The shape of this object: `SAVE_FORMAT`. */ format: typeof SAVE_FORMAT; /** What wrote it, such as `"tane 1.1.1"`. For people; nothing reads it back. */ generator: string; /** The algorithm. Always `"mulberry32"`. */ algorithm: "mulberry32"; seed: number; draws: number; /** The generator's state at that position: `stateAt(seed, draws)`. Checked on the way back in. */ state: number; };
A stream's position as toJSON writes it.
SEED_MOST: number
The largest seed: it travels as a plain integer, so it stays a positive 32-bit signed one.
type SeedBlock = { readonly from: number; readonly size: number };
A range of seeds kept aside: from up to, not including, from + size.
seededRandom: (seed: number) => Random
A seeded stream. The name to reach for; mulberry32 is the same function, for anyone who wants to say which.
seedFrom(input: string | number): number
A seed from whatever a person typed or a link carried. A whole number from 0 to 2^32 − 1, as a number or as its digits, is that seed; any other text is hashed with hashSeed, so "table-7" is a seed as good as 42. Space around text is dropped first. Note that the text "42" and the number 42 are the same seed, and that hashSeed("42") is a different one.
shuffle<T>(random: Random, items: T[]): T[]
The list in place, in a random order (Fisher–Yates, from the end): one draw for each item but the first. Returns the same array.
shuffled<T>(random: Random, items: readonly T[]): T[]
A shuffled copy; the list given is left alone. The same order shuffle would make.
stateAt(seed: number, draws?: number): number
The generator's state after draws numbers have been taken from seed: an unsigned 32-bit integer. It is what step hands back as state after that many steps, worked out in one go. mulberry32(stateAt(seed, n)) carries on from the n-th draw.
step(state: number): Step
One step of mulberry32 as a pure function: the number drawn and the state to keep for the next one. step(seed) gives the same first number as mulberry32(seed)(), so a stream can be stored between requests as one integer and picked up exactly where it stopped.
type Step = { readonly value: number; readonly state: number };
One draw and the state after it, for code that keeps the state itself (in a database row, say).
type StreamPosition = { /** The seed the stream was made from, as an unsigned 32-bit integer. */ readonly seed: number; /** How many numbers have been drawn: 0 for a stream nothing has been taken from. */ readonly draws: number; };
Where a stream is: the seed it started from, and how many numbers have been drawn from it.
STRINGS: Record<Language, TaneStrings>
Every string, in both languages.
type TaneStrings = { /** The command line's help, whole. */ cliUsage: string; cliUnknown: string; cliNeeds: string; cliTryHelp: string; cliCountBad: string; cliSkipBad: string; cliIntBad: string; cliLangBad: string; cliZoneBad: string; cliBoth: string; cliOneJob: string; cliNothing: string; cliSampleBad: string; cliFresh: string; cliToday: string; cliNext: string; cliPositionBad: string; pagePitch: string; pageName:…
The names of the strings. Each is one line or one block of text.
toCSV(position: StreamPosition, count: number): string
The next count numbers from a position as CSV for a spreadsheet: a header, then one row a draw, with the draw's number counted from 1, its value, and the generator's state after it. Lines end CRLF, as RFC 4180 has it.
toJSON(position: StreamPosition): string
A position as JSON, two spaces deep, with the format's number first. fromJSON reads it back.
toText(position: StreamPosition): string
A position as one line to paste into a chat or a bug report: tane:1:42:7 is format 1, seed 42, 7 draws in.
VERSION: "1.1.1"
The version of this package, as package.json has it. A test holds the two together.
weightedIndex(random: Random, weights: readonly number[]): number
An index into weights, each chosen in proportion to its weight: one draw. Weights must not be negative; a list whose weights sum to nothing gives 0.
weightedPick<T>(random: Random, items: readonly T[], weights: readonly number[]): T
One item, chosen by the matching weight: one draw.
@johnmorrisdotca/tane/reactDailySeed useDailySeed useSeeded
type DailySeed = { readonly day: DayKey; readonly seed: number };
Today, as useDailySeed hands it back: the day written YYYY-MM-DD, and its seed.
useDailySeed(timeZone?: string): DailySeed
Today's day and seed, which change on their own at midnight in timeZone (UTC unless named): a page left open overnight moves to the new day's puzzle without a reload.
On the server this reads the server's clock; a page rendered just before midnight and hydrated just after will show the new day once it hydrates.
useSeeded<T>(seed: number, make: (random: Random): T) => T
Something made once from a seeded stream, and made again only when the seed changes: useSeeded(seed, (random) => shuffled(random, deck)). The stream is fresh each time, so the result depends on the seed alone, never on how many times the component rendered. make is read when the seed changes; for anything else it depends on, give the component a key.
この日本語は、まだ日本語を母語とする方の確認を受けていません。訂正を歓迎します。