초기커밋
This commit is contained in:
478
UGQApiServer/Validation/UGQValidator.cs
Normal file
478
UGQApiServer/Validation/UGQValidator.cs
Normal file
@@ -0,0 +1,478 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
|
||||
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Pipelines.Sockets.Unofficial.Arenas;
|
||||
|
||||
|
||||
using ServerCommon;
|
||||
|
||||
|
||||
using UGQDataAccess;
|
||||
using UGQDatabase.Models;
|
||||
using UGQApiServer.Converter;
|
||||
using UGQApiServer.Models;
|
||||
using UGQApiServer.UGQData;
|
||||
|
||||
|
||||
namespace UGQApiServer.Validation;
|
||||
|
||||
public enum ValidationErrorKind
|
||||
{
|
||||
Success,
|
||||
RequireBeaconId, // <20><><EFBFBD><EFBFBD> <20>Է<EFBFBD> <20>ʿ<EFBFBD>
|
||||
NotFoundBeaconId, // <20>Էµ<D4B7> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߸<EFBFBD><DFB8><EFBFBD> <20><><EFBFBD>̵<EFBFBD>
|
||||
FirstTaskIsNotTalkAction, // ù<><C3B9><EFBFBD><EFBFBD> <20>½<EFBFBD>ũ <20><>ȭ <20><EFBFBD><D7BC><EFBFBD> <20>ƴ<EFBFBD>
|
||||
FirstTaskIsNotSameBeacon, // ù<><C3B9><EFBFBD><EFBFBD> <20>½<EFBFBD>ũ<EFBFBD><C5A9> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٸ<EFBFBD>
|
||||
InvalidCostAmount, // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
|
||||
|
||||
|
||||
InvalidDialogType, // <20>Է<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
InvalidDialogConditionId, // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
InvalidDialogConditionValue, // <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
|
||||
InvalidDialogNextSequence, // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
|
||||
InvalidSequenceCount, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3~30<33><30> <20><><EFBFBD><EFBFBD>
|
||||
DontHaveEndSequence, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ᰡ <20><><EFBFBD><EFBFBD>
|
||||
NotSetPlayerTalker, // Player Talker<65><72> <20><><EFBFBD>õǾ<C3B5> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
InvalidTalkerOrder, // Npc <20>ڿ<EFBFBD> Player<65><72> <20><> <20><> <20><><EFBFBD><EFBFBD>
|
||||
|
||||
|
||||
InvalidTaskActionId, // Task <20><EFBFBD> Ÿ<><C5B8> <20><><EFBFBD><EFBFBD>
|
||||
InvalidTaskActionValue, // Task <20><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
|
||||
InvalidTaskCount, // Task <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3~20<32><30> <20><><EFBFBD><EFBFBD>
|
||||
DontHaveTitleImage, // Ÿ<><C5B8>Ʋ <20>̹<EFBFBD><CCB9><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
DontHaveBannerImage, // <20><><EFBFBD><EFBFBD> <20>̹<EFBFBD><CCB9><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
|
||||
InvalidNpcActionId, // Npc <20><EFBFBD> Ÿ<><C5B8> <20><><EFBFBD><EFBFBD>
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class ValidationError
|
||||
{
|
||||
public ValidationErrorKind Kind { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class QuestDialogValidatorError : ValidationError
|
||||
{
|
||||
public int TaskIndex { get; set; } = -1;
|
||||
public int SequenceId { get; set; } = -1; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><DFBB><EFBFBD> SequenceId.
|
||||
public int SequenceActionIndex { get; set; } = -1; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><DFBB><EFBFBD> SequenceAction <20><>ġ. 0 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. -1<><31> <20><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ƴ<EFBFBD>.
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
// Kind<6E><64> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DEBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
|
||||
|
||||
string position = "";
|
||||
if (SequenceActionIndex != -1)
|
||||
{
|
||||
position = $"[TaskIndex: {TaskIndex}, SequenceId: {SequenceId}, SequenceActionIndex: {SequenceActionIndex}] ";
|
||||
}
|
||||
else if (SequenceId != -1)
|
||||
{
|
||||
position = $"[TaskIndex: {TaskIndex}, SequenceId: {SequenceId}] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
position = $"[TaskIndex: {TaskIndex}] ";
|
||||
}
|
||||
|
||||
var textId = $"UGQ_Validator_Error_{Kind.ToString()}";
|
||||
var message = UGQDataHelper.getText(langEnum, textId);
|
||||
|
||||
return $"{position}{message}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public class QuestContentValidatorError : ValidationError
|
||||
{
|
||||
public int TaskIndex { get; set; } = -1; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD><DFBB><EFBFBD> Task <20><>ġ. 0 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
// Kind<6E><64> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DEBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
|
||||
|
||||
string position = "";
|
||||
if (TaskIndex != -1)
|
||||
{
|
||||
position = $"[TaskIndex: {TaskIndex}] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
position = "";
|
||||
}
|
||||
|
||||
var textId = $"UGQ_Validator_Error_{Kind.ToString()}";
|
||||
var message = UGQDataHelper.getText(langEnum, textId);
|
||||
|
||||
return $"{position}{message ?? "Unkonwn"}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class UGQValidator
|
||||
{
|
||||
UGQMetaData _ugqMetadata;
|
||||
|
||||
int MIN_SEQUENCE = 3;
|
||||
int MAX_SEQUENCE = 30;
|
||||
|
||||
int MIN_TASK = 3;
|
||||
int MAX_TASK = 20;
|
||||
|
||||
|
||||
public UGQValidator(UGQMetaData ugqMetadata)
|
||||
{
|
||||
_ugqMetadata = ugqMetadata;
|
||||
}
|
||||
|
||||
public List<ValidationError> Validate(QuestContentEntity questContent, List<QuestDialogEntity> questDialogs)
|
||||
{
|
||||
List<ValidationError> errors = new();
|
||||
|
||||
ValidateQuestContent(questContent, errors);
|
||||
|
||||
|
||||
// <20><><EFBFBD>̾<EFBFBD><CCBE>α<EFBFBD> üũ
|
||||
foreach (var (index, task) in questContent.Tasks.Select((task, index) => (index, task)))
|
||||
{
|
||||
var dialogIndex = questDialogs.FindIndex(x => x.Id == task.DialogId);
|
||||
|
||||
if (task.ActionId == UGQMetaData.TALK_ACTION_ID)
|
||||
{
|
||||
if (dialogIndex == -1)
|
||||
{
|
||||
// Talk <20><EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD> Dialog<6F><67> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||||
QuestContentValidatorError error = new QuestContentValidatorError
|
||||
{
|
||||
Kind = ValidationErrorKind.InvalidSequenceCount,
|
||||
TaskIndex = index,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
continue;
|
||||
}
|
||||
|
||||
var questDialog = questDialogs[dialogIndex];
|
||||
|
||||
// sequence <20><><EFBFBD><EFBFBD> üũ
|
||||
if (questDialog.Sequences.Count < MIN_SEQUENCE || questDialog.Sequences.Count >= MAX_SEQUENCE)
|
||||
{
|
||||
QuestContentValidatorError error = new QuestContentValidatorError
|
||||
{
|
||||
Kind = ValidationErrorKind.InvalidSequenceCount,
|
||||
TaskIndex = index,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
|
||||
ValidateQuestDialog(index, questDialog, errors);
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int getCost(UgqGradeType gradeType)
|
||||
{
|
||||
switch (gradeType)
|
||||
{
|
||||
case UgqGradeType.Amature:
|
||||
return MetaHelper.GameConfigMeta.UgqUsageFeeAmateur;
|
||||
case UgqGradeType.RisingStar:
|
||||
return MetaHelper.GameConfigMeta.UgqUsageFeeRisingStar;
|
||||
case UgqGradeType.Master1:
|
||||
return MetaHelper.GameConfigMeta.UgqUsageFeeMaster1;
|
||||
case UgqGradeType.Master2:
|
||||
return MetaHelper.GameConfigMeta.UgqUsageFeeMaster2;
|
||||
case UgqGradeType.Master3:
|
||||
return MetaHelper.GameConfigMeta.UgqUsageFeeMaster3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ValidateQuestContent(QuestContentEntity questContent, List<ValidationError> errors)
|
||||
{
|
||||
if(questContent.BeaconId == 0 && string.IsNullOrEmpty(questContent.UgcBeaconGuid) == true)
|
||||
{
|
||||
QuestContentValidatorError error = new QuestContentValidatorError
|
||||
{
|
||||
Kind = ValidationErrorKind.RequireBeaconId,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
|
||||
if(questContent.BeaconId != 0)
|
||||
{
|
||||
var errorKind = _ugqMetadata.isValidNpcId(questContent.BeaconId);
|
||||
if (errorKind != ValidationErrorKind.Success)
|
||||
{
|
||||
QuestContentValidatorError error = new QuestContentValidatorError
|
||||
{
|
||||
Kind = errorKind,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
}
|
||||
|
||||
if (questContent.Tasks.Count < MIN_TASK || questContent.Tasks.Count >= MAX_TASK)
|
||||
{
|
||||
QuestContentValidatorError error = new QuestContentValidatorError
|
||||
{
|
||||
Kind = ValidationErrorKind.InvalidTaskCount,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(questContent.TitleImagePath) == true)
|
||||
{
|
||||
QuestContentValidatorError error = new QuestContentValidatorError
|
||||
{
|
||||
Kind = ValidationErrorKind.DontHaveTitleImage,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(questContent.BannerImagePath) == true)
|
||||
{
|
||||
QuestContentValidatorError error = new QuestContentValidatorError
|
||||
{
|
||||
Kind = ValidationErrorKind.DontHaveBannerImage,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
|
||||
//if (questContent.Cost != getCost(questContent.GradeType))
|
||||
//{
|
||||
// QuestContentValidatorError error = new QuestContentValidatorError
|
||||
// {
|
||||
// Kind = ValidationErrorKind.InvalidCostAmount,
|
||||
// };
|
||||
|
||||
// errors.Add(error);
|
||||
//}
|
||||
|
||||
if (questContent.Tasks[0].ActionId != 1)
|
||||
{
|
||||
QuestContentValidatorError error = new QuestContentValidatorError
|
||||
{
|
||||
Kind = ValidationErrorKind.FirstTaskIsNotTalkAction,
|
||||
TaskIndex = 0,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
|
||||
bool validTalkBeacon = false;
|
||||
if (questContent.BeaconId != 0 && questContent.Tasks[0].ActionValue == questContent.BeaconId)
|
||||
validTalkBeacon = true;
|
||||
|
||||
if (string.IsNullOrEmpty(questContent.UgcBeaconGuid) == false && questContent.Tasks[0].UgcActionValueGuid == questContent.UgcBeaconGuid)
|
||||
validTalkBeacon = true;
|
||||
|
||||
if(validTalkBeacon == false)
|
||||
{
|
||||
QuestContentValidatorError error = new QuestContentValidatorError
|
||||
{
|
||||
Kind = ValidationErrorKind.FirstTaskIsNotSameBeacon,
|
||||
TaskIndex = 0,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
|
||||
|
||||
foreach (var (index, task) in questContent.Tasks.Select((task, index) => (index, task)))
|
||||
{
|
||||
if (string.IsNullOrEmpty(task.UgcActionValueGuid) == false)
|
||||
{
|
||||
var errorKind = _ugqMetadata.isValidTackActionId(task.ActionId);
|
||||
if (errorKind != ValidationErrorKind.Success)
|
||||
{
|
||||
QuestContentValidatorError error = new QuestContentValidatorError
|
||||
{
|
||||
Kind = errorKind,
|
||||
TaskIndex = index,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var errorKind = _ugqMetadata.isValidTackActionValue(task.ActionId, task.ActionValue);
|
||||
if (errorKind != ValidationErrorKind.Success)
|
||||
{
|
||||
QuestContentValidatorError error = new QuestContentValidatorError
|
||||
{
|
||||
Kind = errorKind,
|
||||
TaskIndex = index,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ValidateQuestDialogSequenceAction(int taskIndex, List<int> sequenceIds, int sequenceId, int actionIdex, DialogSequenceActionEntity sequenceAction, List<ValidationError> errors)
|
||||
{
|
||||
if (sequenceAction.Talker == DialogTalker.Player)
|
||||
{
|
||||
// Talker<65><72> <20>÷<EFBFBD><C3B7>̾<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> üũ
|
||||
|
||||
var errorKind = _ugqMetadata.isValidDialogActionValue(sequenceAction.Type, sequenceAction.Condition, sequenceAction.ConditionValue);
|
||||
if (errorKind != ValidationErrorKind.Success)
|
||||
{
|
||||
QuestDialogValidatorError error = new QuestDialogValidatorError
|
||||
{
|
||||
TaskIndex = taskIndex,
|
||||
Kind = errorKind,
|
||||
SequenceId = sequenceId,
|
||||
SequenceActionIndex = actionIdex,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
}
|
||||
else if(sequenceAction.Talker == DialogTalker.Npc && sequenceAction.NpcAction != 0)
|
||||
{
|
||||
var errorKind = _ugqMetadata.isValidNpcActionId(sequenceAction.NpcAction);
|
||||
if (errorKind != ValidationErrorKind.Success)
|
||||
{
|
||||
QuestDialogValidatorError error = new QuestDialogValidatorError
|
||||
{
|
||||
TaskIndex = taskIndex,
|
||||
Kind = errorKind,
|
||||
SequenceId = sequenceId,
|
||||
SequenceActionIndex = actionIdex,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
}
|
||||
|
||||
if (sequenceId != -1)
|
||||
{
|
||||
if (sequenceIds.Any(x => x == sequenceId) == false)
|
||||
{
|
||||
QuestDialogValidatorError error = new QuestDialogValidatorError
|
||||
{
|
||||
TaskIndex = taskIndex,
|
||||
Kind = ValidationErrorKind.InvalidDialogNextSequence,
|
||||
SequenceId = sequenceId,
|
||||
SequenceActionIndex = actionIdex,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ValidateQuestDialogSequence(int taskIndex, List<int> sequenceIds, DialogSequenceEntity sequence, List<ValidationError> errors)
|
||||
{
|
||||
foreach (var (index, action) in sequence.Actions.Select((action, index) => (index, action)))
|
||||
{
|
||||
ValidateQuestDialogSequenceAction(taskIndex, sequenceIds, sequence.SequenceId, index, action, errors);
|
||||
}
|
||||
|
||||
int playerTalkerCount = 0;
|
||||
int npcTalkerCount = 0;
|
||||
bool invalidTalkerOrder = false;
|
||||
|
||||
foreach (var (index, action) in sequence.Actions.Select((action, index) => (index, action)))
|
||||
{
|
||||
if (action.Talker == DialogTalker.Player)
|
||||
{
|
||||
playerTalkerCount++;
|
||||
}
|
||||
else if (action.Talker == DialogTalker.Npc)
|
||||
{
|
||||
// Npc<70>ε<EFBFBD>, playerTalkerCount<6E><74> 0<><30><EFBFBD><EFBFBD> ũ<>ٸ<EFBFBD>, Player<65>ڿ<EFBFBD> Npc<70><63> <20><><EFBFBD>Դٴ<D4B4> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3>
|
||||
if (playerTalkerCount > 0)
|
||||
invalidTalkerOrder = true;
|
||||
|
||||
npcTalkerCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (playerTalkerCount < 1)
|
||||
{
|
||||
QuestDialogValidatorError error = new QuestDialogValidatorError
|
||||
{
|
||||
TaskIndex = taskIndex,
|
||||
Kind = ValidationErrorKind.NotSetPlayerTalker,
|
||||
SequenceId = sequence.SequenceId,
|
||||
};
|
||||
}
|
||||
|
||||
if (invalidTalkerOrder == true)
|
||||
{
|
||||
QuestDialogValidatorError error = new QuestDialogValidatorError
|
||||
{
|
||||
TaskIndex = taskIndex,
|
||||
Kind = ValidationErrorKind.InvalidTalkerOrder,
|
||||
SequenceId = sequence.SequenceId,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ValidateQuestDialog(int taskIndex, QuestDialogEntity questDialog, List<ValidationError> errors)
|
||||
{
|
||||
var sequenceIds = questDialog.Sequences.Select(x => x.SequenceId).ToList();
|
||||
|
||||
List<int> npcActionIds = new();
|
||||
var dialogActions = questDialog.Sequences.Select(x => x.Actions).ToList();
|
||||
foreach(var item in dialogActions)
|
||||
npcActionIds.AddRange(item.Select(x => x.NpcAction).ToList());
|
||||
|
||||
bool hasEnd = false;
|
||||
foreach (var sequence in questDialog.Sequences)
|
||||
{
|
||||
ValidateQuestDialogSequence(taskIndex, sequenceIds, sequence, errors);
|
||||
|
||||
foreach (var action in sequence.Actions)
|
||||
{
|
||||
if(action.NextSequence == -1)
|
||||
hasEnd = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasEnd == false)
|
||||
{
|
||||
QuestDialogValidatorError error = new QuestDialogValidatorError
|
||||
{
|
||||
TaskIndex = taskIndex,
|
||||
Kind = ValidationErrorKind.DontHaveEndSequence,
|
||||
};
|
||||
|
||||
errors.Add(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user