1 module mutils.timeline.utils; 2 3 4 import std.traits; 5 6 import std.stdio; 7 8 9 struct TimeIndexGetter{ 10 uint lastIndex=0; 11 float lastTime=float.min_exp; 12 13 void reset(){ 14 this=this.init; 15 } 16 17 void set(T)(in T[] slice, float time){ 18 if(time<=slice[0].time || lastTime>time){ 19 lastIndex=0; 20 } 21 lastTime=time; 22 foreach(uint i; lastIndex+1..cast(uint)slice.length){ 23 if(time<=slice[i].time){ 24 lastIndex=i-1; 25 return ; 26 } 27 28 } 29 lastIndex=cast(uint)slice.length-1; 30 } 31 32 uint[2] index(T)(in T[] slice, float time) { 33 static assert(hasMember!(T, "time")); 34 assert(slice.length<lastIndex.max); 35 assert(slice.length>0); 36 if(lastIndex>=slice.length || lastTime>time){ 37 lastIndex=0; 38 } 39 40 lastTime=time; 41 42 uint[2] ti; 43 if(time<=slice[0].time){ 44 lastIndex=0; 45 return ti; 46 } 47 foreach(uint i; lastIndex+1..cast(uint)slice.length){ 48 if(time<=slice[i].time){ 49 ti[0]=i-1; 50 ti[1]=i; 51 lastIndex=i-1; 52 return ti; 53 } 54 55 } 56 lastIndex=cast(uint)slice.length-2; 57 uint last=cast(uint)(slice.length-1); 58 ti[0]=last; 59 ti[1]=last; 60 return ti; 61 } 62 63 T[] passedFromLast(T)(T[] slice, float time) { 64 static assert(hasMember!(T, "time")); 65 assert(slice.length<lastIndex.max); 66 assert(slice.length>0); 67 68 scope(exit)lastTime=time; 69 70 if(lastIndex>slice.length || lastTime>time || time<=slice[0].time){ 71 lastIndex=0; 72 return null; 73 } 74 75 76 foreach(uint i; lastIndex+1..cast(uint)slice.length){ 77 if(time<=slice[i].time){ 78 bool after=slice[lastIndex].time<lastTime; 79 T[] ret=slice[lastIndex+after..i]; 80 lastIndex=i-1; 81 return ret; 82 } 83 84 } 85 bool after=slice[lastIndex].time<lastTime; 86 T[] ret=slice[lastIndex+after..slice.length]; 87 lastIndex=cast(uint)slice.length-1; 88 return ret; 89 } 90 } 91 92 unittest{ 93 import std.algorithm: equal; 94 struct Data{ 95 float time; 96 } 97 98 TimeIndexGetter getter; 99 Data[] data; 100 data~=[Data(0), Data(1), Data(2), Data(3), Data(4)]; 101 //Check index 102 assert(getter.index(data, 0)==[0, 0]); 103 assert(getter.index(data, 5)==[4, 4]); 104 assert(getter.index(data, 1)==[0, 1]); 105 assert(getter.index(data, 4)==[3, 4]); 106 assert(getter.index(data, -5)==[0, 0]); 107 //Check passedFromLast 108 assert(getter.passedFromLast(data, 0)==null); 109 assert(getter.passedFromLast(data, 0.5)==data[0..1]); 110 assert(getter.passedFromLast(data, 0.5)==null); 111 assert(getter.passedFromLast(data, 1.1)==data[1..2]); 112 assert(getter.passedFromLast(data, 1.1)==null); 113 assert(getter.passedFromLast(data, 4.1)==data[2..5]); 114 assert(getter.passedFromLast(data, 5)==null); 115 assert(getter.passedFromLast(data, 10)==null); 116 assert(getter.passedFromLast(data, -10)==null); 117 assert(getter.passedFromLast(data, 10)==data); 118 //Check index after passedFromLast 119 assert(getter.index(data, 15)==[4, 4]); 120 //Check set 121 getter.set(data, 1.5); 122 assert(getter.index(data, 1.7)==[1, 2]); 123 assert(getter.lastIndex==1); 124 assert(getter.passedFromLast(data, 2.5)==data[2..3]); 125 //Reset 126 getter.reset(); 127 assert(getter==TimeIndexGetter.init); 128 129 }