diff --git a/Assets/Cryville/Crtr/Judge.cs b/Assets/Cryville/Crtr/Judge.cs index cf61135..febfaaa 100644 --- a/Assets/Cryville/Crtr/Judge.cs +++ b/Assets/Cryville/Crtr/Judge.cs @@ -1,7 +1,10 @@ using Cryville.Common; +using Cryville.Common.Buffers; using Cryville.Common.Pdt; using Cryville.Crtr.Event; +using System; using System.Collections.Generic; +using System.Globalization; namespace Cryville.Crtr { public class Judge { @@ -30,14 +33,7 @@ namespace Cryville.Crtr { public Judge(PdtRuleset rs) { _etor = ChartPlayer.etor; _rs = rs; - foreach (var s in rs.scores) { - var key = s.Key; - scoreSrcs.Add(key.Key, new PropSrc.Float(() => scores[key.Key])); - scoreOps.Add(key.Key, new PropOp.Float(v => scores[key.Key] = v)); - scoreFmtKeys.Add(key.Key, IdentifierManager.SharedInstance.Request("_score_" + (string)key.Name)); - scoreDefs.Add(key.Key, s.Value); - scores.Add(key.Key, s.Value.init); - } + InitScores(); } public void Prepare(float st, float et, Identifier input, JudgeDefinition def, ContainerState container) { List list; @@ -166,42 +162,95 @@ namespace Cryville.Crtr { var key = scoreop.Key; _etor.ContextSelfValue = scoreSrcs[key.name.Key]; _etor.Evaluate(scoreOps[key.name.Key], scoreop.Value); - scoreSrcs[key.name.Key].Invalidate(); + InvalidateScore(key.name.Key); foreach (var s in _rs.scores) { if (s.Value.value != null) { _etor.ContextSelfValue = scoreSrcs[s.Key.Key]; _etor.Evaluate(scoreOps[s.Key.Key], s.Value.value); - scoreSrcs[s.Key.Key].Invalidate(); + InvalidateScore(s.Key.Key); } } } - ScoreCache.Clear(); } - readonly Dictionary scoreFmtKeys = new Dictionary(); + readonly Dictionary scoreStringKeys = new Dictionary(); + readonly Dictionary scoreStringKeysRev = new Dictionary(); readonly Dictionary scoreSrcs = new Dictionary(); readonly Dictionary scoreOps = new Dictionary(); 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(scoreFmtKeys[s.Key], s.Value.ToString(scoreDefs[s.Key].format)); - } - return ScoreCache; + readonly Dictionary scores = new Dictionary(); + readonly Dictionary scoreStringCache = new Dictionary(); + readonly Dictionary scoreStringSrcs = new Dictionary(); + readonly ArrayPool scoreStringPool = new ArrayPool(); + void InitScores() { + foreach (var s in _rs.scores) { + var key = s.Key.Key; + var strkey = IdentifierManager.SharedInstance.Request("_score_" + (string)s.Key.Name); + scoreStringKeys.Add(key, strkey); + scoreStringKeysRev.Add(strkey, key); + scoreSrcs.Add(key, new PropSrc.Float(() => scores[key])); + scoreOps.Add(key, new PropOp.Float(v => scores[key] = v)); + scoreDefs.Add(key, s.Value); + scores.Add(key, s.Value.init); + scoreStringCache.Add(scoreStringKeys[key], null); + scoreStringSrcs.Add(scoreStringKeys[key], new ScoreStringSrc(scoreStringPool, () => GetScoreString(strkey))); } } + void InvalidateScore(int key) { + scoreSrcs[key].Invalidate(); + scoreStringCache[scoreStringKeys[key]] = null; + scoreStringSrcs[scoreStringKeys[key]].Invalidate(); + } + string GetScoreString(int key) { + var result = scoreStringCache[key]; + if (result == null) { + var rkey = scoreStringKeysRev[key]; + return scoreStringCache[key] = scores[rkey].ToString(scoreDefs[rkey].format, CultureInfo.InvariantCulture); + } + else return result; + } + public bool TryGetScoreSrc(int key, out PropSrc value) { + return scoreSrcs.TryGetValue(key, out value); + } + public bool TryGetScoreStringSrc(int key, out PropSrc value) { + return scoreStringSrcs.TryGetValue(key, out value); + } 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); + foreach (var s in scores.Keys) { + result += string.Format(flag ? "\n{0}: {1}" : "{0}: {1}", IdentifierManager.SharedInstance.Retrieve(s), GetScoreString(scoreStringKeys[s])); flag = true; } return result; } + class ScoreStringSrc : PropSrc { + readonly Func _cb; + readonly ArrayPool _pool; + byte[] _buf; + public ScoreStringSrc(ArrayPool pool, Func cb) { + _pool = pool; + _cb = cb; + } + public override void Invalidate() { + base.Invalidate(); + if (_buf != null) { + _pool.Return(_buf); + _buf = null; + } + } + protected override unsafe void InternalGet(out int type, out byte[] value) { + var src = _cb(); + int strlen = src.Length; + type = PdtInternalType.String; + value = _pool.Rent(sizeof(int) + strlen * sizeof(char)); + fixed (byte* _ptr = value) { + char* ptr = (char*)(_ptr + sizeof(int)); + *(int*)_ptr = strlen; + int i = 0; + foreach (var c in src) ptr[i++] = c; + } + } + } } public class InputDefinition { public int dim; diff --git a/Assets/Cryville/Crtr/PdtEvaluator.cs b/Assets/Cryville/Crtr/PdtEvaluator.cs index 026f813..ef6160a 100644 --- a/Assets/Cryville/Crtr/PdtEvaluator.cs +++ b/Assets/Cryville/Crtr/PdtEvaluator.cs @@ -23,8 +23,6 @@ namespace Cryville.Crtr { else { var id = new Identifier(name); PropSrc prop; - string str; - float num; if (ContextEvent != null && ContextEvent.PropSrcs.TryGetValue(name, out prop)) { prop.Get(out type, out value); } @@ -32,15 +30,12 @@ namespace Cryville.Crtr { var vec = ContextState.GetRawValue(id); new VectorSrc(() => vec).Get(out type, out value); } - else if (ContextJudge != null && ContextJudge.scores.TryGetValue(name, out num)) { - type = PdtInternalType.Number; - LoadNum(num); - value = _numbuf; + else if (ContextJudge != null && ContextJudge.TryGetScoreSrc(name, out prop)) { + prop.Get(out type, out value); RevokePotentialConstant(); } - else if (ContextJudge != null && ContextJudge.GetFormattedScoreStrings().TryGetValue(name, out str)) { - type = PdtInternalType.String; - value = GetBytes(str); + else if (ContextJudge != null && ContextJudge.TryGetScoreStringSrc(name, out prop)) { + prop.Get(out type, out value); RevokePotentialConstant(); } else { diff --git a/Assets/Cryville/Crtr/PropSrc.cs b/Assets/Cryville/Crtr/PropSrc.cs index 5ce80d1..3519932 100644 --- a/Assets/Cryville/Crtr/PropSrc.cs +++ b/Assets/Cryville/Crtr/PropSrc.cs @@ -6,7 +6,7 @@ namespace Cryville.Crtr { public abstract class PropSrc { int _type; byte[] _buf = null; - public void Invalidate() { _buf = null; } + public virtual void Invalidate() { _buf = null; } public void Get(out int type, out byte[] value) { if (_buf == null) InternalGet(out _type, out _buf); type = _type;