212 lines
6.9 KiB
C#
212 lines
6.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using Logic.Multilingual;
|
|
using UnityEngine;
|
|
|
|
public enum QuestionnaireQuestionType
|
|
{
|
|
Open = 0,
|
|
SingleChoice = 1,
|
|
MultipleChoice = 2
|
|
}
|
|
|
|
public enum QuestionnaireStatus
|
|
{
|
|
Featured = 0,
|
|
LongTerm = 1,
|
|
Expired = 2,
|
|
Hidden = 3
|
|
}
|
|
|
|
[Serializable]
|
|
[CreateAssetMenu(fileName = "QuestionnaireDataAssets", menuName = "TH1 Game Data/Questionnaire Data Asset")]
|
|
public class QuestionnaireDataAssets : ScriptableObject
|
|
{
|
|
public string DefaultQuestionnaireId = "player-feedback-2026-06";
|
|
[MultilingualField] public string MenuButtonText;
|
|
public List<QuestionnaireInfo> QuestionnaireList = new List<QuestionnaireInfo>();
|
|
|
|
[NonSerialized]
|
|
private Dictionary<string, QuestionnaireInfo> _questionnaireDict;
|
|
|
|
public QuestionnaireInfo GetDefaultQuestionnaire()
|
|
{
|
|
if (GetQuestionnaireInfo(DefaultQuestionnaireId, out var info)) return info;
|
|
return QuestionnaireList != null && QuestionnaireList.Count > 0 ? QuestionnaireList[0] : null;
|
|
}
|
|
|
|
public List<QuestionnaireInfo> GetVisibleQuestionnaires(DateTime? nowUtc = null)
|
|
{
|
|
var result = new List<QuestionnaireInfo>();
|
|
if (QuestionnaireList == null) return result;
|
|
|
|
var now = nowUtc ?? DateTime.UtcNow;
|
|
foreach (var info in QuestionnaireList)
|
|
{
|
|
if (info == null || !info.IsVisibleAt(now)) continue;
|
|
result.Add(info);
|
|
}
|
|
|
|
result.Sort(CompareQuestionnaire);
|
|
return result;
|
|
}
|
|
|
|
public bool GetQuestionnaireInfo(string questionnaireId, out QuestionnaireInfo info)
|
|
{
|
|
EnsureDict();
|
|
if (!string.IsNullOrEmpty(questionnaireId) && _questionnaireDict.TryGetValue(questionnaireId, out info))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
info = null;
|
|
return false;
|
|
}
|
|
|
|
private void EnsureDict()
|
|
{
|
|
if (_questionnaireDict != null && QuestionnaireList != null && _questionnaireDict.Count == QuestionnaireList.Count)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_questionnaireDict = new Dictionary<string, QuestionnaireInfo>();
|
|
if (QuestionnaireList == null) return;
|
|
|
|
foreach (var info in QuestionnaireList)
|
|
{
|
|
if (info == null || string.IsNullOrEmpty(info.QuestionnaireId)) continue;
|
|
_questionnaireDict[info.QuestionnaireId] = info;
|
|
}
|
|
}
|
|
|
|
private static int CompareQuestionnaire(QuestionnaireInfo left, QuestionnaireInfo right)
|
|
{
|
|
var statusCompare = GetStatusRank(left?.Status ?? QuestionnaireStatus.Hidden)
|
|
.CompareTo(GetStatusRank(right?.Status ?? QuestionnaireStatus.Hidden));
|
|
if (statusCompare != 0) return statusCompare;
|
|
|
|
var priorityCompare = (right?.Priority ?? 0).CompareTo(left?.Priority ?? 0);
|
|
if (priorityCompare != 0) return priorityCompare;
|
|
|
|
return string.Compare(left?.QuestionnaireId, right?.QuestionnaireId, StringComparison.Ordinal);
|
|
}
|
|
|
|
private static int GetStatusRank(QuestionnaireStatus status)
|
|
{
|
|
return status switch
|
|
{
|
|
QuestionnaireStatus.Featured => 0,
|
|
QuestionnaireStatus.LongTerm => 1,
|
|
QuestionnaireStatus.Expired => 2,
|
|
_ => 3
|
|
};
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class QuestionnaireInfo
|
|
{
|
|
public string QuestionnaireId;
|
|
public int Revision = 1;
|
|
public QuestionnaireStatus Status = QuestionnaireStatus.LongTerm;
|
|
public int Priority;
|
|
public string StartAtUtc;
|
|
public string EndAtUtc;
|
|
public bool AllowMultipleSubmissions = true;
|
|
public int MaxSubmissionCount;
|
|
public int MinSubmitIntervalHours;
|
|
public bool CanViewHistory = true;
|
|
public bool CanSubmitAfterExpired;
|
|
public QuestionnaireTargetRules TargetRules = new QuestionnaireTargetRules();
|
|
[MultilingualField] public string Title;
|
|
[MultilingualField] public string Description;
|
|
[MultilingualField] public string StartButtonText;
|
|
[MultilingualField] public string SubmitButtonText;
|
|
[MultilingualField] public string ResubmitButtonText;
|
|
[MultilingualField] public string CloseButtonText;
|
|
[MultilingualField] public string SubmittedMessage;
|
|
[MultilingualField] public string UploadingMessage;
|
|
[MultilingualField] public string UploadSuccessMessage;
|
|
[MultilingualField] public string UploadFailedMessage;
|
|
[MultilingualField] public string UploadAuthFailedMessage;
|
|
[MultilingualField] public string RequiredMessage;
|
|
[MultilingualField] public string RefillHintText;
|
|
[MultilingualField] public string SaveFailedMessage;
|
|
public List<QuestionnaireQuestionInfo> Questions = new List<QuestionnaireQuestionInfo>();
|
|
|
|
public QuestionnaireStatus GetEffectiveStatus(DateTime utcNow)
|
|
{
|
|
if (Status == QuestionnaireStatus.Hidden) return QuestionnaireStatus.Hidden;
|
|
if (Status == QuestionnaireStatus.Expired) return QuestionnaireStatus.Expired;
|
|
if (HasEnded(utcNow) && !CanSubmitAfterExpired) return QuestionnaireStatus.Expired;
|
|
return Status;
|
|
}
|
|
|
|
public bool IsVisibleAt(DateTime utcNow)
|
|
{
|
|
if (Status == QuestionnaireStatus.Hidden) return false;
|
|
if (!HasStarted(utcNow)) return false;
|
|
return true;
|
|
}
|
|
|
|
public bool CanSubmitAt(DateTime utcNow)
|
|
{
|
|
if (Status == QuestionnaireStatus.Hidden) return false;
|
|
if (Status == QuestionnaireStatus.Expired && !CanSubmitAfterExpired) return false;
|
|
if (!HasStarted(utcNow)) return false;
|
|
if (HasEnded(utcNow) && !CanSubmitAfterExpired) return false;
|
|
return true;
|
|
}
|
|
|
|
private bool HasStarted(DateTime utcNow)
|
|
{
|
|
return !TryParseUtc(StartAtUtc, out var startAt) || utcNow >= startAt;
|
|
}
|
|
|
|
private bool HasEnded(DateTime utcNow)
|
|
{
|
|
return TryParseUtc(EndAtUtc, out var endAt) && utcNow > endAt;
|
|
}
|
|
|
|
private static bool TryParseUtc(string raw, out DateTime value)
|
|
{
|
|
value = default;
|
|
if (string.IsNullOrWhiteSpace(raw)) return false;
|
|
|
|
return DateTime.TryParse(raw, CultureInfo.InvariantCulture,
|
|
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out value);
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class QuestionnaireTargetRules
|
|
{
|
|
public List<string> VersionWhitelist = new List<string>();
|
|
public List<string> PlatformWhitelist = new List<string>();
|
|
public List<string> LanguageWhitelist = new List<string>();
|
|
public bool SteamOnly;
|
|
public bool BetaOnly;
|
|
public int MinFinishedMatchCount;
|
|
}
|
|
|
|
[Serializable]
|
|
public class QuestionnaireQuestionInfo
|
|
{
|
|
public string QuestionId;
|
|
public QuestionnaireQuestionType QuestionType;
|
|
[MultilingualField] public string Title;
|
|
[MultilingualField] public string Hint;
|
|
public bool Required;
|
|
public int MaxSelectCount;
|
|
public List<QuestionnaireOptionInfo> Options = new List<QuestionnaireOptionInfo>();
|
|
}
|
|
|
|
[Serializable]
|
|
public class QuestionnaireOptionInfo
|
|
{
|
|
public string OptionId;
|
|
[MultilingualField] public string Text;
|
|
}
|