export interface BreakActivity { category: "eyes" | "stretch" | "breathing" | "movement"; text: string; } export const breakActivities: BreakActivity[] = [ // Eyes { category: "eyes", text: "Look at something 20 feet away for 20 seconds" }, { category: "eyes", text: "Close your eyes and gently press your palms over them" }, { category: "eyes", text: "Slowly roll your eyes in circles, 5 times each direction" }, { category: "eyes", text: "Focus on a distant object, then a near one -- repeat 5 times" }, { category: "eyes", text: "Blink rapidly 20 times to refresh your eyes" }, { category: "eyes", text: "Look up, down, left, right -- hold each for 2 seconds" }, { category: "eyes", text: "Cup your hands over closed eyes and breathe deeply" }, { category: "eyes", text: "Trace a figure-8 with your eyes, slowly" }, { category: "eyes", text: "Look out the nearest window and find the farthest point" }, { category: "eyes", text: "Gently massage your temples in small circles" }, { category: "eyes", text: "Close your eyes and visualize a calm, dark space for 20 seconds" }, { category: "eyes", text: "Warm your palms by rubbing them together, then rest them over closed eyes" }, { category: "eyes", text: "Slowly shift your gaze along the horizon line outside" }, { category: "eyes", text: "Focus on the tip of your nose for 5 seconds, then a far wall" }, { category: "eyes", text: "Look at something green -- plants reduce eye strain naturally" }, { category: "eyes", text: "Close your eyes and gently press your eyebrows outward from center" }, { category: "eyes", text: "Squeeze your eyes shut for 3 seconds, then open wide -- repeat 5 times" }, { category: "eyes", text: "Trace the outline of a window frame with your eyes, slowly" }, // Stretches { category: "stretch", text: "Roll your shoulders backward slowly, 5 times" }, { category: "stretch", text: "Interlace fingers behind your back and open your chest" }, { category: "stretch", text: "Tilt your head to each side, holding for 10 seconds" }, { category: "stretch", text: "Stretch your arms overhead and reach for the ceiling" }, { category: "stretch", text: "Rotate your wrists in circles, 10 times each direction" }, { category: "stretch", text: "Clasp hands together and push palms away from you" }, { category: "stretch", text: "Gently twist your torso left and right from your chair" }, { category: "stretch", text: "Drop your chin to your chest and slowly roll your neck" }, { category: "stretch", text: "Extend each arm across your chest, hold for 15 seconds" }, { category: "stretch", text: "Open and close your hands, spreading fingers wide" }, { category: "stretch", text: "Place your right hand on your left knee and twist gently -- switch sides" }, { category: "stretch", text: "Reach one arm overhead and lean to the opposite side, hold 10 seconds each" }, { category: "stretch", text: "Interlace your fingers and flip your palms to the ceiling, push up" }, { category: "stretch", text: "Pull each finger gently backward for 3 seconds to stretch your forearms" }, { category: "stretch", text: "Press your palms together at chest height and push for 10 seconds" }, { category: "stretch", text: "Sit tall, reach behind to grab the back of your chair, and open your chest" }, { category: "stretch", text: "Cross one ankle over the opposite knee and lean forward gently" }, { category: "stretch", text: "Shrug your shoulders up to your ears, hold 5 seconds, release slowly" }, // Breathing { category: "breathing", text: "Inhale for 4 seconds, hold for 4, exhale for 6" }, { category: "breathing", text: "Take 5 deep belly breaths -- feel your diaphragm expand" }, { category: "breathing", text: "Box breathing: inhale 4s, hold 4s, exhale 4s, hold 4s" }, { category: "breathing", text: "Breathe in through your nose, out through your mouth -- 5 times" }, { category: "breathing", text: "Sigh deeply 3 times to release tension" }, { category: "breathing", text: "Place a hand on your chest and breathe so only your belly moves" }, { category: "breathing", text: "Alternate nostril breathing: 3 cycles each side" }, { category: "breathing", text: "Exhale completely, then take the deepest breath you can" }, { category: "breathing", text: "Count your breaths backward from 10 to 1" }, { category: "breathing", text: "Breathe in calm, breathe out tension -- 5 rounds" }, { category: "breathing", text: "4-7-8 breathing: inhale 4s, hold 7s, exhale slowly for 8s" }, { category: "breathing", text: "Take 3 breaths making your exhale twice as long as your inhale" }, { category: "breathing", text: "Breathe in for 2 counts, out for 2 -- gradually increase to 6 each" }, { category: "breathing", text: "Hum gently on each exhale for 5 breaths -- feel the vibration in your chest" }, { category: "breathing", text: "Imagine breathing in cool blue air and exhaling warm red air -- 5 rounds" }, { category: "breathing", text: "Place both hands on your ribs and breathe so you feel them expand sideways" }, { category: "breathing", text: "Breathe in through pursed lips slowly, then exhale in a long, steady stream" }, // Movement { category: "movement", text: "Stand up and walk to the nearest window" }, { category: "movement", text: "Do 10 standing calf raises" }, { category: "movement", text: "Walk to get a glass of water" }, { category: "movement", text: "Stand and do 5 gentle squats" }, { category: "movement", text: "Take a short walk around your room" }, { category: "movement", text: "Stand on one foot for 15 seconds, then switch" }, { category: "movement", text: "Do 10 arm circles, forward then backward" }, { category: "movement", text: "March in place for 30 seconds" }, { category: "movement", text: "Shake out your hands and arms for 10 seconds" }, { category: "movement", text: "Stand up, touch your toes, and slowly rise" }, { category: "movement", text: "Walk to the farthest room in your home and back" }, { category: "movement", text: "Do 5 wall push-ups -- hands on the wall, lean in and push back" }, { category: "movement", text: "Stand up and slowly shift your weight side to side for 20 seconds" }, { category: "movement", text: "Walk in a small circle, paying attention to each footstep" }, { category: "movement", text: "Rise onto your tiptoes, hold for 5 seconds, lower slowly -- repeat 5 times" }, { category: "movement", text: "Do a gentle standing forward fold -- let your arms hang loose" }, { category: "movement", text: "Step away from your desk and do 10 hip circles in each direction" }, { category: "movement", text: "Stand with your back against a wall and slide down into a gentle wall sit for 15 seconds" }, ]; const categoryIcons: Record = { eyes: "👁", stretch: "🤸", breathing: "🌬", movement: "🚶", }; const categoryLabels: Record = { eyes: "Eye Exercise", stretch: "Stretch", breathing: "Breathing", movement: "Movement", }; export function getCategoryIcon(cat: BreakActivity["category"]): string { return categoryIcons[cat]; } export function getCategoryLabel(cat: BreakActivity["category"]): string { return categoryLabels[cat]; } /** Pick a random activity, optionally excluding a previous one. * When config is provided, respects disabled/favorite/custom activity settings. */ export function pickRandomActivity( exclude?: BreakActivity, config?: { disabled_builtin_activities?: string[]; favorite_builtin_activities?: string[]; custom_activities?: Array<{ category: string; text: string; is_favorite: boolean; enabled: boolean }>; favorite_weight?: number; }, ): BreakActivity { const disabled = new Set(config?.disabled_builtin_activities ?? []); const favorites = new Set(config?.favorite_builtin_activities ?? []); const weight = config?.favorite_weight ?? 3; // Build pool: enabled builtins + enabled customs let pool: BreakActivity[] = breakActivities.filter((a) => !disabled.has(a.text)); // Add enabled custom activities if (config?.custom_activities) { for (const ca of config.custom_activities) { if (ca.enabled) { const cat = (["eyes", "stretch", "breathing", "movement"].includes(ca.category) ? ca.category : "movement") as BreakActivity["category"]; pool.push({ category: cat, text: ca.text }); } } } // Exclude previous if (exclude) { pool = pool.filter((a) => a.text !== exclude.text); } if (pool.length === 0) { return exclude ?? breakActivities[0]; } // Build weighted pool: favorites appear `weight` times const weighted: BreakActivity[] = []; for (const a of pool) { const isFav = favorites.has(a.text) || (config?.custom_activities?.some((c) => c.text === a.text && c.is_favorite) ?? false); const count = isFav ? weight : 1; for (let i = 0; i < count; i++) { weighted.push(a); } } return weighted[Math.floor(Math.random() * weighted.length)]; }