first commit - migrated from codeberg

This commit is contained in:
Charlotte Croce 2025-04-20 11:17:03 -04:00
commit 5ead03e1f7
567 changed files with 102721 additions and 0 deletions

View file

@ -0,0 +1,226 @@
// SPDX-FileCopyrightText: © 2025 Nøkken.io <nokken.io@proton.me>
// SPDX-License-Identifier: AGPL-3.0
//
// mood_data_generator.dart
//
import 'dart:math' show Random;
import 'package:flutter/material.dart';
import 'package:nokken/src/core/services/database/database_service.dart';
import 'package:nokken/src/core/services/database/database_service_mood.dart';
import 'package:nokken/src/features/mood_tracker/models/mood_entry.dart';
import 'package:uuid/uuid.dart';
/// A tool class to generate historical mood data
class MoodDataGenerator {
final DatabaseService databaseService;
MoodDataGenerator(this.databaseService);
/// Generate 365 days of mood entries
Future<void> generateMoodEntries() async {
final random = Random();
// Start date: 364 days ago from today
final endDate = DateTime.now();
final startDate = endDate.subtract(const Duration(days: 364));
debugPrint(
'Generating mood entries from ${startDate.toIso8601String()} to ${endDate.toIso8601String()}');
// Generate an entry for each day
for (int i = 0; i <= 364; i++) {
final date = startDate.add(Duration(days: i));
// Generate random mood entry
final entry = _generateRandomMoodEntry(date, random);
// Insert into database
await databaseService.insertMoodEntry(entry);
// Print progress
if (i % 30 == 0) {
debugPrint('Generated ${i + 1} entries...');
}
}
debugPrint('Successfully generated 365 mood entries.');
}
/// Generate a random but realistic mood entry for the given date
MoodEntry _generateRandomMoodEntry(DateTime date, Random random) {
// Generate a unique ID
final id = const Uuid().v4();
// Generate a base mood index with some weekly and seasonal patterns
int baseMoodModifier = 0;
// Weekday effects: people often feel better on weekends, worse on Mondays
if (date.weekday == DateTime.saturday || date.weekday == DateTime.sunday) {
baseMoodModifier =
random.nextDouble() < 0.7 ? 1 : 0; // Better mood on weekends
} else if (date.weekday == DateTime.monday) {
baseMoodModifier =
random.nextDouble() < 0.6 ? -1 : 0; // Worse mood on Mondays
}
// Seasonal effects: worse in winter, better in summer
final month = date.month;
int seasonalModifier = 0;
if (month >= 11 || month <= 2) {
// Winter months
seasonalModifier = random.nextDouble() < 0.6 ? -1 : 0;
} else if (month >= 5 && month <= 8) {
// Summer months
seasonalModifier = random.nextDouble() < 0.6 ? 1 : 0;
}
// Calculate final mood index with modifiers and randomness
// Assuming mood from terrible (0) to excellent (4)
int moodIndex =
2 + baseMoodModifier + seasonalModifier; // Start from neutral (2)
moodIndex += (random.nextInt(3) - 1); // Add -1, 0, or 1 for randomness
moodIndex = moodIndex.clamp(0, 4); // Ensure within valid range
// Convert index to actual MoodRating enum
final mood = MoodRating.values[moodIndex];
// Generate 1-6 random emotions
final emotionCount = random.nextInt(6) + 1;
final emotions = <Emotion>{};
while (emotions.length < emotionCount &&
emotions.length < Emotion.values.length) {
final emotionIndex = random.nextInt(Emotion.values.length);
emotions.add(Emotion.values[emotionIndex]);
}
// Decide which health metrics to include (3 to all)
final healthMetricsCount = random.nextInt(5) + 3; // 3 to 7 metrics
final healthMetricsToInclude = List.generate(7, (index) => index)
..shuffle(random);
final selectedHealthMetrics =
healthMetricsToInclude.take(healthMetricsCount).toList();
// Helper function to generate a correlated index
int correlatedIndex(
int baseIndex, double correlationStrength, int maxIndex) {
if (random.nextDouble() < correlationStrength) {
// Correlated value
final variation = random.nextInt(3) - 1; // -1, 0, or 1
return (baseIndex + variation).clamp(0, maxIndex - 1);
} else {
// Random value
return random.nextInt(maxIndex);
}
}
// Generate health metrics
SleepQuality? sleepQuality;
EnergyLevel? energyLevel;
LibidoLevel? libidoLevel;
AppetiteLevel? appetiteLevel;
FocusLevel? focusLevel;
DysphoriaLevel? dysphoriaLevel;
ExerciseLevel? exerciseLevel;
// Sleep quality - somewhat correlated with mood
if (selectedHealthMetrics.contains(0)) {
final sleepIndex =
correlatedIndex(moodIndex, 0.7, SleepQuality.values.length);
sleepQuality = SleepQuality.values[sleepIndex];
}
// Energy level - often follows sleep quality if available
if (selectedHealthMetrics.contains(1)) {
int energyIndex;
if (sleepQuality != null && random.nextDouble() < 0.8) {
// Correlate with sleep
energyIndex = correlatedIndex(SleepQuality.values.indexOf(sleepQuality),
0.8, EnergyLevel.values.length);
} else {
// Correlate with mood
energyIndex =
correlatedIndex(moodIndex, 0.6, EnergyLevel.values.length);
}
energyLevel = EnergyLevel.values[energyIndex];
}
// Libido level - moderately correlated with mood
if (selectedHealthMetrics.contains(2)) {
final libidoIndex =
correlatedIndex(moodIndex, 0.5, LibidoLevel.values.length);
libidoLevel = LibidoLevel.values[libidoIndex];
}
// Appetite level - less correlated with mood
if (selectedHealthMetrics.contains(3)) {
final appetiteIndex =
correlatedIndex(moodIndex, 0.4, AppetiteLevel.values.length);
appetiteLevel = AppetiteLevel.values[appetiteIndex];
}
// Focus level - often correlates with sleep and energy
if (selectedHealthMetrics.contains(4)) {
int focusIndex;
if (sleepQuality != null &&
energyLevel != null &&
random.nextDouble() < 0.7) {
// Derive from average of sleep and energy
final avgIndex = (SleepQuality.values.indexOf(sleepQuality) +
EnergyLevel.values.indexOf(energyLevel)) ~/
2;
focusIndex = correlatedIndex(avgIndex, 0.8, FocusLevel.values.length);
} else {
// Correlate with mood
focusIndex = correlatedIndex(moodIndex, 0.6, FocusLevel.values.length);
}
focusLevel = FocusLevel.values[focusIndex];
}
// Dysphoria level - often inversely correlates with mood
if (selectedHealthMetrics.contains(5)) {
// Invert the mood index for dysphoria correlation (higher mood = lower dysphoria)
final invertedMood = 4 - moodIndex; // Assuming 5 mood levels (0-4)
final dysphoriaIndex =
correlatedIndex(invertedMood, 0.75, DysphoriaLevel.values.length);
dysphoriaLevel = DysphoriaLevel.values[dysphoriaIndex];
}
// Exercise level - less strongly correlated with other metrics
if (selectedHealthMetrics.contains(6)) {
final exerciseIndex = random.nextInt(ExerciseLevel.values.length);
exerciseLevel = ExerciseLevel.values[exerciseIndex];
}
// Generate optional notes (30% chance)
String? notes;
if (random.nextDouble() < 0.3) {
final noteTemplates = [
"Feeling ${moodIndex > 2 ? 'pretty good' : 'a bit down'} today.",
"Today was ${moodIndex > 3 ? 'excellent' : moodIndex > 2 ? 'decent' : 'challenging'}.",
"${moodIndex > 3 ? 'Great' : moodIndex > 2 ? 'Good' : 'Tough'} day overall.",
"Noticed ${sleepQuality != null ? (SleepQuality.values.indexOf(sleepQuality) > 2 ? 'good sleep' : 'poor sleep') : 'fluctuating energy'} today.",
"Mood tracker note for ${date.day}/${date.month}/${date.year}.",
"${energyLevel != null && EnergyLevel.values.indexOf(energyLevel) > 2 ? 'High energy' : 'Low energy'} but ${moodIndex > 2 ? 'good spirits' : 'feeling down'}.",
"Trying to stay ${moodIndex < 2 ? 'positive despite challenges' : 'grateful for the good things'}.",
];
notes = noteTemplates[random.nextInt(noteTemplates.length)];
}
// Create and return the mood entry
return MoodEntry(
id: id,
date: date,
mood: mood,
emotions: emotions,
notes: notes,
sleepQuality: sleepQuality,
energyLevel: energyLevel,
libidoLevel: libidoLevel,
appetiteLevel: appetiteLevel,
focusLevel: focusLevel,
dysphoriaLevel: dysphoriaLevel,
exerciseLevel: exerciseLevel,
);
}
}