VoiceSessions : nombre de sessions ayant utilisé le vocal au moins une fois, lu dans le JSON de Metadata. Volontairement hors d'AppTypeDistribution — le vocal n'est pas une plateforme mais un mode d'interaction : un visiteur passe des lunettes à l'écran dans une même session, or la distribution compte une entrée par session tranchée sur l'événement le plus ancien. Le chiffre aurait dépendu de l'ordre dans lequel le visiteur a touché ses appareils. Colonne Metadata déjà existante : aucune migration, le gel du lot B tient. Le test InMemory ne prouve rien ici — le provider évalue le filtre côté client, donc une requête intraduisible passerait au vert. Un test Postgres l'accompagne. IsAutoTriggered devient IsVisitorQuestion (défaut true). Le nom d'hier ne couvrait qu'un des deux cas : le vrai sens n'est pas « déclenché automatiquement » mais « ce tour n'est pas une question de visiteur », ce qui vaut aussi pour l'aperçu de conversation, où c'est le gestionnaire qui teste sa personnalité. Renommé pendant qu'un seul commit en dépendait. Le défaut à true est délibéré : une app visiteur publiée qui n'envoie pas le champ continue de journaliser, et un test le fixe. dotnet test : 204 passés, 14 sautés, 0 échec. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
106 lines
3.7 KiB
C#
106 lines
3.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
namespace ManagerService.DTOs
|
|
{
|
|
public class StatsSummaryDTO
|
|
{
|
|
public int TotalSessions { get; set; }
|
|
public int AvgVisitDurationSeconds { get; set; }
|
|
public List<SectionStatDTO> TopSections { get; set; } = new();
|
|
public List<DayStatDTO> VisitsByDay { get; set; } = new();
|
|
public Dictionary<string, int> LanguageDistribution { get; set; } = new();
|
|
public Dictionary<string, int> AppTypeDistribution { get; set; } = new();
|
|
|
|
/// <summary>
|
|
/// Nombre de sessions ayant **utilisé le vocal au moins une fois**.
|
|
///
|
|
/// ⚠️ Ce n'est pas une entrée d'<see cref="AppTypeDistribution"/>, et c'est délibéré.
|
|
/// Le vocal n'est pas une plateforme mais un mode d'interaction : un visiteur passe
|
|
/// des lunettes à l'écran dans une même session — c'est tout l'objet du miroir. Or
|
|
/// la distribution compte **une entrée par session**, tranchée sur l'événement le
|
|
/// plus ancien : commencer au doigt puis mettre les lunettes aurait rendu le vocal
|
|
/// invisible, et l'inverse aurait compté toute la navigation tactile comme vocale.
|
|
/// Le KPI devient « part des sessions ayant utilisé le vocal », qui est vrai.
|
|
///
|
|
/// C'est la conception que <c>VisitorQuestion</c> applique déjà : un booléen
|
|
/// <c>IsVoice</c> **à côté** de l'AppType, pas une valeur d'AppType.
|
|
/// </summary>
|
|
public int VoiceSessions { get; set; }
|
|
public List<PoiStatDTO> TopPois { get; set; } = new();
|
|
public List<AgendaEventStatDTO> TopAgendaEvents { get; set; } = new();
|
|
public List<QuizStatDTO> QuizStats { get; set; } = new();
|
|
public List<GameStatDTO> GameStats { get; set; } = new();
|
|
public List<ArticleStatDTO> TopArticles { get; set; } = new();
|
|
public List<MenuItemStatDTO> TopMenuItems { get; set; } = new();
|
|
public QrScanStatDTO QrScans { get; set; } = new();
|
|
}
|
|
|
|
public class SectionStatDTO
|
|
{
|
|
public string SectionId { get; set; }
|
|
public string SectionTitle { get; set; }
|
|
public int Views { get; set; }
|
|
public int AvgDurationSeconds { get; set; }
|
|
}
|
|
|
|
public class DayStatDTO
|
|
{
|
|
public string Date { get; set; } // "2026-03-12"
|
|
public int Total { get; set; }
|
|
public int Mobile { get; set; }
|
|
public int Tablet { get; set; }
|
|
}
|
|
|
|
public class PoiStatDTO
|
|
{
|
|
public int GeoPointId { get; set; }
|
|
public string Title { get; set; }
|
|
public int Taps { get; set; }
|
|
public string SectionId { get; set; }
|
|
}
|
|
|
|
public class AgendaEventStatDTO
|
|
{
|
|
public string EventId { get; set; }
|
|
public string EventTitle { get; set; }
|
|
public int Taps { get; set; }
|
|
}
|
|
|
|
public class QuizStatDTO
|
|
{
|
|
public string SectionId { get; set; }
|
|
public string SectionTitle { get; set; }
|
|
public double AvgScore { get; set; }
|
|
public int TotalQuestions { get; set; }
|
|
public int Completions { get; set; }
|
|
}
|
|
|
|
public class GameStatDTO
|
|
{
|
|
public string GameType { get; set; }
|
|
public int Completions { get; set; }
|
|
public int AvgDurationSeconds { get; set; }
|
|
}
|
|
|
|
public class ArticleStatDTO
|
|
{
|
|
public string SectionId { get; set; }
|
|
public int Reads { get; set; }
|
|
}
|
|
|
|
public class MenuItemStatDTO
|
|
{
|
|
public string TargetSectionId { get; set; }
|
|
public string MenuItemTitle { get; set; }
|
|
public int Taps { get; set; }
|
|
}
|
|
|
|
public class QrScanStatDTO
|
|
{
|
|
public int TotalScans { get; set; }
|
|
public int ValidScans { get; set; }
|
|
public int InvalidScans { get; set; }
|
|
}
|
|
}
|