2026-07-08 17:00:43 +02:00

157 lines
6.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Manager.DTOs;
using ManagerService.DTOs;
using NetTopologySuite.Geometries;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using ManagerService.Helpers;
namespace ManagerService.Data.SubSection
{
public class GuidedStep // Étape dun parcours
{
[Key]
public string Id { get; set; }
[Required]
public string GuidedPathId { get; set; }
[ForeignKey("GuidedPathId")]
public GuidedPath GuidedPath { get; set; }
public int Order { get; set; }
[Required]
[Column(TypeName = "jsonb")]
public List<TranslationDTO> Title { get; set; }
[Column(TypeName = "jsonb")]
public List<TranslationDTO> Description { get; set; }
public Geometry? Geometry { get; set; } // Polygon ou centre du cercle
// Option : si true, cette étape doit être atteinte géographiquement (zone/rayon) pour être validée
public bool IsGeoTriggered { get; set; } = false;
public double? ZoneRadiusMeters { get; set; } // Optionnel, utile si zone cercle ou point
public string ImageUrl { get; set; }
// Rich content (calqué sur SectionArticle)
[Column(TypeName = "jsonb")]
public List<TranslationDTO> AudioIds { get; set; } = new();
[Column(TypeName = "jsonb")]
public List<ContentDTO> Contents { get; set; } = new();
[Column(TypeName = "jsonb")]
public List<TranslationDTO> FactContent { get; set; } = new();
public bool IsHiddenInitially { get; set; } = false;
// Exemple pour escape game
public List<QuizQuestion>? QuizQuestions { get; set; } // One or multiple question
// Option : si true, cette étape a un compte à rebourds, false sinon
public bool IsStepTimer { get; set; } = false;
// Option : si true, cette étape doit être validée avant de passer à la suivante
public bool IsStepLocked { get; set; } = true;
// Timer en secondes (durée max pour valider cette étape, optionnel)
public int? TimerSeconds { get; set; }
// Option : message ou action à effectuer si timer expire (ex: afficher aide, fin du jeu...)
[Column(TypeName = "jsonb")]
public List<TranslationDTO> TimerExpiredMessage { get; set; }
public GuidedStepDTO ToDTO()
{
return new GuidedStepDTO
{
id = Id,
guidedPathId = GuidedPathId,
order = Order,
title = Title,
description = Description,
geometry = Geometry?.ToDto(),
isGeoTriggered = IsGeoTriggered,
zoneRadiusMeters = ZoneRadiusMeters,
imageUrl = ImageUrl,
audioIds = AudioIds,
contents = Contents,
factContent = FactContent,
isHiddenInitially = IsHiddenInitially,
isStepTimer = IsStepTimer,
isStepLocked = IsStepLocked,
timerSeconds = TimerSeconds,
timerExpiredMessage = TimerExpiredMessage,
quizQuestions = QuizQuestions
};
}
public GuidedStep FromDTO(GuidedStepDTO dto)
{
if (dto == null) return null;
GuidedPathId = dto.guidedPathId;
Title = dto.title ?? new List<TranslationDTO>();
Description = dto.description ?? new List<TranslationDTO>();
Geometry = dto.geometry.FromDto();
IsGeoTriggered = dto.isGeoTriggered;
ZoneRadiusMeters = dto.zoneRadiusMeters;
ImageUrl = dto.imageUrl;
AudioIds = dto.audioIds ?? new List<TranslationDTO>();
Contents = dto.contents ?? new List<ContentDTO>();
FactContent = dto.factContent ?? new List<TranslationDTO>();
IsHiddenInitially = dto.isHiddenInitially;
IsStepTimer = dto.isStepTimer;
IsStepLocked = dto.isStepLocked;
TimerSeconds = dto.timerSeconds;
TimerExpiredMessage = dto.timerExpiredMessage ?? new List<TranslationDTO>();
Order = dto.order.GetValueOrDefault();
SyncQuizQuestions(dto.quizQuestions);
return this;
}
// Merges incoming quiz questions into the tracked QuizQuestions collection by Id,
// instead of replacing the reference outright — a blind reassignment would make EF
// treat every incoming question (including already-persisted ones) as a brand new
// row to insert, which fails with a duplicate key error as soon as a step already
// has a saved question and a new one is added alongside it.
public void SyncQuizQuestions(List<QuizQuestion>? dtoQuestions)
{
dtoQuestions ??= new List<QuizQuestion>();
QuizQuestions ??= new List<QuizQuestion>();
var dtoIds = dtoQuestions.Where(q => q.Id != 0).Select(q => q.Id).ToHashSet();
QuizQuestions.RemoveAll(q => !dtoIds.Contains(q.Id));
foreach (var qDto in dtoQuestions)
{
var existing = qDto.Id != 0 ? QuizQuestions.FirstOrDefault(q => q.Id == qDto.Id) : null;
if (existing != null)
{
existing.Label = qDto.Label;
existing.ResourceId = qDto.ResourceId;
existing.Order = qDto.Order;
existing.Responses = qDto.Responses;
existing.ValidationQuestionType = qDto.ValidationQuestionType;
existing.PuzzleImageId = qDto.PuzzleImageId;
existing.PuzzleRows = qDto.PuzzleRows;
existing.PuzzleCols = qDto.PuzzleCols;
existing.IsSlidingPuzzle = qDto.IsSlidingPuzzle;
}
else
{
qDto.Id = 0;
QuizQuestions.Add(qDto);
}
}
}
}
}