using System;
using System.Collections.Generic;
using System.Linq;
using JD.Kernel.Structs;
using JD.LogService;
using TeaBox;
using JD.Serialization;
namespace JD.Timeline.Dance
{
///
/// Validation to check that dance tape is valid
///
public class DanceDocumentValidation
{
public static void Validate(Tape tape, ILogger context)
{
ValidateMoveModels(context, tape);
ValidatePictoModels(context, tape);
foreach (var track in tape.Tracks)
{
if (track is MoveTrack)
{
var moveTrack = track as MoveTrack;
switch (moveTrack.MoveType)
{
case MotionClip.MoveType_Enum.MoveType_HandOnly:
ValidateMoveTrack(context, moveTrack);
break;
case MotionClip.MoveType_Enum.MoveType_FullBody:
ValidateCameraMoveTrack(context, moveTrack);
break;
}
}
else if (track is PictoTrack)
{
ValidatePictoTrack(context, track as PictoTrack);
}
else if (track is GoldEffectTrack)
{
ValidateGoldEffectTrack(context, track as GoldEffectTrack);
}
else if (track is CommunityDancerTrack)
{
//No validation yet
}
else
{
context.LogError("Track '{0}' has to be a MoveTrack or a PictoTrack.", track.Name);
}
}
foreach (var clip in tape.Clips)
{
if (clip.CollisionsWithOther)
{
context.LogWarning(new FileLocation(tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has a collision with an other clip.");
}
var sameIdClipCount = tape.Clips.Count(x => x.Id == clip.Id);
if (sameIdClipCount != 1)
{
context.LogError(new FileLocation(tape.Id, new List { clip.Id }), $"{sameIdClipCount} clips have the same id '{clip.Id}'");
}
}
}
private static void ValidateMoveTrack(ILogger context, MoveTrack track)
{
if (!MoveTrack.NameValidationRegexHandOnly.IsMatch(track.Name))
{
context.LogError($"Track '{track.Name}' has an invalid name.");
}
foreach (var clip in track.Clips())
{
if (clip is MotionClip)
{
var motionClip = clip as MotionClip;
if (motionClip.CoachId != track.CoachId)
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} CoachId is different from Track one.");
}
if (motionClip.MoveType != MotionClip.MoveType_Enum.MoveType_HandOnly)
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} MoveType is invalid.");
}
if (string.IsNullOrEmpty(motionClip.Model.Name))
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has a model with empty name.");
}
}
else
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has in an invalid type.");
}
}
}
private static void ValidateMoveModels(ILogger context, Tape tape)
{
foreach (var moveModel in tape.MoveModels())
{
foreach (var clip in moveModel.Instances)
{
if (Math.Abs(clip.BeatDuration - moveModel.BeatDuration) > float.Epsilon)
{
context.LogError(new FileLocation(tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has a different duration than its model.");
}
if (clip.Color != moveModel.Color)
{
context.LogError(new FileLocation(tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has a different color than its model.");
}
if (!clip.ClassifierPath.Equals(moveModel.ClassifierPath))
{
context.LogError(new FileLocation(tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has a different classifierpath than its model.");
}
if (clip.MoveType != moveModel.MoveType)
{
context.LogError(new FileLocation(tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has a different move type than its model.");
}
}
}
}
private static void ValidateCameraMoveTrack(ILogger context, MoveTrack track)
{
if (!MoveTrack.NameValidationRegexFullBody.IsMatch(track.Name))
{
context.LogError($"Track '{track.Name}' has an invalid name.");
}
foreach (var clip in track.Clips())
{
if (clip is MotionClip)
{
var motionClip = clip as MotionClip;
if (motionClip.CoachId != track.CoachId)
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} CoachId is different from Track one.");
}
if (motionClip.MoveType != MotionClip.MoveType_Enum.MoveType_FullBody)
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} MoveType is invalid.");
}
if (string.IsNullOrEmpty(motionClip.Model.Name))
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has a model with empty name.");
}
}
else
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has in an invalid type. It should be a MotionClip.");
}
}
}
private static void ValidatePictoTrack(ILogger context, PictoTrack track)
{
if (!PictoTrack.NameValidationRegex.IsMatch(track.Name))
{
context.LogError($"Track '{track.Name}' has an invalid name.");
}
foreach (var clip in track.Clips())
{
if (clip is PictogramClip)
{
var pictoClip = clip as PictogramClip;
if (string.IsNullOrEmpty(pictoClip.Model.Name))
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has a model with empty name.");
}
}
else
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has in an invalid type. It shloud be a PictogramClip.");
}
}
}
private static void ValidatePictoModels(ILogger context, Tape tape)
{
foreach (var pictogramModel in tape.PictogramModels())
{
foreach (var clip in pictogramModel.Instances)
{
if (!clip.PictoPath.Equals(pictogramModel.PictoPath))
{
context.LogError(new FileLocation(tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has a different classifierpath than its model.");
}
}
}
}
private static void ValidateGoldEffectTrack(ILogger context, GoldEffectTrack track)
{
if (track.Name != GoldEffectTrack.DefaultName)
{
context.LogError($"Track '{track.Name}' has an invalid name.");
}
foreach (var clip in track.Clips())
{
if (clip is GoldEffectClip)
{
var goldEffect = clip as GoldEffectClip;
if (Math.Abs(goldEffect.BeatDuration - GoldEffectClip.FixedDurationInBeats) > float.Epsilon)
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} duration needs to be {GoldEffectClip.FixedDurationInBeats}.");
}
}
else
{
context.LogError(new FileLocation(track.Tape.Id, new List { clip.Id }), $"{clip.ToStringDetailed()} has in an invalid type. It should be a GoldEffectClip");
}
}
}
}
}