@ioris/core
Version:
This package provides the core functionality for the [@ioris](https://www.npmjs.com/search?q=%40ioris) ecosystem for managing music lyrics with time synchronization.
5 lines • 54.9 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../src/Constants.ts", "../src/factories/createChar.ts", "../src/factories/createWord.ts", "../src/factories/createLine.ts", "../src/factories/createParagraph.ts", "../src/factories/createLyric.ts", "../src/utils/helpers.ts", "../src/utils/current.ts", "../src/utils/navigation.ts", "../src/utils/analysis.ts", "../src/utils/grid.ts", "../src/utils/update.ts"],
"sourcesContent": ["export const CHAR_TYPES = {\n WHITESPACE: \"whitespace\",\n ALPHABET: \"alphabet\",\n NUMBER: \"number\",\n KANJI: \"kanji\",\n HIRAGANA: \"hiragana\",\n KATAKANA: \"katakana\",\n OTHER: \"other\",\n} as const;\n\nexport type CharType = (typeof CHAR_TYPES)[keyof typeof CHAR_TYPES];\n\nexport type WordTimeline = {\n wordID: string;\n text: string;\n begin: number;\n end: number;\n hasWhitespace?: boolean;\n hasNewLine?: boolean;\n};\n", "import { CHAR_TYPES, type CharType } from \"../Constants\";\nimport type { Char } from \"../types\";\n\nexport type CreateCharArgs = {\n wordID: string;\n position: number;\n text: string;\n begin: number;\n end: number;\n};\n\nfunction getCharType(text: string): CharType {\n if (/^\\s+$/.test(text)) {\n return CHAR_TYPES.WHITESPACE;\n }\n if (/^[a-zA-Z]+$/.test(text)) {\n return CHAR_TYPES.ALPHABET;\n }\n if (/^[0-9]+$/.test(text)) {\n return CHAR_TYPES.NUMBER;\n }\n if (/^[\\u4E00-\\u9FFF]+$/.test(text)) {\n return CHAR_TYPES.KANJI;\n }\n if (/^[\\u3040-\\u309F]+$/.test(text)) {\n return CHAR_TYPES.HIRAGANA;\n }\n if (/^[\\u30A0-\\u30FF]+$/.test(text)) {\n return CHAR_TYPES.KATAKANA;\n }\n return CHAR_TYPES.OTHER;\n}\n\nexport function createChar(args: CreateCharArgs): Char {\n const id = `char-${crypto.randomUUID()}`;\n const type = getCharType(args.text);\n\n return Object.freeze({\n id,\n wordID: args.wordID,\n text: args.text,\n type,\n position: args.position,\n begin: args.begin,\n end: args.end,\n });\n}\n", "import type { WordTimeline } from \"../Constants\";\nimport type { Word } from \"../types\";\nimport { createChar } from \"./createChar\";\n\nexport type CreateWordArgs = {\n lineID: string;\n position: number;\n timeline: WordTimeline | Omit<WordTimeline, \"wordID\">;\n};\n\nfunction isWordTimeline(\n timeline: WordTimeline | Omit<WordTimeline, \"wordID\">,\n): timeline is WordTimeline {\n return (timeline as WordTimeline).wordID !== undefined;\n}\n\nexport function createWord(args: CreateWordArgs): Word {\n const id = isWordTimeline(args.timeline)\n ? args.timeline.wordID\n : `word-${crypto.randomUUID()}`;\n\n const timeline: WordTimeline = {\n ...args.timeline,\n wordID: id,\n hasNewLine: args.timeline.hasNewLine ?? false,\n hasWhitespace: args.timeline.hasWhitespace ?? false,\n };\n\n const charTexts = timeline.text.split(\"\");\n const wordDuration = timeline.end - timeline.begin;\n const durationByChar = wordDuration / charTexts.length;\n\n const chars = charTexts.map((char, index) => {\n const position = index + 1;\n return createChar({\n wordID: id,\n position,\n text: char,\n begin: timeline.begin + index * durationByChar,\n end: timeline.begin + position * durationByChar,\n });\n });\n\n return Object.freeze({\n id,\n lineID: args.lineID,\n position: args.position,\n timeline,\n chars,\n });\n}\n", "import type { WordTimeline } from \"../Constants\";\nimport type { Line, Word } from \"../types\";\nimport { createWord } from \"./createWord\";\n\nexport type CreateLineArgs = {\n position: number;\n timelines: WordTimeline[];\n jointNearWord?: boolean;\n};\n\nfunction confirmJointNearWord(\n timeline: WordTimeline,\n nextTimeline: WordTimeline | undefined,\n lastWord: Word | undefined,\n jointNearWord: boolean,\n): { isJoint: boolean; hasWhitespace: boolean } | undefined {\n const isWhitespace = /^\\s+$/.test(timeline.text);\n if (isWhitespace) {\n return undefined;\n }\n\n const nextIsWhitespace = nextTimeline\n ? /^\\s+$/.test(nextTimeline.text)\n : false;\n const hasWhitespace = timeline.hasWhitespace || nextIsWhitespace;\n\n if (jointNearWord !== false) {\n if (\n lastWord &&\n lastWord.timeline.end - timeline.begin <= 0.1 &&\n !lastWord.timeline.hasNewLine &&\n !lastWord.timeline.hasWhitespace\n ) {\n return { isJoint: true, hasWhitespace };\n }\n }\n return { isJoint: false, hasWhitespace };\n}\n\nexport function createLine(args: CreateLineArgs): Line {\n const id = `line-${crypto.randomUUID()}`;\n const sortedTimelines = args.timelines.sort((a, b) => a.begin - b.begin);\n\n const words: Word[] = [];\n\n for (let index = 0; index < sortedTimelines.length; index++) {\n const timeline = sortedTimelines[index];\n const nextTimeline = sortedTimelines[index + 1];\n const lastWord = words[words.length - 1];\n\n const jointResult = confirmJointNearWord(\n timeline,\n nextTimeline,\n lastWord,\n args.jointNearWord === true,\n );\n\n if (!jointResult) {\n continue;\n }\n\n const { isJoint, hasWhitespace } = jointResult;\n\n if (lastWord && isJoint) {\n const updatedWord = createWord({\n lineID: id,\n position: words.length,\n timeline: {\n wordID: lastWord.id,\n begin: lastWord.timeline.begin,\n end: timeline.end,\n text: lastWord.timeline.text + timeline.text,\n hasNewLine: timeline.hasNewLine === true,\n hasWhitespace,\n },\n });\n words[words.length - 1] = updatedWord;\n } else {\n const word = createWord({\n lineID: id,\n position: words.length + 1,\n timeline: {\n ...timeline,\n hasWhitespace,\n },\n });\n words.push(word);\n }\n }\n\n return Object.freeze({\n id,\n position: args.position,\n words,\n });\n}\n", "import type { WordTimeline } from \"../Constants\";\nimport type { Paragraph } from \"../types\";\nimport { createLine } from \"./createLine\";\n\nexport type CreateParagraphArgs = {\n position: number;\n timelines: WordTimeline[][];\n lineTokenizer?: (lineArgs: {\n position: number;\n timelines: WordTimeline[];\n }) => Promise<\n Map<\n number,\n { position: number; timelines: WordTimeline[]; jointNearWord?: boolean }\n >\n >;\n paragraphTokenizer?: (\n timelines: WordTimeline[][],\n ) => Promise<WordTimeline[][]>;\n};\n\nexport async function createParagraph(\n args: CreateParagraphArgs,\n): Promise<Paragraph> {\n const id = `paragraph-${crypto.randomUUID()}`;\n\n let timelines = args.timelines;\n\n if (args.paragraphTokenizer) {\n timelines = await args.paragraphTokenizer(timelines);\n }\n\n const mergedTimelines = timelines.reduce<WordTimeline[][]>(\n (acc, timeline) => {\n const lastTimelines = acc[acc.length - 1];\n const last = lastTimelines\n ? lastTimelines[lastTimelines.length - 1]\n : null;\n const thisFirst = timeline[0];\n\n if (!thisFirst) {\n console.error(\"thisFirst is undefined\", timelines, timeline);\n return acc;\n }\n\n if (\n last &&\n (last.end > thisFirst.begin ||\n (last.end === thisFirst.begin && last.text.length < 6))\n ) {\n last.end = thisFirst.end;\n last.text += ` ${thisFirst.text}`;\n return acc;\n }\n\n acc.push(timeline);\n return acc;\n },\n [],\n );\n\n const lineCreateArgsPromises = mergedTimelines.map(\n async (timeline, index) => {\n const position = index + 1;\n\n if (args.lineTokenizer) {\n return await args.lineTokenizer({ position, timelines: timeline });\n }\n\n return new Map([\n [\n position,\n {\n jointNearWord: true,\n position,\n timelines: timeline,\n },\n ],\n ]);\n },\n );\n\n const resolvedArgsArray = await Promise.all(lineCreateArgsPromises);\n\n const lines = [];\n\n for (const lineByPosition of resolvedArgsArray) {\n for (const [, lineArgs] of lineByPosition) {\n const position = lines.length + 1;\n const line = createLine({\n ...lineArgs,\n position,\n });\n lines.push(line);\n }\n }\n\n return Object.freeze({\n id,\n position: args.position,\n lines,\n });\n}\n", "import type { Lyric, WordTimeline } from \"../types\";\nimport { createParagraph } from \"./createParagraph\";\n\nexport type CreateLyricArgs = {\n initID?: boolean;\n id?: string;\n resourceID: string;\n duration: number;\n timelines: WordTimeline[][][];\n lineTokenizer?: (lineArgs: {\n position: number;\n timelines: WordTimeline[];\n }) => Promise<\n Map<\n number,\n { position: number; timelines: WordTimeline[]; jointNearWord?: boolean }\n >\n >;\n paragraphTokenizer?: (\n timelines: WordTimeline[][],\n ) => Promise<WordTimeline[][]>;\n offsetSec?: number;\n};\n\nexport async function createLyric(args: CreateLyricArgs): Promise<Lyric> {\n const id = args.id\n ? args.id\n : args.initID\n ? `lyric-${crypto.randomUUID()}`\n : \"\";\n\n const paragraphPromises = args.timelines.map(async (timelines, index) => {\n const position = index + 1;\n return await createParagraph({\n position,\n timelines,\n lineTokenizer: args.lineTokenizer,\n paragraphTokenizer: args.paragraphTokenizer,\n });\n });\n\n const paragraphs = await Promise.all(paragraphPromises);\n\n return Object.freeze({\n id,\n resourceID: args.resourceID,\n duration: Number(args.duration.toFixed(2)),\n offsetSec: args.offsetSec ?? 0,\n paragraphs,\n });\n}\n", "import type { Char, Line, Lyric, Paragraph, TimeOptions, Word } from \"../types\";\n\nexport function getWords(lyric: Lyric): Word[] {\n return lyric.paragraphs.flatMap((paragraph) =>\n paragraph.lines.flatMap((line) => line.words),\n );\n}\n\nexport function getLines(lyric: Lyric): Line[] {\n return lyric.paragraphs\n .flatMap((paragraph) => paragraph.lines)\n .sort((a, b) => getLineBegin(a) - getLineBegin(b));\n}\n\nexport function getParagraphs(lyric: Lyric): Paragraph[] {\n return [...lyric.paragraphs].sort(\n (a, b) => getParagraphBegin(a) - getParagraphBegin(b),\n );\n}\n\nexport function getWordChars(word: Word): Char[] {\n return [...word.chars];\n}\n\nexport function getLineChars(line: Line): Char[] {\n return line.words.flatMap((word) => getWordChars(word));\n}\n\nexport function getLineWords(line: Line): Word[] {\n return [...line.words];\n}\n\nexport function getParagraphLines(paragraph: Paragraph): Line[] {\n return [...paragraph.lines];\n}\n\nexport function getCharBegin(char: Char): number {\n return char.begin;\n}\n\nexport function getCharEnd(char: Char): number {\n return char.end;\n}\n\nexport function getWordBegin(word: Word): number {\n return word.timeline.begin;\n}\n\nexport function getWordEnd(word: Word): number {\n return word.timeline.end;\n}\n\nexport function getLineBegin(line: Line): number {\n return line.words[0]?.timeline.begin || 0;\n}\n\nexport function getLineEnd(line: Line): number {\n return line.words[line.words.length - 1]?.timeline.end || 0;\n}\n\nexport function getParagraphBegin(paragraph: Paragraph): number {\n return paragraph.lines[0] ? getLineBegin(paragraph.lines[0]) : 0;\n}\n\nexport function getParagraphEnd(paragraph: Paragraph): number {\n const lastLine = paragraph.lines[paragraph.lines.length - 1];\n return lastLine ? getLineEnd(lastLine) : 0;\n}\n\nexport function getCharDuration(char: Char): number {\n const begin = getCharBegin(char);\n const end = getCharEnd(char);\n if (begin >= end) {\n console.error(\n `Cannot calculate duration of invalid char: ${char.id} ${begin}-${end}`,\n );\n }\n return end - begin;\n}\n\nexport function getWordDuration(word: Word): number {\n const begin = getWordBegin(word);\n const end = getWordEnd(word);\n if (begin >= end) {\n console.error(\n `Cannot calculate duration of invalid word: ${word.id} ${begin}-${end}`,\n );\n }\n return end - begin;\n}\n\nexport function getLineDuration(line: Line): number {\n const begin = getLineBegin(line);\n const end = getLineEnd(line);\n if (begin >= end) {\n console.error(\n `Cannot calculate duration of invalid line: ${line.id} ${begin}-${end}`,\n );\n }\n return end - begin;\n}\n\nexport function getParagraphDuration(paragraph: Paragraph): number {\n const begin = getParagraphBegin(paragraph);\n const end = getParagraphEnd(paragraph);\n if (begin >= end) {\n console.error(\n `Cannot calculate duration of invalid paragraph: ${paragraph.id} ${begin}-${end}`,\n );\n }\n return end - begin;\n}\n\nexport function getWordText(word: Word): string {\n return word.chars.map((char) => char.text).join(\"\");\n}\n\nexport function getLineText(line: Line): string {\n return line.words\n .map(\n (word) =>\n `${getWordText(word)}${!word.timeline.hasNewLine && word.timeline.hasWhitespace ? \" \" : \"\"}${\n word.timeline.hasNewLine ? \"\\n\" : \"\"\n }`,\n )\n .join(\"\");\n}\n\nexport function isCurrentTime(\n begin: number,\n end: number,\n now: number,\n options: TimeOptions = {},\n): boolean {\n const offset = options.offset ?? 0;\n const equal = options.equal ?? true;\n\n return equal\n ? begin <= now + offset && now + offset <= end\n : begin < now + offset && now + offset < end;\n}\n\nexport function findParagraphAt(\n lyric: Lyric,\n position: number,\n): Paragraph | undefined {\n return lyric.paragraphs.find((p) => p.position === position);\n}\n\nexport function findLineAt(\n paragraph: Paragraph,\n position: number,\n): Line | undefined {\n return paragraph.lines.find((l) => l.position === position);\n}\n\nexport function findWordAt(line: Line, position: number): Word | undefined {\n return line.words.find((w) => w.position === position);\n}\n\nexport function findCharAt(word: Word, position: number): Char | undefined {\n return word.chars.find((c) => c.position === position);\n}\n", "import type { Char, Line, Lyric, Paragraph, TimeOptions, Word } from \"../types\";\nimport {\n getCharBegin,\n getCharEnd,\n getLineBegin,\n getLineEnd,\n getLines,\n getLineWords,\n getParagraphBegin,\n getParagraphEnd,\n getParagraphLines,\n getParagraphs,\n getWordBegin,\n getWordChars,\n getWordEnd,\n isCurrentTime,\n} from \"./helpers\";\n\nexport function getCurrentParagraph(\n lyric: Lyric,\n now: number,\n options: TimeOptions = { offset: lyric.offsetSec, equal: true },\n): Paragraph | undefined {\n const offset = options.offset ?? lyric.offsetSec;\n const equal = options.equal ?? true;\n\n return getParagraphs(lyric).find((paragraph) => {\n const begin = getParagraphBegin(paragraph);\n const end = getParagraphEnd(paragraph);\n return isCurrentTime(begin, end, now, { offset, equal });\n });\n}\n\nexport function getCurrentLine(\n lyric: Lyric,\n now: number,\n options: TimeOptions = { offset: lyric.offsetSec, equal: true },\n): Line | undefined {\n const offset = options.offset ?? lyric.offsetSec;\n const equal = options.equal ?? true;\n\n const currentParagraph = getCurrentParagraph(lyric, now, { offset, equal });\n if (!currentParagraph) return undefined;\n\n return getParagraphLines(currentParagraph).find((line) => {\n const begin = getLineBegin(line);\n const end = getLineEnd(line);\n return isCurrentTime(begin, end, now, { offset, equal });\n });\n}\n\nexport function getCurrentWord(\n lyric: Lyric,\n now: number,\n options: TimeOptions = { offset: lyric.offsetSec, equal: true },\n): Word | undefined {\n const offset = options.offset ?? lyric.offsetSec;\n const equal = options.equal ?? true;\n\n const currentLine = getCurrentLine(lyric, now, { offset, equal });\n if (!currentLine) return undefined;\n\n return getLineWords(currentLine)\n .sort((a, b) => getWordBegin(b) - getWordBegin(a))\n .find((word) => {\n const begin = getWordBegin(word);\n const end = getWordEnd(word);\n return isCurrentTime(begin, end, now, { offset, equal });\n });\n}\n\nexport function getCurrentChar(\n lyric: Lyric,\n now: number,\n options: TimeOptions = { offset: lyric.offsetSec, equal: true },\n): Char | undefined {\n const offset = options.offset ?? lyric.offsetSec;\n const equal = options.equal ?? true;\n\n const currentWord = getCurrentWord(lyric, now, { offset, equal });\n if (!currentWord) return undefined;\n\n return getWordChars(currentWord)\n .sort((a, b) => getCharBegin(b) - getCharBegin(a))\n .find((char) => {\n const begin = getCharBegin(char);\n const end = getCharEnd(char);\n return isCurrentTime(begin, end, now, { offset, equal });\n });\n}\n\nexport function getCurrentParagraphFromLine(\n line: Line,\n lyric: Lyric,\n): Paragraph | undefined {\n return getParagraphs(lyric).find((paragraph) =>\n getParagraphLines(paragraph).some((l) => l.id === line.id),\n );\n}\n\nexport function getCurrentLineFromWord(\n word: Word,\n lyric: Lyric,\n): Line | undefined {\n return getLines(lyric).find((line) =>\n getLineWords(line).some((w) => w.id === word.id),\n );\n}\n\nexport function getCurrentWordFromChar(\n char: Char,\n lyric: Lyric,\n): Word | undefined {\n for (const paragraph of getParagraphs(lyric)) {\n for (const line of getParagraphLines(paragraph)) {\n for (const word of getLineWords(line)) {\n if (getWordChars(word).some((c) => c.id === char.id)) {\n return word;\n }\n }\n }\n }\n return undefined;\n}\n", "import type { Line, Lyric, Paragraph, TimeOptions, Word } from \"../types\";\nimport { getCurrentLine } from \"./current\";\nimport {\n getLineBegin,\n getLineEnd,\n getLines,\n getLineWords,\n getParagraphBegin,\n getParagraphEnd,\n getParagraphLines,\n getParagraphs,\n getWordBegin,\n getWordEnd,\n} from \"./helpers\";\n\nexport function getNextParagraph(\n lyric: Lyric,\n now: number,\n options: TimeOptions = { offset: lyric.offsetSec },\n): Paragraph | undefined {\n const offset = options.offset ?? 0;\n return getParagraphs(lyric).find((p) => getParagraphBegin(p) > now + offset);\n}\n\nexport function getNextLine(\n lyric: Lyric,\n now: number,\n options: TimeOptions = { offset: lyric.offsetSec },\n): Line | undefined {\n const offset = options.offset ?? 0;\n return getLines(lyric).find((l) => getLineBegin(l) > now + offset);\n}\n\nexport function getNextWord(\n lyric: Lyric,\n now: number,\n options: TimeOptions = { offset: lyric.offsetSec },\n): Word | undefined {\n const offset = options.offset ?? 0;\n const currentLine = getCurrentLine(lyric, now);\n\n if (currentLine) {\n const nextWordInLine = getLineWords(currentLine)\n .sort((a, b) => getWordBegin(a) - getWordBegin(b))\n .find((word) => getWordBegin(word) > now + offset);\n\n if (nextWordInLine) {\n return nextWordInLine;\n }\n }\n\n const nextLine = getNextLine(lyric, now, { offset });\n return nextLine ? getLineWords(nextLine)[0] : undefined;\n}\n\nexport function getPrevParagraph(\n lyric: Lyric,\n now: number,\n options: TimeOptions = { offset: lyric.offsetSec },\n): Paragraph | undefined {\n const offset = options.offset ?? 0;\n return getParagraphs(lyric)\n .reverse()\n .find((p) => getParagraphEnd(p) < now + offset);\n}\n\nexport function getPrevLine(\n lyric: Lyric,\n now: number,\n options: TimeOptions = { offset: lyric.offsetSec },\n): Line | undefined {\n const offset = options.offset ?? 0;\n return getLines(lyric)\n .reverse()\n .find((l) => getLineEnd(l) < now + offset);\n}\n\nexport function getPrevWord(\n lyric: Lyric,\n now: number,\n options: TimeOptions = { offset: lyric.offsetSec },\n): Word | undefined {\n const offset = options.offset ?? 0;\n const currentLine = getCurrentLine(lyric, now);\n\n if (currentLine) {\n const prevWordInLine = getLineWords(currentLine)\n .sort((a, b) => getWordBegin(b) - getWordBegin(a))\n .find((word) => getWordEnd(word) < now + offset);\n\n if (prevWordInLine) {\n return prevWordInLine;\n }\n }\n\n const prevLine = getPrevLine(lyric, now, { offset });\n if (prevLine) {\n const words = getLineWords(prevLine);\n return words[words.length - 1];\n }\n\n return undefined;\n}\n\nexport function getFirstWord(line: Line): Word | undefined {\n return getLineWords(line)[0];\n}\n\nexport function getLastWord(line: Line): Word | undefined {\n const words = getLineWords(line);\n return words[words.length - 1];\n}\n\nexport function getLinePositionInLyric(line: Line, lyric: Lyric): number {\n return getLines(lyric).findIndex((l) => l.id === line.id) + 1;\n}\n\nexport function getLinePositionInParagraph(\n line: Line,\n lyric: Lyric,\n): number | undefined {\n for (const paragraph of getParagraphs(lyric)) {\n const lines = getParagraphLines(paragraph);\n const index = lines.findIndex((l) => l.id === line.id);\n if (index !== -1) {\n return index + 1;\n }\n }\n return undefined;\n}\n", "import { CHAR_TYPES } from \"../Constants\";\nimport type {\n Char,\n Line,\n Lyric,\n LyricSummary,\n Paragraph,\n TimeOptions,\n VoidPeriod,\n Word,\n} from \"../types\";\nimport {\n getCurrentChar,\n getCurrentLine,\n getCurrentParagraph,\n getCurrentWord,\n} from \"./current\";\nimport {\n getLineBegin,\n getLineDuration,\n getLineEnd,\n getLines,\n getLineWords,\n getParagraphDuration,\n getParagraphEnd,\n getParagraphLines,\n getParagraphs,\n getWordBegin,\n getWordChars,\n getWordDuration,\n getWordEnd,\n getWords,\n} from \"./helpers\";\nimport {\n getNextLine,\n getNextParagraph,\n getNextWord,\n getPrevLine,\n getPrevParagraph,\n getPrevWord,\n} from \"./navigation\";\n\nexport function calculateSpeed(\n items: { duration: () => number; chars?: () => Char[] }[],\n): number {\n const speeds = items.map((item) => {\n const duration = item.duration();\n if (item.chars) {\n const charCount = item.chars().reduce((acc, char) => {\n if (char.type === CHAR_TYPES.WHITESPACE) return acc;\n return (\n acc +\n (char.type === CHAR_TYPES.ALPHABET || char.type === CHAR_TYPES.NUMBER\n ? 0.5\n : 1)\n );\n }, 0);\n return charCount / duration;\n }\n return 0;\n });\n\n speeds.sort((a, b) => a - b);\n const half = Math.floor(speeds.length / 2);\n return Number.parseFloat(\n (speeds.length % 2\n ? speeds[half]\n : (speeds[half - 1] + speeds[half]) / 2\n ).toFixed(2),\n );\n}\n\nexport function getWordSpeed(word: Word): number {\n const duration = getWordDuration(word);\n return (\n getWordChars(word).reduce((acc, char) => {\n if (char.type === CHAR_TYPES.WHITESPACE) return acc;\n return (\n acc +\n (char.type === CHAR_TYPES.ALPHABET || char.type === CHAR_TYPES.NUMBER\n ? 0.5\n : 1)\n );\n }, 0) / duration\n );\n}\n\nexport function getLineSpeed(line: Line): number {\n const words = getLineWords(line).map((word) => ({\n duration: () => getWordDuration(word),\n chars: () => getWordChars(word),\n }));\n return calculateSpeed(words);\n}\n\nexport function getParagraphSpeed(paragraph: Paragraph): number {\n const lines = getParagraphLines(paragraph).map((line) => ({\n duration: () => getLineDuration(line),\n chars: () => getLineWords(line).flatMap((word) => getWordChars(word)),\n }));\n return calculateSpeed(lines);\n}\n\nexport function getLyricSpeed(lyric: Lyric): number {\n const paragraphs = getParagraphs(lyric).map((paragraph) => ({\n duration: () => getParagraphDuration(paragraph),\n chars: () =>\n getParagraphLines(paragraph).flatMap((line) =>\n getLineWords(line).flatMap((word) => getWordChars(word)),\n ),\n }));\n return calculateSpeed(paragraphs);\n}\n\nexport function getVoidPeriods(lyric: Lyric): VoidPeriod[] {\n const words = getWords(lyric);\n\n return words.reduce<VoidPeriod[]>((acc, word, index) => {\n const isFirstWord = index === 0;\n const isLastWord = index === words.length - 1;\n\n if (isFirstWord && getWordBegin(word) > 0) {\n acc.push({\n begin: 0,\n end: getWordBegin(word),\n duration: Number(getWordBegin(word).toFixed(2)),\n });\n }\n\n if (isLastWord && lyric.duration - getWordEnd(word) > 0) {\n acc.push({\n begin: getWordEnd(word),\n end: lyric.duration,\n duration: Number((lyric.duration - getWordEnd(word)).toFixed(2)),\n });\n }\n\n const prevWord = words[index - 1];\n if (prevWord && getWordBegin(word) - getWordEnd(prevWord) > 0) {\n acc.push({\n begin: getWordEnd(prevWord),\n end: getWordBegin(word),\n duration: Number(\n (getWordBegin(word) - getWordEnd(prevWord)).toFixed(2),\n ),\n });\n }\n\n return acc;\n }, []);\n}\n\nexport function isVoidTime(lyric: Lyric, now: number): boolean {\n const voids = getVoidPeriods(lyric);\n return voids.some(({ begin, end }) => now >= begin && now <= end);\n}\n\nexport function getParagraphAverageLineDuration(paragraph: Paragraph): number {\n const durations = getParagraphLines(paragraph).map((line) =>\n getLineDuration(line),\n );\n return (\n durations.reduce((sum, duration) => sum + duration, 0) / durations.length\n );\n}\n\nexport function getCurrentSummary(\n lyric: Lyric,\n now: number,\n options: TimeOptions = { offset: lyric.offsetSec },\n): LyricSummary {\n const currentParagraph = getCurrentParagraph(lyric, now, options);\n const nextParagraph = getNextParagraph(lyric, now, options);\n const prevParagraph = getPrevParagraph(lyric, now, options);\n const allLines = getLines(lyric);\n const currentLine = getCurrentLine(lyric, now, options);\n\n const lastLineIndexInParagraph = currentParagraph\n ? getParagraphLines(currentParagraph).length - 1\n : undefined;\n\n const nextLine = getNextLine(lyric, now, options);\n const nextWord = getNextWord(lyric, now, options);\n const prevLine = getPrevLine(lyric, now, options);\n const prevWord = getPrevWord(lyric, now, options);\n const currentWord = getCurrentWord(lyric, now, options);\n const currentChar = getCurrentChar(lyric, now, options);\n\n const beforeCurrentTimeDiff =\n currentLine && prevLine\n ? getLineBegin(currentLine) - getLineEnd(prevLine)\n : undefined;\n\n const isCurrentParagraphAverageTimeDiff = currentParagraph\n ? getParagraphAverageLineDuration(currentParagraph) < 1.5\n : undefined;\n\n const isConnected =\n isCurrentParagraphAverageTimeDiff === true &&\n beforeCurrentTimeDiff !== undefined &&\n beforeCurrentTimeDiff < 0.1;\n\n const isParagraphFinishMotion = currentParagraph\n ? getParagraphEnd(currentParagraph) < now\n : true;\n\n const nextWaitingTime = nextLine ? getLineBegin(nextLine) - now : undefined;\n const lastLineIndex = allLines.length - 1;\n\n const lyricTextPerSecond = getLyricSpeed(lyric);\n const paragraphTextPerSecond = currentParagraph\n ? getParagraphSpeed(currentParagraph)\n : undefined;\n const lineTextPerSecond = currentLine ? getLineSpeed(currentLine) : undefined;\n\n return {\n currentChar,\n currentLine,\n currentParagraph,\n currentWord,\n isConnected,\n isParagraphFinishMotion,\n lastLineIndex,\n lastLineIndexInParagraph,\n nextLine,\n nextWord,\n nextParagraph,\n nextWaitingTime,\n prevLine,\n prevWord,\n prevParagraph,\n lyricTextPerSecond,\n paragraphTextPerSecond,\n lineTextPerSecond,\n };\n}\n", "import type { CharPosition, GridPosition, Line, Lyric, Word } from \"../types\";\nimport { getLines, getLineWords, getWordChars } from \"./helpers\";\n\nexport function getWordGridPositions(line: Line): Map<string, GridPosition> {\n const words = getLineWords(line);\n const map = new Map<string, GridPosition>();\n\n let row = 1;\n let column = 0;\n\n for (let i = 0; i < words.length; i++) {\n const word = words[i];\n const prevWord = words[i - 1];\n\n if (prevWord?.timeline.hasNewLine) {\n row++;\n column = 1;\n } else {\n column++;\n }\n\n map.set(word.id, {\n row,\n column,\n word,\n });\n }\n\n return map;\n}\n\nexport function getWordsByRow(line: Line): Map<number, Word[]> {\n const gridPositions = getWordGridPositions(line);\n return Array.from(gridPositions.values()).reduce<Map<number, Word[]>>(\n (acc, position) => {\n if (!acc.has(position.row)) {\n acc.set(position.row, []);\n }\n acc.get(position.row)?.push(position.word);\n return acc;\n },\n new Map(),\n );\n}\n\nexport function getRowWords(line: Line, row: number): Word[] {\n const wordsByRow = getWordsByRow(line);\n return wordsByRow.get(row) || [];\n}\n\nexport function getWordRowPosition(\n line: Line,\n wordID: string,\n): number | undefined {\n const gridPositions = getWordGridPositions(line);\n return gridPositions.get(wordID)?.row;\n}\n\nexport function getMaxRowPosition(line: Line): number {\n const gridPositions = getWordGridPositions(line);\n return Math.max(...Array.from(gridPositions.values()).map((pos) => pos.row));\n}\n\nexport function getCharPositions(line: Line): Map<string, CharPosition> {\n const chars = getLineWords(line).flatMap((word) => getWordChars(word));\n const allWords = getLineWords(line);\n const wordPositionMap = getWordGridPositions(line);\n const map = new Map<string, CharPosition>();\n\n for (const char of chars) {\n const word = allWords.find((w) =>\n getWordChars(w).some((c) => c.id === char.id),\n );\n if (!word) {\n throw new Error(`word not found for character ID: ${char.id}`);\n }\n\n const inLinePosition = chars.findIndex((c) => c.id === char.id) + 1;\n const wordPosition = wordPositionMap.get(word.id);\n if (!wordPosition) {\n throw new Error(`wordPosition not found for word ID: ${word.id}`);\n }\n\n const sameRowWords = allWords.filter((w) => {\n const pos = wordPositionMap.get(w.id);\n return (\n pos?.row === wordPosition.row && w.timeline.begin < word.timeline.begin\n );\n });\n\n const charColumnPosition =\n sameRowWords.reduce<number>((sum, w) => {\n return sum + getWordChars(w).length;\n }, 0) + char.position;\n\n map.set(char.id, {\n row: wordPosition.row,\n column: charColumnPosition,\n inLinePosition,\n });\n }\n\n return map;\n}\n\nexport function getWordsByLineIDAndRowPosition(\n lyric: Lyric,\n): Map<string, Map<number, Map<number, Word>>> {\n const lines = getLines(lyric);\n const result = new Map<string, Map<number, Map<number, Word>>>();\n\n for (const line of lines) {\n const gridPositions = getWordGridPositions(line);\n const lineMap = new Map<number, Map<number, Word>>();\n\n for (const { row, column, word } of gridPositions.values()) {\n if (!lineMap.has(row)) {\n lineMap.set(row, new Map<number, Word>());\n }\n lineMap.get(row)?.set(column, word);\n }\n\n result.set(line.id, lineMap);\n }\n\n return result;\n}\n", "import { createLyric } from \"../factories/createLyric\";\nimport type { Lyric, WordTimeline } from \"../types\";\n\nexport type UpdateLyricArgs = {\n resourceID?: string;\n duration?: number;\n timelines?: WordTimeline[][][];\n offsetSec?: number;\n};\n\nexport async function updateLyric(\n lyric: Lyric,\n args: UpdateLyricArgs,\n): Promise<Lyric> {\n const resourceID = args.resourceID || lyric.resourceID;\n const duration = args.duration\n ? Number(args.duration.toFixed(2))\n : lyric.duration;\n const offsetSec =\n args.offsetSec !== undefined ? args.offsetSec : lyric.offsetSec;\n\n if (args.timelines === undefined) {\n return {\n ...lyric,\n resourceID,\n duration,\n offsetSec,\n };\n }\n\n return await createLyric({\n id: lyric.id,\n resourceID,\n duration,\n timelines: args.timelines,\n offsetSec,\n });\n}\n\nexport function getTimelines(lyric: Lyric): WordTimeline[][][] {\n return lyric.paragraphs.map((paragraph) =>\n paragraph.lines.map((line) => line.words.map((word) => word.timeline)),\n );\n}\n\nexport function getTimelinesByLine(lyric: Lyric): WordTimeline[] {\n return lyric.paragraphs.flatMap((paragraph, paragraphIndex) =>\n paragraph.lines.map((line, lineIndex) => {\n const firstWord = line.words[0];\n if (!firstWord) {\n throw new Error(\n `firstWord is undefined in paragraph ${paragraphIndex}, line ${lineIndex}`,\n );\n }\n const lastWord = line.words[line.words.length - 1];\n if (!lastWord) {\n throw new Error(\n `lastWord is undefined in paragraph ${paragraphIndex}, line ${lineIndex}`,\n );\n }\n return {\n wordID: firstWord.id,\n begin: firstWord.timeline.begin,\n end: lastWord.timeline.end,\n text: line.words.map((w) => w.timeline.text).join(\"\"),\n hasNewLine: lastWord.timeline.hasNewLine,\n hasWhitespace: lastWord.timeline.hasWhitespace,\n };\n }),\n );\n}\n"],
"mappings": "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