-- Migration: 099_working_hours.sql -- Description: Working hours profiles for natural traffic pattern simulation -- Created: 2024-12-13 -- Working hours table: defines hourly activity weights to mimic natural traffic CREATE TABLE IF NOT EXISTS working_hours ( id SERIAL PRIMARY KEY, name VARCHAR(50) UNIQUE NOT NULL, description TEXT, -- Hour weights: {"0": 15, "1": 5, ..., "18": 100, ...} -- Value = percent chance to trigger activity that hour (0-100) hour_weights JSONB NOT NULL, -- Day-of-week multipliers (0=Sunday, 6=Saturday) -- Optional adjustment for weekend vs weekday patterns dow_weights JSONB DEFAULT '{"0": 90, "1": 100, "2": 100, "3": 100, "4": 100, "5": 110, "6": 95}', timezone VARCHAR(50) DEFAULT 'America/Phoenix', enabled BOOLEAN DEFAULT true, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Seed: Natural traffic pattern based on internet usage research -- Optimized for cannabis dispensary browsing (lunch + after-work peaks) INSERT INTO working_hours (name, description, timezone, hour_weights) VALUES ( 'natural_traffic', 'Mimics natural user browsing patterns - peaks at lunch and 5-7 PM', 'America/Phoenix', '{ "0": 15, "1": 5, "2": 5, "3": 5, "4": 5, "5": 10, "6": 20, "7": 30, "8": 35, "9": 45, "10": 50, "11": 60, "12": 75, "13": 65, "14": 60, "15": 70, "16": 80, "17": 95, "18": 100, "19": 100, "20": 90, "21": 70, "22": 45, "23": 25 }'::jsonb ) ON CONFLICT (name) DO UPDATE SET hour_weights = EXCLUDED.hour_weights, description = EXCLUDED.description, updated_at = NOW(); -- Index for quick lookups CREATE INDEX IF NOT EXISTS idx_working_hours_name ON working_hours(name); CREATE INDEX IF NOT EXISTS idx_working_hours_enabled ON working_hours(enabled); COMMENT ON TABLE working_hours IS 'Activity profiles for natural traffic simulation. Hour weights are percent chance (0-100) to trigger activity.'; COMMENT ON COLUMN working_hours.hour_weights IS 'JSON object mapping hour (0-23) to percent chance (0-100). 100 = always run, 0 = never run.'; COMMENT ON COLUMN working_hours.dow_weights IS 'Optional day-of-week multipliers. 0=Sunday. Applied as (hour_weight * dow_weight / 100).';