Files
TornadoAce_CJOnStyle/TornadoAce_CJOnStyle/ViewModels/MainViewModel.cs

203 lines
8.3 KiB
C#

using Microsoft.UI;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using System.Collections.ObjectModel;
using TornadoAce_CJOnStyle.Services;
using Windows.UI;
namespace TornadoAce_CJOnStyle.ViewModels
{
public partial class MainViewModel : BaseViewModel
{
private readonly AutomationWorkspace workspace;
public MainViewModel()
{
Title = "CG 제작 자동화";
workspace = AutomationWorkspace.CreateDemo();
BuildPhase = "INITIAL BUILD";
OperatorMessage = "큐시트 플랫폼, Tornado Scene 템플릿, 자동 검수 결과를 한 화면에서 확인하는 운영 콘솔 초안입니다.";
LastCueSheetSyncText = "목 데이터 기준 13:25";
ActiveTemplateName = workspace.ActiveTemplate.TemplateName;
InspectionSummary = "1차 diff 실패 2건 / LLM 검토 대기 1건";
SceneSnapshotLabel = $"{workspace.ActiveScene.SceneName} / visible text objects";
SceneSnapshotText = workspace.ActiveScene.ToPreviewJson();
LlmPolicyText = "사내 LLM 우선, 외부 서비스는 정책 승인 후";
LlmPolicyDetail = "1차 Text Diffing 실패 건만 2차 LLM 판정으로 이동하고, 가격·구성·방송시간 변경은 높은 중요도로 표시합니다.";
LoadStatusCards();
LoadPipelineSteps();
LoadFieldMappings();
LoadEndpoints();
LoadInspectionQueue();
}
private string buildPhase = string.Empty;
private string operatorMessage = string.Empty;
private string lastCueSheetSyncText = string.Empty;
private string activeTemplateName = string.Empty;
private string inspectionSummary = string.Empty;
private string sceneSnapshotLabel = string.Empty;
private string sceneSnapshotText = string.Empty;
private string llmPolicyText = string.Empty;
private string llmPolicyDetail = string.Empty;
public string BuildPhase
{
get => buildPhase;
set => SetProperty(ref buildPhase, value);
}
public string OperatorMessage
{
get => operatorMessage;
set => SetProperty(ref operatorMessage, value);
}
public string LastCueSheetSyncText
{
get => lastCueSheetSyncText;
set => SetProperty(ref lastCueSheetSyncText, value);
}
public string ActiveTemplateName
{
get => activeTemplateName;
set => SetProperty(ref activeTemplateName, value);
}
public string InspectionSummary
{
get => inspectionSummary;
set => SetProperty(ref inspectionSummary, value);
}
public string SceneSnapshotLabel
{
get => sceneSnapshotLabel;
set => SetProperty(ref sceneSnapshotLabel, value);
}
public string SceneSnapshotText
{
get => sceneSnapshotText;
set => SetProperty(ref sceneSnapshotText, value);
}
public string LlmPolicyText
{
get => llmPolicyText;
set => SetProperty(ref llmPolicyText, value);
}
public string LlmPolicyDetail
{
get => llmPolicyDetail;
set => SetProperty(ref llmPolicyDetail, value);
}
public ObservableCollection<StatusCardViewModel> StatusCards { get; } = [];
public ObservableCollection<PipelineStepViewModel> PipelineSteps { get; } = [];
public ObservableCollection<FieldMappingViewModel> FieldMappings { get; } = [];
public ObservableCollection<IntegrationEndpointViewModel> Endpoints { get; } = [];
public ObservableCollection<InspectionQueueItemViewModel> InspectionQueue { get; } = [];
[RelayCommand]
private void RefreshCueSheet()
{
LastCueSheetSyncText = $"목 데이터 동기화 {DateTime.Now:HH:mm:ss}";
OperatorMessage = "큐시트 목 데이터를 다시 읽었습니다. 실제 API 연결 전까지 이 버튼은 화면 흐름 확인용으로 동작합니다.";
StatusCards[0].Metric = "12";
StatusCards[0].Detail = "동기화 완료";
}
[RelayCommand]
private void GenerateScene()
{
OperatorMessage = "선택된 큐시트 레코드를 Tornado Scene 템플릿에 매핑하는 흐름을 확인했습니다.";
StatusCards[1].Metric = "7";
StatusCards[1].Detail = "생성 후보";
}
[RelayCommand]
private void RunInspection()
{
OperatorMessage = "Scene 데이터와 큐시트 데이터를 비교하는 1차 검수 흐름을 확인했습니다.";
InspectionSummary = "1차 diff 실패 2건 / LLM 검토 대기 1건 / 통과 5건";
StatusCards[2].Metric = "99.2%";
StatusCards[2].Detail = "평균 일치율";
}
private void LoadStatusCards()
{
StatusCards.Add(new StatusCardViewModel("큐시트 API", "12", "수신 대기", Symbol.Sync, Brush(0xFF45D6D1)));
StatusCards.Add(new StatusCardViewModel("Scene 매핑", "5", "템플릿 정의", Symbol.Map, Brush(0xFFB48CFF)));
StatusCards.Add(new StatusCardViewModel("자동 검수", "98.7%", "목표 99%+", Symbol.Accept, Brush(0xFFFFB547)));
StatusCards.Add(new StatusCardViewModel("Tornado", "Mock", "SDK 어댑터 자리", Symbol.Repair, Brush(0xFF37D67A)));
}
private void LoadPipelineSteps()
{
PipelineSteps.Add(new PipelineStepViewModel("01", "큐시트 데이터 수신", "AI ON Studio / 자막 큐시트 API", "설계", 35, Brush(0xFF45D6D1)));
PipelineSteps.Add(new PipelineStepViewModel("02", "Data Field Mapping", "큐시트 필드 -> Tornado Scene 객체", "초안", 45, Brush(0xFFB48CFF)));
PipelineSteps.Add(new PipelineStepViewModel("03", "Scene 생성/갱신", "Tornado2 우선, Tornado3 어댑터 준비", "대기", 25, Brush(0xFF37D67A)));
PipelineSteps.Add(new PipelineStepViewModel("04", "Scene Data API 추출", "Text/Image visible object snapshot", "초안", 30, Brush(0xFFFFB547)));
PipelineSteps.Add(new PipelineStepViewModel("05", "자동 검수 피드백", "Text Diffing + LLM 중요도 판정", "초안", 40, Brush(0xFFFF5B61)));
}
private void LoadFieldMappings()
{
foreach (var mapping in workspace.ActiveTemplate.Mappings)
{
FieldMappings.Add(new FieldMappingViewModel(mapping.CueSheetField, mapping.SceneObjectName, mapping.Rule, mapping.Attribute));
}
}
private void LoadEndpoints()
{
Endpoints.Add(new IntegrationEndpointViewModel("큐시트 플랫폼", "GET /api/cuesheets/{broadcastDate}", "AI ON Studio", "Mock", Brush(0xFF45D6D1)));
Endpoints.Add(new IntegrationEndpointViewModel("ERP 편성", "GET /api/schedules/{programCode}", "CJ OnStyle ERP", "대기", Brush(0xFFFFB547)));
Endpoints.Add(new IntegrationEndpointViewModel("Tornado Scene API", "POST /api/scenes/extract", "Tornado Adapter", "설계", Brush(0xFF37D67A)));
Endpoints.Add(new IntegrationEndpointViewModel("LLM 검수", "POST /api/inspection/llm", "Internal LLM", "정책 확인", Brush(0xFFB48CFF)));
}
private void LoadInspectionQueue()
{
foreach (var item in workspace.InspectionResults)
{
InspectionQueue.Add(new InspectionQueueItemViewModel(
item.ProgramTitle,
item.SceneName,
$"{item.MatchRate:0.0}%",
item.Severity,
item.Decision,
SeverityBrush(item.Severity)));
}
}
private static SolidColorBrush SeverityBrush(string severity)
{
return severity switch
{
"High" => Brush(0xFFFF5B61),
"Medium" => Brush(0xFFFFB547),
_ => Brush(0xFF37D67A)
};
}
private static SolidColorBrush Brush(uint argb)
{
return new SolidColorBrush(Color.FromArgb(
(byte)(argb >> 24),
(byte)(argb >> 16),
(byte)(argb >> 8),
(byte)argb));
}
}
}