first commit - migrated from codeberg
This commit is contained in:
commit
5ead03e1f7
567 changed files with 102721 additions and 0 deletions
226
lib/tools/mood_data_generator.dart
Normal file
226
lib/tools/mood_data_generator.dart
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue