Make hit expression comparable.

This commit is contained in:
2023-05-11 16:18:36 +08:00
parent fe4280aa2e
commit bee3401283

View File

@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Runtime.Serialization;
using System.Text.Formatting;
using UnsafeIL;
namespace Cryville.Crtr {
public class Judge {
@@ -47,7 +48,7 @@ namespace Cryville.Crtr {
_numsrc2 = new PropSrc.Float(() => _numbuf2);
_numsrc3 = new PropSrc.Float(() => _numbuf3);
_numsrc4 = new PropSrc.Float(() => _numbuf4);
_rs.judges.TryGetValue(new Identifier(_var_pause), out _judgePause);
_rs.judges.Judges.TryGetValue(new Identifier(_var_pause), out _judgePause);
foreach (var i in rs.inputs) {
var id = i.Key;
var l = new List<JudgeEvent>();
@@ -98,6 +99,33 @@ namespace Cryville.Crtr {
}
static bool _flag;
static readonly PropOp.Boolean _flagop = new PropOp.Boolean(v => _flag = v);
static readonly HitOp _hitop = new HitOp();
class HitOp : PdtOperator {
const int MAX_SORTS = 16;
readonly float[] _buf = new float[MAX_SORTS];
readonly float[] _sorts = new float[MAX_SORTS];
public bool LastHit { get; private set; }
public HitOp() : base(MAX_SORTS) { }
protected unsafe override void Execute() {
LastHit = false;
for (int i = 0; i < LoadedOperandCount; i++) {
var sort = GetOperand(i).AsNumber();
if (sort <= 0) return;
if (!LastHit && sort < _sorts[i]) return;
if (sort > _sorts[i]) LastHit = true;
_buf[i] = sort;
}
if (!LastHit) return;
Array.Clear(_buf, LoadedOperandCount, MAX_SORTS - LoadedOperandCount);
fixed (float* ptrsrc = _buf, ptrdest = _sorts) {
Unsafe.CopyBlock(ptrdest, ptrsrc, MAX_SORTS * sizeof(float));
}
}
public void Clear() { Array.Clear(_sorts, 0, MAX_SORTS); }
}
static readonly int _var_fn = IdentifierManager.Shared.Request("judge_clip_from");
static readonly int _var_tn = IdentifierManager.Shared.Request("judge_clip_to");
static readonly int _var_ft = IdentifierManager.Shared.Request("input_time_from");
@@ -121,14 +149,13 @@ namespace Cryville.Crtr {
}
return ~num;
}
int BinarySearchFirst(List<JudgeEvent> list, float time, int stack) {
if (list[0].Definition.stack == stack && list[0].StartClip == time) return 0;
int BinarySearchFirst(List<JudgeEvent> list, int stack) {
if (list[0].Definition.stack == stack) return 0;
int num = 0;
int num2 = list.Count - 1;
while (num <= num2) {
int num3 = num + (num2 - num >> 1);
int num4 = -list[num3].Definition.stack.CompareTo(stack);
if (num4 == 0) num4 = list[num3].StartClip.CompareTo(time);
if (num4 > 0) num2 = num3 - 1;
else if (num4 < 0) num = num3 + 1;
else if (num != num3) num2 = num3;
@@ -143,28 +170,43 @@ namespace Cryville.Crtr {
_numbuf3 = ft; _numsrc3.Invalidate(); _etor.ContextCascadeUpdate(_var_ft, _numsrc3);
_numbuf4 = tt; _numsrc4.Invalidate(); _etor.ContextCascadeUpdate(_var_tt, _numsrc4);
int index = 0, iter = 0;
while (index >= 0 && index < actlist.Count) {
var ev = actlist[index];
_numbuf1 = (float)ev.StartTime; _numsrc1.Invalidate(); _etor.ContextCascadeUpdate(_var_fn, _numsrc1);
_numbuf2 = (float)ev.EndTime; _numsrc2.Invalidate(); _etor.ContextCascadeUpdate(_var_tn, _numsrc2);
var def = ev.Definition;
if (def.hit != null) _etor.Evaluate(_flagop, def.hit);
else _flag = true;
if (_flag) {
if (ev.Definition == _judgePause) _sys.TogglePause();
while (index < actlist.Count) {
if (iter++ >= 16) throw new JudgePropagationException();
_hitop.Clear();
int cstack = actlist[index].Definition.stack;
int hitIndex = -1;
while (index >= 0 && index < actlist.Count) {
var ev = actlist[index];
if (ev.Definition.stack != cstack) break;
_numbuf1 = (float)ev.StartTime; _numsrc1.Invalidate(); _etor.ContextCascadeUpdate(_var_fn, _numsrc1);
_numbuf2 = (float)ev.EndTime; _numsrc2.Invalidate(); _etor.ContextCascadeUpdate(_var_tn, _numsrc2);
var def = ev.Definition;
if (def.hit != null) {
_etor.Evaluate(_hitop, def.hit);
if (_hitop.LastHit) hitIndex = index;
}
else if (hitIndex == -1) hitIndex = index;
index++;
}
if (hitIndex != -1) {
var hitEvent = actlist[hitIndex];
_numbuf1 = (float)hitEvent.StartTime; _numsrc1.Invalidate(); _etor.ContextCascadeUpdate(_var_fn, _numsrc1);
_numbuf2 = (float)hitEvent.EndTime; _numsrc2.Invalidate(); _etor.ContextCascadeUpdate(_var_tn, _numsrc2);
var def = hitEvent.Definition;
if (def == _judgePause) _sys.TogglePause();
if (def.scores != null) UpdateScore(def.scores);
if (def.pass != null) Pass(ev, (ft + tt) / 2, def.pass);
if (def.pass != null) Pass(hitEvent, (ft + tt) / 2, def.pass);
if (def.persist != null) _etor.Evaluate(_flagop, def.persist);
else _flag = false;
if (!_flag) actlist.RemoveAt(index);
if (!_flag) {
actlist.RemoveAt(hitIndex);
--index;
}
if (def.prop != 0 && actlist.Count > 0) {
index = BinarySearchFirst(actlist, (float)ev.StartClip, def.stack - def.prop);
index = BinarySearchFirst(actlist, def.stack - def.prop);
if (index < 0) index = ~index;
}
else index++;
if (iter++ >= 16) throw new JudgePropagationException();
}
else index++;
}
}
}