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 }