using Cryville.Common; using Cryville.Common.Pdt; using Cryville.Crtr.Event; using System.Collections.Generic; namespace Cryville.Crtr { public class Judge { readonly PdtEvaluator _etor; readonly PdtRuleset _rs; readonly Dictionary ct = new Dictionary(); readonly Dictionary> evs = new Dictionary>(); readonly Dictionary> activeEvs = new Dictionary>(); struct JudgeEvent { public float StartTime { get; set; } public float EndTime { get; set; } public JudgeDefinition Definition { get; set; } public ContainerState State { get; set; } } static IComparer _stcmp = new JudgeEventStartTimeComparer(); class JudgeEventStartTimeComparer : IComparer { public int Compare(JudgeEvent x, JudgeEvent y) { return x.StartTime.CompareTo(y.StartTime); } } static IComparer _etcmp = new JudgeEventEndTimeComparer(); class JudgeEventEndTimeComparer : IComparer { public int Compare(JudgeEvent x, JudgeEvent y) { return x.EndTime.CompareTo(y.EndTime); } } public Judge(PdtRuleset rs) { _etor = ChartPlayer.etor; _rs = rs; foreach (var s in rs.scores) { var name = s.Key.Key; scoreDefs.Add(name, s.Value); scores.Add(name, s.Value.init); } } public void Prepare(float st, float et, Identifier input, JudgeDefinition def, ContainerState container) { List list; if (!evs.TryGetValue(input, out list)) { ct.Add(input, 0); evs.Add(input, list = new List()); activeEvs.Add(input, new List()); } var ev = new JudgeEvent { StartTime = st + def.clip[0], EndTime = et + def.clip[1], Definition = def, State = container, }; var index = list.BinarySearch(ev, _stcmp); if (index < 0) index = ~index; list.Insert(index, ev); } public void Feed(Identifier target, float ft, float tt) { Forward(target, tt); var actlist = activeEvs[target]; foreach (var ev in actlist) { // TODO judge ev } } public void Cleanup(Identifier target, float ft, float tt) { Forward(target, tt); var actlist = activeEvs[target]; for (int i = actlist.Count - 1; i >= 0; i--) { JudgeEvent ev = actlist[i]; if (tt > ev.EndTime) { actlist.RemoveAt(i); // TODO miss ev } } } void Forward(Identifier target, float tt) { var list = evs[target]; var actlist = activeEvs[target]; JudgeEvent ev; while (list.Count > 0 && (ev = list[0]).StartTime <= tt) { list.RemoveAt(0); var index = actlist.BinarySearch(ev, _etcmp); if (index < 0) index = ~index; actlist.Insert(index, ev); // TODO priority? } } public readonly Dictionary scoreDefs = new Dictionary(); public readonly Dictionary scores = new Dictionary(); readonly Dictionary ScoreCache = new Dictionary(); readonly object _lock = new object(); public Dictionary GetFormattedScoreStrings() { lock (_lock) { if (ScoreCache.Count == 0) { foreach (var s in scores) ScoreCache.Add(s.Key, s.Value.ToString(scoreDefs[s.Key].format)); } return ScoreCache; } } public string GetFullFormattedScoreString() { bool flag = false; string result = ""; foreach (var s in GetFormattedScoreStrings()) { result += string.Format(flag ? "\n{0}: {1}" : "{0}: {1}", IdentifierManager.SharedInstance.Retrieve(s.Key), s.Value); flag = true; } return result; } } public class InputDefinition { public int dim; public bool notnull; public Dictionary pass; } public class JudgeDefinition { public float[] clip; public PdtExpression input; public PdtExpression hit; public Identifier[] pass; public Identifier miss; public Dictionary scores; } public class ScoreOperation { public Identifier name; public Identifier op; public override string ToString() { if (op == default(Identifier)) return name.ToString(); else return string.Format("{0} {1}", name, op); } } public class ScoreDefinition { public PdtExpression value; public float init = 0; public string format = ""; } }