137 lines
4.8 KiB
C#
137 lines
4.8 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using Newtonsoft.Json;
|
|||
|
using Newtonsoft.Json.Converters;
|
|||
|
using SupportChild.Interviews;
|
|||
|
|
|||
|
namespace SupportChild.Interviews;
|
|||
|
|
|||
|
// This class is identical to the normal interview question and just exists as a hack to get JSON validation when
|
|||
|
// new entries are entered but not when read from database in order to be more lenient with old interviews.
|
|||
|
// I might do this in a more proper way at some point.
|
|||
|
public class ValidatedInterviewQuestion
|
|||
|
{
|
|||
|
[JsonProperty("title", Required = Required.Default)]
|
|||
|
public string title;
|
|||
|
|
|||
|
[JsonProperty("message", Required = Required.Always)]
|
|||
|
public string message;
|
|||
|
|
|||
|
[JsonConverter(typeof(StringEnumConverter))]
|
|||
|
[JsonProperty("type", Required = Required.Always)]
|
|||
|
public QuestionType type;
|
|||
|
|
|||
|
[JsonProperty("color", Required = Required.Always)]
|
|||
|
public string color;
|
|||
|
|
|||
|
[JsonProperty("summary-field", Required = Required.Default)]
|
|||
|
public string summaryField;
|
|||
|
|
|||
|
[JsonConverter(typeof(StringEnumConverter))]
|
|||
|
[JsonProperty("button-style", Required = Required.Default)]
|
|||
|
public ButtonType? buttonStyle;
|
|||
|
|
|||
|
[JsonProperty("selector-placeholder", Required = Required.Default)]
|
|||
|
public string selectorPlaceholder;
|
|||
|
|
|||
|
[JsonProperty("selector-description", Required = Required.Default)]
|
|||
|
public string selectorDescription;
|
|||
|
|
|||
|
[JsonProperty("max-length", Required = Required.Default)]
|
|||
|
public int? maxLength;
|
|||
|
|
|||
|
[JsonProperty("min-length", Required = Required.Default)]
|
|||
|
public int? minLength;
|
|||
|
|
|||
|
[JsonProperty("paths", Required = Required.Always)]
|
|||
|
public Dictionary<string, ValidatedInterviewQuestion> paths;
|
|||
|
|
|||
|
public void Validate(ref List<string> errors, out int summaryCount, out int summaryMaxLength)
|
|||
|
{
|
|||
|
if (string.IsNullOrWhiteSpace(message))
|
|||
|
{
|
|||
|
errors.Add("Message cannot be empty.");
|
|||
|
}
|
|||
|
|
|||
|
if (type is QuestionType.ERROR or QuestionType.END_WITH_SUMMARY or QuestionType.END_WITHOUT_SUMMARY)
|
|||
|
{
|
|||
|
if (paths.Count > 0)
|
|||
|
{
|
|||
|
errors.Add("'" + type + "' questions cannot have child paths.");
|
|||
|
}
|
|||
|
}
|
|||
|
else if (paths.Count == 0)
|
|||
|
{
|
|||
|
errors.Add("'" + type + "' questions must have at least one child path.");
|
|||
|
}
|
|||
|
|
|||
|
List<int> summaryCounts = [];
|
|||
|
Dictionary<string, int> childMaxLengths = new Dictionary<string, int>();
|
|||
|
foreach (KeyValuePair<string, ValidatedInterviewQuestion> path in paths)
|
|||
|
{
|
|||
|
path.Value.Validate(ref errors, out int summaries, out int maxLen);
|
|||
|
summaryCounts.Add(summaries);
|
|||
|
childMaxLengths.Add(path.Key, maxLen);
|
|||
|
}
|
|||
|
|
|||
|
summaryCount = summaryCounts.Count == 0 ? 0 : summaryCounts.Max();
|
|||
|
|
|||
|
string childPathString = "";
|
|||
|
int childMaxLength = 0;
|
|||
|
if (childMaxLengths.Count != 0)
|
|||
|
{
|
|||
|
(childPathString, childMaxLength) = childMaxLengths.ToArray().MaxBy(x => x.Key.Length + x.Value);
|
|||
|
}
|
|||
|
|
|||
|
summaryMaxLength = childMaxLength;
|
|||
|
|
|||
|
if (string.IsNullOrWhiteSpace(summaryField))
|
|||
|
{
|
|||
|
++summaryCount;
|
|||
|
}
|
|||
|
|
|||
|
// Only count summaries that end in a summary question.
|
|||
|
if (type == QuestionType.END_WITH_SUMMARY)
|
|||
|
{
|
|||
|
summaryMaxLength = message?.Length ?? 0;
|
|||
|
summaryMaxLength += title?.Length ?? 0;
|
|||
|
}
|
|||
|
// Only add to the total max length if the summary field is not empty. That way we know this branch ends in a summary.
|
|||
|
else if (summaryMaxLength > 0 && !string.IsNullOrEmpty(summaryField))
|
|||
|
{
|
|||
|
summaryMaxLength += summaryField.Length;
|
|||
|
switch (type)
|
|||
|
{
|
|||
|
case QuestionType.BUTTONS:
|
|||
|
case QuestionType.TEXT_SELECTOR:
|
|||
|
summaryMaxLength += childPathString.Length;
|
|||
|
break;
|
|||
|
case QuestionType.USER_SELECTOR:
|
|||
|
case QuestionType.ROLE_SELECTOR:
|
|||
|
case QuestionType.MENTIONABLE_SELECTOR:
|
|||
|
case QuestionType.CHANNEL_SELECTOR:
|
|||
|
// Approximate length of a mention
|
|||
|
summaryMaxLength += 23;
|
|||
|
break;
|
|||
|
case QuestionType.TEXT_INPUT:
|
|||
|
summaryMaxLength += Math.Min(maxLength ?? 1024, 1024);
|
|||
|
break;
|
|||
|
case QuestionType.END_WITH_SUMMARY:
|
|||
|
case QuestionType.END_WITHOUT_SUMMARY:
|
|||
|
case QuestionType.ERROR:
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class ValidatedTemplate(ulong categoryID, ValidatedInterviewQuestion interview)
|
|||
|
{
|
|||
|
[JsonProperty("category-id", Required = Required.Always)]
|
|||
|
public ulong categoryID = categoryID;
|
|||
|
|
|||
|
[JsonProperty("interview", Required = Required.Always)]
|
|||
|
public ValidatedInterviewQuestion interview = interview;
|
|||
|
}
|