UNPKG

@applicaster/zapp-react-native-utils

Version:

Applicaster Zapp React Native utilities package

77 lines (62 loc) 2.75 kB
import { createLogger } from "../../logger"; const { log_error } = createLogger({ category: "AccessibilityManager", subsystem: "AppUtils", }); /** * Calculates the reading time for a given text based on word count * @param text - The text to calculate the reading time for (string or number) * @param wordsPerMinute - Words per minute reading speed (default: 140) * @param minimumPause - Minimum pause time in milliseconds (default: 500) * @param announcementDelay - Additional delay for announcement in milliseconds (default: 700) * @returns The reading time in milliseconds */ export function calculateReadingTime( text: string | number, wordsPerMinute: number = 140, minimumPause: number = 500, announcementDelay: number = 700 ): number { if (typeof text !== "string" && typeof text !== "number") { log_error( `Invalid text input for reading time calculation got: ${ typeof text === "symbol" ? String(text) : text }` ); return 0; } const trimmed = typeof text === "number" ? String(text) : text.trim(); if (!trimmed) { return 0; } // Count words (split on whitespace and punctuation, keep alnum boundaries) const words = trimmed .split(/(?<=\d)(?=[a-zA-Z])|(?<=[a-zA-Z])(?=\d)|[^\w\s]+|\s+/) .filter(Boolean).length; // Count spaces - multiple consecutive spaces add extra pause time const spaceMatches: string[] = trimmed.match(/\s+/g) || []; const totalSpaces = spaceMatches.reduce( (sum: number, match: string) => sum + match.length, 0 ); const extraSpaces = Math.max(0, totalSpaces - (words - 1)); // words-1 is normal spacing // Heuristic: punctuation increases TTS duration beyond word-based WPM. // Commas typically introduce short pauses, sentence terminators longer ones. const commaCount = (trimmed.match(/,/g) || []).length; const semicolonCount = (trimmed.match(/;/g) || []).length; const colonCount = (trimmed.match(/:/g) || []).length; const dashCount = (trimmed.match(/\u2013|\u2014|-/g) || []).length; // – — - const sentenceEndCount = (trimmed.match(/[.!?](?!\d)/g) || []).length; const commaPauseMs = 220; // short prosody pause for "," const midPauseMs = 260; // for ";", ":", dashes const sentenceEndPauseMs = 420; // for ".", "!", "?" const extraSpacePauseMs = 50; // per extra space beyond normal spacing const punctuationPause = commaCount * commaPauseMs + (semicolonCount + colonCount + dashCount) * midPauseMs + sentenceEndCount * sentenceEndPauseMs + extraSpaces * extraSpacePauseMs; const baseByWordsMs = (words / wordsPerMinute) * 60 * 1000; const estimatedMs = Math.max(minimumPause, baseByWordsMs + punctuationPause); return estimatedMs + announcementDelay; }