var Type = require('./type'); var Node = require('./node'); function State(){ var t; /*if(perf){ t = start + perf.now(); // Danger: Accuracy decays significantly over time, even if precise. } else {*/ t = time(); //} if(last < t){ return N = 0, last = t + State.drift; } return last = t + ((N += 1) / D) + State.drift; } var time = Type.time.is, last = -Infinity, N = 0, D = 1000; // WARNING! In the future, on machines that are D times faster than 2016AD machines, you will want to increase D by another several orders of magnitude so the processing speed never out paces the decimal resolution (increasing an integer effects the state accuracy). var perf = (typeof performance !== 'undefined')? (performance.timing && performance) : false, start = (perf && perf.timing && perf.timing.navigationStart) || (perf = false); State._ = '>'; State.drift = 0; State.is = function(n, k, o){ // convenience function to get the state on a key on a node and return it. var tmp = (k && n && n[N_] && n[N_][State._]) || o; if(!tmp){ return } return num_is(tmp = tmp[k])? tmp : -Infinity; } State.lex = function(){ return State().toString(36).replace('.','') } State.ify = function(n, k, s, v, soul){ // put a key's state on a node. if(!n || !n[N_]){ // reject if it is not node-like. if(!soul){ // unless they passed a soul return; } n = Node.soul.ify(n, soul); // then make it so! } var tmp = obj_as(n[N_], State._); // grab the states data. if(u !== k && k !== N_){ if(num_is(s)){ tmp[k] = s; // add the valid state. } if(u !== v){ // Note: Not its job to check for valid values! n[k] = v; } } return n; } State.to = function(from, k, to){ var val = from[k]; // BUGGY! if(obj_is(val)){ val = obj_copy(val); } return State.ify(to, k, State.is(from, k), val, Node.soul(from)); } ;(function(){ State.map = function(cb, s, as){ var u; // for use with Node.ify var o = obj_is(o = cb || s)? o : null; cb = fn_is(cb = cb || s)? cb : null; if(o && !cb){ s = num_is(s)? s : State(); o[N_] = o[N_] || {}; obj_map(o, map, {o:o,s:s}); return o; } as = as || obj_is(s)? s : u; s = num_is(s)? s : State(); return function(v, k, o, opt){ if(!cb){ map.call({o: o, s: s}, v,k); return v; } cb.call(as || this || {}, v, k, o, opt); if(obj_has(o,k) && u === o[k]){ return } map.call({o: o, s: s}, v,k); } } function map(v,k){ if(N_ === k){ return } State.ify(this.o, k, this.s) ; } }()); var obj = Type.obj, obj_as = obj.as, obj_has = obj.has, obj_is = obj.is, obj_map = obj.map, obj_copy = obj.copy; var num = Type.num, num_is = num.is; var fn = Type.fn, fn_is = fn.is; var N_ = Node._, u; module.exports = State;