File size: 9,507 Bytes
bf04727
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7004388
 
bf04727
 
 
 
7004388
 
 
 
bf04727
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
"""
Seed the database with 30 days of realistic mock data for demo mode.
Run: python seed_data.py
"""
import sys
import os
import uuid
import random
from datetime import datetime, timedelta
from dotenv import load_dotenv

load_dotenv()
sys.path.insert(0, os.path.dirname(__file__))

from models.database import init_db, SessionLocal, User, VoiceEntry, MoodAlert, ChatMessage

DEMO_USER_EMAIL = "demo@innervoice.app"
DEMO_USER_NAME = "Alex (Demo)"

EMOTIONS = ["happy", "neutral", "sad", "anxious", "fearful", "angry"]
EMOTION_WEIGHTS = [0.30, 0.28, 0.18, 0.12, 0.07, 0.05]

TRANSCRIPTIONS = {
    "happy": [
        "Today was actually really good. I feel like things are finally clicking into place and I'm excited about what's ahead.",
        "I had a great time with friends this evening. Laughed a lot. Really needed that connection.",
        "Finished a project I've been working on for weeks. Feels so satisfying to see it done.",
        "Went for a long walk this morning and the sunshine just lifted everything. Feeling grateful.",
    ],
    "neutral": [
        "It's been a regular day. Nothing spectacular, nothing bad. Just steady.",
        "Work was fine. Meetings ran long but got through it. Feeling okay overall.",
        "Pretty normal Tuesday. Had lunch outside which was nice. Mostly just going through the motions.",
        "No major feelings today. I'm present, just... existing. That's okay too.",
    ],
    "sad": [
        "I don't really know how to explain it. Just feel a heaviness today that I can't shake.",
        "Missing some people today. Feeling a bit disconnected from everything.",
        "Things feel harder than they should. I'm trying but motivation is low.",
        "Cried a little this evening and I'm not even sure why. Just needed to let it out.",
    ],
    "anxious": [
        "My mind keeps racing about things I can't control. Hard to focus on the present.",
        "Feeling that familiar chest tightness again. Too many things on my plate.",
        "The week ahead feels overwhelming. I'm trying to take it one thing at a time.",
        "Lots of uncertainty right now and my nervous system is definitely feeling it.",
    ],
    "fearful": [
        "Something doesn't feel right but I can't name it. Just uneasy.",
        "Woke up with a sense of dread this morning. Trying to ground myself.",
        "Scared about some changes happening in my life. Trying to trust the process.",
    ],
    "angry": [
        "Really frustrated today. Feel like I'm not being heard or seen.",
        "Had a tense situation at work. Hard not to carry that home.",
        "Some things happened today that felt unfair and I'm still processing the anger.",
    ],
}


def generate_entry(user_id: str, days_ago: int) -> VoiceEntry:
    # Generate a realistic mood arc (dip in middle, recovery)
    progress = days_ago / 30.0  # 0 = most recent, 1 = oldest
    base_mood_shift = int(20 * (0.5 - abs(progress - 0.6)))  # dip 18 days ago

    emotion = random.choices(EMOTIONS, weights=EMOTION_WEIGHTS)[0]
    confidence = round(random.uniform(0.60, 0.95), 3)

    from services.mood_calculator import calculate_mood_scores
    pitch_mean = random.uniform(100, 200)
    pitch_std = random.uniform(10, 60)
    energy = random.uniform(0.005, 0.04)
    tempo = random.uniform(60, 120)
    avg_pause = random.uniform(0.1, 0.8)
    filler_rate = random.uniform(0.01, 0.08)

    scores = calculate_mood_scores(
        emotion=emotion,
        confidence=confidence,
        pitch_mean=pitch_mean,
        pitch_std=pitch_std,
        energy=energy,
        tempo=tempo,
        avg_pause=avg_pause,
        filler_rate=filler_rate,
    )

    # Apply arc shift
    for key in scores:
        scores[key] = max(0, min(100, scores[key] + base_mood_shift + random.randint(-5, 5)))

    transcription_options = TRANSCRIPTIONS.get(emotion, TRANSCRIPTIONS["neutral"])
    transcription = random.choice(transcription_options)

    created_at = datetime.utcnow() - timedelta(days=days_ago, hours=random.randint(6, 22))

    return VoiceEntry(
        id=str(uuid.uuid4()),
        user_id=user_id,
        created_at=created_at,
        audio_url=None,
        duration_seconds=round(random.uniform(30, 65), 1),
        transcription=transcription,
        primary_emotion=emotion,
        emotion_confidence=confidence,
        energy_score=scores["energy"],
        calmness_score=scores["calmness"],
        mood_score=scores["mood"],
        clarity_score=scores["clarity"],
        pitch_mean=round(pitch_mean, 2),
        pitch_std=round(pitch_std, 2),
        energy_raw=round(energy, 6),
        speech_rate=round(tempo, 2),
        pause_count=random.randint(2, 15),
        avg_pause_duration=round(avg_pause, 3),
        filler_rate=round(filler_rate, 4),
        mfcc_features=[round(random.uniform(-50, 50), 2) for _ in range(13)],
    )


