Implement story integration foundation: - Create Domain/Entities/StorySegment.cs with full CRUD methods - Create Domain/Entities/StoryProgress.cs for user story progress tracking - Create Application/DTOs/StorySegmentDto.cs with multiple DTO types - Create Domain/Interfaces/IStoryRepository.cs - Create Domain/Interfaces/IStoryProgressRepository.cs - Create Infrastructure/Data/Repositories/StoryRepository.cs - Create Infrastructure/Data/Repositories/StoryProgressRepository.cs - Add DbSets and entity configurations to AppDbContext - Add navigation properties to Level, Lesson, and User entities Next: Phase 2 - Backend Services (StoryService, StoryGenerationService) Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
200 lines
5.7 KiB
C#
200 lines
5.7 KiB
C#
using System.ComponentModel.DataAnnotations;
|
|
using System.ComponentModel.DataAnnotations.Schema;
|
|
|
|
namespace GermanApp.Domain.Entities;
|
|
|
|
/// <summary>
|
|
/// Represents a segment of a continuous story for a specific level and lesson.
|
|
/// Story segments are unlocked sequentially as users complete lessons.
|
|
/// </summary>
|
|
public class StorySegment
|
|
{
|
|
public int Id { get; private set; }
|
|
|
|
/// <summary>
|
|
/// The CEFR level this story segment belongs to.
|
|
/// </summary>
|
|
public int LevelId { get; private set; }
|
|
|
|
/// <summary>
|
|
/// The lesson this story segment is associated with.
|
|
/// Can be null if the segment is an introduction or conclusion.
|
|
/// </summary>
|
|
public int? LessonId { get; private set; }
|
|
|
|
/// <summary>
|
|
/// The text content of the story segment.
|
|
/// </summary>
|
|
public string Content { get; private set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// URL path to the audio file for this story segment.
|
|
/// </summary>
|
|
public string? AudioUrl { get; private set; }
|
|
|
|
/// <summary>
|
|
/// The order of this segment within the level's story.
|
|
/// Segments are displayed in ascending order.
|
|
/// </summary>
|
|
public int Order { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Title or brief description of this story segment.
|
|
/// </summary>
|
|
public string Title { get; private set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Theme or topic of this story segment.
|
|
/// </summary>
|
|
public string Theme { get; private set; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Estimated reading time in minutes.
|
|
/// </summary>
|
|
public int EstimatedReadingMinutes { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Whether this segment is active and visible to users.
|
|
/// </summary>
|
|
public bool IsActive { get; private set; } = true;
|
|
|
|
/// <summary>
|
|
/// Timestamp when the segment was created.
|
|
/// </summary>
|
|
public DateTime CreatedAt { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Timestamp when the segment was last updated.
|
|
/// </summary>
|
|
public DateTime? UpdatedAt { get; private set; }
|
|
|
|
// Navigation properties (EF Core will handle these)
|
|
public virtual Level? Level { get; private set; }
|
|
public virtual Lesson? Lesson { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Constructor for EF Core deserialization.
|
|
/// </summary>
|
|
private StorySegment() { }
|
|
|
|
/// <summary>
|
|
/// Factory method to create a new story segment.
|
|
/// </summary>
|
|
/// <param name="levelId">ID of the level this segment belongs to</param>
|
|
/// <param name="lessonId">Optional ID of the associated lesson</param>
|
|
/// <param name="content">The story text content</param>
|
|
/// <param name="order">The order within the level's story</param>
|
|
/// <param name="title">Title of the segment</param>
|
|
/// <param name="theme">Theme or topic of the segment</param>
|
|
/// <param name="estimatedReadingMinutes">Estimated reading time in minutes</param>
|
|
/// <returns>New StorySegment instance</returns>
|
|
public static StorySegment Create(
|
|
int levelId,
|
|
int? lessonId,
|
|
string content,
|
|
int order,
|
|
string title,
|
|
string theme,
|
|
int estimatedReadingMinutes = 2)
|
|
{
|
|
return new StorySegment
|
|
{
|
|
LevelId = levelId,
|
|
LessonId = lessonId,
|
|
Content = content,
|
|
Order = order,
|
|
Title = title,
|
|
Theme = theme,
|
|
EstimatedReadingMinutes = estimatedReadingMinutes,
|
|
CreatedAt = DateTime.UtcNow
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the content of the story segment.
|
|
/// </summary>
|
|
/// <param name="newContent">New content text</param>
|
|
public void UpdateContent(string newContent)
|
|
{
|
|
Content = newContent;
|
|
UpdatedAt = DateTime.UtcNow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the audio URL for this segment.
|
|
/// </summary>
|
|
/// <param name="audioUrl">URL path to the audio file</param>
|
|
public void UpdateAudioUrl(string audioUrl)
|
|
{
|
|
AudioUrl = audioUrl;
|
|
UpdatedAt = DateTime.UtcNow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the title of the story segment.
|
|
/// </summary>
|
|
/// <param name="newTitle">New title</param>
|
|
public void UpdateTitle(string newTitle)
|
|
{
|
|
Title = newTitle;
|
|
UpdatedAt = DateTime.UtcNow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the theme of the story segment.
|
|
/// </summary>
|
|
/// <param name="newTheme">New theme</param>
|
|
public void UpdateTheme(string newTheme)
|
|
{
|
|
Theme = newTheme;
|
|
UpdatedAt = DateTime.UtcNow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the estimated reading time.
|
|
/// </summary>
|
|
/// <param name="minutes">Estimated reading time in minutes</param>
|
|
public void UpdateEstimatedReadingMinutes(int minutes)
|
|
{
|
|
EstimatedReadingMinutes = minutes;
|
|
UpdatedAt = DateTime.UtcNow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the order of this segment within the level's story.
|
|
/// </summary>
|
|
/// <param name="newOrder">New order value</param>
|
|
public void UpdateOrder(int newOrder)
|
|
{
|
|
Order = newOrder;
|
|
UpdatedAt = DateTime.UtcNow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the associated lesson.
|
|
/// </summary>
|
|
/// <param name="newLessonId">New lesson ID (can be null)</param>
|
|
public void UpdateLesson(int? newLessonId)
|
|
{
|
|
LessonId = newLessonId;
|
|
UpdatedAt = DateTime.UtcNow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Activates this story segment.
|
|
/// </summary>
|
|
public void Activate()
|
|
{
|
|
IsActive = true;
|
|
UpdatedAt = DateTime.UtcNow;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deactivates this story segment.
|
|
/// </summary>
|
|
public void Deactivate()
|
|
{
|
|
IsActive = false;
|
|
UpdatedAt = DateTime.UtcNow;
|
|
}
|
|
}
|