def seed():
    init_db()
    db = SessionLocal()
    try:
        # Create or get demo user
        user = db.query(User).filter(User.email == DEMO_USER_EMAIL).first()
        if not user:
            from routes.auth import get_password_hash
            hashed_pwd = get_password_hash("password")
            user = User(
                id=str(uuid.uuid4()),
                email=DEMO_USER_EMAIL,
                name=DEMO_USER_NAME,
                password_hash=hashed_pwd,
                baseline_pitch=150.0,
                baseline_energy=0.03,
                baseline_speech_rate=100.0,
            )
            db.add(user)
            db.commit()
            db.refresh(user)
            print(f"[Seed] Created demo user: {user.id}")
        else:
            print(f"[Seed] Demo user exists: {user.id}")
            # Clear old entries
            db.query(VoiceEntry).filter(VoiceEntry.user_id == user.id).delete()
            db.query(MoodAlert).filter(MoodAlert.user_id == user.id).delete()
            db.query(ChatMessage).filter(ChatMessage.user_id == user.id).delete()
            db.commit()

        # Generate 30 days of entries (skip ~20% of days for realism)
        entries = []
        for days_ago in range(30, 0, -1):
            if random.random() < 0.80:  # 80% check-in rate
                entry = generate_entry(user.id, days_ago)
                db.add(entry)
                entries.append(entry)

        db.commit()
        print(f"[Seed] Created {len(entries)} voice entries.")

        # Create sample alerts
        alerts = [
            MoodAlert(
                id=str(uuid.uuid4()),
                user_id=user.id,
                created_at=datetime.utcnow() - timedelta(days=2),
                alert_type="mood_decline",
                severity="warning",
                message="Your mood has declined 24% this week compared to last week.",
                suggested_action="Try scheduling something enjoyable today, even something small.",
                is_read=False,
            ),
            MoodAlert(
                id=str(uuid.uuid4()),
                user_id=user.id,
                created_at=datetime.utcnow() - timedelta(days=1),
                alert_type="low_energy",
                severity="concern",
                message="Your energy has been consistently low for the past 5 days.",
                suggested_action="Even a 10-minute walk can shift your energy. Try it today.",
                is_read=False,
            ),
        ]
        for alert in alerts:
            db.add(alert)

        # Create sample chat messages
        chats = [
            ChatMessage(
                id=str(uuid.uuid4()),
                user_id=user.id,
                created_at=datetime.utcnow() - timedelta(hours=3),
                role="user",
                content="I'm fine, just tired.",
            ),
            ChatMessage(
                id=str(uuid.uuid4()),
                user_id=user.id,
                created_at=datetime.utcnow() - timedelta(hours=3, seconds=-5),
                role="assistant",
                content="I hear you — and 'tired' can mean so many things. Your voice this week has been a little lower in energy than usual. Is there something specific weighing on you, or is it more of a general fatigue?",
            ),
            ChatMessage(
                id=str(uuid.uuid4()),
                user_id=user.id,
                created_at=datetime.utcnow() - timedelta(hours=2),
                role="user",
                content="Why have I been feeling off lately?",
            ),
            ChatMessage(
                id=str(uuid.uuid4()),
                user_id=user.id,
                created_at=datetime.utcnow() - timedelta(hours=2, seconds=-5),
                role="assistant",
                content="Looking at your last two weeks, your mood started dipping around 18 days ago and your energy has been below your baseline since then. That sometimes happens during seasonal changes or when routines get disrupted. Does anything stand out from around that time?",
            ),
        ]
        for chat in chats:
            db.add(chat)

        db.commit()
        print(f"[Seed] Created {len(alerts)} alerts and {len(chats)} chat messages.")
        print(f"[Seed] Demo user ID: {user.id}")
        print(f"[Seed] Seeding complete ✓")

        return user.id

    finally:
        db.close()


if __name__ == "__main__":
    user_id = seed()
    print(f"\nDemo user ID: {user_id}")
    print("Use this ID in Demo Mode or set NEXT_PUBLIC_DEMO_USER_ID in frontend/.env.local")