-
- Since timing object position P is covered by cue C, an enter event will be generated by the code above.
-
- However, if the timing object additionally has velocity in the direction away from cue C, a playback exit event will
- immediately be needed. However, this will not be picked up by load/schedule, as this will only consider cue endpoints
- within the next segment on the timeline, which does not include point P, i.e. , depending
- on direction.
-
- Entering open intervals should be covered by schedule/load on next timeline segment.
-
- To solve this we will generate the needed playback events here. Active cues will be adjusted as part of that process.
-
- This issue is not likely to be easily reproducible, because for instance setting the timing object to
- {position:0, velocity:1} with yield a nowVector sampled a little bit later, which gives a position which is 0+delta, which
- means that cues that are tied to endpoint 0 will be detected by code above. So one really needs to be precise to a large
- number of decimal places for a cueendpoint to match the position exactly.
-
- */
- const directionInt = motionutils.calculateDirection(nowVector, now);
-
- if (isMoving(nowVector)) {
- const cuepoints = this._axis.getCuePointsByInterval(new Interval(pos));
- const direction = DirectionType.fromInteger(directionInt);
- exitCues = new Map();
- for (let cp of cuepoints.values()) {
- if (cp.cue.interval.singular) {
- exitCues.set(cp.cue.key, cp.cue);
- } else {
- // closed interval ?
- const interval = cp.cue.interval;
- const pointType = getPointType(pos, interval);
- let closed = false;
- if (pointType === PointType.LOW && interval.lowInclude) {
- closed = true;
- } else if (pointType === PointType.HIGH && interval.highInclude) {
- closed = true;
- }
- // exiting or entering interval?
- var entering = true;
- if (pointType === PointType.LOW && direction === DirectionType.BACKWARDS) {
- entering = false;
- } else if (pointType === PointType.HIGH && direction === DirectionType.FORWARDS) {
- entering = false;
- }
- // exiting closed interval
- if (!entering && closed) {
- exitCues.set(cp.cue.key, cp.cue);
- }
- }
- }
- // make events
- const _now = this._to.clock.now();
- const eList = [];
- for (let cue of exitCues.values()) {
- let eArg = makeEArg(_now, pos, cue, directionInt, Cause.PLAYBACK, VerbType.EXIT, now);
- eList.push({type: eArg.type, e:eArg});
- this._activeCues.delete(cue.key);
- }
- this.eventifyTriggerEvents(eList);
- }
-
- // update list version of activeCues
- this._activeCuesList = [...this._activeCues.values()];
-
- // clear schedule
- if (this._schedule == undefined) {
- this._schedule = new Schedule(now);
- } else {
- this._schedule.advance(now);
- }
-
- // kick off main loop
- if (isMoving(nowVector)) {
- this._load(now);
- this._main(now);
- } else {
- // stop main loop
- this._clearTimeout();
- }
- };
-
-
- /*
- Make events triggered by changes, either timing object changes or cue changes
- */
- Sequencer.prototype._makeChangeEvents = function (now, point, cause, exitCues, enterCues, changeCues) {
- const directionInt = motionutils.calculateDirection(this._to.vector, now);
- let eArgList = [];
- for (let cue of exitCues.values()) {
- eArgList.push(makeEArg(now, point, cue, directionInt, cause, VerbType.EXIT));
- }
- for (let cue of enterCues.values()) {
- eArgList.push(makeEArg(now, point, cue, directionInt, cause, VerbType.ENTER));
- }
-
- for (let cue of changeCues.values()) {
- eArgList.push(makeEArg(now, point, cue, directionInt, cause, VerbType.UPDATE))
- }
- // make sure events are correctly ordered
- eArgList = this._reorderEventList(eArgList, directionInt);
- return eArgList.map(function (eArg) {
- return {type: eArg.type, e:eArg};
- });
- };
-
-
- /*
- Make events during playback, from schedule task list
- */
- Sequencer.prototype._makePlaybackEvents = function (now, scheduleEntries) {
- const directionInt = motionutils.calculateDirection(this._to.vector, now);
- let eArgList = [];
- let entry, task;
- let dirty = false;
- for (let i=0; i 0) {
- let eList = this._makePlaybackEvents(now, tasks);
- this.eventifyTriggerEvents(eList);
- }
-
- // advance schedule window if end is reached
- var _isMoving = isMoving(this._to.vector);
- if (_isMoving && this._schedule.isExpired(now)) {
- // advance schedule to end of current window
- now = this._schedule.getTimeInterval().high;
- this._schedule.advance(now);
- this._load(now);
- // process tasks again in case some are due immediately
- let tasks = this._schedule.pop(now);
- if (tasks.length > 0) {
- let eList = this._makePlaybackEvents(now, tasks);
- this.eventifyTriggerEvents(eList);
- }
- }
- // adjust timeout if needed
- if (_isMoving) {
- let newTimeoutRequired = (this._timeout === null);
- if (!newTimeoutRequired) {
- // timeout exist - modify?
- // avoid modifying timeout if new timeout is equal to existing timeout
- // i.e. if task point is the same as last time
- var nextTimeoutPoint = this._schedule.getNextTaskPoint();
- if (nextTimeoutPoint === null) {
- // timeout is set for schedule window - no tasks in schedule
- // do not modify timeout
- } else {
- // nextTimeoutPoint defined - tasks in the schedule
- if (nextTimeoutPoint === this._currentTimeoutPoint) {
- // do not modify timeout
- } else {
- // modify timeout
- newTimeoutRequired = true
- }
- }
- }
- if (newTimeoutRequired) {
- // clear timeout
- this._clearTimeout();
- // update timeout
- var secAnchor = this._to.clock.now();
- var secDelay = this._schedule.getDelayNextTs(secAnchor); // seconds
- this._currentTimeoutPoint = nextTimeoutPoint;
- var self = this;
- this._timeout = this._to.clock.setTimeout(function () {
- self._clearTimeout();
- self._main(undefined, true);
- }, secDelay, {anchor: secAnchor, early: 0.005});
- }
- }
- };
-
-
- Sequencer.prototype._clearTimeout = function () {
- this._currentTimeoutPoint = null;
- if (this._timeout !== null) {
- this._timeout.cancel();
- this._timeout = null;
- }
- };
-
- /*
- LOAD
-
- Sequencer loads a new batch of points from axis into
- the schedule
-
- If given_points is specified, this implies that the
- points to load are known in advance. This is the case when
- axis is being updated dynamically during execution. If
- points are not known the load function fetches points from
- the axis by means of the time cover of the schedule.
-
- load only makes sense when timing object is moving
- */
-
- Sequencer.prototype._load = function (now, givenPoints) {
-
- /*
- MOVING
- Load events from time interval
- */
- var timeInterval = this._schedule.getTimeInterval();
- var tStart = timeInterval.low;
- var tEnd = timeInterval.high;
- var tDelta = timeInterval.length;
- // range
- var range = this._to.range;
- var vectorStart = motionutils.calculateVector(this._to.vector, tStart);
- var points = givenPoints;
-
- // Calculate points if not provided
- if (!points) {
-
- // 1) find the interval covered by the movement of timing object during the time delta
- var posRange = motionutils.calculateInterval(vectorStart, tDelta);
- var pStart = Math.round10(Math.max(posRange[0], range[0]), -10);
- var pEnd = Math.round10(Math.min(posRange[1], range[1]), -10);
-
- /*
- posInterval always <,]
- */
- const posInterval = new Interval(pStart, pEnd, false, true);
- this._schedule.setPosInterval(posInterval);
-
- // 2) find all points in this interval
- points = this._axis.getCuePointsByInterval(posInterval);
- }
-
- // create ordered list of all events for time interval t_delta
- var eventList = motionutils.calculateSolutionsInInterval(vectorStart, tDelta, points);
- if (points.length !== eventList.length) {
- console.log("warning : mismatch points and events", points.length, eventList.length);
- }
-
- /*
- SUBTLE 1 : adjust for range restrictions within
- time-interval tasks with larger delta will not be
- pushed to schedule it is not necessary to truncate the
- time interval of schedule similarly - just drop all
- events after prospective range violations. is
- time to (first) range violation
- */
- var rDelta = motionutils.calculateDelta(vectorStart, range)[0];
-
- /*
- SUBTLE 2: avoid tasks exactly at start of time-interval
- assume that this point should already be processed by the
- previous covering interval.
- */
-
- // filter and push events on sched
- eventList.forEach(function (e) {
-
- var d = e[0];
- var task = e[1];
- const pointType = getPointType(task.point, task.cue.interval);
- var push = true;
-
- /*
- events from within the time interval may still be too late,
- if they are before now .
- this may happen when new items are added dynamically
- even though we drop them here, they already had their
- effect in calculation of enter/exit events.
- */
- if (tStart + d < now) {
- push = false;
- }
-
- /*
- drop events exactly at the start of the time covering
- interval.
- likely obsolete since we are fetching points [low, high]
- */
- if (d === 0) {
- console.log("drop - exactly at start of time covering");
- push = false;
- }
- /*
- drop all events scheduled after (in time) range
- violation should occur
- */
- if (d > rDelta) {
- console.log("drop - events after range violations");
- push = false;
- }
- /*
- event scheduled exactly at range point.
- - interval :
- Exiting/entering a interval should not happen at range point - drop
- */
- if (d === rDelta) {
- console.log("drop - events exactly at range point")
- push = false;
- }
-
- /*
- check if we are touching an interval without
- entering or exiting. Note that direction will
- not be zero at this point, because direction
- includes acceleration, which is not zero in
- this case.
- drop all interval events that have zero velocity
- at the time it is supposed to fire
- */
- if (pointType === PointType.LOW || pointType === PointType.HIGH) {
- var v = motionutils.calculateVector(this._to.vector, tStart + d);
- if (v.velocity === 0){
- console.log("drop - touch endpoint during acceleration");
- push = false;
- }
- }
- // push
- if (push) {
- this._schedule.push(now, tStart + d, task);
- }
- }, this);
- };
-
-
- /*
- Event list is sorted by time.
- There can be multiple events on the same time.
- Events with the same point (thus time) need to be sorted according to the following precedence
- a. exit interval > (interval does not include exit-point)
- x. enter interval [ (interval includes enter-point)
- b. enter singular
- c. exit singular
- y. exit intervals ] (interval includes exit-point)
- d. enter intervals < (interval does not include enter-point)
- */
- Sequencer.prototype._reorderEventList = function (eArgList, directionInt) {
- if (eArgList.length < 2) return eArgList;
- // stack events per point
- var point, dueTs, newList = [];
- var s = {"a": [], "x": [], "b": [], "c": [], "y": [], "d": []};
- eArgList.sort(function (a, b) {
- return a.interval.low - b.interval.low;
- }).forEach(function(eArg) {
- // new point - pop from stack
- if (eArg.point !== point || eArg.dueTs !== dueTs) {
- // pop last from stack
- if (directionInt >= 0) {
- newList = newList.concat(s["a"], s["x"], s["b"], s["c"], s["y"], s["d"]);
- } else {
- newList = newList.concat(s["d"], s["y"], s["c"], s["b"], s["x"], s["a"]);
- }
- s = {"a": [], "x": [], "b": [], "c": [], "y": [], "d": []};
- point = eArg.point;
- dueTs = eArg.dueTs;
- }
- // push on stack
- if (eArg.pointType === PointType.SINGULAR) {
- if (eArg.type === VerbType.ENTER) {
- // enter singular
- s["b"].push(eArg);
- } else {
- // exit singular
- s["c"].push(eArg);
- }
- } else {
- /*
- Interval
- special ordering when we enter or exit interval
- through endpoint (low or high) and this endpoint is CLOSED ] as opposed to OPEN >
- */
- var closed = false;
- if ((eArg.pointType === PointType.LOW) && eArg.interval.lowInclude) {
- closed = true;
- } else if ((eArg.pointType === PointType.HIGH) && eArg.interval.highInclude) {
- closed = true;
- }
- if (eArg.type === VerbType.ENTER) {
- // enter interval
- if (closed) s["x"].push(eArg);
- else s["d"].push(eArg);
- } else {
- // exit interval
- if (closed) s["y"].push(eArg);
- else s["a"].push(eArg);
- }
- }
- }, this);
-
- // pop last from stack
- if (directionInt >= 0) {
- return newList.concat(s["a"], s["x"], s["b"], s["c"], s["y"], s["d"]);
- } else {
- return newList.concat(s["d"], s["y"], s["c"], s["b"], s["x"], s["a"]);
- }
- };
-
-
- /*
- Active Cues API
- */
-
- // return true if cue of given key is currently active
- Sequencer.prototype.isActive = function (key) {
- return (this._activeCues.has(key));
- };
-
- // Get keys of active cues
- Sequencer.prototype.getActiveKeys = function () {
- return [...this._activeCues.keys()];
- };
-
- Sequencer.prototype.getActiveCues = function () {
- return this._activeCuesList;
- };
-
- /*
- Export Axis API
-
- Alternative - expose Axis object itself with .getAxis()
- */
-
- Sequencer.prototype.update = function (cues) {
- return this._axis.update(cues);
- };
-
- Sequencer.prototype.addCue = function (key, interval, data) {
- return this._axis.addCue(key, interval, data)
- };
-
- Sequencer.prototype.removeCue = function (key) {
- return this._axis.removeCue(key);
- };
-
- // true if cues exists with given key
- Sequencer.prototype.hasCue = function (key) {
- return this._axis.has(key);
- };
-
- // get specific cue {key: key, interval:interva} given key
- Sequencer.prototype.getCue = function (key) {
- return this._axis.get(key);
- };
-
- // get all keys
- Sequencer.prototype.keys = function () {
- return this._axis.keys();
- };
-
- // get all cues
- Sequencer.prototype.getCues = function () {
- return this._axis.cues();
- };
-
- Sequencer.prototype.getCuesByInterval = function (interval, semantic) {
- return this._axis.getCuesByInterval(interval, semantic);
- };
-
- Sequencer.prototype.removeCuesByInterval = function (interval, semantic) {
- return this._axis.removeCuesByInterval(interval, semantic);
- };
-
-
- // shutdown
- Sequencer.prototype.close = function () {
- this._to.off("change", this._wrappedOnTimingChange, this);
- this._axis.off("change", this._wrappedOnAxisChange, this);
- if (this._timeout !== null) {
- this._timeout.cancel();
- this._timeout = null;
- }
- };
-
- /*
- utility - print event
- */
- Sequencer.prototype.eventToString = function (e) {
- var s = "[" + e.point.toFixed(2) + "]";
- s += " " + e.key;
- s += " " + e.interval.toString();
- s += " " + e.type;
- var verb = "none";
- if (e.enter) verb = "enter";
- else if (e.exit) verb = "exit";
- s += " (" + e.cause + "," + verb + ")";
- s += " " + e.directionType;
- s += " " + e.pointType;
- s += " delay:" + e.delay.toFixed(4);
- if (e.data) s += " " + JSON.stringify(e.data);
- return s;
- };;
-
- return Sequencer;
-});
-
-
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-/*
- WINDOW SEQUENCER
-
- - a collection of Intervals are defined on an axis
- - a searchInterval is defined by two endpoints.
- - we are interested in all Intervals on the axis that are partially/fully covered by searchInterval
- - we then want to move the searchInterval along the axis
- - trigger onenter/onexit events as Intervals go from being not covered to partialy/fully covered and vica versa
- - define searchInterval endpoints by two motions that may or may not be dependent
- - use pointsequencer on each motion to generate events.
-
-
-
- EVENT PROCESSING FROM TIMING OBJECTS AND SEQUENCERS
-
- Timing Object events
-
- - Jumps (setting the position on the timing object) may cause some
- intervals to be covered or cease to be covered.
- Some of these intervals may remain active of inactive with respect to the point-
- sequencer, implying that there will be no events from the sequencer
-
- - Velocity adjustments (without position changs) can not cause changes to the WindowSequencer
- without also causing changes to the sequencers
-
- Sequencer events
-
- - required during playback to trigger timed refresh
- - sequencer provides events on both jumps and non-jumps
-
- There is possible event redundancy for events caused by jumps and non-jumps of the timing object.
- I.e. we receive an event from both timing object as well as
- events from the sequencer that were caused by the same event from the timing object.
-
- Fortunately, the overhead of this event duplication is small,
- since it only involves an extra reevaluate(), and if we are lucky the to events may be collapsed
- with the request_reevaluate mechanism. If not, the second invokation will cause some redundant processing
- but will ultimately have no effect.'
-
-
- Possible optimization 1)
- ignore non-jumps from timing object and depend on the sequencer for this
- - requires cashing the vector from the timing object, so that the new vector can be compared
- to the old one. This is necessary for discriminating between jumps and non-jumps.
- - not implemented
-
- Possible optimization 2)
- ignore sequencer events for jumps.
- - difficult because the sequencer at present does not distinguish event causes
- {jump|non-jump|playback}
- - not implemented
-
- Possible optimization 3)
- It is also possible to filter out updates from axis that are not relevant, in order to not invoke
- re-evaluate when it is not needed.
- - easy, but basically just saves a lookup on the axis, and only if all updates are non relevant.
- - not implemented
-*/
-
-define('sequencing/windowsequencer',['require','exports','module','util/eventify','util/motionutils','util/interval','./axis','./sequencer'],function(require, exports, module) {
-
- 'use strict';
-
- const eventify = require('util/eventify');
- const motionutils = require('util/motionutils');
- const Interval = require('util/interval');
- const Axis = require('./axis');
- const Sequencer = require('./sequencer');
-
- /*
- get the difference of two Maps
- key in a but not in b
- */
- const map_difference = function (a, b) {
- if (a.size == 0) {
- return new Map();
- } else if (b.size == 0) {
- return a;
- } else {
- return new Map([...a].filter(function ([key, value]) {
- return !b.has(key)
- }));
- }
- };
-
- /*
- get the intersection of two Maps
- key in a and b
- */
- const map_intersect = function (a, b) {
- [a, b] = (a.size <= b.size) ? [a,b] : [b,a];
- if (a.size == 0) {
- // No intersect
- return new Map();
- }
- return new Map([...a].filter(function ([key, value]) {
- return b.has(key)
- }));
- };
-
-
- // Event cause
- const Cause = Object.freeze({
- INIT: "init",
- TIMINGCHANGE: "timing-change",
- CUECHANGE: "cue-change",
- PLAYBACK: "playback"
- });
-
-
- var WindowSequencer = function (timingObjectA, timingObjectB, _axis) {
- if (!(this instanceof WindowSequencer)) {
- throw new Error("Contructor function called without new operation");
- }
- this._axis = _axis || new Axis();
- this._toA = timingObjectA;
- this._toB = timingObjectB;
-
- this._seqA = new Sequencer(this._toA, this._axis);
- this._seqB = new Sequencer(this._toB, this._axis);
-
- // ready
- this._ready = new eventify.EventBoolean(false, {init:true});
-
- // true if re_evalute has been requested but not performed yet
- this._pending_reevaluate = false;
-
- // active cues
- this._activeCues = new Map(); // key -> cue
- this._activeCuesList = [];
-
- // Define Events API
- // event type "events" defined by default
- eventify.eventifyInstance(this);
- this.eventifyDefineEvent("change", {init:true}); // define change event (supporting init-event)
- this.eventifyDefineEvent("remove");
-
-
- var self = this;
-
- // Store references to handler on instance
- this._onAxisChange = function (eventMap) {
- // console.log("on Axis Change");
- self._reevaluate(eventMap);
- };
- this._onToAChange = function () {
- // console.log("on ToA Change");
- self._request_reevaluate();
- };
- this._onToBChange = function () {
- // console.log("on ToB Change");
- self._request_reevaluate();
- };
- this._onSeqAChange = function (e) {
- // console.log("on SeqA Change");
- self._request_reevaluate();
- };
- this._onSeqBChange = function (e) {
- // console.log("on SeqB Change");
- self._request_reevaluate();
- };
- this._toA.on("change", this._onToAChange, this);
- this._toB.on("change", this._onToBChange, this);
- this._seqA.on("events", this._onSeqAChange, this);
- this._seqB.on("events", this._onSeqBChange, this);
-
-
- Promise.all([this._seqA.ready, this._seqB.ready]).then(function (values) {
- // both sequencers are ready
- // by implication - both timing objects are ready too
- self._axis.on("change", self._onAxisChange, self);
- self._ready.value = true;
- self._request_reevaluate();
- });
-
- };
- eventify.eventifyPrototype(WindowSequencer.prototype);
-
-
- /*
- READY STATE
-
- The interval sequencer is ready when both timing objects are ready
- */
- WindowSequencer.prototype.isReady = function () {
- return (this._ready.value === true);
- };
-
- // ready promise
- Object.defineProperty(WindowSequencer.prototype, 'ready', {
- get : function () {
- var self = this;
- return new Promise (function (resolve, reject) {
- if (self._ready.value === true) {
- resolve();
- } else {
- var onReady = function () {
- if (self._ready.value === true) {
- self._ready.off("change", onReady);
- resolve();
- }
- };
- self._ready.on("change", onReady);
- }
- });
- }
- });
-
-
- /*
-
- EVENT HANDLERS
-
- */
-
- /*
- overrides how immediate events are constructed
- */
- WindowSequencer.prototype.eventifyMakeInitEvents = function (type) {
- if (type === "change") {
- // make event items from active keys
- let eArgList = []
- for (let cue of this._activeCues.values()) {
- eArgList.push({
- cue: cue,
- type : "change",
- cause: Cause.INIT,
- enter : true,
- exit : false
- });
- }
- return eArgList;
- }
- return [];
- };
-
- /*
- figure out the current active interval
- */
- WindowSequencer.prototype._getActiveInterval = function () {
- var vectorA = this._toA.query();
- var vectorB = this._toB.query();
- var start = Math.min(vectorA.position, vectorB.position);
- var end = Math.max(vectorA.position, vectorB.position);
- return new Interval(start, end, true, true);
- };
-
-
- /*
- Request reevaluate
- Buffering and collapsing requests to reevaluate
- noop if reevaluate has already been requested, but not performed
- else - append reevaluate to the task queue
- */
- WindowSequencer.prototype._request_reevaluate = function () {
- if (this._pending_reevaluate == false) {
- this._pending_reevaluate = true;
- var self = this;
- setTimeout(function() {
- self._pending_reevaluate = false;
- self._reevaluate()
- }, 0)
- }
- };
-
- /*
- RE-EVALUATE
-
- Figure out what kind of events need to be triggered (if any)
- in order to bring the WindowSequencer to the correct state.
- */
-
- WindowSequencer.prototype._reevaluate = function (eventMap) {
- if (this._ready.value === false) {
- return [];
- }
-
- const activeInterval = this._getActiveInterval();
-
- /*
- find new active cues
- */
- const activeCues = new Map(this._axis.getCuesByInterval(activeInterval).map(function(cue) {
- return [cue.key, cue];
- }));
-
- /*
- find exit cues
- were in old active cues - but not in new
- */
- let exitCues = map_difference(this._activeCues, activeCues);
- /*
- find enter cues
- were not in old active cues - but are in new
- */
- let enterCues = map_difference(activeCues, this._activeCues);
-
- /*
- find change cues
- those cues that were modified and also remain within the set of active cues
- */
- let changeCues = new Map();
- if (eventMap) {
- const modifiedCues = new Map([...eventMap].filter(function ([key, eItem]) {
- return eItem.new && eItem.old;
- }).map(function([key, eItem]) {
- return [key, eItem.new];
- }));
- changeCues = map_intersect(modifiedCues, activeCues);
- }
-
- // update active cues
- this._activeCues = activeCues;
- this._activeCuesList = [...this._activeCues.values()];
-
- // make event items from enter/exit keys
- const eList = [];
- const cause = (eventMap) ? Cause.CUECHANGE : Cause.PLAYBACK;
- for (let cue of exitCues.values()) {
- eList.push({
- type: "remove",
- e: {
- key: cue.key,
- interval: cue.interval,
- data: cue.data,
- type : "remove",
- cause : cause,
- enter: false,
- exit : true
- }
- });
- }
- for (let cue of enterCues.values()) {
- eList.push({
- type: "change",
- e: {
- key: cue.key,
- interval: cue.interval,
- data: cue.data,
- type: "change",
- cause : cause,
- enter : true,
- exit : false
- }
- });
- }
- for (let cue of changeCues.values()) {
- eList.push({
- type: "change",
- e: {
- cue: cue,
- key: cue.key,
- interval: cue.interval,
- data: cue.data,
- type: "change",
- cause : cause,
- enter : false,
- exit : false
- }
- });
- }
-
- this.eventifyTriggerEvents(eList);
- };
-
- /*
- Active Cues API
- */
-
- // return true if cue of given key is currently active
- WindowSequencer.prototype.isActive = function (key) {
- return this._activeCues.has(key);
- };
-
- // Get keys of active cues
- WindowSequencer.prototype.getActiveKeys = function () {
- return [...this._activeCues.keys()];
- };
-
- WindowSequencer.prototype.getActiveCues = function () {
- return this._activeCuesList;
- };
-
- /*
- Export Axis API
-
- Alternative - expose Axis object itself with .getAxis()
- */
-
- WindowSequencer.prototype.update = function (cues) {
- return this._axis.update(cues);
- };
-
- WindowSequencer.prototype.addCue = function (key, interval, data) {
- return this._axis.addCue(key, interval, data)
- };
-
- WindowSequencer.prototype.removeCue = function (key) {
- return this._axis.removeCue(key);
- };
-
- // true if cues exists with given key
- WindowSequencer.prototype.hasCue = function (key) {
- return this._axis.has(key);
- };
-
- // get specific cue {key: key, interval:interva} given key
- WindowSequencer.prototype.getCue = function (key) {
- return this._axis.get(key);
- };
-
- // get all keys
- WindowSequencer.prototype.keys = function () {
- return this._axis.keys();
- };
-
- // get all cues
- WindowSequencer.prototype.getCues = function () {
- return this._axis.cues();
- };
-
- WindowSequencer.prototype.getCuesByInterval = function (interval) {
- return this._axis.getCuesByInterval(interval);
- };
-
- WindowSequencer.prototype.removeCuesByInterval = function (interval) {
- return this._axis.removeCuesByInterval(interval);
- };
-
- // shutdown
- WindowSequencer.prototype.close = function () {
- this._axis.off("change", this._onAxisChange);
- this._toA.off("change", this._onToAChange);
- this._toB.off("change", this._onToBChange);
- this._seqA.off("events", this._onSeqAChange);
- this._seqB.off("events", this._onSeqBChange);
- this._seqA.close();
- this._seqB.close();
- };
-
- return WindowSequencer;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-define('util/timeoututils',[],function () {
-
- 'use strict';
-
- /*
- TIMEOUT
-
- Wraps setTimeout() to implement improved version
- - guarantee that timeout does not wake up too early
- - offers precise timeout by "busy"-looping just before timeout
- - wraps a single timeout
- - clock operates in seconds
- - parameters expected in seconds - breaking conformance with setTimeout
- - wakes up 3 seconds before on long timeouts to readjust
- */
-
- var Timeout = function (clock, callback, delay, options) {
- // clock
- this._clock = clock; // seconds
- var now = this._clock.now(); // seconds
- // timeout
- this._tid = null;
- this._callback = callback;
- this._delay_counter = 0;
- this._options = options || {};
-
- // options
- this._options.anchor = this._options.anchor || now; // seconds
- this._options.early = Math.abs(this._options.early) || 0; // seconds
- this._target = this._options.anchor + delay; // seconds
-
- // Initialise
- var self = this;
- window.addEventListener("message", this, true); // this.handleEvent
- var time_left = this._target - this._clock.now(); // seconds
- if (time_left > 10) {
- // long timeout > 10s - wakeup 3 seconds earlier to readdjust
- this._tid = setTimeout(function () {self._ontimeout();}, time_left - 3000);
- } else {
- // wake up just before
- this._tid = setTimeout(function () {self._ontimeout();}, (time_left - self._options.early)*1000);
- }
- };
-
- Object.defineProperty(Timeout.prototype, 'target', {
- get : function () {
- return this._target;
- }
- });
-
- // Internal function
- Timeout.prototype._ontimeout = function () {
- if (this._tid !== null) {
- var time_left = this._target - this._clock.now(); // seconds
- if (time_left <= 0) {
- // callback due
- this.cancel();
- this._callback();
- } else if (time_left > this._options.early) {
- // wakeup before target - options early sleep more
- var self = this;
- this._tid = setTimeout(function () {self._ontimeout();}, (time_left - this._options.early)*1000);
- } else {
- // wake up just before (options early) - event loop
- this._smalldelay();
- }
- }
- };
-
- // Internal function - handler for small delays
- Timeout.prototype.handleEvent = function (event) {
- if (event.source === window && event.data.indexOf("smalldelaymsg_") === 0) {
- event.stopPropagation();
- // ignore if timeout has been canceled
- var the_tid = parseInt(event.data.split("_")[1]);
- if (this._tid !== null && this._tid === the_tid) {
- this._ontimeout();
- }
- }
- };
-
- Timeout.prototype._smalldelay = function () {
- this._delay_counter ++;
- var self = this;
- window.postMessage("smalldelaymsg_" + self._tid, "*");
- };
-
- Timeout.prototype.cancel = function () {
- if (this._tid !== null) {
- clearTimeout(this._tid);
- this._tid = null;
- var self = this;
- window.removeEventListener("message", this, true);
- }
- };
-
- // return module object
- return {
- setTimeout: function (clock, callback, delay, options) {
- return new Timeout(clock, callback, delay, options);
- }
- };
-});
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-/*
- MASTER CLOCK
-
-
- MasterClock is the reference clock used by TimingObjects.
-
- It is implemented using performance.now,
- but is skewed and rate-adjusted relative to this local clock.
-
- This allows it to be used as a master clock in a distributed system,
- where synchronization is generally relative to some other clock than the local clock.
-
- The master clock may need to be adjusted in time, for instance as a response to
- varying estimation of clock skew or drift. The master clock supports an adjust primitive for this purpose.
-
- What policy is used for adjusting the master clock may depend on the circumstances
- and is out of scope for the implementation of the MasterClock.
- This policy is implemented by the timing object. This policy may or may not
- provide monotonicity.
-
- A change event is emitted every time the masterclock is adjusted.
-
- Vector values define
- - position : absolute value of the clock in seconds
- - velocity : how many seconds added per second (1.0 exactly - or very close)
- - timestamp : timstamp from local system clock (performance) in seconds. Defines point in time where position and velocity are valid.
-
- If initial vector is not provided, default value is
- {position: now, velocity: 1.0, timestamp: now};
- implying that master clock is equal to local clock.
-*/
-
-define('util/masterclock',['./eventify', './timeoututils'], function (eventify, timeoututils) {
-
- 'use strict';
-
- // Need a polyfill for performance,now as Safari on ios doesn't have it...
- (function(){
- if ("performance" in window === false) {
- window.performance = {};
- window.performance.offset = new Date().getTime();
- }
- if ("now" in window.performance === false){
- window.performance.now = function now(){
- return new Date().getTime() - window.performance.offset;
- };
- }
- })();
-
- // local clock in seconds
- var localClock = {
- now : function () {return performance.now()/1000.0;}
- };
-
- var calculateVector = function (vector, tsSec) {
- if (tsSec === undefined) tsSec = localClock.now();
- var deltaSec = tsSec - vector.timestamp;
- return {
- position : vector.position + vector.velocity*deltaSec,
- velocity : vector.velocity,
- timestamp : tsSec
- };
- };
-
- var MasterClock = function (options) {
- var now = localClock.now();
- options = options || {};
- this._vector = {position: now, velocity: 1.0, timestamp: now};
- // event support
- eventify.eventifyInstance(this);
- this.eventifyDefineEvent("change"); // define change event (no init-event)
- // adjust
- this.adjust(options);
- };
- eventify.eventifyPrototype(MasterClock.prototype);
-
-
- /*
- ADJUST
- - could also accept timestamp for velocity if needed?
- - given skew is relative to local clock
- - given rate is relative to local clock
- */
- MasterClock.prototype.adjust = function (options) {
- options = options || {};
- var now = localClock.now();
- var nowVector = this.query(now);
- if (options.skew === undefined && options.rate === undefined) {
- return;
- }
- this._vector = {
- position : (options.skew !== undefined) ? now + options.skew : nowVector.position,
- velocity : (options.rate !== undefined) ? options.rate : nowVector.velocity,
- timestamp : nowVector.timestamp
- }
- this.eventifyTriggerEvent("change");
- };
-
- /*
- NOW
- - calculates the value of the clock right now
- - shorthand for query
- */
- MasterClock.prototype.now = function () {
- return calculateVector(this._vector, localClock.now()).position;
- };
-
- /*
- QUERY
- - calculates the state of the clock right now
- - result vector includes position and velocity
- */
- MasterClock.prototype.query = function (now) {
- return calculateVector(this._vector, now);
- };
-
- /*
- Timeout support
- */
- MasterClock.prototype.setTimeout = function (callback, delay, options) {
- return timeoututils.setTimeout(this, callback, delay, options);
- };
-
- return MasterClock;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-
-define('timingobject/timingobject',['../util/eventify', '../util/motionutils', '../util/masterclock'], function (eventify, motionutils, MasterClock) {
-
- 'use strict';
-
- // Utility inheritance function.
- var inherit = function (Child, Parent) {
- var F = function () {}; // empty object to break prototype chain - hinder child prototype changes to affect parent
- F.prototype = Parent.prototype;
- Child.prototype = new F(); // child gets parents prototypes via F
- Child.uber = Parent.prototype; // reference in parent to superclass
- Child.prototype.constructor = Child; // resetting constructor pointer
- };
-
-
- // Polyfill for performance.now as Safari on ios doesn't have it...
- (function(){
- if ("performance" in window === false) {
- window.performance = {};
- window.performance.offset = new Date().getTime();
- }
- if ("now" in window.performance === false){
- window.performance.now = function now(){
- return new Date().getTime() - window.performance.offset;
- };
- }
- })();
-
-
- /*
- TIMING BASE
-
- abstract base class for objects that may be used as timingsrc
-
- essential internal state
- - range, vector
-
- external methods
- query, update
-
- events
- on/off "change", "timeupdate"
-
- internal methods for range timeouts
-
- defines internal processing steps
- - preProcess(vector) <- from external timingobject
- - vector = onChange(vector)
- - process(vector) <- from timeout or preProcess
- - process (vector)
- - set internal vector
- - postProcess(vector)
- - renew range timeout
- - postprocess (vector)
- - emit change event and timeupdate event
- - turn periodic timeupdate on or off
-
- individual steps in this structure may be specialized
- by subclasses (i.e. timing converters)
- */
-
-
- var TimingBase = function (options) {
-
- this._options = options || {};
-
- // cached vector
- this._vector = {
- position : undefined,
- velocity : undefined,
- acceleration : undefined,
- timestamp : undefined
- };
-
- // cached range
- this._range = [undefined,undefined];
-
- // readiness
- this._ready = new eventify.EventBoolean(false, {init:true});
-
- // exported events
- eventify.eventifyInstance(this);
- this.eventifyDefineEvent("change", {init:true}); // define change event (supporting init-event)
- this.eventifyDefineEvent("timeupdate", {init:true}); // define timeupdate event (supporting init-event)
-
- // timeout support
- this._timeout = null; // timeoutid for range violation etc.
- this._tid = null; // timeoutid for timeupdate
- if (!this._options.hasOwnProperty("timeout")) {
- // range timeouts off by default
- this._options.timeout = false;
- }
- };
- eventify.eventifyPrototype(TimingBase.prototype);
-
-
- /*
-
- EVENTS
-
- */
-
- /*
- overrides how immediate events are constructed
- specific to eventutils
- - overrides to add support for timeupdate events
- */
- TimingBase.prototype.eventifyMakeInitEvents = function (type) {
- if (type === "change") {
- return (this._ready.value === true) ? [undefined] : [];
- } else if (type === "timeupdate") {
- return (this._ready.value === true) ? [undefined] : [];
- }
- return [];
- };
-
-
- /*
-
- API
-
- */
-
- // version
- Object.defineProperty(TimingBase.prototype, 'version', {
- get : function () { return this._version; }
- });
-
- // ready or not
- TimingBase.prototype.isReady = function () {
- return this._ready.value;
- };
-
- // ready promise
- Object.defineProperty(TimingBase.prototype, 'ready', {
- get : function () {
- var self = this;
- return new Promise (function (resolve, reject) {
- if (self._ready.value === true) {
- resolve();
- } else {
- var onReady = function () {
- if (self._ready.value === true) {
- self._ready.off("change", onReady);
- resolve();
- }
- };
- self._ready.on("change", onReady);
- }
- });
- }
- });
-
- // range
-
- Object.defineProperty(TimingBase.prototype, 'range', {
- get : function () {
- // copy range
- return [this._range[0], this._range[1]];
- }
- });
-
-
- // internal vector
- Object.defineProperty(TimingBase.prototype, 'vector', {
- get : function () {
- // copy vector
- return {
- position : this._vector.position,
- velocity : this._vector.velocity,
- acceleration : this._vector.acceleration,
- timestamp : this._vector.timestamp
- };
- }
- });
-
- // internal clock
- Object.defineProperty(TimingBase.prototype, 'clock', {
- get : function () { throw new Error ("not implemented") }
- });
-
- // query
- TimingBase.prototype.query = function () {
- if (this._ready.value === false) {
- return {position:undefined, velocity:undefined, acceleration:undefined, timestamp:undefined};
- }
- // reevaluate state to handle range violation
- var vector = motionutils.calculateVector(this._vector, this.clock.now());
- var state = motionutils.getCorrectRangeState(vector, this._range);
- // detect range violation - only if timeout is set
- if (state !== motionutils.RangeState.INSIDE && this._timeout !== null) {
- this._preProcess(vector);
- }
- // re-evaluate query after state transition
- return motionutils.calculateVector(this._vector, this.clock.now());
- };
-
- // update - to be ovverridden
- TimingBase.prototype.update = function (vector) {
- throw new Error ("not implemented");
- };
-
- TimingBase.prototype.checkUpdateVector = function(vector) {
- if (vector == undefined) {
- throw new Error ("drop update, illegal updatevector");
- }
-
- // todo - check that vector properties are numbers
- var pos = vector.position;
- var vel = vector.velocity;
- var acc = vector.acceleration;
-
- if (pos == undefined && vel == undefined && acc == undefined) {
- throw new Error ("drop update, noop");
- }
-
- // default values
- var p = 0, v = 0, a = 0;
- var now = vector.timestamp || this.clock.now();
- if (this.isReady()) {
- var nowVector = motionutils.calculateVector(this._vector, now);
- nowVector = motionutils.checkRange(nowVector, this._range);
- p = nowVector.position;
- v = nowVector.velocity;
- a = nowVector.acceleration;
- }
-
- pos = (pos != undefined) ? pos : p;
- vel = (vel != undefined) ? vel : v;
- acc = (acc != undefined) ? acc : a;
- return {
- position : pos,
- velocity : vel,
- acceleration : acc,
- timestamp : now
- };
- }
-
-
- // shorthand accessors
- Object.defineProperty(TimingBase.prototype, 'pos', {
- get : function () {
- return this.query().position;
- }
- });
-
- Object.defineProperty(TimingBase.prototype, 'vel', {
- get : function () {
- return this.query().velocity;
- }
- });
-
- Object.defineProperty(TimingBase.prototype, 'acc', {
- get : function () {
- return this.query().acceleration;
- }
- });
-
-
- /*
-
- INTERNAL METHODS
-
- */
-
-
- /*
- do not override
- Handle incoming vector, from "change" from external object
- or from an internal timeout.
-
- onVectorChange is invoked allowing subclasses to specify transformation
- on the incoming vector before processing.
- */
- TimingBase.prototype._preProcess = function (vector) {
- vector = this.onVectorChange(vector);
- this._process(vector);
- };
-
-
- // may be overridden by subclsaa
- TimingBase.prototype.onRangeChange = function (range) {
- return range;
- };
-
- /*
- specify transformation
- on the incoming vector before processing.
- useful for Converters that do mathematical transformations,
- or as a way to enforse range restrictions.
- invoming vectors from external change events or internal
- timeout events
-
- returning null stops further processing, exept renewtimeout
- */
- TimingBase.prototype.onVectorChange = function (vector) {
- return motionutils.checkRange(vector, this._range);
- };
-
- /*
- core processing step after change event or timeout
- assignes the internal vector
- */
- TimingBase.prototype._process = function (vector) {
- if (vector !== null) {
- var old_vector = this._vector;
- // update internal vector
- this._vector = vector;
- // trigger events
- this._ready.value = true;
- this._postProcess(this._vector);
- }
- // renew timeout
- this._renewTimeout();
- };
-
- /*
- process a new vector applied in order to trigger events
- overriding this is only necessary if external change events
- need to be suppressed,
- */
- TimingBase.prototype._postProcess = function (vector) {
- // trigger change events
- this.eventifyTriggerEvent("change");
- // trigger timeupdate events
- this.eventifyTriggerEvent("timeupdate");
- var moving = vector.velocity !== 0.0 || vector.acceleration !== 0.0;
- if (moving && this._tid === null) {
- var self = this;
- this._tid = setInterval(function () {
- self.eventifyTriggerEvent("timeupdate");
- }, 200);
- } else if (!moving && this._tid !== null) {
- clearTimeout(this._tid);
- this._tid = null;
- }
- };
-
-
- /*
-
- TIMEOUTS
-
- */
-
- /*
- do not override
- renew timeout is called during evenry processing step
- in order to recalculate timeouts.
- the calculation may be specialized in
- _calculateTimeoutVector
- */
- TimingBase.prototype._renewTimeout = function () {
- if (this._options.timeout === true) {
- this._clearTimeout();
- var vector = this._calculateTimeoutVector();
- if (vector === null) {return;}
- var now = this.clock.now();
- var secDelay = vector.timestamp - now;
- var self = this;
- this._timeout = this.clock.setTimeout(function () {
- self._process(self.onTimeout(vector));
- }, secDelay, {anchor: now, early: 0.005});
- }
- };
-
- /*
- to be overridden
- must be implemented by subclass if range timeouts are required
- calculate a vector that will be delivered to _process().
- the timestamp in the vector determines when it is delivered.
- */
- TimingBase.prototype._calculateTimeoutVector = function () {
- var freshVector = this.query();
- var res = motionutils.calculateDelta(freshVector, this._range);
- var deltaSec = res[0];
- if (deltaSec === null) return null;
- if (deltaSec === Infinity) return null;
- var position = res[1];
- var vector = motionutils.calculateVector(freshVector, freshVector.timestamp + deltaSec);
- vector.position = position; // avoid rounding errors
- return vector;
- };
-
- /*
- do not override
- internal utility function for clearing vector timeout
- */
- TimingBase.prototype._clearTimeout = function () {
- if (this._timeout !== null) {
- this._timeout.cancel();
- this._timeout = null;
- }
- };
-
- /*
- to be overridden
- subclass may implement transformation on timeout vector
- before it is given to process.
- returning null stops further processing, except renewtimeout
- */
- TimingBase.prototype.onTimeout = function (vector) {
- return motionutils.checkRange(vector, this._range);
- };
-
-
-
-
- /*
- INTERNAL PROVIDER
-
- Timing provider internal to the browser context
-
- Used by timing objects as timingsrc if no timingsrc is specified.
- */
-
- var InternalProvider = function (options) {
- options = options || {};
- options.timeout = true;
- TimingBase.call(this, options);
-
- // initialise internal state
- this._clock = new MasterClock({skew:0});
- // range
- this._range = this._options.range || [-Infinity, Infinity];
- // vector
- var vector = this._options.vector || {
- position : 0,
- velocity : 0,
- acceleration : 0
- };
- this.update(vector);
- };
- inherit(InternalProvider, TimingBase);
-
- // internal clock
- Object.defineProperty(InternalProvider.prototype, 'clock', {
- get : function () { return this._clock; }
- });
-
- // update
- InternalProvider.prototype.update = function (vector) {
- var newVector = this.checkUpdateVector(vector);
- this._preProcess(newVector);
- return newVector;
- };
-
-
- /*
- EXTERNAL PROVIDER
-
- External Provider bridges the gap between the PROVIDER API (implemented by external timing providers)
- and the TIMINGSRC API
-
- Objects implementing the TIMINGSRC API may be used as timingsrc (parent) for another timing object.
-
- - wraps a timing provider external
- - handles some complexity that arises due to the very simple API of providers
- - implements a clock for the provider
- */
-
-
- // Need a polyfill for performance,now as Safari on ios doesn't have it...
-
- // local clock in seconds
- var local_clock = {
- now : function () {return performance.now()/1000.0;}
- };
-
- var ExternalProvider = function (provider, options) {
- options = options || {};
- options.timeout = true;
- TimingBase.call(this);
-
- this._provider = provider;
-
- this._provider_clock; // provider clock (may fluctuate based on live skew estimates)
- /*
- local clock
- provider clock normalised to values of performance now
- normalisation based on first skew measurement, so
- */
- this._clock;
-
-
- // register event handlers
- var self = this;
- this._provider.on("vectorchange", function () {self._onVectorChange();});
- this._provider.on("skewchange", function () {self._onSkewChange();});
-
- // check if provider is ready
- if (this._provider.skew != undefined) {
- var self = this;
- Promise.resolve(function () {
- self._onSkewChange();
- });
- }
- };
- inherit(ExternalProvider, TimingBase);
-
- // internal clock
- Object.defineProperty(ExternalProvider.prototype, 'clock', {
- get : function () { return this._clock; }
- });
-
- // internal provider object
- Object.defineProperty(ExternalProvider.prototype, 'provider', {
- get : function () { return this._provider; }
- });
-
- ExternalProvider.prototype._onSkewChange = function () {
- if (!this._clock) {
- this._provider_clock = new MasterClock({skew: this._provider.skew});
- this._clock = new MasterClock({skew:0});
- } else {
- this._provider_clock.adjust({skew: this._provider.skew});
- // provider clock adjusted with new skew - correct local clock similarly
- // current_skew = clock_provider - clock_local
- var current_skew = this._provider_clock.now() - this._clock.now();
- // skew delta = new_skew - current_skew
- var skew_delta = this._provider.skew - current_skew;
- this._clock.adjust({skew: skew_delta});
- }
- if (!this.isReady() && this._provider.vector != undefined) {
- // just became ready (onVectorChange has fired earlier)
- this._range = this._provider.range;
- this._preProcess(this._provider.vector);
- }
- };
-
- ExternalProvider.prototype._onVectorChange = function () {
- if (this._clock) {
- // is ready (onSkewChange has fired earlier)
- if (!this._range) {
- this._range = this._provider.range;
- }
- this._preProcess(this._provider.vector);
- }
- };
-
-
- /*
- - local timestamp of vector is set for each new vector, using the skew available at that time
- - the vector then remains unchanged
- - skew changes affect local clock, thereby affecting the result of query operations
-
- - one could imagine reevaluating the vector as well when the skew changes,
- but then this should be done without triggering change events
-
- - ideally the vector timestamp should be a function of the provider clock
-
- */
-
-
-
- // override timing base to recalculate timestamp
- ExternalProvider.prototype.onVectorChange = function (provider_vector) {
- // local_ts = provider_ts - skew
- var local_ts = provider_vector.timestamp - this._provider.skew;
- return {
- position : provider_vector.position,
- velocity : provider_vector.velocity,
- acceleration : provider_vector.acceleration,
- timestamp : local_ts
- }
- };
-
-
- // update
- ExternalProvider.prototype.update = function (vector) {
- return this._provider.update(vector);
- };
-
-
-
- /*
-
- TIMING OBJECT BASE
-
- */
-
- var TimingObjectBase = function (timingsrc, options) {
- TimingBase.call(this, options);
- this._version = 4;
- /*
- store a wrapper function used as a callback handler from timingsrc
- (if this was a prototype function - it would be shared by multiple objects thus
- prohibiting them from subscribing to the same timingsrc)
- */
- var self = this;
- this._internalOnChange = function () {
- var vector = self._timingsrc.vector;
- self._preProcess(vector);
- };
- this._timingsrc = undefined;
- this.timingsrc = timingsrc;
- };
- inherit(TimingObjectBase, TimingBase);
-
-
- // attach inheritance function on base constructor for convenience
- TimingObjectBase.inherit = inherit;
-
- // internal clock
- Object.defineProperty(TimingObjectBase.prototype, 'clock', {
- get : function () { return this._timingsrc.clock; }
- });
-
- TimingObjectBase.prototype.onRangeChange = function (range) {
- return range;
- };
-
- // invoked just after timingsrc switch
- TimingObjectBase.prototype.onSwitch = function () {
- };
-
-
- /*
-
- timingsrc property and switching on assignment
-
- */
- Object.defineProperty(TimingObjectBase.prototype, 'timingsrc', {
- get : function () {
- if (this._timingsrc instanceof InternalProvider) {
- return undefined
- } else if (this._timingsrc instanceof ExternalProvider) {
- return this._timingsrc.provider;
- } else {
- return this._timingsrc;
- }
- },
- set : function (timingsrc) {
- // new timingsrc undefined
- if (!timingsrc) {
- var options;
- if (!this._timingsrc) {
- // first time - use options
- options = {
- vector : this._options.vector,
- range : this._options.range
- }
- } else {
- // not first time - use current state
- options = {
- vector : this._vector,
- range : this._range
- }
- }
- timingsrc = new InternalProvider(options);
- }
- else if ((timingsrc instanceof TimingObjectBase) === false) {
- // external provider - try to wrap it
- try {
- timingsrc = new ExternalProvider(timingsrc);
- } catch (e) {
- console.log(timingsrc);
- throw new Error ("illegal timingsrc - not instance of timing object base and not timing provider");
- }
- }
- // transformation when new timingsrc is ready
- var self = this;
- var doSwitch = function () {
- // disconnect and clean up timingsrc
- if (self._timingsrc) {
- self._timingsrc.off("change", self._internalOnChange);
- }
- self._timingsrc = timingsrc;
- if (self._timingsrc.range !== self._range) {
- self._range = self.onRangeChange(self._timingsrc.range);
- }
- self.onSwitch();
- self._timingsrc.on("change", self._internalOnChange);
- };
- if (timingsrc.isReady()) {
- doSwitch();
- } else {
- timingsrc.ready.then(function (){
- doSwitch();
- });
- }
- }
- });
-
- // update
- TimingObjectBase.prototype.update = function (vector) {
- return this._timingsrc.update(vector);
- };
-
-
- /*
- Timing Object
- */
- var TimingObject = function (options) {
- options = options || {};
- var timingsrc = options.timingsrc || options.provider;
- TimingObjectBase.call(this, timingsrc, options);
- };
- inherit(TimingObject, TimingObjectBase);
-
- // module
- return {
- InternalProvider : InternalProvider,
- ExternalProvider : ExternalProvider,
- TimingObjectBase : TimingObjectBase,
- TimingObject : TimingObject
- };
-});
-
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-define ('sequencing/timingcallbacks',['../util/motionutils'], function (motionutils) {
-
- 'use strict';
-
- // Utility inheritance function.
- var inherit = function (Child, Parent) {
- var F = function () {}; // empty object to break prototype chain - hinder child prototype changes to affect parent
- F.prototype = Parent.prototype;
- Child.prototype = new F(); // child gets parents prototypes via F
- Child.uber = Parent.prototype; // reference in parent to superclass
- Child.prototype.constructor = Child; // resetting constructor pointer
- };
-
- var TimingCallbackBase = function (timingObject, handler) {
- this._timingsrc = timingObject;
- this._handler = handler;
- this._timeout = null;
- this._wrappedOnChange = function () {this._onChange();};
- // initialise
- this.timingsrc = timingObject;
- };
-
- TimingCallbackBase.prototype._renewTimeout = function () {
- this._clearTimeout();
- var res = this._calculateTimeout();
- if (res.delay === null) return null;
- var self = this;
- this._timeout = this._timingsrc.clock.setTimeout(function () {
- self._onTimeout();
- }, res.delay, {anchor: res.anchor, early: 0.005});
- };
-
- // update event from timing object
- TimingCallbackBase.prototype._clearTimeout = function () {
- // cleanup
- if (this._timeout !== null) {
- this._timeout.cancel();
- this._timeout = null;
- }
- };
-
- // update event from timing object
- TimingCallbackBase.prototype.cancel = function () {
- // cleanup
- this._clearTimeout();
- this._timingsrc.off("change", this._wrappedOnChange, this);
- };
-
- /*
- Accessor for timingsrc.
- Supports dynamic switching of timing source by assignment.
- */
- Object.defineProperty(TimingCallbackBase.prototype, 'timingsrc', {
- get : function () {return this._timingsrc;},
- set : function (timingObject) {
- if (this._timingsrc) {
- this._timingsrc.off("change", this._wrappedOnChange, this);
- }
- clearTimeout(this._tid);
- this._timingsrc = timingObject;
- this._timingsrc.on("change", this._wrappedOnChange, this);
- }
- });
-
-
- /*
- SET POINT CALLBACK
- callback when timing object position is equal to point
- options {repeat:true} implies that callback will occur repeatedly
- every time timing object passes point.
- Default is to fire only once, similar to setTimeout
- */
-
- var SetPointCallback = function (timingObject, handler, point, options) {
- if (!(this instanceof SetPointCallback)) {
- throw new Error("Contructor function called without new operation");
- }
- TimingCallbackBase.call(this, timingObject, handler);
- this._options = options || {};
- this._options.repeat = (this._options.repeat !== undefined) ? this._options.repeat : false;
- this._point = point;
- };
- inherit(SetPointCallback, TimingCallbackBase);
-
-
- // update event from timing object
- SetPointCallback.prototype._onChange = function () {
- if (this._timingsrc.query().position === this._point) {
- this._handler();
- }
- this._renewTimeout();
- };
-
- // update event from timing object
- SetPointCallback.prototype._onTimeout = function () {
- if (!this._options.repeat) {
- this.cancel();
- };
- this._handler();
- this._renewTimeout();
- };
-
- SetPointCallback.prototype._calculateTimeout = function () {
- var vector = this._timingsrc.query();
- var delay = motionutils.calculateMinPositiveRealSolution(vector, this._point);
- return {
- anchor: vector.timestamp,
- delay: delay
- };
- };
-
-
- /*
-
- SET INTERVAL CALLBACK
-
- callback callback for every point x, where (x - offset) % length === 0
- options : {offset:offset}
- Default is offset 0
- */
-
- var SetIntervalCallback = function (timingObject, handler, length, options) {
- if (!(this instanceof SetIntervalCallback)) {
- throw new Error("Contructor function called without new operation");
- }
- TimingCallbackBase.call(this, timingObject, handler);
- this._options = options || {};
- this._options.offset = (this._options.offset !== undefined) ? this._options.offset : 0;
- this._length = length;
- };
- inherit(SetIntervalCallback, TimingCallbackBase);
-
- // ovverride modulo to behave better for negative numbers
- SetIntervalCallback.prototype._mod = function (n, m) {
- return ((n % m) + m) % m;
- };
-
- // get point representation from float
- SetIntervalCallback.prototype._getPoint = function (x) {
- var skew = this._options.offset;
- return {
- n : Math.floor((x-skew)/this._length),
- offset : this._mod(x-skew, this._length)
- };
- };
-
- // get float value from point representation
- SetIntervalCallback.prototype._getFloat = function (p) {
- var skew = this._options.offset;
- return skew + (p.n * this._length) + p.offset;
- };
-
- // update event from timing object
- SetIntervalCallback.prototype._onChange = function () {
- var points = this._calculatePoints(this._timingsrc.query().position);
- if (points.isTarget) {
- this._handler();
- }
- this._renewTimeout();
- };
-
- // update event from timing object
- SetIntervalCallback.prototype._onTimeout = function () {
- this._handler();
- this._renewTimeout();
- };
-
- /*
- Calculate target points before and after a given position.
- If the given position is itself a target point, this will
- be reported as isTarget===true.
- */
-
- SetIntervalCallback.prototype._calculatePoints = function (position) {
- var beforePoint = {}, afterPoint = {};
- var target;
- var point = this._getPoint(position);
- if (point.offset === 0) {
- target = true;
- beforePoint.n = point.n - 1;
- beforePoint.offset = point.offset;
- afterPoint.n = point.n + 1;
- afterPoint.offset = point.offset;
- } else {
- target = false;
- beforePoint.n = point.n;
- beforePoint.offset = 0;
- afterPoint.n = point.n + 1;
- afterPoint.offset = 0;
- }
- return {
- isTarget : target,
- before : this._getFloat(beforePoint),
- after : this._getFloat(afterPoint)
- }
- };
-
- SetIntervalCallback.prototype._calculateTimeout = function () {
- var vector = this._timingsrc.query();
- var points = this._calculatePoints(vector.position);
- var delay = motionutils.calculateDelta(vector, [points.before, points.after])[0];
- return {
- anchor: vector.timestamp,
- delay: delay
- };
- };
-
-
- // module definition
- return {
- setPointCallback: function (timingObject, handler, point, options) { return new SetPointCallback(timingObject, handler, point, options);},
- setIntervalCallback : function (timingObject, handler, length, options) { return new SetIntervalCallback(timingObject, handler, length, options);}
- };
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-/*
- SKEW CONVERTER
-
- Skewing the timeline by 2 means that the timeline position 0 of the timingsrc becomes position 2 of Converter.
-
-*/
-
-define('timingobject/skewconverter',['./timingobject'], function (timingobject) {
-
- 'use strict';
-
- var TimingObjectBase = timingobject.TimingObjectBase;
- var inherit = TimingObjectBase.inherit;
-
- var SkewConverter = function (timingsrc, skew, options) {
- if (!(this instanceof SkewConverter)) {
- throw new Error("Contructor function called without new operation");
- }
- this._skew = skew;
- TimingObjectBase.call(this, timingsrc, options);
- };
- inherit(SkewConverter, TimingObjectBase);
-
- // overrides
- SkewConverter.prototype.onRangeChange = function (range) {
- range[0] = (range[0] === -Infinity) ? range[0] : range[0] + this._skew;
- range[1] = (range[1] === Infinity) ? range[1] : range[1] + this._skew;
- return range;
- };
-
- // overrides
- SkewConverter.prototype.onVectorChange = function (vector) {
- vector.position += this._skew;
- return vector;
- };
-
- SkewConverter.prototype.update = function (vector) {
- if (vector.position !== undefined && vector.position !== null) {
- vector.position = vector.position - this._skew;
- }
- return this.timingsrc.update(vector);
- };
-
-
- Object.defineProperty(SkewConverter.prototype, 'skew', {
- get : function () {
- return this._skew;
- },
- set : function (skew) {
- this._skew = skew;
- // pick up vector from timingsrc
- var src_vector = this.timingsrc.vector;
- // use this vector to emulate new event from timingsrc
- this._preProcess(src_vector);
- }
- });
-
-
- return SkewConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-/*
- DELAY CONVERTER
-
- Delay Converter introduces a positive time delay on a source timing object.
-
- Generally - if the source timing object has some value at time t,
- then the delayConverter will provide the same value at time t + delay.
-
- Since the delay Converter is effectively replaying past events after the fact,
- it is not LIVE and not open to interactivity (i.e. update)
-
-*/
-
-
-define('timingobject/delayconverter',['./timingobject'], function (timingobject) {
-
- 'use strict';
-
- var TimingObjectBase = timingobject.TimingObjectBase;
- var inherit = TimingObjectBase.inherit;
-
- var DelayConverter = function (timingObject, delay) {
- if (!(this instanceof DelayConverter)) {
- throw new Error("Contructor function called without new operation");
- }
- if (delay < 0) {throw new Error ("negative delay not supported");}
- if (delay === 0) {throw new Error ("zero delay makes delayconverter pointless");}
- TimingObjectBase.call(this, timingObject);
- // fixed delay
- this._delay = delay;
- };
- inherit(DelayConverter, TimingObjectBase);
-
- // overrides
- DelayConverter.prototype.onVectorChange = function (vector) {
- /*
- Vector's timestamp always time-shifted (back-dated) by delay
-
- Normal operation is to delay every incoming vector update.
- This implies returning null to abort further processing at this time,
- and instead trigger a later continuation.
-
- However, delay is calculated based on the timestamp of the vector (age), not when the vector is
- processed in this method. So, for small small delays the age of the vector could already be
- greater than delay, indicating that the vector is immediately valid and do not require delayed processing.
-
- This is particularly true for the first vector, which may be old.
-
- So we generally check the age to figure out whether to apply the vector immediately or to delay it.
- */
-
- // age of incoming vector
- var age = this.clock.now() - vector.timestamp;
-
- // time-shift vector timestamp
- vector.timestamp += this._delay;
-
- if (age < this._delay) {
- // apply vector later - abort processing now
- var self = this;
- var delayMillis = (this._delay - age) * 1000;
- setTimeout(function () {
- self._process(vector);
- }, delayMillis);
- return null;
- }
- // apply vector immediately - continue processing
- return vector;
- };
-
- DelayConverter.prototype.update = function (vector) {
- // Updates are prohibited on delayed timingobjects
- throw new Error ("update is not legal on delayed (non-live) timingobject");
- };
-
- return DelayConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-/*
- SCALE CONVERTER
-
- Scaling by a factor 2 means that values of the timing object (position, velocity and acceleration) are multiplied by two.
- For example, if the timing object represents a media offset in seconds, scaling it to milliseconds implies a scaling factor of 1000.
-
-*/
-
-
-define('timingobject/scaleconverter',['./timingobject'], function (timingobject) {
-
- 'use strict';
-
- var TimingObjectBase = timingobject.TimingObjectBase;
- var inherit = TimingObjectBase.inherit;
-
- var ScaleConverter = function (timingsrc, factor) {
- if (!(this instanceof ScaleConverter)) {
- throw new Error("Contructor function called without new operation");
- }
- this._factor = factor;
- TimingObjectBase.call(this, timingsrc);
- };
- inherit(ScaleConverter, TimingObjectBase);
-
- // overrides
- ScaleConverter.prototype.onRangeChange = function (range) {
- return [range[0]*this._factor, range[1]*this._factor];
- };
-
- // overrides
- ScaleConverter.prototype.onVectorChange = function (vector) {
- vector.position = vector.position * this._factor;
- vector.velocity = vector.velocity * this._factor;
- vector.acceleration = vector.acceleration * this._factor;
- return vector;
- };
-
- ScaleConverter.prototype.update = function (vector) {
- if (vector.position !== undefined && vector.position !== null) vector.position = vector.position / this._factor;
- if (vector.velocity !== undefined && vector.velocity !== null) vector.velocity = vector.velocity / this._factor;
- if (vector.acceleration !== undefined && vector.acceleration !== null) vector.acceleration = vector.acceleration / this._factor;
- return this.timingsrc.update(vector);
- };
-
- return ScaleConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-/*
- LOOP CONVERTER
-
- This is a modulo type transformation where the converter will be looping within
- a given range. Potentially one could create an associated timing object keeping track of the
- loop number.
-*/
-
-
-define('timingobject/loopconverter',['../util/motionutils', './timingobject'], function (motionutils, timingobject) {
-
- 'use strict';
-
- var TimingObjectBase = timingobject.TimingObjectBase;
- var inherit = TimingObjectBase.inherit;
-
- /*
- Coordinate system based on counting segments
- skew + n*length + offset === x
- skew : coordinate system is shifted by skew, so that segment 0 starts at offset.
- n : segment counter
- length : segment length
- offset : offset of value x into the segment where it lies
- x: float point value
- */
- var SegmentCoords = function (skew, length) {
- this.skew = skew;
- this.length = length;
- };
-
- /*
- Static method
- ovverride modulo to behave better for negative numbers
- */
- SegmentCoords.mod = function (n, m) {
- return ((n % m) + m) % m;
- };
-
- // get point representation from float
- SegmentCoords.prototype.getPoint = function (x) {
- return {
- n : Math.floor((x-this.skew)/this.length),
- offset : SegmentCoords.mod(x-this.skew,this.length)
- };
- };
-
- // get float value from point representation
- SegmentCoords.prototype.getFloat = function (p) {
- return this.skew + (p.n * this.length) + p.offset;
- };
-
- // transform float x into segment defined by other float y
- // if y isnt specified - transform into segment [skew, skew + length]
- SegmentCoords.prototype.transformFloat = function (x, y) {
- y = (y === undefined) ? this.skew : y;
- var xPoint = this.getPoint(x);
- var yPoint = this.getPoint(y);
- return this.getFloat({n:yPoint.n, offset:xPoint.offset});
- };
-
-
- /*
- LOOP CONVERTER
- */
-
- var LoopConverter = function (timingsrc, range) {
- if (!(this instanceof LoopConverter)) {
- throw new Error("Contructor function called without new operation");
- }
- TimingObjectBase.call(this, timingsrc, {timeout:true});
- /*
- note :
- if a range point of the loop converter is the same as a range point of timingsrc,
- then there will be duplicate events
- */
- this._range = range;
- this._coords = new SegmentCoords(range[0], range[1]-range[0]);
- };
- inherit(LoopConverter, TimingObjectBase);
-
- // transform value from coordiantes X of timing source
- // to looper coordinates Y
- LoopConverter.prototype._transform = function (x) {
- return this._coords.transformFloat(x);
- };
-
- // transform value from looper coordinates Y into
- // coordinates X of timing object - maintain relative diff
- LoopConverter.prototype._inverse = function (y) {
- var current_y = this.query().position;
- var current_x = this.timingsrc.query().position;
- var diff = y - current_y;
- var x = diff + current_x;
- // verify that x is witin range
- return x;
- };
-
- // overrides
- LoopConverter.prototype.query = function () {
- if (this.vector === null) return {position:undefined, velocity:undefined, acceleration:undefined};
- var vector = motionutils.calculateVector(this.vector, this.clock.now());
- // trigger state transition if range violation is detected
- if (vector.position > this._range[1]) {
- this._process(this._calculateInitialVector());
- } else if (vector.position < this._range[0]) {
- this._process(this._calculateInitialVector());
- } else {
- // no range violation
- return vector;
- }
- // re-evaluate query after state transition
- return motionutils.calculateVector(this.vector, this.clock.now());
- };
-
- // overrides
- LoopConverter.prototype.update = function (vector) {
- if (vector.position !== undefined && vector.position !== null) {
- vector.position = this._inverse(vector.position);
- }
- return this.timingsrc.update(vector);
- };
-
- // overrides
- LoopConverter.prototype._calculateTimeoutVector = function () {
- var freshVector = this.query();
- var res = motionutils.calculateDelta(freshVector, this.range);
- var deltaSec = res[0];
- if (deltaSec === null) return null;
- var position = res[1];
- var vector = motionutils.calculateVector(freshVector, freshVector.timestamp + deltaSec);
- vector.position = position; // avoid rounding errors
- return vector;
- };
-
- // overrides
- LoopConverter.prototype.onRangeChange = function(range) {
- return this._range;
- };
-
- // overrides
- LoopConverter.prototype.onTimeout = function (vector) {
- return this._calculateInitialVector();
- };
-
- // overrides
- LoopConverter.prototype.onVectorChange = function (vector) {
- return this._calculateInitialVector();
- };
-
- LoopConverter.prototype._calculateInitialVector = function () {
- // parent snapshot
- var parentVector = this.timingsrc.query();
- // find correct position for looper
- var position = this._transform(parentVector.position);
- // find looper vector
- return {
- position: position,
- velocity: parentVector.velocity,
- acceleration: parentVector.acceleration,
- timestamp: parentVector.timestamp
- };
- };
-
- return LoopConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-/*
-
- RANGE CONVERTER
-
- The converter enforce a range on position.
-
- It only has effect if given range is a restriction on the range of the timingsrc.
- Range converter will pause on range endpoints if timingsrc leaves the range.
- Range converters will continue mirroring timingsrc once it comes into the range.
-*/
-
-define('timingobject/rangeconverter',['../util/motionutils', './timingobject'], function (motionutils, timingobject) {
-
- 'use strict';
-
- var TimingObjectBase = timingobject.TimingObjectBase;
- var inherit = TimingObjectBase.inherit;
- var RangeState = motionutils.RangeState;
-
-
- var state = function () {
- var _state = RangeState.INIT;
- var _range = null;
- var is_special_state_change = function (old_state, new_state) {
- // only state changes between INSIDE and OUTSIDE* are special state changes.
- if (old_state === RangeState.OUTSIDE_HIGH && new_state === RangeState.OUTSIDE_LOW) return false;
- if (old_state === RangeState.OUTSIDE_LOW && new_state === RangeState.OUTSIDE_HIGH) return false;
- if (old_state === RangeState.INIT) return false;
- return true;
- }
- var get = function () {return _state;};
- var set = function (new_state, new_range) {
-
- var absolute = false; // absolute change
- var special = false; // special change
-
- // check absolute change
- if (new_state !== _state || new_range !== _range) {
- absolute = true;
- }
- // check special change
- if (new_state !== _state) {
- special = is_special_state_change(_state, new_state);
- }
- // range change
- if (new_range !== _range) {
- _range = new_range;
- }
- // state change
- if (new_state !== _state) {
- _state = new_state;
- }
- return {special:special, absolute:absolute};
-
- }
- return {get: get, set:set};
- };
-
-
- /*
- Range converter allows a new (smaller) range to be specified.
- */
-
- var RangeConverter = function (timingObject, range) {
- if (!(this instanceof RangeConverter)) {
- throw new Error("Contructor function called without new operation");
- }
- TimingObjectBase.call(this, timingObject, {timeout:true});
- /*
- note :
- if a range point of the loop converter is the same as a range point of timingsrc,
- then there will be duplicate events
- */
- this._state = state();
- // todo - check range
- this._range = range;
- };
- inherit(RangeConverter, TimingObjectBase);
-
- // overrides
- RangeConverter.prototype.query = function () {
- if (this._ready.value === false) {
- return {position:undefined, velocity:undefined, acceleration:undefined, timestamp:undefined};
- }
- // reevaluate state to handle range violation
- var vector = motionutils.calculateVector(this._timingsrc.vector, this.clock.now());
- var state = motionutils.getCorrectRangeState(vector, this._range);
- // detect range violation - only if timeout is set
- if (state !== motionutils.RangeState.INSIDE && this._timeout !== null) {
- this._preProcess(vector);
- }
- // re-evaluate query after state transition
- return motionutils.calculateVector(this._vector, this.clock.now());
- };
-
- // overridden
- RangeConverter.prototype._calculateTimeoutVector = function () {
- var freshVector = this._timingsrc.query();
- var res = motionutils.calculateDelta(freshVector, this.range);
- var deltaSec = res[0];
- if (deltaSec === null) return null;
- var position = res[1];
- var vector = motionutils.calculateVector(freshVector, freshVector.timestamp + deltaSec);
- vector.position = position; // avoid rounding errors
- return vector;
- };
-
- // override range
- Object.defineProperty(RangeConverter.prototype, 'range', {
- get : function () {
- return [this._range[0], this._range[1]];
- },
- set : function (range) {
- this._range = range;
- // use vector from timingsrc to emulate new event from timingsrc
- this._preProcess(this.timingsrc.vector);
- }
- });
-
- // overrides
- RangeConverter.prototype.onRangeChange = function(range) {
- return this._range;
- };
-
- // overrides
- RangeConverter.prototype.onTimeout = function (vector) {
- return this.onVectorChange(vector);
- };
-
- // overrides
- RangeConverter.prototype.onVectorChange = function (vector) {
- // console.log("onVectorChange vector", vector);
- // console.log("onVectorChange range", this._range);
- var new_state = motionutils.getCorrectRangeState(vector, this._range);
- // console.log("onVectorChange state", new_state);
- var state_changed = this._state.set(new_state, this._range);
- if (state_changed.special) {
- // state transition between INSIDE and OUTSIDE
- if (this._state.get() === RangeState.INSIDE) {
- // OUTSIDE -> INSIDE, generate fake start event
- // vector delivered by timeout
- // forward event unchanged
- } else {
- // INSIDE -> OUTSIDE, generate fake stop event
- vector = motionutils.checkRange(vector, this._range);
- }
- }
- else {
- // no state transition between INSIDE and OUTSIDE
- if (this._state.get() === RangeState.INSIDE) {
- // stay inside or first event inside
- // forward event unchanged
- } else {
- // stay outside or first event outside
- // forward if
- // - first event outside
- // - skip from outside-high to outside-low
- // - skip from outside-low to outside-high
- // - range change
- // else drop
- // - outside-high to outside-high (no range change)
- // - outside-low to outside-low (no range change)
- if (state_changed.absolute) {
- vector = motionutils.checkRange(vector, this._range);
- } else {
- // drop event
- return null;
- }
- }
- }
- return vector;
- };
-
- return RangeConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-/*
- TIMESHIFT CONVERTER
-
- Timeshift Converter timeshifts a timing object by timeoffset.
- Positive timeoffset means that the timeshift Converter will run ahead of the source timing object.
- Negative timeoffset means that the timeshift Converter will run behind the source timing object.
-
- Updates affect the converter immediately. This means that update vector must be re-calculated
- to the value it would have at time-shifted time. Timestamps are not time-shifted, since the motion is still live.
- For instance, (0, 1, ts) becomes (0+(1*timeshift), 1, ts)
-
- However, this transformation may cause range violation
- - this happens only when timing object is moving.
- - implementation requires range converter logic
-
- - range is infinite
-*/
-
-
-define('timingobject/timeshiftconverter',['../util/motionutils', './timingobject'], function (motionutils, timingobject) {
-
- 'use strict';
-
- var TimingObjectBase = timingobject.TimingObjectBase;
- var inherit = TimingObjectBase.inherit;
-
-
- var TimeShiftConverter = function (timingsrc, timeOffset) {
- if (!(this instanceof TimeShiftConverter)) {
- throw new Error("Contructor function called without new operation");
- }
-
- TimingObjectBase.call(this, timingsrc);
- this._timeOffset = timeOffset;
- };
- inherit(TimeShiftConverter, TimingObjectBase);
-
- // overrides
- TimeShiftConverter.prototype.onRangeChange = function (range) {
- return [-Infinity, Infinity];
- };
-
-
- // overrides
- TimeShiftConverter.prototype.onVectorChange = function (vector) {
- // calculate timeshifted vector
- var newVector = motionutils.calculateVector(vector, vector.timestamp + this._timeOffset);
- newVector.timestamp = vector.timestamp;
- return newVector;
- };
-
- return TimeShiftConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-/*
- DERIVATIVE CONVERTER
-
- this Converter implements the derivative of it source timing object.
-
- The velocity of timingsrc becomes the position of the Converter.
-
- This means that the derivative Converter allows sequencing on velocity of a timing object,
- by attatching a sequencer on the derivative Converter.
-*/
-
-define('timingobject/derivativeconverter',['./timingobject'], function (timingobject) {
-
- 'use strict';
-
- var TimingObjectBase = timingobject.TimingObjectBase;
- var inherit = TimingObjectBase.inherit;
-
- var DerivativeConverter = function (timingsrc) {
- if (!(this instanceof DerivativeConverter)) {
- throw new Error("Contructor function called without new operation");
- }
- TimingObjectBase.call(this, timingsrc);
- };
- inherit(DerivativeConverter, TimingObjectBase);
-
- // overrides
- DerivativeConverter.prototype.onRangeChange = function (range) {
- return [-Infinity, Infinity];
- };
-
- // overrides
- DerivativeConverter.prototype.onVectorChange = function (vector) {
- var newVector = {
- position : vector.velocity,
- velocity : vector.acceleration,
- acceleration : 0,
- timestamp : vector.timestamp
- };
- return newVector;
- };
-
- DerivativeConverter.prototype.update = function (vector) {
- throw new Error("updates illegal on derivative of timingobject");
- };
-
- return DerivativeConverter;
-});
-/*
- Copyright 2017 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-define ('sequencing/timinginteger',['../util/motionutils', '../util/eventify'], function (motionutils, eventify) {
-
- /*
- Integer value that is controlled by a timing object.
- implemented as a tiny wrapper around a timing object.
- Change event emitted whenever the integer value changes.
- */
- var isNumeric = function(obj){
- return !Array.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
- };
-
-
- var TimingInteger = function (timingObject, options) {
- // timingsrc
- this._timingsrc;
-
- options = options || {};
-
- // option value
- if (options.value === undefined) {
- options.value = 0;
- }
- if (!isNumeric(options.value)) {
- throw new Error ("value not nummeric", options.value);
- }
- this._value = options.value;
-
- // option - min - max
- if (options.min !== undefined) {
- if (!isNumeric(options.min)) {
- throw new Error ("option.min not nummeric", options.min);
- }
- }
- if (options.max !== undefined) {
- if (!isNumeric(options.max)) {
- throw new Error ("option.min not nummeric", options.max);
- }
- }
- this._options = options;
-
-
- // events
- eventify.eventifyInstance(this);
- this.eventifyDefineEvent("change", {init:true});
-
- // timeout
- this._timeout = null;
-
- // timing object
- var self = this;
- this._wrappedOnChange = function () {self._onChange();};
- this.timingsrc = timingObject;
- }
- eventify.eventifyPrototype(TimingInteger.prototype);
-
-
- /*
- events
- */
-
- TimingInteger.prototype.eventifyMakeInitEvents = function (type) {
- if (type === "change") {
- return [this.value];
- }
- return [];
- };
-
- /*
- readiness
- */
-
- Object.defineProperty(TimingInteger.prototype, "ready", {
- get: function () {return this._timingsrc.ready;}
- });
-
- TimingInteger.prototype.isReady = function () {
- return this._timingsrc.isReady();
- };
-
- /*
- public api - integer value
- forwards to timing object position
- */
-
- Object.defineProperty(TimingInteger.prototype, "value", {
- get : function () {
- return this._value;
- },
- set : function (value) {
- // set will fail if to is not ready
- this._timingsrc.update({position:value});
- }
- });
-
-
- /*
- timingsrc
- Supports dynamic switching of timing source by assignment.
- */
- Object.defineProperty(TimingInteger.prototype, 'timingsrc', {
- get : function () {return this._timingsrc;},
- set : function (timingObject) {
- if (this._timingsrc) {
- this._timingsrc.off("change", this._wrappedOnChange, this);
- }
- clearTimeout(this._tid);
- this._timingsrc = timingObject;
- this._timingsrc.on("change", this._wrappedOnChange, this);
- }
- });
-
- /*
- Timeouts
- */
-
- TimingInteger.prototype._renewTimeout = function () {
- this._clearTimeout();
- var res = this._calculateTimeout();
- if (res.delay === null) return null;
- var self = this;
- this._timeout = this._timingsrc.clock.setTimeout(function () {
- self._onTimeout();
- }, res.delay, {anchor: res.anchor, early: 0.005});
- };
-
- // update event from timing object
- TimingInteger.prototype._clearTimeout = function () {
- // cleanup
- if (this._timeout !== null) {
- this._timeout.cancel();
- this._timeout = null;
- }
- };
-
- // update event from timingsrc
- TimingInteger.prototype._onChange = function () {
- this._refresh();
- this._renewTimeout();
- };
-
- // update event from timing object
- TimingInteger.prototype._onTimeout = function () {
- this._refresh();
- this._renewTimeout();
- };
-
- TimingInteger.prototype._refresh = function () {
- var value = Math.floor(this._timingsrc.query().position);
- if (this._options.max !== undefined && value > this._options.max) {
- value = this._options.max;
- }
- if (this._options.min !== undefined && value < this._options.min) {
- value = this._options.min;
- }
- if (value !== this._value) {
- this._value = value;
- this.eventifyTriggerEvent("change", this.value);
- }
- };
-
- /*
- Calculate target points before and after a given position.
- If the given position is itself a target point, this will
- be reported as isTarget===true.
- */
-
- TimingInteger.prototype._calculatePoints = function (position) {
- var before, after;
- var isTarget = Number.isInteger(position);
- if (isTarget === true) {
- before = position - 1;
- after = position + 1;
- } else {
- before = Math.floor(position);
- after = before + 1;
- }
- return {
- isTarget : isTarget,
- before : before,
- after : after
- };
- };
-
-
- TimingInteger.prototype._calculateTimeout = function () {
- var vector = this._timingsrc.query();
- var points = this._calculatePoints(vector.position);
- var delay = motionutils.calculateDelta(vector, [points.before, points.after])[0];
- return {
- anchor: vector.timestamp,
- delay: delay
- };
- };
-
-
- TimingInteger.prototype.close = function () {
- this._clearTimeout();
- if (this._timingsrc) {
- this._timingsrc.off("change", this._wrappedOnChange, this);
- this._timingsrc = undefined;
- }
- };
-
- return TimingInteger;
-});
-define('sequencing/activecue',['../util/eventify'], function (eventify) {
-
- /*
- Wrapping around a sequencer to safely present a single active cue as value
-
- implements same interface as an event variable - except variable may not be set
- */
-
- var ActiveCue = function (seq) {
- this._seq = seq;
- this._stack = [];
- this._dirty = false;
- this._value = undefined;
-
- eventify.eventifyInstance(this);
- this.eventifyDefineEvent("change", {init:true});
-
- var self = this;
- this._wrappedHandler = function (eList) {self._onSeqEvents(eList);}
- this._seq.on("events", this._wrappedHandler);
- };
- eventify.eventifyPrototype(ActiveCue.prototype);
-
- // ovverride to specify initialevents
- ActiveCue.prototype.eventifyMakeInitEvents = function (type) {
- if (type === "change") {
- return [this._value];
- }
- return [];
- };
-
- ActiveCue.prototype._touch = function () {
- if (!this._dirty) {
- var self = this;
- Promise.resolve().then(function () {
- self._refresh()
- });
- }
- this._dirty = true;
- };
-
- ActiveCue.prototype._refresh = function () {
- var len = this._stack.length;
- // pick last item
- var value = (len > 0) ? this._stack[len-1][1] : undefined;
- if (value !== this._value) {
- this._value = value;
- this.eventifyTriggerEvent("change", value);
- }
- this._dirty = false;
- };
-
- ActiveCue.prototype._onSeqEvents = function (eList) {
- eList.forEach(function (eArg) {
- var seqCue = eArg.e;
- if (eArg.type === "change") {
- this._stack.push([seqCue.key, seqCue.data]);
- this._touch();
- } else if (eArg.type === "remove") {
- var i = this._stack.findIndex(function (element, index, array) {
- return (element[0] === seqCue.key);
- });
- if (i > -1) {
- this._stack.splice(i, 1);
- this._touch();
- }
- }
- }, this);
- };
-
- Object.defineProperty(ActiveCue.prototype, "value", {
- get: function () {
- return this._value;
- }
- });
- ActiveCue.prototype.get = function () { return this._value;};
-
-
- ActiveCue.prototype.close = function () {
- this._seq.off("events", this._wrappedHandler);
- };
-
-
- return ActiveCue;
-});
-
-
-
-/*
- Written by Ingar Arntzen, Norut
-*/
-
-define('timingsrc',['require','exports','module','sequencing/sequencer','sequencing/windowsequencer','timingobject/timingobject','sequencing/timingcallbacks','util/interval','util/eventify','timingobject/skewconverter','timingobject/delayconverter','timingobject/scaleconverter','timingobject/loopconverter','timingobject/rangeconverter','timingobject/timeshiftconverter','timingobject/derivativeconverter','sequencing/axis','sequencing/timinginteger','sequencing/activecue'],function(require, exports, module) {
-
- const DefaultSequencer = require('sequencing/sequencer');
- const WindowSequencer = require('sequencing/windowsequencer');
- const timingobject = require('timingobject/timingobject');
- const timingcallbacks = require('sequencing/timingcallbacks');
-
- /*
- Common constructor DefaultSequencer and WindowSequencer
- */
- const Sequencer = function (toA, toB, _axis) {
- if (toB === undefined) {
- return new DefaultSequencer(toA, _axis);
- } else {
- return new WindowSequencer(toA, toB, _axis);
- }
- };
-
- // Add clone prototype to both Sequencer and WindowSequencer
- DefaultSequencer.prototype.clone = function (toA, toB) {
- return Sequencer(toA, toB, this._axis);
- };
- WindowSequencer.prototype.clone = function (toA, toB) {
- return Sequencer(toA, toB, this._axis);
- };
-
- return {
- version : "v2.1",
-
- // util
- Interval: require('util/interval'),
- eventify: require('util/eventify'),
-
- // Timing Object
- TimingObject : timingobject.TimingObject,
-
- // Timing Converters
- ConverterBase : timingobject.ConverterBase,
- SkewConverter : require('timingobject/skewconverter'),
- DelayConverter : require('timingobject/delayconverter'),
- ScaleConverter : require('timingobject/scaleconverter'),
- LoopConverter : require('timingobject/loopconverter'),
- RangeConverter : require('timingobject/rangeconverter'),
- TimeShiftConverter : require('timingobject/timeshiftconverter'),
- DerivativeConverter : require('timingobject/derivativeconverter'),
-
- // Sequencing
-
- Axis: require('sequencing/axis'),
- Sequencer : Sequencer,
- setPointCallback : timingcallbacks.setPointCallback,
- setIntervalCallback : timingcallbacks.setIntervalCallback,
- TimingInteger : require('sequencing/timinginteger'),
- ActiveCue : require('sequencing/activecue')
- };
-});
-
- //The modules for your project will be inlined above
- //this snippet. Ask almond to synchronously require the
- //module value for 'main' here and return it as the
- //value to use for the public API for the built file.
- return require('timingsrc');
-}));
\ No newline at end of file
diff --git a/docs/lib/timingsrc-min-v3.js b/docs/lib/timingsrc-min-v3.js
new file mode 100644
index 0000000..a6e44cf
--- /dev/null
+++ b/docs/lib/timingsrc-min-v3.js
@@ -0,0 +1,2 @@
+var TIMINGSRC=function(t){"use strict";function e(t){for(var e="",i="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",n=0;n!e.has(t)))}const o=function(t,e){return 0==t.size?new Map:0==e.size?t:new Map([...t].filter((function([t,i]){return!e.has(t)})))},l=function(t,e){return[t,e]=t.size<=e.size?[t,e]:[e,t],0==t.size?new Map:new Map([...t].filter((function([t,i]){return e.has(t)})))};function a(t){return null!=t&&"function"==typeof t[Symbol.iterator]}function h(t,e={}){let{copy:i=!1,order:n=!1}=e;if(0==t.length)return[];if(1==t.length)return t[0];let r=t.reduce((t,e)=>t+e.length,0);n||t.sort((t,e)=>e.length-t.length);let s,o,l=i?[]:t.shift(),a=l.length;l.length=r;for(let e of t){o=e.length,s=a+o;for(let t=0;tt instanceof Map).every(t=>1==t))throw new Error("some object in array_of_maps is not a Map",t);n||t.sort((t,e)=>e.size-t.size);let r=i?new Map:t.shift();for(let e of t)for(let[t,i]of e.entries())r.set(t,i);return r},divmod:function(t,e){let i=t%e;return[(t-i)/e,i]},isIterable:a,array_concat:h,object_equals:c,docready:u});const d=function(t){let e=parseFloat(t);return t===e&&!isNaN(e)};function p(t,e,i,n){if(t==1/0&&(0==e||0==i))throw new Error("Infinity endpoint must be right-closed or singular");if(t==-1/0&&(1==e||0==i))throw new Error("-Infinity endpoint must be left-closed or singular");return[t,e,i,n]}function f(t){let[e,i,n,r]=t;return r||null==i?2:i?n?3:0:n?1:4}function v(t,e){if(void 0===t.length){if(!d(t))throw new Error("e1 not a number",t);t=p(t,void 0,void 0,!0)}if(void 0===e.length){if(!d(e))throw new Error("e2 not a number",e);e=p(e,void 0,void 0,!0)}return t[0]!=e[0]?[t[0],e[0]]:[f(t),f(e)]}function g(t,e){let[i,n]=v(t,e),r=i-n;return 0==r?0:r>0?1:-1}var m={cmp:g,toString:function(t){if(void 0===t.length)return t.toString();{let e=f(t),i=t[0];if(i!=1/0&&i!=-1/0||(i="--"),0==e)return i+")";if(1==e)return"["+i;if(2==e)return`[${i}]`;if(3==e)return i+"]";if(4==e)return"("+i}},equals:function(t,e){let[i,n]=v(t,e);return i==n},rightof:function(t,e){let[i,n]=v(t,e);return i>n},leftof:function(t,e){let[i,n]=v(t,e);return ie)throw new w(`low > high, ${t}, ${e}`);if(t===e&&(i=!0,n=!0),t===-1/0&&(i=!0),e===1/0&&(n=!0),void 0===i&&(i=!0),void 0===n&&(n=!1),"boolean"!=typeof i)throw new w("lowInclude not boolean, "+i);if("boolean"!=typeof n)throw new w("highInclude not boolean, "+n);this._low=t,this._high=e,this._lowInclude=i,this._highInclude=n,this._length=this._high-this._low,this._singular=this._low===this._high,this._finite=isFinite(this._low)&&isFinite(this._high),this._endpointLow=m.create(this._low,!1,this._lowInclude,this._singular),this._endpointHigh=m.create(this._high,!0,this._highInclude,this._singular)}get low(){return this._low}get high(){return this._high}get lowInclude(){return this._lowInclude}get highInclude(){return this._highInclude}get length(){return this._length}get singular(){return this._singular}get finite(){return this._finite}get endpointLow(){return this._endpointLow}get endpointHigh(){return this._endpointHigh}toString(){if(this._singular){return`[${this._endpointLow[0]}]`}return`${m.toString(this._endpointLow)},${m.toString(this._endpointHigh)}`}asArray(){return[this._low,this._high,this._lowInclude,this._highInclude]}covers_endpoint(t){let e=m.leftof(t,this._endpointLow),i=m.rightof(t,this._endpointHigh);return!e&&!i}compare(t){return M(this,t)}equals(t){return M(this,t)==k.EQUALS}match(t,e=O){let i=M(this,t);return Boolean(e&i)}}R.Relation=k,R.Match=S,R.cmpLow=A(!0),R.cmpHigh=A(!1),R.fromEndpoints=function(t,e){let[i,n,r,s]=t,[o,l,a,h]=e;if(n)throw new w("illegal endpointLow - bracket must be left");if(!l)throw new w("illegal endpointHigh - bracket must be right");return new R(i,o,r,a)},R.intersect=function(t,e){let i=M(t,e);return i==k.OUTSIDE_LEFT?[]:i==k.OVERLAP_LEFT?[R.fromEndpoints(e.endpointLow,t.endpointHigh)]:i==k.COVERS?[e]:i==k.EQUALS||i==k.COVERED?[t]:i==k.OVERLAP_RIGHT?[R.fromEndpoints(t.endpointLow,e.endpointHigh)]:i==k.OUTSIDE_RIGHT?[]:void 0},R.union=function(t,e){let i=M(t,e);return i==k.OUTSIDE_LEFT?t.high!=e.low||!t.highInclude&&!e.lowInclude?[t,e]:[R.fromEndpoints(t.endpointLow,e.endpointHigh)]:i==k.OVERLAP_LEFT?[R.fromEndpoints(t.endpointLow,e.endpointHigh)]:i==k.COVERS||i==k.EQUALS?[t]:i==k.COVERED?[e]:i==k.OVERLAP_RIGHT?[R.fromEndpoints(e.endpointLow,t.endpointHigh)]:i==k.OUTSIDE_RIGHT?e.high!=t.low||!e.highInclude&&!t.lowInclude?[e,t]:[R.fromEndpoints(e.endpointLow,t.endpointHigh)]:void 0},R.intersectAll=function(t){if(t.sort(R.cmpLow),t.length<=1)return t;const e=[t.shift()];for(;t.length>0;){let i=e.pop(),n=t.shift();e.push(...R.intersect(i,n))}return e},R.unionAll=function(t){if(t.sort(R.cmpLow),t.length<=1)return t;const e=[t.shift()];for(;t.length>0;){let i=e.pop(),n=t.shift();e.push(...R.union(i,n))}return e},function(){function t(t,e,i){return void 0===i||0==+i?Math[t](e):(e=+e,i=+i,isNaN(e)||"number"!=typeof i||i%1!=0?NaN:(e=e.toString().split("e"),+((e=(e=Math[t](+(e[0]+"e"+(e[1]?+e[1]-i:-i)))).toString().split("e"))[0]+"e"+(e[1]?+e[1]+i:i))))}Math.round10||(Math.round10=function(e,i){return t("round",e,i)}),Math.floor10||(Math.floor10=function(e,i){return t("floor",e,i)}),Math.ceil10||(Math.ceil10=function(e,i){return t("ceil",e,i)})}();const L=function(t,e){return t-e};function D(t,e){let i=t.position==e.position,n=t.velocity==e.velocity,r=t.acceleration==e.acceleration,s=t.timestamp==e.timestamp;return i&&n&&r&&s}function C(t,e){if(void 0===e)throw new Error("no ts provided for calculateVector");const i=e-t.timestamp;return{position:t.position+t.velocity*i+.5*t.acceleration*i*i,velocity:t.velocity+t.acceleration*i,acceleration:t.acceleration,timestamp:e}}function N(t,e){let i;i=null==e?t:C(t,e);let n=L(i.velocity,0);return 0===n&&(n=L(t.acceleration,0)),n}function x(t){return 0!==t.velocity||0!==t.acceleration}const P=Object.freeze({INIT:"init",INSIDE:"inside",OUTSIDE_LOW:"outsidelow",OUTSIDE_HIGH:"outsidehigh"});function H(t,e){const{position:i,velocity:n,acceleration:r}=t;if(i>e[1])return P.OUTSIDE_HIGH;if(i0)return P.OUTSIDE_HIGH;if(0===n&&r>0)return P.OUTSIDE_HIGH}else if(i===e[0]){if(n<0)return P.OUTSIDE_LOW;if(0==n&&r<0)return P.OUTSIDE_HIGH}return P.INSIDE}function V(t,e){return H(t,e)!=P.INSIDE}function z(t,e){const i=H(t,e);return i!==P.INSIDE&&(t.velocity=0,t.acceleration=0,i===P.OUTSIDE_HIGH?t.position=e[1]:t.position=e[0]),t}function U(t,e){let i=t.timestamp,n=G(t,e[0]),r=G(t,e[1]);return void 0!==n&&void 0!==r?n=0}function q(t,e,i,n){if(0===i&&0===e)return t!=n?[]:[0];if(0===i)return[(n-t)/e];if(!1===B(t,e,i,n))return[];if(0===e*e-2*i*(t-n))return[-e/i];const r=Math.sqrt(Math.pow(e,2)-2*i*(t-n)),s=(-e+r)/i,o=(-e-r)/i;return[Math.min(s,o),Math.max(s,o)]}function G(t,e){const{position:i,velocity:n,acceleration:r}=t,s=function(t,e,i,n){const r=q(t,e,i,n);return 0===r.length?[]:1==r.length?r[0]>0?[r[0]]:[]:2==r.length?r[1]<0?[]:r[0]>0?[r[0],r[1]]:r[1]>0?[r[1]]:[]:[]}(i,n,r,e);return 0===s.length?void 0:s[0]}function j(t,e){let i=G(t,e[0]),n=G(t,e[1]);return i==1/0&&(i=void 0),n==1/0&&(n=void 0),void 0!==i&&void 0!==n?i0?lt))return e;r=e-1}return~r}isFound(t,e){return t>0||0==t&&this.array.length>0&&this.array[0]==e}indexOf(t){var e=this.binaryIndexOf(t);return this.isFound(e,t)?e:-1}indexOfElements(t){let e,i,n=[];for(let r=0;r-1&&n.push(i);return n}has(t){return this.indexOf(t)>-1}get(t){return this.array[t]}_update_splice(t,e,i){if(this.array.length>0){let e=this.indexOfElements(t);e.sort((function(t,e){return t-e}));for(let t=e.length-1;t>-1;t--)this.array.splice(e[t],1)}let n,r,s=e.length;for(let t=0;t0&&t.length>0){let e=this.indexOfElements(t);for(let t=0;t0){let t=this.array.indexOf(void 0);t>-1&&this.array.splice(t,this.array.length-t)}var n;this.array=(n=this.array,[...new Set(n)])}update(t,e,i){let n=t.length+e.length;if(0==n)return;let r=(s=this.array.length,o=n,0==s?"sort":o<=100?"splice":"sort");var s,o;"splice"==r?this._update_splice(t,e,i):"sort"==r&&this._update_sort(t,e,i)}getMinimum(){return this.array.length>0?this.array[0]:void 0}getMaximum=function(){return this.array.length>0?this.array[this.array.length-1]:void 0};ltIndexOf(t){var e=this.binaryIndexOf(t);return this.isFound(e,t)?e>0?e-1:-1:Math.abs(e)-1}leIndexOf(t){var e=this.binaryIndexOf(t);return this.isFound(e,t)||(e=Math.abs(e)-1)>=0?e:-1}gtIndexOf(t){var e=this.binaryIndexOf(t);if(this.isFound(e,t))return e-1?[e,e+1]:[void 0,void 0]}var e=-1,i=-1;return-1===(e=t.lowInclude?this.geIndexOf(t.low):this.gtIndexOf(t.low))||-1===(i=t.highInclude?this.leIndexOf(t.high):this.ltIndexOf(t.high))?[void 0,void 0]:[e,i+1]}lookup(t){let[e,i]=this.lookupIndexes(t);return null!=e?this.array.slice(e,i):[]}remove(t){let[e,i]=this.lookupIndexes(t);return null!=e?this.array.splice(e,i-e):[]}slice(t,e){return this.array.slice(t,e)}splice(t,e){return this.array.splice(t,e)}removeInSlice(t){if(0==t.length)return;const e=t[0],i=t[t.length-1];let[n,r]=this.lookupIndexes(new R(e,i,!0,!0)),s=n,o=n,l=0;for(;s-1&&(this.subscriptions.splice(e,1),t.terminate())}}class it{constructor(t,e,i){i=i||{},this.event=t,this.name=t.name,this.callback=e,this.init=void 0===i.init?this.event.init:i.init,this.init_pending=!1,this.terminated=!1,this.ctx=i.ctx}terminate(){this.terminated=!0,this.callback=void 0,this.event.unsubscribe(this)}}function nt(t){return t.__eventify_eventMap=new Map,t.__eventify_buffer=[],t}function rt(t){function e(t,e){const i=t.__eventify_eventMap.get(e);if(null==i)throw new Error("Event undefined",e);return i}t.eventifyDefine=function(t,e){if(this.__eventify_eventMap.has(t))throw new Error("Event already defined",t);this.__eventify_eventMap.set(t,new et(this,t,e))},t.eventifyTrigger=function(t,e){return this.eventifyTriggerAll([{name:t,eArg:e}])},t.eventifyTriggerAlike=function(t,e){return this.eventifyTriggerAll(e.map(e=>({name:t,eArg:e})))},t.eventifyTriggerAll=function(t){if(0==t.length)return;let i=t.map(t=>{let{name:i,eArg:n}=t,r=e(this,i),s=r.subscriptions.filter(t=>0==t.init_pending);return[r,n,s]},this);const n=i.length,r=this.__eventify_buffer,s=this.__eventify_buffer.length;this.__eventify_buffer.length=s+n;for(let t=0;t({key:t,new:e,old:void 0}));return this.sortItems(e),"batch"==t?[e]:e}}_notifyEvents(t){if(0==t.length)return;const e=this.eventifySubscriptions("batch").length>0,i=this.eventifySubscriptions("remove").length>0,n=this.eventifySubscriptions("change").length>0;if(e&&this.eventifyTrigger("batch",t),i||n)for(let e of t)null==e.new&&null!=e.old?i&&this.eventifyTrigger("remove",e):n&&this.eventifyTrigger("change",e)}get size(){return this.datasource.size}has(t){return this.datasource.has(t)}get(t){return this.datasource.get(t)}keys(){return this.datasource.keys()}values(){return this.datasource.values()}entries(){return this.datasource.entries()}set(t,e){let i=void 0;return this.datasource.has(t)&&(i=this.datasource.get(t)),this.datasource.set(t,e),this._notifyEvents([{key:t,new:e,old:i}]),this}delete(t){let e=!1,i=void 0;return this.datasource.has(t)&&(i=this.datasource.get(t),this.datasource.delete(t),e=!0),this._notifyEvents([{key:t,new:void 0,old:i}]),e}clear(){const t=[...this.datasource.entries()].map(([t,e])=>({key:t,new:void 0,old:e}));this.datasource.clear(),this._notifyEvents(t)}}ot.eventifyPrototype(lt.prototype);class at extends lt{static cmpLow(t,e){return R.cmpLow(t.interval,e.interval)}static cmpHigh(t,e){return R.cmpHigh(t.interval,e.interval)}sortOrder(t={}){let e=t.order||super.sortOrder(t);return"low"==e?at.cmpLow:"high"==e?at.cmpHigh:"function"==typeof e?e:void 0}cues(t={}){let e=this.sortValues(this.values(),t);return Array.isArray(e)?e:[...e]}}class ht{constructor(t,e){this.tid=void 0,this.to=t,this.callback=e}isSet(){return null!=this.tid}setTimeout(t,e){if(null!=this.tid)throw new Error("at most on timeout");let i=this.to.clock.now(),n=1e3*Math.max(t-i,0);this.tid=setTimeout(this.onTimeout.bind(this),n,t,e)}onTimeout(t,e){if(null!=this.tid){this.tid=void 0;let i=this.to.clock.now();inull!=t);return this.__update(t),n}__handleEvent(t){let{range:e,live:i=!0,...n}=t;null!=e&&(e=[e[0],e[1]]);let r={range:e,live:i,...n};if(r=this.onUpdateStart(r),null!=r)return this.__process(r)}__handleTimeout(t,e){this.__process({...e})}__process(t){let{range:e,position:i,velocity:n,acceleration:r,timestamp:s,live:o=!0,...l}=t,a=!1;if(null!=e){let[t,i]=e;t-1&&t.splice(i,1),0==t.length}}const Ot=[0,10,100,1e3,1e4,1e5,1/0];var Tt=function(t){for(let e=0;ethis._submit.bind(this)())}_push(t){let e=this._cues.length,i=0==e,n=t.length;this._cues.length+=n;for(let i=0;i0&&(this._done.value=!0)}_submit(){let t=[];return this._cues.length>0&&(t=this._ds.update(this._cues,this._options)),this._reset(),t}addCue(t,e,i){let n={key:t};return n.interval=e,arguments.length>2&&(n.data=i),n=At(n),this._push([n]),this}removeCue(t){return this._push([{key:t}]),this}update(t){t=t.map(t=>At(t)),this._push(t)}clear(){return this._cues=[],this}submit(){if(this._options.autosubmit)throw new Error("manual submit while options.autosubmit is true");this._done.value=!0}}class Lt extends at{constructor(t){super(t),this._map=new Map,this._builder=new Rt(this),this._cueBuckets=new Map;for(let t=0;t-1&&this._update_callbacks.splice(e,1)}_notify_callbacks(t,e){this._update_callbacks.forEach((function(i){i.handler(t,e)}))}set(t,e){throw new Error("not implemented")}delete(t){throw new Error("not implemented")}makeBuilder(t){return new Rt(this,t)}get builder(){return this._builder}addCue(t,e,i){return arguments.length>2?this._builder.addCue(t,e,i):this._builder.addCue(t,e),this}removeCue(t){return this._builder.removeCue(t),this}get updateDone(){return this._builder.updateDone}_addCue(t,e,i,n){let r={key:t,interval:e,data:i};return r=At(r),this.update(r,n)}_removeCue(t,e){return this.update({key:t},e)}update(t,e={}){const i=new Map;let n,r,s,{debug:o=!1,equals:l,check_needed:h=!0}=e;a(t)||(t=[t]);const c={ts:Et(),author:e.author};for(let o of t){if(h)try{o=At(o)}catch(t){console.log(t,o);continue}r=o.hasOwnProperty("interval"),s=o.hasOwnProperty("data"),n=this._map.get(o.key),null==n?(r||(o.interval=void 0),s||(o.data=void 0)):null!=n&&(r||s?s?r||(o.interval=n.interval):o.data=n.data:(o.interval=void 0,o.data=void 0)),this._update_cue(i,n,o,c,e)}if(this._call_buckets("flush"),i.size>0){let t={low:1/0,high:-1/0},e=[...i.values()].map(e=>(e.new&&e.new.interval&&(t.low=m.min(t.low,e.new.interval.endpointLow),t.high=m.max(t.high,e.new.interval.endpointHigh)),e.old&&e.old.interval&&(t.low=m.min(t.low,e.old.interval.endpointLow),t.high=m.max(t.high,e.old.interval.endpointHigh)),{key:e.key,new:e.new,old:e.old,info:e.info})),n=e.filter(t=>{let e=Mt(t.new,t.old,l);return e.interval!=St.NOOP||e.data!=St.NOOP});this._notifyEvents(n);let r=void 0;return t.low!=1/0&&(r=R.fromEndpoints(t.low,t.high)),this._notify_callbacks(i,r),o&&this.integrity(),e}return o&&this.integrity(),[]}_update_cue(t,e,i,n,r){let s,o,l,a,h,c,u,_,d,p,{chaining:f=!0,safe:v=!1,equals:g}=r;if(e===i)throw Error("illegal cue arg: same object as current cue");let m=Mt(e,i,g);if(m.interval==St.NOOP&&m.data==St.NOOP)return l={key:i.key,new:e,old:e,delta:m},void t.set(i.key,l);if(null==e)null==i.info&&(i.info={ts:n.ts,change_ts:n.ts,change_id:0}),s=void 0,o=v?Object.freeze(i):i,this._map.set(i.key,o);else if(null==i.interval&&null==i.data)s=e,o=void 0,this._map.delete(i.key);else if(null==i.info&&(i.info={ts:e.info.ts,change_ts:n.ts,change_id:e.info.change_id+1}),s=e,o={key:i.key,interval:i.interval,data:i.data,info:i.info},v&&(o=Object.freeze(o)),this._map.set(i.key,o),s.interval){let t=Tt(s.interval.length),e=this._cueBuckets.get(t);e.replace_endpoint(s.interval.low,o),s.singular||e.replace_endpoint(s.interval.high,o)}if(l={key:i.key,new:o,old:s,delta:m,info:n},f&&(a=t.get(i.key),null!=a&&(l.old=a.old,l.delta=Mt(o,l.old,g))),t.set(i.key,l),m.interval!=St.NOOP){if(m.interval==St.INSERT?(d=!1,p=!0,u=!0,_=!0):m.interval==St.DELETE?(d=!0,p=!1,u=!0,_=!0):m.interval==St.REPLACE&&(d=!0,p=!0,u=o.interval.low!=s.interval.low,_=o.interval.high!=s.interval.high),d){let t=Tt(s.interval.length);h=this._cueBuckets.get(t)}if(p){let t=Tt(o.interval.length);c=this._cueBuckets.get(t)}h&&c&&h!=c&&(d=!0,p=!0,u=!0,_=!0),u&&(d&&h.del_endpoint(s.interval.low,s),p&&c.add_endpoint(o.interval.low,o)),_&&(d&&!s.interval.singular&&h.del_endpoint(s.interval.high,s),p&&!o.interval.singular&&c.add_endpoint(o.interval.high,o))}}_call_buckets(t,...e){const i=[];for(let n of this._cueBuckets.values()){let r=n[t](...e);null!=r&&r.length>0&&i.push(r)}return h(i)}lookup_endpoints(t){return t=bt(t),this._call_buckets("lookup_endpoints",t)}lookup(t,e){return t=bt(t),this._call_buckets("lookup",t,e)}lookup_delete(t,e,i={}){t=bt(t);const n=this._call_buckets("lookup_delete",t,e),r=[],s={ts:Et(),author:i.author};let o;for(let t=0;tnull==t.interval),r=e.length,s=n.length,l=this._map.size,a=l-r-s;if(0!=a)throw console.log("count buckets",r),console.log("count no intervals",s),console.log("count map",l),console.log("count diff",a),new Error("inconsistent cue count");let h=new Map(e.map(t=>[t.key,t])),c=new Map([...this._map.entries()].filter(([t,e])=>null!=e.interval)),u=o(h,c);if(u.size>0)throw console.log("buckets missing cues:"),console.log([...u.keys()]),new Error("buckets missing cues: "+[...u.keys()]);if(u=o(c,h),u.size>0)throw new Error("buckets too many cues: "+[...u.keys()]);return{cues:e.length,points:i.length}}}Lt.Delta=St,Lt.cue_delta=Mt,Lt.cue_equals=function(t,e){let i=Mt(t,e);return i.interval==St.NOOP&&i.data==St.NOOP};class Dt{constructor(t){this._maxLength=t,this._pointMap=new Map,this._pointIndex=new tt,this._created=new Set,this._dirty=new Set}add_endpoint(t,e){let i=0==this._pointMap.size?void 0:this._pointMap.get(t);null==i?(this._pointMap.set(t,[e]),this._created.add(t)):i.push(e)}del_endpoint(t,e){let i=0==this._pointMap.size?void 0:this._pointMap.get(t);if(null!=i){It(i,e)&&this._dirty.add(t)}}replace_endpoint(t,e){let i=0==this._pointMap.size?void 0:this._pointMap.get(t);if(null!=i){(function(t,e){if(0==t.length)return!1;if(1==t.length){if(t[0].key==e.key)return t[0]=e,!0}else{let i=t.findIndex((function(t){return t.key==e.key}));if(i>-1)return t[i]=e,!0}return!1})(i,e)||console.log("WARNING: attempt to replace non-existent cue in pointMap")}}flush(){if(0==this._created.size&&0==this._dirty.size)return;let t=[],e=[];for(let t of this._created.values()){this._pointMap.get(t).length>0?e.push(t):this._pointMap.delete(t)}for(let e of this._dirty.values()){let i=this._pointMap.get(e);null!=i&&(0==i.length&&(t.push(e),this._pointMap.delete(e)))}this._pointIndex.update(t,e),this._created.clear(),this._dirty.clear()}lookup_endpoints(t){if(0==this._pointMap.size)return[];const e=new R(t.low,t.high,!0,!0),i=this._pointIndex.lookup(e),n=[],r=i.length;let s,o;for(let l=0;lthis._maxLength)return i;if(e&kt.COVERS){let e;if(this._maxLength==1/0)e=new R(-1/0,t.low);else{let i=t.high-this._maxLength,n=t.low;[i,n]=[Math.min(i,n),Math.max(i,n)],e=new R(i,n,!0,!0)}this._lookup_cues(e).forEach((function(e){e.interval.match(t,kt.COVERS)&&i.push(e)}))}return i}lookup_delete(t,e){const i=this.lookup(t,e),n=[];let r,s,o;for(let t=0;t0)throw new Error("pointMap missing points: "+[...i]);if(i=s(e,t),i.size>0)throw new Error("pointIndex missing points: "+[...i])}let n=[...this._pointIndex.values()];if(n.length!=t.size)throw new Error("pointIndex include duplicate points");for(let t=1;t=n[t])throw new Error("pointIndex not ordered");for(let t of n){let e=this._pointMap.get(t);for(let i of e)if(t!=i.interval.low&&t!=i.interval.high)throw console.log("POINT:",t),console.log("CUE:",i.interval.toString()),new Error("pointMap: wrong cue")}for(let t of[...this._pointMap.values()])for(let e of t)for(let t of[e.interval.low,e.interval.high])if(!this._pointMap.has(t))throw new Error(`cue found with low or high point not in pointMap ${t} -> ${e.interval.toString()} `);let r=[];for(let t of this._pointMap.values())for(let e of t)r.push(e);let o=new Map;for(let t of r){let e=o.get(t.key);if(null==e)o.set(t.key,t);else if(t!==e)throw new Error("pointMap: different cue objects for same key")}let l=[...o.values()];for(let t of l.values())if(t.interval.length>this._maxLength)throw new Error(`cue in wrong cue bucket ${this._maxLength}, ${t.interval.toString()}`);return[{maxLength:this._maxLength,points:[...this._pointMap.keys()],cues:l}]}}const Ct=$;function Nt(t,e){return m.cmp(t.tsEndpoint,e.tsEndpoint)}class xt{constructor(t,e,i){this.to=e,this.timeout=new ht(e,this.run.bind(this)),this.vector,this.timeInterval,this.posInterval,this.dataset=t,this.queue=[],this.callbacks=[],(i=i||{}).lookahead=i.lookahead||5,this.options=i}add_callback(t){let e={handler:t};return this.callbacks.push(e),e}del_callback(t){let e=this.callbacks.indexof(t);e>-1&&this.callbacks.splice(e,1)}_notify_callbacks(...t){this.callbacks.forEach((function(e){e.handler(...t)}))}setVector(t){let e=t.timestamp;this.vector;null!=this.vector&&(this.timeout.clear(),this.timeInterval=void 0,this.posInterval=void 0,this.queue=[]),this.vector=t,x(this.vector)&&this.run(e)}push(t){t.forEach((function(t){this.timeInterval.covers_endpoint(t.tsEndpoint)&&this.queue.push(t)}),this),this.queue.sort(Nt)}pop(t){let e=[];this.queue.length;for(;this.queue.length>0&&this.queue[0].tsEndpoint[0]<=t;)e.push(this.queue.shift());return e}next(){return this.queue.length>0?this.queue[0].tsEndpoint[0]:void 0}advance(t){let e,i=this.options.lookahead,n=!1;return null==this.timeInterval?(e=t,n=!0):m.leftof(this.timeInterval.endpointHigh,t)&&(e=this.timeInterval.high,n=!0),n&&(this.timeInterval=new R(e,e+i,!0,!1),this.posInterval=Ct(this.timeInterval,this.vector),this.queue=[]),n}load(t,e){let i=X(this.timeInterval,this.posInterval,this.vector,t),n=U(this.vector,this.to.range)[0];return null==e&&(e=this.timeInterval.endpointLow),i.filter((function(t){if(n<=t.tsEndpoint[0])return!1;if(m.leftof(t.tsEndpoint,e))return!1;if(0!=this.vector.acceleration){let e=t.tsEndpoint[0];if(e>this.timeInterval.endpointLow[0]){let i=C(this.vector,e);if(i.position==t.endpoint[0]&&0==i.velocity)return!1}}return!0}),this)}run(t){let e=this.pop(t);if(this.advance(t)){let i=this.dataset.lookup_endpoints(this.posInterval),n=this.load(i);this.push(n);let r=this.pop(t);e.push(...r)}e.length>0&&this._notify_callbacks(t,e,this);let i=this.next()||this.timeInterval.high;this.timeout.setTimeout(Math.min(i,this.timeInterval.high))}}function Pt(t){return t.interval==Lt.Delta.NOOP&&t.data==Lt.Delta.NOOP}const Ht=Object.freeze({ENTER:1,STAY:0,EXIT:-1,ENTER_EXIT:2}),Vt=new Map([["LRL",Ht.STAY],["LRR",Ht.EXIT],["LRS",Ht.EXIT],["LLL",Ht.STAY],["LLR",Ht.ENTER],["LLS",Ht.ENTER],["RRL",Ht.ENTER],["RRR",Ht.STAY],["RRS",Ht.ENTER],["RLL",Ht.EXIT],["RLR",Ht.STAY],["RLS",Ht.EXIT],["SRL",Ht.ENTER],["SRR",Ht.EXIT],["SRS",Ht.ENTER_EXIT],["SLL",Ht.EXIT],["SLR",Ht.ENTER],["SLS",Ht.ENTER_EXIT]]);function zt(t,e){return R.cmpLow(t.interval,e.interval)}function Ut(t,e){return-1*R.cmpHigh(t.interval,e.interval)}function Bt(t,e){return zt(t.new?t.new:t.old,e.new?e.new:e.old)}function qt(t,e){return Ut(t.new?t.new:t.old,e.new?e.new:e.old)}class Gt extends at{constructor(t,e){super(e),this._map=new Map,this._ds=t;let i=this._onDatasetCallback.bind(this);this._ds_cb=this._ds.add_callback(i)}get datasource(){return this._map}get dataset(){return this._ds}_movementDirection(){throw new Error("not implemented")}sortValues(t,e={}){if("function"==typeof this.sortOrder(e))return super.sortValues(t,e);{let e=Array.isArray(t)?t:[...t];return this._movementDirection()>=0?e.sort(zt):e.sort(Ut),e}}sortItems(t,e){let i=this.sortOrder();if("function"==typeof i)return super.sortItems(t);null==i&&(null==e&&(e=this._movementDirection()),e>=0?t.sort(Bt):t.sort(qt))}set(t,e){throw new Error("not implemented")}delete(t){throw new Error("not implemented")}clear(t){throw new Error("not implemented")}_onDatasetCallback(t,e){throw new Error("not implemented")}_items_from_dataset_events(t,e){const i=[],n=[],r=[],s=0==this._map.size;let o,l,a;for(let h of t.values())Pt(h.delta)||(o=!s&&this._map.has(h.key),l=!1,null!=h.new&&h.new.interval.match(e)&&(l=!0),o&&!l?(a={key:h.key,new:void 0,old:h.old,info:h.info},r.push(a)):!o&&l?(a={key:h.key,new:h.new,old:void 0,info:h.info},i.push(a)):o&&l&&(a={key:h.key,new:h.new,old:h.old,info:h.info},n.push(a)));return[r,n,i]}_items_from_dataset_lookup(t,e){const i=new Map(this._ds.lookup(e).map((function(t){return[t.key,t]})));let n,r=[],s=[],a=0==this._map.size;if(!a){let e=l(this._map,i);if(e.size>0){let i,n;for(let s of t.values())i=e.get(s.key),null==i||Pt(s.delta)||(n={key:s.key,new:s.new,old:s.old},r.push(n))}s=[...o(this._map,i).values()].map(t=>({key:t.key,new:void 0,old:t}))}n=a?i:o(i,this._map);let h=[...n.values()].map(t=>({key:t.key,new:t,old:void 0}));for(let e in[s,r,h])for(let i of e){let e=t.get(i.key);null!=e&&(i.info=e.info)}return[s,r,h]}get builder(){return this.dataset.builder}addCue(t,e,i){return this.dataset.addCue(t,e,i)}removeCue(t){return this.dataset.removeCue(t)}_addCue(t,e,i){return this.dataset._addCue(t,e,i)}_removeCue(t){return this.dataset._removeCue(t)}update(t,e){return this.dataset.update(t,e)}clear(){return this.dataset.clear()}hasCue(t){return this.dataset.has(t)}getCue(t){return this.dataset.get(t)}getCues(){return this.dataset.cues()}getActiveKeys(){return[...this.keys()]}getActiveCues(){return this.cues()}isActive(t){return this.has(t)}}Gt.Active=Ht,Gt.ActiveMap=Vt;const jt=Y.PosDelta,$t=Y.MoveDelta,Ft=Gt.Active,Xt=Gt.ActiveMap;class Qt extends Gt{constructor(t,e,i){super(t,i),this._to=e,this._sub=this._to.on("timingsrc",this._onTimingCallback.bind(this)),this._sched=new xt(this._ds,e);let n=this._onScheduleCallback.bind(this);this._sched_cb=this._sched.add_callback(n)}_movementDirection(){const t=this._to.clock.now();return N(this._to.vector,t)}_onDatasetCallback(t,e){if(!this._to.isReady())return;if(null==e)return;const i=this._to.clock.now(),n=C(this._to.vector,i),r=new R(n.position);if(!r.match(e,R.Match.OUTSIDE)){let e=this._items_from_dataset_events.bind(this);5e3{this._map.delete(t.key)}),s.forEach(t=>{this._map.set(t.key,t.new)}),o.forEach(t=>{this._map.set(t.key,t.new)});let l=N(n);this.sortItems(i,l),this.sortItems(s,l),this.sortItems(o,l);const a=h([i,s,o],{copy:!0,order:!0});this._notifyEvents(a)}this._sched.posInterval&&(this._sched.posInterval.match(e,R.Match.OUTSIDE)||this._sched.setVector(n))}_onTimingCallback(t){let e=C(t,this._to.clock.now()),i=new Y(this._to.old_vector,e);if(i.posDelta==jt.CHANGE||i.moveDelta==$t.STOP){let t=e.position,i=e.position,n=new R(t,i,!0,!0),r=new Map(this._ds.lookup(n).map(t=>[t.key,t])),s=o(this._map,r),l=o(r,this._map);this._map=r;let a=[...s.values()].map(t=>({key:t.key,new:void 0,old:t})),c=[...l.values()].map(t=>({key:t.key,new:t,old:void 0})),u=N(e);this.sortItems(a,u),this.sortItems(c,u);const _=h([a,c],{copy:!0,order:!0});this._notifyEvents(_)}this._sched.setVector(e)}_onScheduleCallback=function(t,e,i){if(!this._to.isReady())return;const n=[];e.forEach((function(t){let e=t.cue,i=this._map.has(e.key),[r,s,o,l]=t.endpoint,a=t.direction>0?"R":"L",h=l?"S":s?"R":"L",c=Xt.get(`S${a}${h}`);c==Ft.ENTER_EXIT?i?(n.push({key:e.key,new:void 0,old:e}),this._map.delete(e.key)):(n.push({key:e.key,new:e,old:void 0}),n.push({key:e.key,new:void 0,old:e})):c==Ft.ENTER?i||(n.push({key:e.key,new:e,old:void 0}),this._map.set(e.key,e)):c==Ft.EXIT&&i&&(n.push({key:e.key,new:void 0,old:e}),this._map.delete(e.key))}),this),this._notifyEvents(n)}}const Wt=Y.PosDelta,Yt=Y.MoveDelta,Jt=Gt.Active,Kt=Gt.ActiveMap;function Zt(t,e){let i=N(t)+N(e);return i>0?1:i<0?-1:0}class te extends Gt{constructor(t,e,i,n){super(t,n),this._toA=e,this._toA_ready=!1,this._toB=i,this._toB_ready=!1;let r=this._onTimingCallback.bind(this);this._subA=this._toA.on("timingsrc",r),this._subB=this._toB.on("timingsrc",r);let s=this._onScheduleCallback.bind(this);this._schedA=new xt(this._ds,e),this._schedA_cb=this._schedA.add_callback(s),this._schedB=new xt(this._ds,i),this._schedB_cb=this._schedB.add_callback(s),this._toA_vector,this._toB_vector}_isReady(){return this._toA_ready&&this._toB_ready}_movementDirection(){const t=this._toA.clock.now();return Zt(C(this._toA.vector,t),C(this._toB.vector,t))}_onDatasetCallback(t,e){if(!this._isReady())return;if(null==e)return;const i=this._toA.clock.now(),n=C(this._toA_vector,i),r=C(this._toB_vector,i);let[s,o]=[n.position,r.position],[l,a]=s<=o?[s,o]:[o,s];const c=new R(l,a,!0,!0);if(!c.match(e,R.Match.OUTSIDE)){let e=this._items_from_dataset_events.bind(this);5e3{this._map.delete(t.key)}),s.forEach(t=>{this._map.set(t.key,t.new)}),o.forEach(t=>{this._map.set(t.key,t.new)});let l=Zt(n,r);this.sortItems(i,l),this.sortItems(s,l),this.sortItems(o,l);const a=h([i,s,o],{copy:!0,order:!0});this._notifyEvents(a,l)}this._schedA.posInterval&&(this._schedA.posInterval.match(e,R.Match.OUTSIDE)||this._schedA.setVector(n)),this._schedB.posInterval&&(this._schedB.posInterval.match(e,R.Match.OUTSIDE)||this._schedB.setVector(r))}_onTimingCallback(t,e){let i=!1;if(!this._isReady()){if(e.src==this._toA?this._toA_ready=!0:this._toB_ready=!0,!this._isReady())return;i=!0}this._toA_vector=this._toA.vector,this._toB_vector=this._toB.vector;const n=e.src,r=n==this._toA?this._toB:this._toA;let s=C(n.vector,n.clock.now());const l=new Y(n.old_vector,s);let a=s.timestamp,c=C(r.vector,a);if(l.posDelta==Wt.CHANGE||l.MoveDelta==Yt.STOP){let t=Math.min(s.position,c.position),e=Math.max(s.position,c.position),i=new R(t,e,!0,!0),n=new Map(this._ds.lookup(i).map(t=>[t.key,t])),r=o(this._map,n),l=o(n,this._map);this._map=n;let a=[...r.values()].map(t=>({key:t.key,new:void 0,old:t})),u=[...l.values()].map(t=>({key:t.key,new:t,old:void 0})),_=Zt(s,c);this.sortItems(a,_),this.sortItems(u,_);const d=h([a,u],{copy:!0,order:!0});this._notifyEvents(d)}n==this._toA?this._schedA.setVector(s):n==this._toB&&this._schedB.setVector(s),i&&(r==this._toA?this._schedA.setVector(c):r==this._toB&&this._schedB.setVector(c))}_onScheduleCallback=function(t,e,i){if(!this._isReady())return;const n=i.to==this._toA?this._toB:this._toA,r=[];e.forEach((function(t){let[e,i,s,o]=t.endpoint,l=t.tsEndpoint[0],a=C(n.vector,l),h=a.position,c=e0?"R":"L",_=o?"S":i?"R":"L",d=Kt.get(`${c}${u}${_}`),p=t.cue,f=this._map.has(p.key);if(d==Jt.ENTER_EXIT){if(x(a)){d=N(a)!=t.direction?Jt.ENTER:Jt.EXIT}else d=Jt.ENTER}d==Jt.STAY&&(d=Jt.ENTER),d==Jt.ENTER&&f||(d!=Jt.EXIT||f)&&(d==Jt.ENTER?(r.push({key:p.key,new:p,old:void 0}),this._map.set(p.key,p)):d==Jt.EXIT&&(r.push({key:p.key,new:void 0,old:p}),this._map.delete(p.key)))}),this),this._notifyEvents(r)}}class ee{static position2percent(t,e){let[i,n]=e;return 100*(t-i)/(n-i)}static percent2position(t,e){let[i,n]=e;return t=Math.max(0,t),i+(n-i)*(t=Math.min(100,t))/100}constructor(t,e,i={}){this._to=t,this._sampler=i.sampler,this._progress_elem=e,this._lock=!1,this._options=i,this._range=i.range||this._to.range;let[n,r]=this._range;if(n==-1/0||r==1/0)throw new Error("illegal range",this._range);this._progress_elem.addEventListener("input",function(){this._lock_value=!0}.bind(this)),this._progress_elem.addEventListener("change",function(){this._lock_value=!1;let t=parseInt(this._progress_elem.value),e=ee.percent2position(t,this._range);this._to.update({position:e})}.bind(this)),this._sampler&&this._sampler.on("change",this.refresh.bind(this))}refresh(){let t=this._to.pos;if(!this._lock_value){let e=ee.position2percent(t,this._range);if(this._options.thumb){if(e<0||100t instanceof Lt),e=t.length>0?t[0]:new Lt,i=[...arguments].filter(t=>t instanceof ft),n=[...arguments].filter(t=>Object.getPrototypeOf(t)===Object.prototype),r=n.length>0?n[0]:{};if(0==i.length)throw new Error("no timingobject in arguments");return 1==i.length?new Qt(e,i[0],r):new te(e,i[0],i[1],r)}Qt.prototype.clone=function(){let t=[this.dataset];return t.push.apply(t,[...arguments]),ie(...t)},te.prototype.clone=function(){let t=[this.dataset];return t.push.apply(t,[...arguments]),ie(...t)};return t.BinarySearch=tt,t.CueCollection=at,t.Dataset=Lt,t.DatasetViewer=class{constructor(t,i){this.ds=t,this.elem=i,this.nonce=e(4),this.ds.on("change",this.onchange.bind(this)),this.ds.on("remove",this.onremove.bind(this))}cue2string(t){let e=t.interval?t.interval.toString():"undefined",i=JSON.stringify(t.data);return`${t.key}, ${e}, ${i}`}onchange(t){let e=`${this.nonce}-${t.key}`,i=this.elem.querySelector("#"+e);if(i)i.innerHTML=this.cue2string(t.new);else{let i=document.createElement("div");i.innerHTML=this.cue2string(t.new),i.setAttribute("id",e),this.elem.appendChild(i)}}onremove(t){let e=`${this.nonce}-${t.key}`,i=document.getElementById(e);i&&i.parentNode.removeChild(i)}},t.DelayConverter=class extends ft{constructor(t,e){if(e<0)throw new Error("negative delay not supported");if(0===e)throw new Error("zero delay makes delayconverter pointless");super(t),this._delay=e,this._buffer=[],this._timeout=new ht(this,this.__handleDelayed.bind(this)),this.eventifyDefine("delaychange",{init:!0})}eventifyInitEventArgs(t){return"delaychange"==t?[this._delay]:super.eventifyInitEventArgs(t)}onUpdateStart(t){this._buffer.push(t),this._timeout.isSet()||this.__handleDelayed()}__handleDelayed(){let t,e,i=this.clock.now();for(;this._buffer.length>0&&(e=this._buffer[0].timestamp+this._delay,!(i0&&(e=this._buffer[0].timestamp+this._delay,this._timeout.setTimeout(e))}update(t){throw new Error("update is not legal on delayed (non-live) timingobject")}get delay(){return this._delay}set delay(t){t!=this._delay&&(this._delay=t,this._timeout.clear(),this.__handleDelayed(),this.eventifyTrigger("delaychange",t))}},t.Interval=R,t.LoopConverter=class extends ft{constructor(t,e){if(super(t,{timeout:!0}),!Array.isArray(e)||2!=e.length)throw new Error("range must be array [low, high], "+e);this.__range=e}update(t){if(null!=t.range){let[e,i]=t.range;if(e>=i)throw new Error("illegal range",t.range);if(e!=this.__range[0]||i!=this.__range[1]){this.__range=[e,i];let t=this.__get_timingsrc().query();t.position=vt(t.position,this.__range),this.__vector=t;let n={range:this.__range,...this.__vector,live:!0};this.__dispatchEvents(n,!0,!0)}delete t.range}if(null!=t.position){let e=this.clock.now(),i=C(this.vector,e).position-t.position,n=C(this.__get_timingsrc().vector,e);t.position=n.position-i}return super.update(t)}onRangeViolation(t){return t.position=vt(t.position,this.__range),t}onUpdateStart(t){return null!=t.range&&(t.range=this.__range),null!=t.position&&(t.position=vt(t.position,this.__range)),t}},t.PositionCallback=class{constructor(t,e,i={}){this._to=t;let{stride:n=1,offset:r=0}=i;this._offset=r,this._stride=n,this._callback=e,this._timeout=new ht(this._to,this._handleTimeout.bind(this)),this._to.on("timingsrc",this._onChange.bind(this))}_onChange(t,e){let i=t.live?t.position:this._to.pos;this._renewTimeout(i)}_calculateTimeout(t,e){let i=this._to.query(),[n,r]=j(i,[t,e]);if(null==n)return;let[s,o]=this._to.range;return r-1&&this._callbacks.splice(e,1)}_notify_callbacks(t,e){this._callbacks.forEach((function(i){i.handler(t,e)}))}_cue_keep(t){return null!=t&&(!(this._interval&&!this._interval.match(t.interval))&&(!(this._key_filter&&!this._key_filter(t.key))&&!(this._data_filter&&!this._data_filter(t.data))))}_cue_convert(t){return null!=t&&this._data_convert?{key:t.key,interval:t.interval,data:this._data_convert(t.data)}:t}_items_filter_convert(t){let e=[];for(let i of t){if(null==i.new&&null==i.old)continue;let t=this._cue_keep(i.old)?i.old:void 0,n=this._cue_keep(i.new)?i.new:void 0;null==t&&null==n||(t=this._cue_convert(t),n=this._cue_convert(n),e.push({key:i.key,new:n,old:t}))}return e}_check_interval(t){if(this._interval)if(t){let e=R.intersect(t,this._interval);if(0==e.length)return console.log(`warning - lookup interval ${t.toString()} outside the subset interval ${this._interval.toString()}`),[];t=e[0]}else t=this._interval;return t}lookup(t,e){let i,n=this._check_interval(t);return i=n?this.datasource.lookup(n,e):[...this.datasource.values()],i.filter(this._cue_keep,this).map(this._cue_convert,this)}lookup_endpoints(t){let e=this._check_interval(t);return this.datasource.lookup_endpoints(e).filter(t=>this._cue_keep(t.cue),this).map(t=>({endpoint:t.endpoint,cue:this._cue_convert(t.cue)}),this)}eventifyInitEventArgs(t){if("batch"==t||"change"==t){let e=this.lookup().map(t=>({key:t.key,new:t,old:void 0}));return this.sortItems(e),"batch"==t?[e]:e}}_onDatasetCallback(t,e){let i=[...t.values()];i=this._items_filter_convert(i);for(let t of i)null!=t.new&&null==t.old?this._size+=1:null==t.new&&null!=t.old&&(this._size-=1);super._notifyEvents(i);let n=new Map(i.map(t=>[t.key,t]));this._interval&&(e=R.intersect(this._inverval,e)),this._notify_callbacks(n,e)}_setInterval(t){if(!t instanceof R)throw new Error("must be interval",t.toString());if(!this._interval||!this._interval.equals(t)){let e=this.lookup();this._interval=t;let i=this.datasource.lookup(t);i=i.filter(this._cue_keep,this).map(this._cue_convert,this);let n=new Map([...e].map(t=>[t.key,t])),r=new Map([...i].map(t=>[t.key,t])),s=o(n,r),l=o(r,n),a=[...s.values()].map(t=>({key:t.key,new:void 0,old:t})),c=[...l.values()].map(t=>({key:t.key,new:t,old:void 0}));this._size-=a.length,this._size+=c.length;const u=h([a,c],{copy:!1,order:!0});this._notifyEvents(u)}}get size(){return this._size}has(t){return null!=this.get(t)}get(t){let e=super.get(t);if(null!=e&&this._cue_keep(e))return this._cue_convert(e)}keys(){return this.values().map(t=>t.key)}values(){return[...super.values()].filter(t=>this._cue_keep(t),this).map(t=>this._cue_convert(t),this)}entries(){return this.values().map(t=>[t.key,t])}update(t,e){throw new Error("not implemented")}set(t,e){throw new Error("not implemented")}delete(t){throw new Error("not implemented")}clear(t){throw new Error("not implemented")}},t.Timeout=ht,t.TimeshiftConverter=class extends ft{constructor(t,e){super(t),this._offset=e,this.eventifyDefine("offsetchange",{init:!0})}eventifyInitEventArgs(t){return"offsetchange"==t?[this._offset]:super.eventifyInitEventArgs(t)}onUpdateStart(t){if(null!=t.range&&(t.range=[-1/0,1/0]),null!=t.position){let e=t.timestamp,i=C(t,e+this._offset);t.position=i.position,t.velocity=i.velocity,t.acceleration=i.acceleration,t.timestamp=e}return t}get offset(){return this._offset}set offset(t){t!=this._offset&&(this._offset=t,this.__handleEvent({...this.__get_timingsrc().vector,range:this.__get_timingsrc().range}),this.eventifyTrigger("offsetchange",t))}},t.TimingObject=ft,t.TimingProgress=ee,t.TimingSampler=mt,t.endpoint=m,t.eventify=ot,t.motionutils=J,t.utils=_,t.version="v3.0",t}({});
+//# sourceMappingURL=timingsrc-min-v3.js.map
diff --git a/docs/lib/timingsrc-min-v3.js.map b/docs/lib/timingsrc-min-v3.js.map
new file mode 100644
index 0000000..be7b787
--- /dev/null
+++ b/docs/lib/timingsrc-min-v3.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"timingsrc-min-v3.js","sources":["../../v3/util/utils.js","../../v3/util/endpoint.js","../../v3/util/interval.js","../../v3/util/motionutils.js","../../v3/util/binarysearch.js","../../v3/util/eventify.js","../../v3/util/observablemap.js","../../v3/dataset/cuecollection.js","../../v3/util/timeout.js","../../v3/timingobject/masterclock.js","../../v3/timingobject/internalprovider.js","../../v3/timingobject/externalprovider.js","../../v3/timingobject/timingobject.js","../../v3/timingobject/loopconverter.js","../../v3/timingobject/rangeconverter.js","../../v3/timingobject/timingsampler.js","../../v3/timingobject/positioncallback.js","../../v3/dataset/dataset.js","../../v3/sequencing/schedule.js","../../v3/sequencing/basesequencer.js","../../v3/sequencing/pointsequencer.js","../../v3/sequencing/intervalsequencer.js","../../v3/ui/timingprogress.js","../../v3/index.js","../../v3/ui/datasetviewer.js","../../v3/timingobject/delayconverter.js","../../v3/timingobject/scaleconverter.js","../../v3/timingobject/skewconverter.js","../../v3/dataset/subset.js","../../v3/timingobject/timeshiftconverter.js"],"sourcesContent":["/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n\nexport function random_string(length) {\n var text = \"\";\n var possible = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n for(var i = 0; i < length; i++) {\n text += possible.charAt(Math.floor(Math.random() * possible.length));\n }\n return text;\n}\n\n\n/* Set Comparison */\nexport function eqSet(as, bs) {\n return as.size === bs.size && all(isIn(bs), as);\n}\n\nexport function all(pred, as) {\n for (var a of as) if (!pred(a)) return false;\n return true;\n}\n\nexport function isIn(as) {\n return function (a) {\n return as.has(a);\n };\n}\n\nexport function set_difference(as, bs) {\n return new Set([...as].filter((e) => !bs.has(e)));\n}\n\n\n\n\n\n/*\n get the difference of two Maps\n key in a but not in b\n*/\nexport const map_difference = function (a, b) {\n if (a.size == 0) {\n return new Map();\n } else if (b.size == 0) {\n return a;\n } else {\n return new Map([...a].filter(function ([key, value]) {\n return !b.has(key)\n }));\n }\n};\n\n/*\n get the intersection of two Maps\n key in a and b\n*/\nexport const map_intersect = function (a, b) {\n [a, b] = (a.size <= b.size) ? [a,b] : [b,a];\n if (a.size == 0) {\n // No intersect\n return new Map();\n }\n return new Map([...a].filter(function ([key, value]) {\n return b.has(key)\n }));\n};\n\n/*\n\nNOTE : just as good to do \n let merged = new Map(...map0, ...map1, ...)\n\neffective concatenation of multiple arrays\n- order - if true preserves ordering of input arrays\n - else sorts input arrays (longest first)\n - default false is more effective\n- copy - if true leaves input arrays unchanged, copy\n values into new array\n - if false copies remainder arrays into the first\n array\n - default false is more effective\n*/\nexport function map_merge(array_of_maps, options={}) {\n let {copy=false, order=false} = options;\n // check input\n if (array_of_maps instanceof Map) {\n return array_of_maps;\n }\n if (!Array.isArray(array_of_maps)) {\n throw new Error(\"illegal input array_of_maps\", array_of_maps);\n }\n if (array_of_maps.length == 0) {\n throw new Error(\"empty array_of_maps\");\n }\n let is_maps = array_of_maps.map((o) => {\n return (o instanceof Map);\n });\n if (!is_maps.every((e) => e == true)) {\n throw new Error(\"some object in array_of_maps is not a Map\", array_of_maps);\n }\n // order\n if (!order) {\n // sort array_of_maps according to size - longest first\n array_of_maps.sort((a, b) => b.size - a.size);\n }\n // copy\n let first = (copy) ? new Map() : array_of_maps.shift(); \n // fill up first Map with entries from other Maps\n for (let m of array_of_maps) {\n for (let [key, val] of m.entries()) {\n first.set(key, val);\n }\n }\n return first;\n}\n\n\nexport function divmod (n, d) {\n let r = n % d;\n let q = (n-r)/d;\n return [q, r];\n}\n\n\nexport function isIterable(obj) {\n // checks for null and undefined\n if (obj == null) {\n return false;\n }\n return typeof obj[Symbol.iterator] === 'function';\n}\n\n/*\n effective concatenation of multiple arrays\n - order - if true preserves ordering of input arrays\n - else sorts input arrays (longest first)\n - default false is more effective\n - copy - if true leaves input arrays unchanged, copy\n values into new array\n - if false copies remainder arrays into the first\n array\n - default false is more effective\n*/\nexport function array_concat(arrays, options = {}) {\n let {copy=false, order=false} = options;\n if (arrays.length == 0) {\n return [];\n }\n if (arrays.length == 1) {\n return arrays[0];\n }\n let total_len = arrays.reduce((acc, cur) => acc + cur.length, 0);\n // order\n if (!order) {\n // sort arrays according to length - longest first\n arrays.sort((a, b) => b.length - a.length);\n }\n // copy\n let first = (copy) ? [] : arrays.shift();\n let start = first.length;\n // reserve memory total length\n first.length = total_len;\n // fill up first with entries from other arrays\n let end, len;\n for (let arr of arrays) {\n len = arr.length;\n end = start + len;\n for (let i=0; i not equal\n if (aProps.length != bProps.length) {\n return false;\n }\n for (let i=0; i not equal\n if (a[propName] !== b[propName]) {\n return false;\n }\n }\n // equal\n return true;\n}\n\n\n/* document readypromise */\nexport const docready = new Promise(function(resolve) {\n if (document.readyState === 'complete') {\n resolve();\n } else {\n let onReady = function () {\n resolve();\n document.removeEventListener('DOMContentLoaded', onReady, true);\n window.removeEventListener('load', onReady, true);\n };\n document.addEventListener('DOMContentLoaded', onReady, true);\n window.addEventListener('load', onReady, true);\n }\n});\n\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\nconst isNumber = function(n) {\n\tlet N = parseFloat(n);\n return (n===N && !isNaN(N));\n};\n\n\n/*********************************************************\n\nENDPOINT\n\nUtilities for interval endpoints comparison\n\n**********************************************************/\n\n/*\n\tendpoint modes - in endpoint order\n\tendpoint order\n\tp), [p, [p], p], (p\n*/\nconst MODE_RIGHT_OPEN = 0;\nconst MODE_LEFT_CLOSED = 1;\nconst MODE_SINGULAR = 2;\nconst MODE_RIGHT_CLOSED = 3;\nconst MODE_LEFT_OPEN = 4;\n\n// create endpoint\nfunction create(val, right, closed, singular) {\n\t// make sure infinity endpoints are legal\n\tif (val == Infinity) {\n\t\tif (right == false || closed == false) {\n\t\t\tthrow new Error(\"Infinity endpoint must be right-closed or singular\");\n\t\t}\n\t}\n\tif (val == -Infinity) {\n\t\tif (right == true || closed == false) {\n\t\t\tthrow new Error(\"-Infinity endpoint must be left-closed or singular\")\n\t\t}\n\t}\n\treturn [val, right, closed, singular];\n}\n\n\n/*\n\tresolve endpoint mode\n*/\nfunction get_mode(e) {\n\t// if right, closed is given\n\t// use that instead of singular\n\tlet [val, right, closed, singular] = e;\n\tif (singular || right == undefined) {\n\t\treturn MODE_SINGULAR;\n\t} else if (right) {\n\t\tif (closed) {\n\t\t\treturn MODE_RIGHT_CLOSED;\n\t\t} else {\n\t\t\treturn MODE_RIGHT_OPEN;\n\t\t}\n\t} else {\n\t\tif (closed) {\n\t\t\treturn MODE_LEFT_CLOSED;\n\t\t} else {\n\t\t\treturn MODE_LEFT_OPEN;\n\t\t}\n\t}\n}\n\n/*\n\tget order\n\n\tgiven two endpoints\n\treturn two numbers representing their order\n\n\talso accepts regular numbers as endpoints\n\tregular number are represented as singular endpoints\n\n\tfor endpoint values that are not\n\tequal, these values convey order directly,\n\totherwise endpoint mode numbers 0-4 are returned\n\n\tparameters are either\n\t- point: Number\n\tor,\n\t- endpoint: [\n\t\tvalue (number),\n\t\tright (bool),\n\t\tclosed (bool),\n\t\tsingular (bool)\n\t ]\n*/\n\nfunction get_order(e1, e2) {\n\t// support plain numbers (not endpoints)\n\tif (e1.length === undefined) {\n\t\tif (!isNumber(e1)) {\n\t\t\tthrow new Error(\"e1 not a number\", e1);\n\t\t}\n\t\te1 = create(e1, undefined, undefined, true);\n\t}\n\tif (e2.length === undefined) {\n\t\tif (!isNumber(e2)) {\n\t\t\tthrow new Error(\"e2 not a number\", e2);\n\t\t}\n\t\te2 = create(e2, undefined, undefined, true);\n\t}\n\tif (e1[0] != e2[0]) {\n\t\t// different values\n\t\treturn [e1[0], e2[0]];\n\t} else {\n\t\t// equal values\n\t\treturn [get_mode(e1), get_mode(e2)];\n\t}\n}\n\n/*\n\treturn true if e1 is ordered before e2\n\tfalse if equal\n*/\n\nfunction leftof(e1, e2) {\n\tlet [order1, order2] = get_order(e1, e2);\n\treturn (order1 < order2);\n}\n\n/*\n\treturn true if e1 is ordered after e2\n\tfalse is equal\n*/\n\nfunction rightof(e1, e2) {\n\tlet [order1, order2] = get_order(e1, e2);\n\treturn (order1 > order2);\n}\n\n/*\n\treturn true if e1 is ordered equal to e2\n*/\n\nfunction equals(e1, e2) {\n\tlet [order1, order2] = get_order(e1, e2);\n\treturn (order1 == order2);\n}\n\n/*\n\treturn -1 if ordering e1, e2 is correct\n\treturn 0 if e1 and e2 is equal\n\treturn 1 if ordering e1, e2 is incorrect\n*/\n\nfunction cmp(e1, e2) {\n\tlet [order1, order2] = get_order(e1, e2);\n\tlet diff = order1 - order2;\n\tif (diff == 0) return 0;\n\treturn (diff > 0) ? 1 : -1;\n}\n\n\nfunction min(e1, e2) {\n return (cmp(e1, e2) <= 0) ? e1 : e2;\n}\n\n\nfunction max(e1, e2) {\n return (cmp(e1, e2) <= 0) ? e2 : e1;\n}\n\n\n/*\n\thuman friendly endpoint representation\n*/\nfunction toString(e) {\n\tif (e.length === undefined) {\n\t\treturn e.toString();\n\t} else {\n\t\tlet mode = get_mode(e);\n\t\tlet val = e[0];\n\t\tif (val == Infinity || val == -Infinity) {\n\t\t\tval = \"--\";\n\t\t}\n\t\tif (mode == MODE_RIGHT_OPEN) {\n\t\t\treturn `${val})`\n\t\t} else if (mode == MODE_LEFT_CLOSED) {\n\t\t\treturn `[${val}`\n\t\t} else if (mode == MODE_SINGULAR){\n\t\t\treturn `[${val}]`\n\t\t} else if (mode == MODE_RIGHT_CLOSED) {\n\t\t\treturn `${val}]`\n\t\t} else if (mode == MODE_LEFT_OPEN) {\n\t\t\treturn `(${val}`\n\t\t}\n\t}\n}\n\n\nexport default {\n\tcmp,\n\ttoString,\n\tequals,\n\trightof,\n\tleftof,\n\tcreate,\n\tmin,\n\tmax\n};\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\nimport endpoint from './endpoint.js';\n\n\nconst isNumber = function(n) {\n\tlet N = parseFloat(n);\n return (n===N && !isNaN(N));\n};\n\n/*********************************************************\nINTERVAL ERROR\n**********************************************************/\n\nclass IntervalError extends Error {\n\tconstructor(message) {\n\t\tsuper(message);\n\t\tthis.name == \"IntervalError\";\n\t}\n};\n\n\n/*********************************************************\nINTERVAL\n**********************************************************/\n\n// Interval Relations\nconst Relation = Object.freeze({\n\tOUTSIDE_LEFT: 64, \t// 0b1000000\n\tOVERLAP_LEFT: 32, \t// 0b0100000\n\tCOVERED: 16,\t\t// 0b0010000\n\tEQUALS: 8,\t\t\t// 0b0001000\n\tCOVERS: 4,\t\t\t// 0b0000100\n\tOVERLAP_RIGHT: 2,\t// 0b0000010\n\tOUTSIDE_RIGHT: 1\t// 0b0000001\n});\n\n/*\n Masks for Interval matching\n*/\nconst MATCH_OUTSIDE = Relation.OUTSIDE_LEFT + Relation.OUTSIDE_RIGHT;\nconst MATCH_INSIDE = Relation.EQUALS + Relation.COVERED;\nconst MATCH_OVERLAP = MATCH_INSIDE +\n\tRelation.OVERLAP_LEFT + Relation.OVERLAP_RIGHT;\nconst MATCH_COVERS = MATCH_OVERLAP + Relation.COVERS;\nconst MATCH_ALL = MATCH_COVERS + MATCH_OUTSIDE;\n\nconst Match = Object.freeze({\n\tOUTSIDE: MATCH_OUTSIDE,\n\tINSIDE: MATCH_INSIDE,\n\tOVERLAP: MATCH_OVERLAP,\n\tCOVERS: MATCH_COVERS,\n\tALL: MATCH_ALL\n});\n\n\n/*********************************************************\nCOMPARE INTERVALS\n**********************************************************\n\ncompare (a, b)\nparam a Interval\nparam b Interval\nreturns IntervalRelation\n\ncompares interval b to interval a\ne.g. return value COVERED reads b is covered by a.\n\ncmp_1 = endpoint_compare(b_low, a_low);\ncmp_2 = endpoint_compare(b_high, a_high);\n\nkey = 10*cmp_1 + cmp_2\n\ncmp_1 cmp_2 key relation\n===== ===== === ============================\n-1 -1 -11 OUTSIDE_LEFT, PARTIAL_LEFT\n-1 \t 0 -10 COVERS\n-1 1 -9 COVERS\n0\t -1 -1 COVERED\n0 0 0 EQUAL\n0 \t 1 1 COVERS\n1 -1 9 COVERED\n1 \t 0 10 COVERED\n1 \t 1 11 OUTSIDE_RIGHT, OVERLAP_RIGHT\n===== ===== === ============================\n\n**********************************************************/\n\nfunction compare(a, b) {\n\tif (! a instanceof Interval) {\n\t\t// could be a number\n\t\tif (isNumber(a)) {\n\t\t\ta = new Interval(a);\n\t\t} else {\n\t\t\tthrow new IntervalError(\"a not interval\", a);\n\t\t}\n\t}\n\tif (! b instanceof Interval) {\n\t\t// could be a number\n\t\tif (isNumber(b)) {\n\t\t\tb = new Interval(b);\n\t\t} else {\n\t\t\tthrow new IntervalError(\"b not interval\", b);\n\t\t}\n\t}\n\n\tlet cmp_1 = endpoint.cmp(a.endpointLow, b.endpointLow);\n\tlet cmp_2 = endpoint.cmp(a.endpointHigh, b.endpointHigh);\n\tlet key = cmp_1*10 + cmp_2;\n\n\tif (key == 11) {\n\t\t// OUTSIDE_LEFT or PARTIAL_LEFT\n\t\tif (endpoint.leftof(b.endpointHigh, a.endpointLow)) {\n\t\t\treturn Relation.OUTSIDE_RIGHT;\n\t\t} else {\n\t\t\treturn Relation.OVERLAP_RIGHT;\n\t\t}\n\t} else if ([-1, 9, 10].includes(key)) {\n\t\treturn Relation.COVERED;\n\t} else if ([1, -9, -10].includes(key)) {\n\t\treturn Relation.COVERS;\n\t} else if (key == 0) {\n\t\treturn Relation.EQUALS;\n\t} else {\n\t\t// key == -11\n\t\t// OUTSIDE_RIGHT, PARTIAL_RIGHT\n\t\tif (endpoint.rightof(b.endpointLow, a.endpointHigh)) {\n\t\t\treturn Relation.OUTSIDE_LEFT;\n\t\t} else {\n\t\t\treturn Relation.OVERLAP_LEFT;\n\t\t}\n\t}\n}\n\n/*********************************************************\nCOMPARE INTERVALS BY ENDPOINT\n**********************************************************\n\ncmp functions for sorting intervals (ascending) based on\nendpoint low or high\n\nuse with array.sort()\n\n**********************************************************/\n\nfunction _make_interval_cmp(low) {\n\treturn function cmp (a, b) {\n\t\tlet e1, e2;\n\t\tif (low) {\n\t\t\te1 = [a.low, false, a.lowInclude, a.singular];\n\t\t\te2 = [b.low, false, b.lowInclude, a.singular];\n\t\t} else {\n\t\t\te1 = [a.high, true, a.highInclude, a.singular];\n\t\t\te2 = [b.high, true, b.highInclude, a.singular];\n\t\t}\n\t\treturn endpoint.cmp(e1, e2);\n\t}\n}\n\n\n\n/**\n * Create interval from two endpoints\n */\n\nfunction fromEndpoints(endpointLow, endpointHigh) {\n\tlet [low, low_right, low_closed, low_singular] = endpointLow;\n\tlet [high, high_right, high_closed, high_singular] = endpointHigh;\n\tif (low_right) {\n\t\tthrow new IntervalError(\"illegal endpointLow - bracket must be left\");\n\t}\n\tif (!high_right) {\n\t\tthrow new IntervalError(\"illegal endpointHigh - bracket must be right\");\n\t}\n\treturn new Interval(low, high, low_closed, high_closed);\n};\n\n\n// intersect two intervals\nfunction intersect(a, b) {\n\tlet rel = compare(a, b);\n\tif (rel == Relation.OUTSIDE_LEFT) {\n\t\treturn [];\n\t} else if (rel == Relation.OVERLAP_LEFT) {\n\t\treturn [Interval.fromEndpoints(b.endpointLow, a.endpointHigh)];\n\t} else if (rel == Relation.COVERS) {\n\t\treturn [b];\n\t} else if (rel == Relation.EQUALS) {\n\t\treturn [a]; // or b\n\t} else if (rel == Relation.COVERED) {\n\t\treturn [a];\n\t} else if (rel == Relation.OVERLAP_RIGHT) {\n\t\treturn [Interval.fromEndpoints(a.endpointLow, b.endpointHigh)];\n\t} else if (rel == Relation.OUTSIDE_RIGHT) {\n\t\treturn [];\n\t}\n}\n\n// union of two intervals\nfunction union(a, b) {\n\tlet rel = compare(a, b);\n\tif (rel == Relation.OUTSIDE_LEFT) {\n\t\t// merge\n\t\t// [aLow,aHigh)[bLow, bHigh] or [aLow,aHigh](bLow, bHigh]\n\t\tif (a.high != b.low || (!a.highInclude && !b.lowInclude)) {\n\t\t\t// no merge\n\t\t\treturn [a, b];\n\t\t} else {\n\t\t\t// merge\n\t\t\treturn [Interval.fromEndpoints(a.endpointLow, b.endpointHigh)]; \n\t\t}\n\t} else if (rel == Relation.OVERLAP_LEFT) {\n\t\treturn [Interval.fromEndpoints(a.endpointLow, b.endpointHigh)];\n\t} else if (rel == Relation.COVERS) {\n\t\treturn [a];\n\t} else if (rel == Relation.EQUALS) {\n\t\treturn [a]; // or b\n\t} else if (rel == Relation.COVERED) {\n\t\treturn [b];\n\t} else if (rel == Relation.OVERLAP_RIGHT) {\n\t\treturn [Interval.fromEndpoints(b.endpointLow, a.endpointHigh)];\n\t} else if (rel == Relation.OUTSIDE_RIGHT) {\n\t\t// merge\n\t\t// [bLow,bHigh)[aLow, aHigh] or [bLow,bHigh](aLow, aHigh]\n\t\tif (b.high != a.low || (!b.highInclude && !a.lowInclude)) {\n\t\t\t// no merge\n\t\t\treturn [b, a];\n\t\t} else {\n\t\t\t// merge\n\t\t\treturn [Interval.fromEndpoints(b.endpointLow, a.endpointHigh)];\n\t\t}\n\t}\n}\n\n// intersection of multiple intervals\nfunction intersectAll(intervals) {\n\tintervals.sort(Interval.cmpLow);\n\tif (intervals.length <= 1) {\n\t\treturn intervals;\n\t}\n\tconst result = [intervals.shift()];\n\twhile (intervals.length > 0) {\n\t\tlet prev = result.pop();\n\t\tlet next = intervals.shift()\n\t\tresult.push(...Interval.intersect(prev, next));\n\t}\n\treturn result;\n}\n\n// union of multiple interval\nfunction unionAll(intervals) {\n\tintervals.sort(Interval.cmpLow);\n\tif (intervals.length <= 1) {\n\t\treturn intervals;\n\t}\n\tconst result = [intervals.shift()];\n\twhile (intervals.length > 0) {\n\t\tlet prev = result.pop();\n\t\tlet next = intervals.shift()\n\t\tresult.push(...Interval.union(prev, next));\n\t}\n\treturn result;\n}\n\n\n/*********************************************************\nINTERVAL CLASS\n**********************************************************/\n\nclass Interval {\n\n\n\t// private variables\n\n\t/*\n\t\tConstructor\n\t*/\n\tconstructor (low, high, lowInclude, highInclude) {\n\t\tvar lowIsNumber = isNumber(low);\n\t\t// new Interval(3.0) defines singular - low === high\n\t\tif (lowIsNumber && high === undefined) high = low;\n\t\tif (!isNumber(low)) throw new IntervalError(`low not a number, ${low}`);\n\t\tif (!isNumber(high)) throw new IntervalError(`high not a number, ${high}`);\n\t\tif (low > high) throw new IntervalError(`low > high, ${low}, ${high}`);\n\t\tif (low === high) {\n\t\t\tlowInclude = true;\n\t\t\thighInclude = true;\n\t\t}\n\t\tif (low === -Infinity) lowInclude = true;\n\t\tif (high === Infinity) highInclude = true;\n\t\tif (lowInclude === undefined) lowInclude = true;\n\t\tif (highInclude === undefined) highInclude = false;\n\t\tif (typeof lowInclude !== \"boolean\") {\n\t\t\tthrow new IntervalError(`lowInclude not boolean, ${lowInclude}`);\n\t\t}\n\t\tif (typeof highInclude !== \"boolean\") {\n\t\t\tthrow new IntervalError(`highInclude not boolean, ${highInclude}`);\n\t\t}\n\t\tthis._low = low;\n\t\tthis._high = high;\n\t\tthis._lowInclude = lowInclude;\n\t\tthis._highInclude = highInclude;\n\t\tthis._length = this._high - this._low;\n\t\tthis._singular = (this._low === this._high);\n\t\tthis._finite = (isFinite(this._low) && isFinite(this._high));\n\n\t\t/*\n\t\t\tAccessors for full endpoint representationo\n\t\t\t[value (number), right (bool), closed (bool)]\n\n\t\t\t- use with inside(endpoint, interval)\n\t\t*/\n\t\tthis._endpointLow = endpoint.create(this._low, false, this._lowInclude, this._singular);\n\t\tthis._endpointHigh = endpoint.create(this._high, true, this._highInclude, this._singular);\n\t}\n\n\t// accessors\n\tget low () {return this._low;}\n\tget high () {return this._high;}\n\tget lowInclude () {return this._lowInclude;}\n\tget highInclude () {return this._highInclude;}\n\tget length () {return this._length;}\n\tget singular () {return this._singular;}\n\tget finite () {return this._finite;}\n\tget endpointLow () {return this._endpointLow;}\n\tget endpointHigh () {return this._endpointHigh;}\n\t\n\t/**\n\t * Instance methods\n\t */\n\n\ttoString () {\n\t\tconst toString = endpoint.toString;\n\t\tif (this._singular) {\n\t\t\tlet p = this._endpointLow[0];\n\t\t\treturn `[${p}]`;\n\t\t} else {\n\t\t\tlet low = endpoint.toString(this._endpointLow);\n\t\t\tlet high = endpoint.toString(this._endpointHigh);\n\t\t\treturn `${low},${high}`;\n\t\t}\n\t};\n\n\n\tasArray() {\n\t\treturn [this._low, this._high, this._lowInclude, this._highInclude];\n\t}\n\n\tcovers_endpoint (p) {\n\t\tlet leftof = endpoint.leftof(p, this._endpointLow);\n\t\tlet rightof = endpoint.rightof(p, this._endpointHigh);\n\t\treturn !leftof && !rightof;\n\t}\n\n\tcompare (other) {\n\t\treturn compare(this, other);\n\t}\n\n\tequals (other) {\n\t\treturn compare(this, other) == Relation.EQUALS;\n\t}\n\n\t/*\n\t\tdefault mode - all except outside\n\t\t2+4+8+16+32 = 62\n\t*/\n\tmatch (other, mask=MATCH_COVERS) {\n\t\tlet relation = compare(this, other);\n\t\treturn Boolean(mask & relation);\n\t}\n}\n\n/*\n\tAdd static properties to Interval class.\n*/\n\nInterval.Relation = Relation;\nInterval.Match = Match;\nInterval.cmpLow = _make_interval_cmp(true);\nInterval.cmpHigh = _make_interval_cmp(false);\nInterval.fromEndpoints = fromEndpoints;\nInterval.intersect = intersect;\nInterval.union = union;\nInterval.intersectAll = intersectAll;\nInterval.unionAll = unionAll;\n\n\nexport default Interval;\n\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport endpoint from './endpoint.js';\nimport Interval from './interval.js';\n\n// Closure\n(function() {\n /**\n * Decimal adjustment of a number.\n *\n * @param {String} type The type of adjustment.\n * @param {Number} value The number.\n * @param {Integer} exp The exponent (the 10 logarithm of the adjustment base).\n * @returns {Number} The adjusted value.\n */\n function decimalAdjust(type, value, exp) {\n // If the exp is undefined or zero...\n if (typeof exp === 'undefined' || +exp === 0) {\n return Math[type](value);\n }\n value = +value;\n exp = +exp;\n // If the value is not a number or the exp is not an integer...\n if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {\n return NaN;\n }\n // Shift\n value = value.toString().split('e');\n value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));\n // Shift back\n value = value.toString().split('e');\n return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));\n }\n\n // Decimal round\n if (!Math.round10) {\n Math.round10 = function(value, exp) {\n return decimalAdjust('round', value, exp);\n };\n }\n // Decimal floor\n if (!Math.floor10) {\n Math.floor10 = function(value, exp) {\n return decimalAdjust('floor', value, exp);\n };\n }\n // Decimal ceil\n if (!Math.ceil10) {\n Math.ceil10 = function(value, exp) {\n return decimalAdjust('ceil', value, exp);\n };\n }\n})();\n\n\n// sort func\nconst cmp = function (a, b) {return a - b;};\n\n/*******************************************************************\n BASIC\n*******************************************************************/\n\nexport function equalVectors(vector_a, vector_b) {\n let pos = vector_a.position == vector_b.position;\n let vel = vector_a.velocity == vector_b.velocity;\n let acc = vector_a.acceleration == vector_b.acceleration;\n let ts = vector_a.timestamp == vector_b.timestamp;\n return pos && vel && acc && ts;\n};\n\n\nexport function copyVector(vector) {\n return {\n position: vector.position,\n velocity: vector.velocity,\n acceleration: vector.acceleration,\n timestamp: vector.timestamp\n }\n};\n\n/*\n Calculate vector snapshot for motion defined by vector at time ts\n\n vector: [p0,v0,a0,t0]\n t0 and ts are absolute time from same clock, in seconds\n*/\n\nexport function calculateVector(vector, ts) {\n\tif (ts === undefined) {\n\t throw new Error (\"no ts provided for calculateVector\");\n\t}\n\tconst deltaSec = ts - vector.timestamp;\n\treturn {\n\t\tposition : vector.position + vector.velocity*deltaSec + 0.5*vector.acceleration*deltaSec*deltaSec,\n\t\tvelocity : vector.velocity + vector.acceleration*deltaSec,\n\t\tacceleration : vector.acceleration,\n\t\ttimestamp : ts\n\t};\n};\n\n\n/*\n Calculate direction of motion at time ts\n 1 : forwards, -1 : backwards: 0, no movement\n*/\nexport function calculateDirection(vector, ts) {\n /*\n Given initial vector calculate direction of motion at time t\n (Result is valid only if (t > vector[T]))\n Return Forwards:1, Backwards -1 or No-direction (i.e. no-motion) 0.\n If t is undefined - t is assumed to be now.\n */\n let freshVector;\n if (ts == undefined) {\n freshVector = vector;\n } else {\n freshVector = calculateVector(vector, ts);\n }\n // check velocity\n let direction = cmp(freshVector.velocity, 0.0);\n if (direction === 0) {\n // check acceleration\n direction = cmp(vector.acceleration, 0.0);\n }\n return direction;\n};\n\n\n/*\n isMoving\n\n returns true if motion is moving else false\n*/\nexport function isMoving(vector) {\n return (vector.velocity !== 0.0 || vector.acceleration !== 0.0);\n};\n\n\n/*******************************************************************\n RANGE\n*******************************************************************/\n\n//\tRANGE STATE is used for managing/detecting range violations.\nexport const RangeState = Object.freeze({\n INIT : \"init\",\n INSIDE: \"inside\",\n OUTSIDE_LOW: \"outsidelow\",\n OUTSIDE_HIGH: \"outsidehigh\"\n});\n\n/*\n\tA snapshot vector is checked with respect to range,\n\tcalclulates correct RangeState (i.e. INSIDE|OUTSIDE)\n*/\nexport function correctRangeState(vector, range) {\n const {position: p, velocity: v, acceleration: a} = vector;\n\tif (p > range[1]) return RangeState.OUTSIDE_HIGH;\n\tif (p < range[0]) return RangeState.OUTSIDE_LOW;\n\t// corner cases\n\tif (p === range[1]) {\n\t\tif (v > 0.0) return RangeState.OUTSIDE_HIGH;\n\t\tif (v === 0.0 && a > 0.0) return RangeState.OUTSIDE_HIGH;\n\t} else if (p === range[0]) {\n\t if (v < 0.0) return RangeState.OUTSIDE_LOW;\n\t if (v == 0.0 && a < 0.0) return RangeState.OUTSIDE_HIGH;\n\t}\n\treturn RangeState.INSIDE;\n};\n\n\n/* \n detect range violation\n vector assumed to be valid now\n*/\nexport function detectRangeViolation(now_vector, range) {\n return (correctRangeState(now_vector, range) != RangeState.INSIDE);\n}\n\n\n/*\n\tA snapshot vector is checked with respect to range.\n\tReturns vector corrected for range violations, or input vector unchanged.\n\n vector assumed to be valid now\n*/\nexport function checkRange(vector, range) {\n\tconst state = correctRangeState(vector, range);\n\tif (state !== RangeState.INSIDE) {\n\t\t// protect from range violation\n\t\tvector.velocity = 0.0;\n\t\tvector.acceleration = 0.0;\n\t\tif (state === RangeState.OUTSIDE_HIGH) {\n\t\t\tvector.position = range[1];\n\t\t} else vector.position = range[0];\n\t}\n\treturn vector;\n};\n\n\n/*\n Return tsEndpoint of (first) range intersect if any.\n*/\nexport function rangeIntersect(vector, range) {\n let t0 = vector.timestamp;\n // Time delta to hit rangeLeft\n let deltaLeft = calculateMinPositiveRealSolution(vector, range[0]);\n // Time delta to hit rangeRight\n let deltaRight = calculateMinPositiveRealSolution(vector, range[1]);\n // Pick the appropriate solution\n if (deltaLeft !== undefined && deltaRight !== undefined) {\n if (deltaLeft < deltaRight) {\n return [t0 + deltaLeft, range[0]];\n }\n else\n return [t0 + deltaRight, range[1]];\n }\n else if (deltaLeft !== undefined)\n return [t0 + deltaLeft, range[0]];\n else if (deltaRight !== undefined)\n return [t0 + deltaRight, range[1]];\n else return [undefined, undefined];\n}\n\n\n/*******************************************************************\n EQUATIONS\n*******************************************************************/\n\n/*\n hasRealSolution\n\n Given motion determined from p,v,a,t.\n Determine if equation p(t) = p + vt + 0.5at^2 = x\n has solutions for some real number t.\n*/\n\nfunction hasRealSolution (p,v,a,x) {\n\tif ((Math.pow(v,2) - 2*a*(p-x)) >= 0.0) return true;\n\telse return false;\n};\n\n\n/*\n calculateRealSolution\n\n Given motion determined from p,v,a,t.\n Determine if equation p(t) = p + vt + 0.5at^2 = x\n has solutions for some real number t.\n Calculate and return real solutions, in ascending order.\n*/\n\nfunction calculateRealSolutions(p,v,a,x) {\n\t// Constant Position\n\tif (a === 0.0 && v === 0.0) {\n\t if (p != x) return [];\n\t else return [0.0];\n\t}\n\t// Constant non-zero Velocity\n\tif (a === 0.0) return [(x-p)/v];\n\t// Constant Acceleration\n\tif (hasRealSolution(p,v,a,x) === false) return [];\n\t// Exactly one solution\n\tconst discriminant = v*v - 2*a*(p-x);\n\tif (discriminant === 0.0) {\n\t return [-v/a];\n\t}\n\tconst sqrt = Math.sqrt(Math.pow(v,2) - 2*a*(p-x));\n\tconst d1 = (-v + sqrt)/a;\n\tconst d2 = (-v - sqrt)/a;\n\treturn [Math.min(d1,d2),Math.max(d1,d2)];\n};\n\n\n/*\n calculatePositiveRealSolutions\n\n Given motion determined from p,v,a,t.\n Determine if equation p(t) = p + vt + 0.5at^2 = x\n has solutions for some real number t.\n Calculate and return positive real solutions, in ascending order.\n*/\n\nfunction calculatePositiveRealSolutions(p,v,a,x) {\n\tconst res = calculateRealSolutions(p,v,a,x);\n\tif (res.length === 0) return [];\n\telse if (res.length == 1) {\n\t if (res[0] > 0.0) {\n\t\t\treturn [res[0]];\n\t }\n\t else return [];\n\t}\n\telse if (res.length == 2) {\n\t if (res[1] < 0.0) return [];\n\t if (res[0] > 0.0) return [res[0], res[1]];\n\t if (res[1] > 0.0) return [res[1]];\n\t return [];\n\t}\n\telse return [];\n};\n\n\n/*\n calculateMinPositiveRealSolution\n\n Given motion determined from p,v,a,t.\n Determine if equation p(t) = p + vt + 0.5at^2 = x\n has solutions for some real number t.\n Calculate and return the least positive real solution.\n*/\nexport function calculateMinPositiveRealSolution(vector, x) {\n const {position: p, velocity: v, acceleration: a} = vector;\n\tconst res = calculatePositiveRealSolutions(p,v,a,x);\n\tif (res.length === 0) {\n return;\n }\n\telse return res[0];\n};\n\n\n/*\n calculateDelta\n\n\n Given motion determined from p0,v0,a0 (initial conditions or snapshot),\n Supply two posisions, posBefore < p0 < posAfter.\n Calculate which of these positions will be reached first,\n if any, by the movement described by the vector.\n In addition, calculate when this position will be reached.\n Result will be expressed as time delta relative to t0, if solution exists,\n and a flag to indicate Before (false) or After (true)\n Note: t1 == (delta + t0) is only guaranteed to be in the\n future as long as the function\n is evaluated at time t0 or immediately after.\n*/\nexport function calculateDelta(vector, range) {\n\t// Time delta to hit posBefore\n\tlet deltaBeforeSec = calculateMinPositiveRealSolution(vector, range[0]);\n\t// Time delta to hit posAfter\n\tlet deltaAfterSec = calculateMinPositiveRealSolution(vector, range[1]);\n // Infinity is no good solution\n if (deltaBeforeSec == Infinity) {\n deltaBeforeSec = undefined;\n }\n if (deltaAfterSec == Infinity) {\n deltaAfterSec = undefined;\n }\n // Pick the appropriate solution\n\tif (deltaBeforeSec !== undefined && deltaAfterSec !== undefined) {\n\t if (deltaBeforeSec < deltaAfterSec)\n\t\t\treturn [deltaBeforeSec, range[0]];\n\t else\n\t\t\treturn [deltaAfterSec, range[1]];\n\t}\n\telse if (deltaBeforeSec !== undefined)\n\t return [deltaBeforeSec, range[0]];\n\telse if (deltaAfterSec !== undefined)\n\t return [deltaAfterSec, range[1]];\n\telse return [undefined, undefined];\n};\n\n\n/*******************************************************************\n TIME_INTERVAL POS_INTERVAL\n*******************************************************************/\n\n/*\n posInterval_from_timeInterval\n\n given\n - a time interval\n - a vector describing motion within the time interval\n\n figure out an interval (of positions)\n which covers all possible positions during the time interval\n\n the interval may be a little bigger, so we will round down and up\n to the nearest integer. Also, the interval will always be closed.\n\n*/\n\nexport function posInterval_from_timeInterval (timeInterval, vector) {\n\n /*\n no motion or singular time interval\n */\n if (!isMoving(vector) || timeInterval.singular) {\n return new Interval(vector.position);\n }\n\n let t0 = timeInterval.low;\n let t1 = timeInterval.high;\n let t0_closed = timeInterval.lowInclude;\n let t1_closed = timeInterval.highInclude;\n\n let vector0 = calculateVector(vector, t0);\n let p0 = vector0.position;\n let v0 = vector0.velocity;\n let a0 = vector0.acceleration;\n let p1 = calculateVector(vector, t1).position;\n\n let low, high;\n\n if (a0 != 0) {\n\n /*\n motion, with acceleration\n\n position over time is a parabola\n figure out if extrema happens to occor within\n timeInterval. If it does, extreme point is endpoint in\n position Interval. p0 or p1 will be the other\n interval endpoint.\n\n I extreme point is not occuring within timeInterval,\n interval endpoint will be p0 and p1.\n\n general parabola\n y = Ax*x + Bx + C\n extrema (x,y) : x = - B/2A, y = -B*B/4A + C\n\n where t0 <= t <= t1\n p(t) = 0.5*a0*(t-t0)*(t-t0) + v0*(t-t0) + p0,\n\n A = a0/2, B = v0, C = p0\n\n extrema (t_extrema, p_extrema):\n t_extrem = -v0/a0 + t0\n p_extrem = -v0*v0/(2*a0) + p0\n\n */\n let t_extrem = -v0/a0 + t0;\n if (timeInterval.covers_endpoint(t_extrem)) {\n let p_extrem = -v0*v0/(2.0*a0) + p0;\n // maximal point reached in time interval\n if (a0 > 0.0) {\n // p_extrem is minimum\n // figure out if p0 or p1 is maximum\n if (p0 < p1) {\n low = p_extrem;\n high = p1;\n } else {\n low = p_extrem;\n high = p0;\n }\n } else {\n // p_extrem is maximum\n // figure out if p0 or p1 is minimum\n if (p0 < p1) {\n low = p0;\n high = p_extrem;\n } else {\n low = p1;\n high = p_extrem;\n }\n }\n } else {\n // see below\n }\n }\n\n /*\n Motion, with or without acceleration,\n yet with no extreme points within interval\n\n positition monotonic increasing (forward velocity)\n or decreasing (backward velocity)\n\n extrem positions are associated with p0 and p1.\n */\n if (p0 < p1) {\n // forward\n low = p0;\n high = p1;\n } else {\n // backward\n low = p1;\n high = p0;\n }\n\n /*\n round down and up - to the nearest decimal\n\n Math.floor10(4.999999, -1) -> 4.9\n Math.floor10(5, -1) -> 5\n Math.floor10(5.000001, -1) -> 5\n\n Math.ceil10(4.999999, -1) -> 5\n Math.ceil10(5, -1) -> 5\n Math.ceil10(5.000001, -1) -> 5.1\n */\n low = Math.floor10(low, -1);\n high = Math.ceil10(high, -1);\n return new Interval(low, high, true, true);\n}\n\n\n/*\n time endpoint and pos endpoints.\n\n time is always increasing even when position\n is decreasing. When making a timeEndpoint from\n a posEndpoin the right/left aspect of the endpoint\n needs to be flipped.\n\n ts - the value of the timeEndpoint, ie. the time when\n motion will pass over posEndpoing\n direction - direction of motion at time ts\n*/\n\nexport function timeEndpoint_from_posEndpoint(posEndpoint, ts, direction) {\n let [pos, right, close, singular] = posEndpoint;\n // flip right/left if direction is backwards\n if (direction < 0 && right !== undefined) {\n right = !right\n }\n return [ts, right, close, singular];\n}\n\n\n/*******************************************************************\n ENDPOINT EVENTS\n*******************************************************************/\n\n/*\n endpointEvents\n\n Given a motion and a set of endpoints, calculate when\n the motion will pass by each endpoint.\n\n Given\n - timeInterval\n - posInterval\n - vector describing motion within timeInterval\n - list of endpointItems\n\n endpointItem\n {\n endpoint: [value, high, closed, singular],\n cue: {\n key: \"mykey\",\n interval: new Interval(...),\n data: {...}\n }\n }\n\n Creates eventItem by adding to endpointItem\n - tsEndpoint : timestamp endpoint (future) when motion will pass the endpoint\n - direction: true if motion passes endpoint while moving forward\n\n EventItems will be sorted by ts\n\n Issue:\n\n timeInterval [t0, t1)\n posinterval [p0, p1)\n\n Consider event at time t1 concerning endpoint p1)\n This will be outside the timeInterval, but inside\n the posInterval.\n\n Conversely, it will be inside the next timeInterval,\n but not the next posInterval.\n\n This is a problem - like falling between chairs.\n\n Resolve this by representing timestamps as endpoints too\n\n*/\n\nexport function endpointEvents (timeInterval, posInterval, vector, endpointItems) {\n\n /*\n no motion or singular time interval\n */\n if (timeInterval.singular) {\n throw new Error(\"endpointEvents: timeInterval is singular\");\n }\n if (!isMoving(vector)) {\n throw new Error(\"endpointEvents: no motion\")\n }\n\n let p0 = vector.position;\n let v0 = vector.velocity;\n let a0 = vector.acceleration;\n let t0 = vector.timestamp;\n\n let value, ts, deltas;\n let tsEndpoint, direction;\n let eventItems = [];\n\n endpointItems.forEach(function(item) {\n // check that endpoint is inside given posInterval\n if (!posInterval.covers_endpoint(item.endpoint)) {\n console.log(\"fuck 1\");\n return;\n }\n value = item.endpoint[0];\n // check if equation has any solutions\n if (!hasRealSolution(p0, v0, a0, value)) {\n console.log(\"fuck 2\");\n return;\n }\n // find time when motion will pass value\n // time delta is relative to t0\n // could be both in history or future\n deltas = calculateRealSolutions(p0,v0,a0, value);\n // include any timestamp within the timeinterval\n deltas.forEach(function(delta) {\n ts = t0 + delta;\n direction = calculateDirection(vector, ts);\n tsEndpoint = timeEndpoint_from_posEndpoint(item.endpoint, ts, direction);\n if (timeInterval.covers_endpoint(tsEndpoint)){\n item.tsEndpoint = tsEndpoint;\n item.direction = direction;\n eventItems.push(item);\n }\n });\n });\n\n // sort eventItems according to tsEndpoints\n const cmp = function (a,b) {\n return endpoint.cmp(a.tsEndpoint, b.tsEndpoint);\n };\n eventItems.sort(cmp);\n\n /*\n if (eventItems.length != endpointItems.length) {\n console.log(\"BADNESS\");\n console.log(\"timeInterval\", timeInterval);\n console.log(\"posInterval\", posInterval);\n console.log(\"vector\", vector);\n console.log(\"endpointItems\", JSON.stringify(endpointItems));\n }\n */\n\n return eventItems;\n};\n\n\n/*******************************************************************\n MOTION TRANSITION\n*******************************************************************/\n\n/*\n Figure the nature of the transition from one motion to another,\n i.e. when old_vector is replaced by new_vector.\n\n The time when this transition occured is given bey\n new_vector.timestamp, by definition.\n\n - was moving (boolean) - true if moving before change\n - is moving (boolean) - true if moving after change\n - pos changed (boolean) - true if position was changed instantaneously\n - move changed (boolean) - true if movement was changed instantaneously\n\n report changed in two independent aspects\n - change in position (i.e. discontinuity in position)\n - change in movement (i.e. starting, stopping, changed)\n\n These are represented as\n - PosDelta\n - MoveDelta\n\n return [PosDelta, MoveDelta]\n*/\n\n\n/* Static properties */\n\nconst PosDelta = Object.freeze({\n NOOP: 0, // no change in position\n CHANGE: 1 // change in position\n});\n\n\nconst MoveDelta = Object.freeze({\n NOOP: 0, // no change in movement, not moving\n NOOP_MOVING: 1, // no change in movement, moving\n START: 2, // not moving -> moving\n CHANGE: 3, // keep moving, movement changed\n STOP: 4 // moving -> not moving\n});\n\n\nexport class MotionDelta {\n\n constructor (old_vector, new_vector) {\n let ts = new_vector.timestamp;\n let is_moving = isMoving(new_vector)\n let init = (old_vector == undefined || old_vector.position == undefined);\n\n if (init) {\n /*\n Possible to introduce\n PosDelta.INIT here instead of PosDelta.CHANGE\n Not sure if this is needed.\n */\n if (is_moving) {\n this._mc = [PosDelta.CHANGE, MoveDelta.START];\n } else {\n this._mc = [PosDelta.CHANGE, MoveDelta.NOOP];\n }\n } else {\n let was_moving = isMoving(old_vector);\n let end_vector = calculateVector(old_vector, ts);\n let start_vector = calculateVector(new_vector, ts);\n\n // position change\n let pos_changed = (end_vector.position != start_vector.position);\n let pct = (pos_changed) ? PosDelta.CHANGE : PosDelta.NOOP;\n\n // movement change\n let mct;\n if (was_moving && is_moving) {\n let vel_changed = (end_vector.velocity != start_vector.velocity);\n let acc_changed = (end_vector.acceleration != start_vector.acceleration);\n let move_changed = (vel_changed || acc_changed);\n if (move_changed) {\n mct = MoveDelta.CHANGE;\n } else {\n mct = MoveDelta.NOOP_MOVING;\n }\n } else if (!was_moving && is_moving) {\n mct = MoveDelta.START;\n } else if (was_moving && !is_moving) {\n mct = MoveDelta.STOP;\n } else if (!was_moving && !is_moving) {\n mct = MoveDelta.NOOP;\n }\n this._mc = [pct, mct];\n }\n }\n\n get posDelta () {\n return this._mc[0];\n }\n\n get moveDelta () {\n return this._mc[1]\n }\n\n toString() {\n const PosDelta = MotionDelta.PosDelta;\n const MoveDelta = MotionDelta.MoveDelta;\n let str = (this.posDelta == PosDelta.CHANGE) ? \"jump, \" : \"\";\n if (this.moveDelta == MoveDelta.START) {\n str += \"movement started\";\n } else if (this.moveDelta == MoveDelta.CHANGE) {\n str += \"movement changed\";\n } else if (this.moveDelta == MoveDelta.STOP) {\n str += \"movement stopped\";\n } else if (this.moveDelta == MoveDelta.NOOP_MOVING) {\n str += \"movement noop - moving\";\n } else if (this.moveDelta == MoveDelta.NOOP) {\n str += \"movement noop - not moving\";\n }\n return str;\n }\n}\n\n\nMotionDelta.PosDelta = PosDelta;\nMotionDelta.MoveDelta = MoveDelta;\n\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport Interval from './interval.js';\n\n// check if n is a number\nfunction is_number(n) {\n\tvar N = parseFloat(n);\n return (n==N && !isNaN(N));\n};\n\n\n/*\n utility function for protecting against duplicates\n*/\nfunction unique(A) {\n return [...new Set(A)];\n};\n\n\n\n/*\n batch inserts and removes have two strategies\n 1) change-sort\n 2) splice\n\n simple rule by measurement\n splice is better for batchlength <= 100 for both insert and remove\n*/\nfunction resolve_approach(arrayLength, batchLength) {\n if (arrayLength == 0) {\n return \"sort\";\n }\n return (batchLength <= 100) ? \"splice\" : \"sort\";\n};\n\n\nclass BinarySearchError extends Error {\n\n constructor(message) {\n super(message);\n this.name = \"BinarySearchError\";\n }\n\n}\n\n\n/*\n\nBINARY SEARCH\n\n- based on sorted list of unique elements\n- implements protection against duplicates\n\n\nPublic API\n- update (remove_elements, insert_elements)\n- lookup (interval) - returns list for all elements\n- remove (interval) - removes elements within interval\n- has (element) - returns true if element exists with value == element, else false\n- get (element) - returns element with value if exists, else undefined\n- values () - returns iterable for all elements\n- indexOf(element) - returns index of element\n- indexOfElements(elements)\n- getByIndex(index) - returns element at given index\n\n\n*/\n\nfunction cmp(a, b) {return a-b;};\n\n\nclass BinarySearch {\n\n constructor(options) {\n this.array = [];\n this.options = options || {};\n }\n\n\n /**\n * Binary search on sorted array\n * @param {*} searchElement The item to search for within the array.\n * @return {Number} The index of the element which defaults to -1 when not found.\n */\n binaryIndexOf(searchElement) {\n let minIndex = 0;\n let maxIndex = this.array.length - 1;\n let currentIndex;\n let currentElement;\n while (minIndex <= maxIndex) {\n \t\tcurrentIndex = (minIndex + maxIndex) / 2 | 0;\n \t\tcurrentElement = this.array[currentIndex];\n if (currentElement < searchElement) {\n minIndex = currentIndex + 1;\n } else if (currentElement > searchElement) {\n maxIndex = currentIndex - 1;\n } else {\n // found\n \t\t return currentIndex;\n \t\t}\n }\n // not found - indicate at what index the element should be inserted\n \treturn ~maxIndex;\n\n // NOTE : ambiguity\n\n /*\n search for an element that is less than array[0]\n should return a negative value indicating that the element\n was not found. Furthermore, as it escapes the while loop\n the returned value should indicate the index that this element\n would have had - had it been there - as is the idea of this bitwise\n operator trick\n\n so, it follows that search for value of minimum element returns 0 if it exists, and 0 if it does not exists\n this ambiguity is compensated for in relevant methods\n */\n };\n\n\n /*\n utility function for resolving ambiguity\n */\n isFound(index, x) {\n if (index > 0) {\n return true;\n }\n if (index == 0 && this.array.length > 0 && this.array[0] == x) {\n return true;\n }\n return false;\n };\n\n /*\n returns index of value or -1\n */\n indexOf(x) {\n var index = this.binaryIndexOf(x);\n return (this.isFound(index, x)) ? index : -1;\n };\n\n indexOfElements(elements) {\n let x, index;\n let indexes = [];\n for (let i=0; i -1) {\n indexes.push(index);\n }\n }\n return indexes;\n };\n\n /*\n element exists with value\n */\n has(x) {\n return (this.indexOf(x) > -1) ? true : false;\n };\n\n get(index) {\n return this.array[index];\n };\n\n\n\n /*\n REMOVE\n Removes all elements with given values\n search for each one and splice remove them individually\n (reverse order)\n\n INSERT\n binarysearch and splice\n insert - binarysearch and splice\n\n WARNING - there should be no need to insert elements that are already\n present in the array. This function drops such duplicates\n */\n _update_splice(to_remove, to_insert, options) {\n\n // REMOVE\n if (this.array.length > 0) {\n let indexes = this.indexOfElements(to_remove);\n /*\n sort indexes to make sure we are removing elements\n in backwards order\n optimization\n - if elements were sorted in the first place this should not be necessary\n */\n indexes.sort(function(a,b){return a-b;});\n for (let i=indexes.length-1; i > -1; i--) {\n this.array.splice(indexes[i], 1);\n }\n }\n\n // INSERT\n let x, index;\n let len = to_insert.length;\n for (let i=0; i 0 && to_remove.length > 0) {\n // visit all elements and set their value to undefined\n // undefined values will be sorted to the end of the array\n let indexes = this.indexOfElements(to_remove);\n for (let i=0; i 0) {\n let index = this.array.indexOf(undefined);\n if (index > -1) {\n this.array.splice(index, this.array.length-index);\n }\n }\n // remove duplicates\n this.array = unique(this.array);\n };\n\n\n /*\n Update - removing and inserting elements in one operation\n\n a single element should only be present once in the list, thus avoiding\n multiple operations to one element. This is presumed solved externally.\n - also objects must not be members of both lists.\n\n - internally selects the best method - searchsplice or concatsort\n - selection based on relative sizes of existing elements and new elements\n\n */\n update(to_remove, to_insert, options) {\n let size = to_remove.length + to_insert.length;\n if (size == 0) {\n return;\n }\n\n // regular case\n let approach = resolve_approach(this.array.length, size);\n if (approach == \"splice\") {\n this._update_splice(to_remove, to_insert, options);\n } else if (approach == \"sort\"){\n this._update_sort(to_remove, to_insert, options);\n }\n };\n\n\n /*\n Accessors\n */\n\n getMinimum() {\n return (this.array.length > 0) ? this.array[0] : undefined;\n };\n\n getMaximum = function () {\n return (this.array.length > 0) ? this.array[this.array.length - 1] : undefined;\n };\n\n\n /*\n Internal search functions\n */\n\n /*\n Find index of largest value less than x\n Returns -1 if noe values exist that are less than x\n */\n ltIndexOf(x) {\n var i = this.binaryIndexOf(x);\n if (this.isFound(i, x)) {\n /*\n found - x is found on index i\n consider element to the left\n if we are at the left end of the array nothing is found\n return -1\n */\n if (i > 0) {\n return i-1;\n } else {\n return -1;\n }\n } else {\n /*\n not found - Math.abs(i) is index where x should be inserted\n => Math.abs(i) - 1 is the largest value less than x\n */\n return Math.abs(i)-1;\n }\n };\n\n /*\n Find index of rightmost value less than x or equal to x\n Returns -1 if noe values exist that are less than x or equal to x\n */\n leIndexOf(x) {\n var i = this.binaryIndexOf(x);\n if (this.isFound(i, x)) {\n /*\n element found\n */\n return i;\n } else {\n // not found - consider element to the left\n i = Math.abs(i) - 1;\n return (i >= 0) ? i : -1;\n }\n };\n\n /*\n \tFind index of leftmost value greater than x\n \tReturns -1 if no values exist that are greater than x\n */\n\n gtIndexOf(x) {\n var i = this.binaryIndexOf(x);\n if (this.isFound(i, x)) {\n /*\n found - x is found on index i\n if there are no elements to the right return -1\n */\n if (i < this.array.length -1) {\n return i+1;\n } else {\n return -1;\n }\n } else {\n /*\n not found - Math.abs(i) is index where x should be inserted\n => Math.abs(i) is the smallest value greater than x\n unless we hit the end of the array, in which cas no smalles value\n exist which is greater than x\n */\n let idx = Math.abs(i);\n return (idx < this.array.length) ? idx : -1;\n }\n };\n\n\n /*\n Find index of leftmost value which is greater than x or equal to x\n Returns -1 if noe values exist that are greater than x or equal to x\n */\n\n geIndexOf(x) {\n var i = this.binaryIndexOf(x);\n if (this.isFound(i, x)) {\n /*\n found element\n */\n return i;\n } else {\n // not found - consider the element where x would be inserted\n i = Math.abs(i);\n return (i -1) {\n return [index, index + 1];\n } else {\n return [undefined, undefined];\n }\n }\n\n // regular non-singular interval\n var start_index = -1, end_index = -1;\n if (interval.lowInclude) {\n start_index = this.geIndexOf(interval.low);\n } else {\n start_index = this.gtIndexOf(interval.low);\n }\n if (start_index === -1) {\n return [undefined, undefined];\n }\n if (interval.highInclude) {\n end_index = this.leIndexOf(interval.high);\n } else {\n end_index = this.ltIndexOf(interval.high);\n }\n if (end_index === -1) { // not reachable - I think\n return [undefined, undefined];\n }\n return [start_index, end_index + 1];\n };\n\n\n /*\n lookup by interval\n */\n lookup(interval) {\n let [start, end] = this.lookupIndexes(interval);\n return (start != undefined) ? this.array.slice(start, end) : [];\n };\n\n /*\n remove by interval\n */\n remove(interval) {\n let [start, end] = this.lookupIndexes(interval);\n return (start != undefined) ? this.array.splice(start, end-start) : [];\n };\n\n\n slice(start, end) {\n return this.array.slice(start, end);\n };\n\n splice(start, length) {\n return this.array.splice(start, length);\n };\n\n\n\n /*\n method for removing multiple closely placed elements in place\n - removeList is sorted\n - changes only affect the part of the index between first and last element\n - move remaining elements to the left, remove elements with a single splice\n - efficent if removelist references elements that are close to eachother\n */\n\n removeInSlice(removeList) {\n if (removeList.length == 0){\n return;\n }\n const low = removeList[0];\n const high = removeList[removeList.length-1];\n let [start, end] = this.lookupIndexes(new Interval(low, high, true, true));\n\n let rd_ptr = start;\n let wr_ptr = start;\n let rm_ptr = 0;\n\n while (rd_ptr < end) {\n let rd_elem = this.array[rd_ptr];\n let rm_elem = removeList[rm_ptr];\n if (rd_elem < rm_elem) {\n this.array[wr_ptr] = this.array[rd_ptr];\n wr_ptr++;\n rd_ptr++;\n } else if (rd_elem == rm_elem) {\n rd_ptr++;\n rm_ptr++;\n } else {\n // rd_elem > rm_elem\n rm_ptr++;\n }\n if (rm_ptr == removeList.length) {\n break\n }\n }\n this.array.splice(wr_ptr, rd_ptr-wr_ptr);\n };\n\n\n values() {\n return this.array.values();\n };\n\n clear() {\n this.array = [];\n };\n\n get length () {\n return this.array.length;\n }\n\n}\n\nexport default BinarySearch;\n\n\n\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\n\n/*\n\tEvent\n\t- name: event name\n\t- publisher: the object which defined the event\n\t- init: true if the event suppports init events\n\t- subscriptions: subscriptins to this event\n\n*/\n\nclass Event {\n\n\tconstructor (publisher, name, options) {\n\t\toptions = options || {}\n\t\tthis.publisher = publisher;\n\t\tthis.name = name;\n\t\tthis.init = (options.init === undefined) ? false : options.init;\n\t\tthis.subscriptions = [];\n\t}\n\n\t/*\n\t\tsubscribe to event\n\t\t- subscriber: subscribing object\n\t\t- callback: callback function to invoke\n\t\t- options:\n\t\t\tinit: if true subscriber wants init events\n\t*/\n\tsubscribe (callback, options) {\n\t\tif (!callback || typeof callback !== \"function\") {\n\t\t\tthrow new Error(\"Callback not a function\", callback);\n\t\t}\n\t\tconst sub = new Subscription(this, callback, options);\n\t\tthis.subscriptions.push(sub);\n\t // Initiate init callback for this subscription\n\t if (this.init && sub.init) {\n\t \tsub.init_pending = true;\n\t \tlet self = this;\n\t \tPromise.resolve().then(function () {\n\t \t\tconst eArgs = self.publisher.eventifyInitEventArgs(self.name) || [];\n\t \t\tsub.init_pending = false;\n\t \t\tfor (let eArg of eArgs) {\n\t \t\t\tself.trigger(eArg, [sub], true);\n\t \t\t}\n\t \t});\n\t }\n\t\treturn sub\n\t}\n\n\t/*\n\t\ttrigger event\n\n\t\t- if sub is undefined - publish to all subscriptions\n\t\t- if sub is defined - publish only to given subscription\n\t*/\n\ttrigger (eArg, subs, init) {\n\t\tlet eInfo, ctx;\n\t\tfor (const sub of subs) {\n\t\t\t// ignore terminated subscriptions\n\t\t\tif (sub.terminated) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\teInfo = {\n\t\t\t\tsrc: this.publisher,\n\t\t\t\tname: this.name,\n\t\t\t\tsub: sub,\n\t\t\t\tinit: init\n\t\t\t}\n\t\t\tctx = sub.ctx || this.publisher;\n\t\t\ttry {\n\t\t\t\tsub.callback.call(ctx, eArg, eInfo);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.log(`Error in ${this.name}: ${sub.callback} ${err}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\tunsubscribe from event\n\t- use subscription returned by previous subscribe\n\t*/\n\tunsubscribe(sub) {\n\t\tlet idx = this.subscriptions.indexOf(sub);\n\t\tif (idx > -1) {\n\t\t\tthis.subscriptions.splice(idx, 1);\n\t\t\tsub.terminate();\n\t\t}\n\t}\n}\n\n\n/*\n\tSubscription class\n*/\n\nclass Subscription {\n\n\tconstructor(event, callback, options) {\n\t\toptions = options || {}\n\t\tthis.event = event;\n\t\tthis.name = event.name;\n\t\tthis.callback = callback\n\t\tthis.init = (options.init === undefined) ? this.event.init : options.init;\n\t\tthis.init_pending = false;\n\t\tthis.terminated = false;\n\t\tthis.ctx = options.ctx;\n\t}\n\n\tterminate() {\n\t\tthis.terminated = true;\n\t\tthis.callback = undefined;\n\t\tthis.event.unsubscribe(this);\n\t}\n}\n\n\n/*\n\n\tEVENTIFY INSTANCE\n\n\tEventify brings eventing capabilities to any object.\n\n\tIn particular, eventify supports the initial-event pattern.\n\tOpt-in for initial events per event type.\n\n\teventifyInitEventArgs(name) {\n\t\tif (name == \"change\") {\n\t\t\treturn [this._value];\n\t\t}\n\t}\n\n*/\n\nexport function eventifyInstance (object) {\n\tobject.__eventify_eventMap = new Map();\n\tobject.__eventify_buffer = [];\n\treturn object;\n};\n\n\n/*\n\tEVENTIFY PROTOTYPE\n\n\tAdd eventify functionality to prototype object\n*/\n\nexport function eventifyPrototype(_prototype) {\n\n\tfunction eventifyGetEvent(object, name) {\n\t\tconst event = object.__eventify_eventMap.get(name);\n\t\tif (event == undefined) {\n\t\t\tthrow new Error(\"Event undefined\", name);\n\t\t}\n\t\treturn event;\n\t}\n\n\t/*\n\t\tDEFINE EVENT\n\t\t- used only by event source\n\t\t- name: name of event\n\t\t- options: {init:true} specifies init-event semantics for event\n\t*/\n\tfunction eventifyDefine(name, options) {\n\t\t// check that event does not already exist\n\t\tif (this.__eventify_eventMap.has(name)) {\n\t\t\tthrow new Error(\"Event already defined\", name);\n\t\t}\n\t\tthis.__eventify_eventMap.set(name, new Event(this, name, options));\n\t};\n\n\t/*\n\t\tON\n\t\t- used by subscriber\n\t\tregister callback on event.\n\t*/\n\tfunction on(name, callback, options) {\n\t\treturn eventifyGetEvent(this, name).subscribe(callback, options);\n\t};\n\n\t/*\n\t\tOFF\n\t\t- used by subscriber\n\t\tUn-register a handler from a specfic event type\n\t*/\n\tfunction off(sub) {\n\t\treturn eventifyGetEvent(this, sub.name).unsubscribe(sub);\n\t};\n\n\n\tfunction eventifySubscriptions(name) {\n\t\treturn eventifyGetEvent(this, name).subscriptions;\n\t}\n\n\n\n\t/*\n\t\tTrigger list of eventItems on object\n\n\t\teventItem: {name:.., eArg:..}\n\n\t\tcopy all eventItems into buffer.\n\t\trequest emptying the buffer, i.e. actually triggering events,\n\t\tevery time the buffer goes from empty to non-empty\n\t*/\n\tfunction eventifyTriggerAll(eventItems) {\n\t\tif (eventItems.length == 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// make trigger items\n\t\t// resolve non-pending subscriptions now\n\t\t// else subscriptions may change from pending to non-pending\n\t\t// between here and actual triggering\n\t\t// make list of [ev, eArg, subs] tuples\n\t\tlet triggerItems = eventItems.map((item) => {\n\t\t\tlet {name, eArg} = item;\n\t\t\tlet ev = eventifyGetEvent(this, name);\n\t\t\tlet subs = ev.subscriptions.filter(sub => sub.init_pending == false);\n\t\t\treturn [ev, eArg, subs];\n\t\t}, this);\n\n\t\t// append trigger Items to buffer\n\t\tconst len = triggerItems.length;\n\t\tconst buf = this.__eventify_buffer;\n\t\tconst buf_len = this.__eventify_buffer.length;\n\t\t// reserve memory - set new length\n\t\tthis.__eventify_buffer.length = buf_len + len;\n\t\t// copy triggerItems to buffer\n\t\tfor (let i=0; i {\n\t\t\treturn {name, eArg};\n\t\t}));\n\t}\n\n\t/*\n\t\tTrigger single event\n\t*/\n\tfunction eventifyTrigger(name, eArg) {\n\t\treturn this.eventifyTriggerAll([{name, eArg}]);\n\t}\n\n\t_prototype.eventifyDefine = eventifyDefine;\n\t_prototype.eventifyTrigger = eventifyTrigger;\n\t_prototype.eventifyTriggerAlike = eventifyTriggerAlike;\n\t_prototype.eventifyTriggerAll = eventifyTriggerAll;\n\t_prototype.eventifySubscriptions = eventifySubscriptions;\n\t_prototype.on = on;\n\t_prototype.off = off;\n};\n\n\n/*\n\tEvent Variable\n\n\tObjects with a single \"change\" event\n*/\n\nexport class EventVariable {\n\n\tconstructor (value) {\n\t\teventifyInstance(this);\n\t\tthis._value = value;\n\t\tthis.eventifyDefine(\"change\", {init:true});\n\t}\n\n\teventifyInitEventArgs(name) {\n\t\tif (name == \"change\") {\n\t\t\treturn [this._value];\n\t\t}\n\t}\n\n\tget value () {return this._value};\n\tset value (value) {\n\t\tif (value != this._value) {\n\t\t\tthis._value = value;\n\t\t\tthis.eventifyTrigger(\"change\", value);\n\t\t}\n\t}\n}\neventifyPrototype(EventVariable.prototype);\n\n/*\n\tEvent Boolean\n\n\n\tNote : implementation uses falsiness of input parameter to constructor and set() operation,\n\tso eventBoolean(-1) will actually set it to true because\n\t(-1) ? true : false -> true !\n*/\n\nexport class EventBoolean extends EventVariable {\n\tconstructor(value) {\n\t\tsuper(Boolean(value));\n\t}\n\n\tset value (value) {\n\t\tsuper.value = Boolean(value);\n\t}\n\tget value () {return super.value};\n}\n\n\n/*\n\tmake a promise which is resolved when EventBoolean changes\n\tvalue.\n*/\nexport function makePromise(eventObject, conditionFunc) {\n\tconditionFunc = conditionFunc || function(val) {return val == true};\n\treturn new Promise (function (resolve, reject) {\n\t\tlet sub = eventObject.on(\"change\", function (value) {\n\t\t\tif (conditionFunc(value)) {\n\t\t\t\tresolve(value);\n\t\t\t\teventObject.off(sub);\n\t\t\t}\n\t\t});\n\t});\n};\n\n// module api\nexport default {\n\teventifyPrototype,\n\teventifyInstance,\n\tEventVariable,\n\tEventBoolean,\n\tmakePromise\n};\n\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport eventify from './eventify.js';\n\n/*******************************************************************\n BASE OBSERVABLE MAP\n*******************************************************************/\n\n/*\n This is a base class for observable map\n*/\n\nclass ObservableMap {\n\n constructor (options={}) {\n \n this.options = options;\n\n // Events\n eventify.eventifyInstance(this);\n this.eventifyDefine(\"batch\", {init:true});\n this.eventifyDefine(\"change\", {init:true});\n this.eventifyDefine(\"remove\", {init:false});\n }\n\n /**\n * Abstract accessor to datasource backing implementation\n * of observable map. Typically this is an instance of Map() class.\n * \n * Must be implemented by subclass. \n */\n\n get datasource () {\n throw new Error(\"not implemented\");\n }\n\n /***************************************************************\n ORDERING\n ***************************************************************/\n\n sortOrder(options={}) {\n // sort options override constructor options\n let {order=this.options.order} = options;\n if (typeof order == \"function\") {\n return order;\n } \n }\n\n /* \n Sort values of Observable map\n ordering can be overidden by specifying option \n fallback to order from constructor\n noop if no ordering is defined\n */\n sortValues(iter, options={}) {\n let order = this.sortOrder(options);\n if (typeof order == \"function\") {\n // sort\n // if iterable not array - convert into array ahead of sorting\n let arr = (Array.isArray(iter)) ? iter : [...iter];\n return arr.sort(order);\n } else {\n // noop\n return iter;\n }\n }\n\n /* \n Sort items (in-place) by value {new:value, old:value} using\n ordering function for values\n */\n sortItems(items) {\n let order = this.sortOrder(); \n if (typeof order == \"function\") {\n items.sort(function(item_a, item_b) {\n let cue_a = (item_a.new) ? item_a.new : item_a.old;\n let cue_b = (item_b.new) ? item_b.new : item_b.old;\n return order(cue_a, cue_b);\n });\n }\n }\n\n /***************************************************************\n EVENTS\n ***************************************************************/\n\n /*\n Eventify: immediate events\n */\n eventifyInitEventArgs(name) {\n if (name == \"batch\" || name == \"change\") {\n let items = [...this.datasource.entries()].map(([key, val]) => {\n return {key:key, new:val, old:undefined};\n });\n // sort init items (if order defined)\n this.sortItems(items);\n return (name == \"batch\") ? [items] : items;\n }\n }\n\n /*\n Event Notification\n */\n _notifyEvents(items) {\n // event notification\n if (items.length == 0) {\n return;\n }\n const has_update_subs = this.eventifySubscriptions(\"batch\").length > 0;\n const has_remove_subs = this.eventifySubscriptions(\"remove\").length > 0;\n const has_change_subs = this.eventifySubscriptions(\"change\").length > 0;\n // update\n if (has_update_subs) {\n this.eventifyTrigger(\"batch\", items);\n }\n // change, remove\n if (has_remove_subs || has_change_subs) {\n for (let item of items) {\n if (item.new == undefined && item.old != undefined) {\n if (has_remove_subs) {\n this.eventifyTrigger(\"remove\", item);\n }\n } else {\n if (has_change_subs) {\n this.eventifyTrigger(\"change\", item);\n }\n }\n }\n }\n }\n\n\n /***************************************************************\n ACCESSORS\n ***************************************************************/\n\n get size () {\n return this.datasource.size;\n }\n\n has(key) {\n return this.datasource.has(key);\n };\n\n get(key) {\n return this.datasource.get(key);\n };\n\n keys() {\n return this.datasource.keys();\n };\n\n values() {\n return this.datasource.values();\n };\n\n entries() {\n return this.datasource.entries();\n }\n\n\n /***************************************************************\n MODIFY\n ***************************************************************/\n\n set(key, value) {\n let old = undefined;\n if (this.datasource.has(key)) {\n old = this.datasource.get(key);\n }\n this.datasource.set(key, value);\n this._notifyEvents([{key: key, new:value, old: old}]);\n return this;\n }\n\n delete(key) {\n let result = false;\n let old = undefined;\n if (this.datasource.has(key)) {\n old = this.datasource.get(key);\n this.datasource.delete(key);\n result = true;\n }\n this._notifyEvents([{key: key, new:undefined, old: old}]);\n return result;\n }\n\n clear() {\n // create change events for all cues\n const items = [...this.datasource.entries()].map(([key, val]) => {\n return {key: key, new: undefined, old: val};\n })\n // clear _map\n this.datasource.clear();\n // event notification\n this._notifyEvents(items);\n }\n\n}\n\neventify.eventifyPrototype(ObservableMap.prototype);\n\nexport default ObservableMap;\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport ObservableMap from '../util/observablemap.js';\nimport Interval from '../util/interval.js';\n\n/**\n * Extends ObservableMap\n * \n * with logic specific to collections of cues.\n */\n\nclass CueCollection extends ObservableMap {\n\n static cmpLow(cue_a, cue_b) {\n return Interval.cmpLow(cue_a.interval, cue_b.interval);\n }\n\n static cmpHigh(cue_a, cue_b) {\n return Interval.cmpHigh(cue_a.interval, cue_b.interval);\n }\n\n // extend sortOrder to accept order as string\n sortOrder(options={}) {\n let order = options.order || super.sortOrder(options);\n if (order == \"low\") {\n return CueCollection.cmpLow;\n } else if (order == \"high\") {\n return CueCollection.cmpHigh;\n } else {\n if (typeof order != \"function\") {\n return;\n }\n }\n return order;\n }\n\n // add cues method\n cues (options = {}) {\n let cues = this.sortValues(this.values(), options);\n // ensure array\n return (Array.isArray(cues)) ? cues : [...cues];\n }\n}\n\n// module definition\nexport default CueCollection;","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n\n/*\n Wraps the built in setTimeout to provide a\n Timeout that does not fire too early.\n\n Importantly, the Timeout object manages at most\n one timeout.\n\n - Given clock.now() returns a value in seconds.\n - The timeout is set with and absolute timestamp,\n not a delay.\n*/\n\nclass Timeout {\n\n constructor (timingObject, callback) {\n this.tid = undefined;\n this.to = timingObject;\n this.callback = callback;\n }\n\n isSet() {\n return this.tid != undefined;\n }\n\n /*\n set timeout to point in time (seconds)\n */\n setTimeout(target_ts, arg) {\n if (this.tid != undefined) {\n throw new Error(\"at most on timeout\");\n }\n let now = this.to.clock.now();\n let delay = Math.max(target_ts - now, 0) * 1000;\n this.tid = setTimeout(this.onTimeout.bind(this), delay, target_ts, arg);\n }\n\n /*\n handle timeout intended for point in time (seconds)\n */\n onTimeout(target_ts, arg) {\n if (this.tid != undefined) {\n this.tid = undefined;\n // check if timeout was too early\n let now = this.to.clock.now()\n if (now < target_ts) {\n // schedule new timeout\n this.setTimeout(target_ts, arg);\n } else {\n // handle timeout\n this.callback(now, arg);\n }\n }\n }\n\n /*\n cancel and clear timeout if active\n */\n clear() {\n if (this.tid != undefined) {\n clearTimeout(this.tid);\n this.tid = undefined;\n }\n }\n}\n\nexport default Timeout;\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\n/*\n\tMASTER CLOCK\n\n\n\tMasterClock is the reference clock used by TimingObjects.\n\n\tIt is implemented using performance.now,\n\tbut is skewed and rate-adjusted relative to this local clock.\n\n\tThis allows it to be used as a master clock in a distributed system,\n\twhere synchronization is generally relative to some other clock than the local clock.\n\n\tThe master clock may need to be adjusted in time, for instance as a response to\n\tvarying estimation of clock skew or drift. The master clock supports an adjust primitive for this purpose.\n\n\tWhat policy is used for adjusting the master clock may depend on the circumstances\n\tand is out of scope for the implementation of the MasterClock.\n\tThis policy is implemented by the timing object. This policy may or may not\n\tprovide monotonicity.\n\n\tA change event is emitted every time the masterclock is adjusted.\n\n\tVector values define\n\t- position : absolute value of the clock in seconds\n\t- velocity : how many seconds added per second (1.0 exactly - or very close)\n\t- timestamp : timstamp from local system clock (performance) in seconds. Defines point in time where position and velocity are valid.\n\n\tIf initial vector is not provided, default value is\n\t{position: now, velocity: 1.0, timestamp: now};\n\timplying that master clock is equal to local clock.\n*/\n\nimport eventify from '../util/eventify.js';\n\n\n// Need a polyfill for performance,now as Safari on ios doesn't have it...\n(function(){\n if (\"performance\" in window === false) {\n window.performance = {};\n window.performance.offset = new Date().getTime();\n }\n if (\"now\" in window.performance === false){\n window.performance.now = function now(){\n return new Date().getTime() - window.performance.offset;\n };\n }\n\t})();\n\n// local clock in seconds\nconst local_clock = {\n\tnow : function () {return performance.now()/1000.0;}\n};\n\nfunction calculateVector(vector, tsSec) {\n\tif (tsSec === undefined) tsSec = local_clock.now();\n\tvar deltaSec = tsSec - vector.timestamp;\n\treturn {\n\t\tposition : vector.position + vector.velocity*deltaSec,\n\t\tvelocity : vector.velocity,\n\t\ttimestamp : tsSec\n\t};\n};\n\nclass MasterClock {\n\n\tconstructor (options) {\n\t\tvar now = local_clock.now();\n\t\toptions = options || {};\n\t\tthis._vector = {position: now, velocity: 1.0, timestamp: now};\n\t\t// event support\n\t\teventify.eventifyInstance(this);\n\t\tthis.eventifyDefine(\"change\", {init:false}); // define change event (no init-event)\n\t\t// adjust\n\t\tthis.adjust(options);\n\t};\n\n\t/*\n\t\tADJUST\n\t\t- could also accept timestamp for velocity if needed?\n\t\t- given skew is relative to local clock\n\t\t- given rate is relative to local clock\n\t*/\n\tadjust(options) {\n\t\toptions = options || {};\n\t\tvar now = local_clock.now();\n\t\tvar nowVector = this.query(now);\n\t\tif (options.skew === undefined && options.rate === undefined) {\n\t\t\treturn;\n\t\t}\n\t\tthis._vector = {\n\t\t\tposition : (options.skew !== undefined) ? now + options.skew : nowVector.position,\n\t\t\tvelocity : (options.rate !== undefined) ? options.rate : nowVector.velocity,\n\t\t\ttimestamp : nowVector.timestamp\n\t\t}\n\t\tthis.eventifyTrigger(\"change\");\n\t};\n\n\t/*\n\t\tNOW\n\t\t- calculates the value of the clock right now\n\t\t- shorthand for query\n\t*/\n\tnow() {\n\t\treturn calculateVector(this._vector, local_clock.now()).position;\n\t};\n\n\t/*\n\t\tQUERY\n\t\t- calculates the state of the clock right now\n\t\t- result vector includes position and velocity\n\t*/\n\tquery(now) {\n\t\treturn calculateVector(this._vector, now);\n\t};\n\n}\neventify.eventifyPrototype(MasterClock.prototype);\n\nexport default MasterClock;\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\nimport MasterClock from './masterclock.js';\nimport {calculateVector, checkRange} from '../util/motionutils.js';\n\n\n/*\n\tINTERNAL PROVIDER\n\n\tTiming provider internal to the browser context\n\n\tUsed by timing objects as timingsrc if no timingsrc is specified.\n*/\n\nclass InternalProvider {\n\n\tconstructor (callback, options) {\n\t\toptions = options || {};\n\t\t// initialise internal state\n\t\tthis._clock = new MasterClock({skew:0});\n\t\tthis._range = [-Infinity, Infinity];\n\t\tthis._vector;\n\t\tthis._callback = callback;\n\t\t// options\n\t\toptions.timestamp = options.timestamp || this._clock.now();\n\t\tthis._process_update(options);\n\t};\n\n\t// internal clock\n\tget clock() {return this._clock;};\n\tget range() {return this._range;};\n\tget vector() {return this._vector;};\n\n\tisReady() {return true;};\n\n\t// update\n\t_process_update(arg) {\n\t\t// process arg\n\t\tlet {\n\t\t\tposition: pos,\n\t\t\tvelocity: vel,\n\t\t\tacceleration: acc,\n\t\t\ttimestamp: ts,\n\t\t\trange: range,\n\t\t\t...rest\n\t\t} = arg;\n\n\t\t// record state from current motion\n\t\tlet p = 0, v = 0, a = 0;\n\t\tif (this._vector != undefined) {\n\t\t\tlet nowVector = calculateVector(this._vector, ts);\n\t\t\tnowVector = checkRange(nowVector, this._range);\n\t\t\tp = nowVector.position;\n\t\t\tv = nowVector.velocity;\n\t\t\ta = nowVector.acceleration;\n\t\t}\n\n\t\t// fill in from current motion, for missing properties\n\t\tlet vector = {\n\t\t\tposition : (pos != undefined) ? pos : p,\n\t\t\tvelocity : (vel != undefined) ? vel : v,\n\t\t\tacceleration : (acc != undefined) ? acc : a,\n\t\t\ttimestamp : ts\n\t\t};\n\n\t\t// update range\n\t\tif (range != undefined) {\n\t\t\tlet [low, high] = range;\n\t\t\tif (low < high) {\n\t\t\t\tif (low != this._range[0] || high != this._range[1]) {\n\t\t\t\t\tthis._range = [low, high];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// check vector with respect to range\n\t\tvector = checkRange(vector, this._range);\n\t\t// save old vector\n\t\tthis._old_vector = this._vector;\n\t\t// update vector\n\t\tthis._vector = vector;\n\t\treturn {range, ...vector, ...rest};\n\t};\n\n\t// update\n\tupdate(arg) {\n\t\targ = this._process_update(arg);\n\t\treturn this._callback(arg);\n\t}\n\n\tclose() {\n\t\tthis._callback = undefined;\n\t}\n}\n\nexport default InternalProvider;\n\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n\n*/\n\n\n\nimport MasterClock from './masterclock.js';\n\n\nfunction checkTimingProvider(obj){\n\tlet required = [\"on\", \"skew\", \"vector\", \"range\", \"update\"];\n\tfor (let prop of required) {\n\t\tif (!(prop in obj)) {\n\t\t\tthrow new Error(`TimingProvider ${obj} missing property ${prop}`);\n\t\t}\n\t}\n}\n\n\n/*\n\tEXTERNAL PROVIDER\n\n\tExternal Provider bridges the gap between the PROVIDER API (implemented by external timing providers)\n\tand the TIMINGSRC API\n\n\tObjects implementing the TIMINGSRC API may be used as timingsrc (parent) for another timing object.\n\n\t- wraps a timing provider external\n\t- handles some complexity that arises due to the very simple API of providers\n\t- implements a clock for the provider\n*/\n\nclass ExternalProvider {\n\n\tconstructor(provider, callback, options) {\n\t\tcheckTimingProvider(provider);\n\t\toptions = options || {};\n\n\t\tthis._provider = provider;\n\t\tthis._callback = callback;\n\t\tthis._range;\n\t\tthis._vector;\n\t\tthis._ready = false\n\n\t\t/*\n\t\t\tprovider clock (may fluctuate based on live skew estimates)\n\t\t*/\n\t\tthis._provider_clock;\n\t\t/*\n\t\t\tlocal clock\n\t\t\tprovider clock normalised to values of performance now\n\t\t\tnormalisation based on first skew measurement, so\n\t\t*/\n\t\tthis._clock;\n\n\t\t// register event handlers\n\t\tthis._provider.on(\"vectorchange\", this._onVectorChange.bind(this));\n\t\tthis._provider.on(\"skewchange\", this._onSkewChange.bind(this));\n\n\t\t// check if provider is ready\n\t\tif (this._provider.skew != undefined) {\n\t\t\t// initialise immediately - without a callback\n\t\t\tthis._onSkewChange(true);\n\t\t}\n\t};\n\n\tisReady() {return this._ready;};\n\n\t// internal clock\n\tget clock() {return this._clock;};\n\tget range() {return this._range;};\n\n\n\t/*\n\t\t- local timestamp of vector is set for each new vector, using the skew available at that time\n\t\t- the vector then remains unchanged\n\t\t- skew changes affect local clock, thereby affecting the result of query operations\n\n\t\t- one could imagine reevaluating the vector as well when the skew changes,\n\t\t\tbut then this should be done without triggering change events\n\n\t\t- ideally the vector timestamp should be a function of the provider clock\n\t*/\n\n\tget vector() {\n\t\t// local_ts = provider_ts - skew\n\t\tlet local_ts = this._vector.timestamp - this._provider.skew;\n\t\treturn {\n\t\t\tposition : this._vector.position,\n\t\t\tvelocity : this._vector.velocity,\n\t\t\tacceleration : this._vector.acceleration,\n\t\t\ttimestamp : local_ts\n\t\t}\n\t}\n\n\n\t// internal provider object\n\tget provider() {return this._provider;};\n\n\n\t_onSkewChange(init=false) {\n\t\tif (!this._clock) {\n\t\t\tthis._provider_clock = new MasterClock({skew: this._provider.skew});\n\t\t\tthis._clock = new MasterClock({skew:0});\n\t\t} else {\n\t\t\tthis._provider_clock.adjust({skew: this._provider.skew});\n\t\t\t// provider clock adjusted with new skew - correct local clock similarly\n\t\t\t// current_skew = clock_provider - clock_local\n\t\t\tlet current_skew = this._provider_clock.now() - this._clock.now();\n\t\t\t// skew delta = new_skew - current_skew\n\t\t\tlet skew_delta = this._provider.skew - current_skew;\n\t\t\tthis._clock.adjust({skew: skew_delta});\n\t\t}\n\t\t// no upcalls on skew change\n\t};\n\n\t_onVectorChange() {\n\t\tif (this._clock) {\t\t\t\n\t\t\t// is ready (onSkewChange has fired earlier)\n\t\t\tif (!this._ready && this._provider.vector != undefined) {\n\t\t\t\t// become ready\n\t\t\t\tthis._ready = true;\n\t\t\t}\n\t\t\tif (this._ready) {\n\t\t\t\tif (!this._range) {\n\t\t\t\t\tthis._range = this._provider.range;\n\t\t\t\t}\n\t\t\t\tthis._vector = this._provider.vector;\n\t\t\t\tlet eArg = {\n\t\t\t\t\trange: this.range,\n\t\t\t\t\t...this.vector\n\t\t\t\t}\n\t\t\t\tif (this._callback) {\n\t\t\t\t\tthis._callback(eArg);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t// update\n\t/*\n\t\tTODO - support setting range on provider\n\t\tTODO - suppport tunnel\n\t\tTODO - support onRangeChange from provider\n\t*/\n\tupdate(arg) {\n\t\tlet vector = {\n\t\t\tposition: arg.position,\n\t\t\tvelocity: arg.velocity,\n\t\t\tacceleration: arg.acceleration,\n\t\t\ttimestamp: arg.timestamp\n\t\t};\n\t\t// calc back to provider ts\n\t\t// local_ts = provider_ts - skew\n\t\tvector.timestamp = vector.timestamp + this._provider.skew;\n\t\tlet res = this._provider.update(vector);\n\t\t// return success\n\t\treturn true;\n\t};\n\n\tclose() {\n\t\tthis._callback = undefined;\n\t}\n\n}\n\nexport default ExternalProvider;\n\n\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\nimport eventify from '../util/eventify.js';\nimport Timeout from '../util/timeout.js';\nimport * as motionutils from '../util/motionutils.js';\nimport InternalProvider from './internalprovider.js';\nimport ExternalProvider from './externalprovider.js';\n\nconst MAX_NONCE = 10000;\n\nfunction getRandomInt() {\n \treturn Math.floor(Math.random() * MAX_NONCE);\n};\n\nfunction isTimingProvider(obj){\n\tlet required = [\"on\", \"skew\", \"vector\", \"range\", \"update\"];\n\tfor (let prop of required) {\n\t\tif (!(prop in obj)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n\n/*\n\tTIMING BASE\n\n\tabstract base class for objects that may be used as timingsrc\n\n\tessential internal state\n\t- range, vector\n\n\texternal methods\n\tquery, update\n\n\tevents\n\ton/off \"change\", \"timeupdate\"\n\n\tinternal methods for range timeouts\n\n\tdefines internal processing steps\n\t- handleEvent(arg) <- from external timingobject\n\t\t- vector = onChange(vector)\n\t\t- process(vector) <- from timeout or preProcess\n\t- handleTimeout(arg) <- timeout on range restrictions\n\t- process (arg)\n\t\t- set internal vector, range\n\t\t- dispatchEvents(arg)\n\t\t- renew range timeout\n\t- dispatchEvent (arg)\n\t\t- emit change event and timeupdate event\n\t\t- turn periodic timeupdate on or off\n\n\tindividual steps in this structure may be specialized\n\tby subclasses (i.e. timing converters)\n*/\n\n\nclass TimingObject {\n\n\tconstructor (timingsrc, options) {\n\n\t\t// special support for options given as first and only argument\n\t\t// equivalent to new TimingObject(undefined, options)\n\t\t// in this case, timingsrc may be found in options\n\t\tif (timingsrc != undefined && options == undefined) {\n\t\t\tif (!(timingsrc instanceof TimingObject) && !isTimingProvider(timingsrc)) {\n\t\t\t\t// timingsrc is neither timing object nor timingprovider\n\t\t\t\t// assume timingsrc is options\n\t\t\t\toptions = timingsrc;\n\t\t\t\ttimingsrc = undefined;\n\t\t\t\tif (options.provider) {\n\t\t\t\t\ttimingsrc = options.provider;\n\t\t\t\t} else if (options.timingsrc) {\n\t\t\t\t\ttimingsrc = options.timingsrc;\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t// options\n\t\toptions = options || {};\n\t\tthis.__options = options;\n\n\n\t\t// default timeout option\n\t\tif (options.timeout == undefined) {\n\t\t\toptions.timeout = true;\n\t\t}\n\n\t\t// cached vectors and range\n\t\tthis.__old_vector;\n\t\tthis.__vector;\n\t\tthis.__range = [-Infinity, Infinity];\n\n\t\t// range restriction timeout\n\t\tthis.__timeout = new Timeout(this, this.__handleTimeout.bind(this));\n\n\t\t// timeoutid for timeupdate event\n\t\tthis.__tid = undefined;\n\n\t\t// timingsrc\n\t\tthis.__timingsrc;\n\t\tthis.__sub;\n\n\t\t// update promises\n\t\tthis.__update_events = new Map();\n\n\t\t// readiness\n\t\tthis.__ready = new eventify.EventBoolean();\n\n\t\t// exported events\n\t\teventify.eventifyInstance(this);\n\t\tthis.eventifyDefine(\"timingsrc\", {init:true});\n\t\tthis.eventifyDefine(\"change\", {init:true});\n\t\tthis.eventifyDefine(\"rangechange\", {init:true});\n\t\tthis.eventifyDefine(\"timeupdate\", {init:true});\n\n\t\t// initialise timingsrc\n\t\tthis.__set_timingsrc(timingsrc, options);\n\t};\n\n\n\t/***************************************************************\n\n\t\tEVENTS\n\n\t***************************************************************/\n\n\t/*\n\t \toverrides how immediate events are constructed\n\t \tspecific to eventutils\n\t \t- overrides to add support for timeupdate events\n\t*/\n\teventifyInitEventArgs(name) {\n\t\tif (this.__ready.value) {\n\t\t\tif (name == \"timingsrc\") {\n\t\t\t\tlet eArg = {\n\t\t\t\t\t...this.__vector,\n\t\t\t\t\trange: this.__range,\n\t\t\t\t\tlive:false\n\t\t\t\t}\n\t\t\t\treturn [eArg];\n\t\t\t} else if (name == \"timeupdate\") {\n\t\t\t\treturn [undefined];\n\t\t\t} else if (name == \"change\") {\n\t\t\t\treturn [this.__vector];\n\t\t\t} else if (name == \"rangechange\") {\n\t\t\t\treturn [this.__range];\n\t\t\t}\n\t\t}\n\t};\n\n\n\t/***************************************************************\n\n\t\tACCESSORS\n\n\t***************************************************************/\n\n\t// ready or not\n\tisReady() {return this.__ready.value;};\n\n\t// ready promise\n get ready() {return eventify.makePromise(this.__ready);};\n\n // range\n get range() {\n \t// copy\n \treturn [this.__range[0], this.__range[1]];\n };\n\n // vector\n get vector() {\n \t// copy\n\t\treturn {\n\t\t\tposition : this.__vector.position,\n\t\t\tvelocity : this.__vector.velocity,\n\t\t\tacceleration : this.__vector.acceleration,\n\t\t\ttimestamp : this.__vector.timestamp\n\t\t};\n };\n\n // old vector\n get old_vector() {return this.__old_vector;};\n\n // delta\n get delta() {\n \treturn new motionutils.MotionDelta(this.__old_vector, this.__vector);\n }\n\n\t// clock - from timingsrc or provider\n\tget clock() {return this.__timingsrc.clock};\n\n\tget version() {return 5;}\n\n\n\t/***************************************************************\n\n\t\tQUERY\n\n\t***************************************************************/\n\n\t// query\n\tquery() {\n\t\tif (this.__ready.value == false) {\n\t\t\tthrow new Error(\"query before timing object is ready\");\n\t\t}\n\t\t// reevaluate state to handle range violation\n\t\tlet vector = motionutils.calculateVector(this.__vector, this.clock.now());\n\t\t// detect range violation - only if timeout is set {\n\t\tif (this.__timeout.isSet()) {\n\t\t\tif (vector.position < this.__range[0] || this.__range[1] < vector.position) {\n\t\t\t\t// emulate update event to trigger range restriction\n\t\t\t\tthis.__process({...vector});\n\t\t\t}\n\t\t\t// re-evaluate query after state transition\n\t\t\treturn motionutils.calculateVector(this.__vector, this.clock.now());\n\t\t}\n\t\treturn vector;\n\t};\n\n\t// shorthand query\n\tget pos() {return this.query().position;};\n\tget vel() {return this.query().velocity;};\n\tget acc() {return this.query().acceleration;};\n\n\n\t/***************************************************************\n\n\t\tUPDATE\n\n\t***************************************************************/\n\n\t// internal update\n\t__update(arg) {\n\t\tif (this.__timingsrc instanceof TimingObject) {\n\t\t\treturn this.__timingsrc.__update(arg);\n\t\t} else {\n\t\t\t// provider\n\t\t\treturn this.__timingsrc.update(arg);\n\t\t}\n\t};\n\n\t// external update\n\tupdate(arg) {\n\t\t// check if noop\n\t\tlet ok = (arg.range != undefined);\n\t\tok = ok || (arg.position != undefined);\n\t\tok = ok || (arg.velocity != undefined);\n\t\tok = ok || (arg.acceleration != undefined);\n\t\tif (!ok) {\n\t\t\treturn Promise.resolve(arg);\n\t\t}\n\t\targ.tunnel = getRandomInt();\n\t\tif (arg.timestamp == undefined) {\n\t\t\targ.timestamp = this.clock.now();\n\t\t}\n\t\tlet event = new eventify.EventVariable();\n\t\tthis.__update_events.set(arg.tunnel, event);\n\t\tlet promise = eventify.makePromise(event, val => (val != undefined));\n\t\tthis.__update(arg);\n\t\treturn promise;\n\t}\n\n\n\t/***************************************************************\n\n\t\tCORE UPDATE PROCESSING\n\n\t***************************************************************/\n\n\t/*\n\t\tdo not override\n\t\thandle incoming change event\n\t\teArg = {vector:vector, range:range, live:true}\n\n\t\tsubclasses may specialise behaviour by overriding\n\t\tonVectorChange\n\n\t*/\n\t__handleEvent(arg) {\n\t\tlet {\n\t\t\trange,\n\t\t\tlive = true,\n\t\t\t...rest\n\t\t} = arg;\n\t\t// copy range object\n\t\tif (range != undefined) {\n\t\t\trange = [range[0], range[1]];\n\t\t}\n\t\t// new arg object\n\t\tlet _arg = {\n\t\t\trange,\n\t\t\tlive,\n\t\t\t...rest,\n\t\t};\n\t\t_arg = this.onUpdateStart(_arg);\n\t\tif (_arg != undefined) {\n\t\t\treturn this.__process(_arg);\n\t\t}\n\t};\n\n\t/*\n\t\tdo not override\n\t\thandle timeout\n\t*/\n\t__handleTimeout(now, timeout_vector) {\n\t\tthis.__process({...timeout_vector});\n\t}\n\n\t/*\n\t\tcore processing step after change event or timeout\n\t\tassignes the internal vector\n\t*/\n\t__process(arg) {\n\t\tlet {\n\t\t\trange,\n\t\t\tposition,\n\t\t\tvelocity,\n\t\t\tacceleration,\n\t\t\ttimestamp,\n\t\t\tlive=true,\n\t\t\t...rest\n\t\t} = arg;\n\n\n\t\t// update range\n\t\tlet range_change = false;\n\t\tif (range != undefined) {\n\t\t\tlet [low, high] = range;\n\t\t\tif (low < high) {\n\t\t\t\tif (low != this.__range[0] || high != this.__range[1]) {\n\t\t\t\t\tthis.__range = [low, high];\n\t\t\t\t\trange = [low, high];\n\t\t\t\t\trange_change = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\t- vector change (all vector elements defined)\n\t\t\t- range change (no vector elements defined)\n\t\t\t- both (all vector elements and range defined)\n\t\t*/\n\t\tlet vector_change = (position != undefined);\n\t\tif (!vector_change && !range_change) {\n\t\t\tconsole.log(\"__process: WARNING - no vector change and no range change\")\n\t\t}\n\n\t\t/*\n\t\t\tcheck if vector is consistent with range\n\t\t\trange violation may occur if \n\t\t\t- vector change\n\t\t\t- range change\n\t\t\t- both\n\n\t\t\t- vector must be recalculated for present for detection\n\t\t\t of range violation\n\t\t*/\n\t\tlet vector;\n\t\tif (vector_change) {\n\t\t\t// vector change\n\t\t\tvector = {position, velocity, acceleration, timestamp};\n\t\t} else {\n\t\t\tvector = {...this.__vector};\n\t\t}\n\t\tlet now = this.clock.now();\n\t\tlet now_vector = motionutils.calculateVector(vector, now);\n\t\tlet violation = motionutils.detectRangeViolation(now_vector, this.__range);\n\t\tif (violation) {\n\t\t\tvector = this.onRangeViolation(now_vector);\n\t\t\tlive = true;\n\t\t}\n\n\t\t// reevaluate vector change and live\n\t\tvector_change = vector_change || !motionutils.equalVectors(vector, this.__vector);\n\n\t\t// update vector\t\t\n\t\tif (vector_change) {\n\t\t\t// save old vector\n\t\t\tthis.__old_vector = this.__vector;\n\t\t\t// update vector\n\t\t\tthis.__vector = vector;\n\t\t}\n\n\t\tlet _arg;\n\t\tif (range_change && vector_change) {\n\t\t\t_arg = {range, ...vector, live, ...rest};\n\t\t} else if (range_change) {\n\t\t\t_arg = {range, live, ...rest};\n\t\t} else if (vector_change) {\n\t\t\t_arg = {...vector, live, ...rest};\n\t\t} else {\n\t\t\t_arg = {live, ...rest};\n\t\t}\n\n\t\t// trigger events\n\t\tthis.__ready.value = true;\n\t\tthis.__dispatchEvents(_arg, range_change, vector_change);\n\t\t// renew timeout\n\t\tif (this.__options.timeout) {\n\t\t\tthis.__renewTimeout();\n\t\t}\n\t\t// release update promises\n\t\tif (_arg.tunnel != undefined) {\n\t\t\tlet event = this.__update_events.get(_arg.tunnel);\n\t\t\tif (event) {\n\t\t\t\tthis.__update_events.delete(_arg.tunnel);\n\t\t\t\tdelete _arg.tunnel;\n\t\t\t\tevent.value = _arg;\n\t\t\t}\n\t\t}\n\t\t// TODO\n\t\t// since externalprovider does not support tunnel yet\n\t\t// free all remaining promises\n\t\tfor (let event of this.__update_events.values()) {\n\t\t\tevent.value = {};\n\t\t}\n\t\tthis.onUpdateDone(_arg);\n\t\treturn _arg;\n\t};\n\n\t/*\n\t\tprocess a new vector applied in order to trigger events\n\t\toverriding this is only necessary if external change events\n\t\tneed to be suppressed,\n\t*/\n\t__dispatchEvents(arg, range_change, vector_change) {\n\t\tlet {\n\t\t\trange,\n\t\t\tposition,\n\t\t\tvelocity,\n\t\t\tacceleration,\n\t\t\ttimestamp\n\t\t} = arg;\n\t\t// trigger timingsrc events\n\t\tthis.eventifyTrigger(\"timingsrc\", arg);\n\t\t// trigger public change events\n\t\tif (vector_change) {\n\t\t\tlet vector = {position, velocity, acceleration, timestamp};\n\t\t\tthis.eventifyTrigger(\"change\", vector);\n\t\t}\n\t\tif (range_change) {\n\t\t\tthis.eventifyTrigger(\"rangechange\", range);\n\t\t}\n\t\t// trigger timeupdate events\n\t\tthis.eventifyTrigger(\"timeupdate\");\n\t\tlet moving = motionutils.isMoving(this.__vector);\n\t\tif (moving && this.__tid === undefined) {\n\t\t\tlet self = this;\n\t\t\tthis.__tid = setInterval(function () {\n\t\t\t\tself.eventifyTrigger(\"timeupdate\");\n\t\t\t}, 200);\n\t\t} else if (!moving && this.__tid !== undefined) {\n\t\t\tclearTimeout(this.__tid);\n\t\t\tthis.__tid = undefined;\n\t\t}\n\t};\n\n\n\t/***************************************************************\n\n\t\tSUBCLASS MAY OVERRIDE\n\n\t***************************************************************/\n\n\t/*\n\t\tmay be overridden\n\t*/\n\tonRangeViolation(now_vector) {\n\t\treturn motionutils.checkRange(now_vector, this.__range);\n\t};\n\n\t/*\n\t\tmay be overridden\n\t*/\n\tonUpdateStart(arg) {return arg;};\n\n\t/*\n\t\tmay be overridden\n\t*/\n\tonUpdateDone(arg) {};\n\n\n\t/***************************************************************\n\n\t\tTIMEOUTS\n\n\t***************************************************************/\n\n\t/*\n\t\trenew timeout is called during every processing step\n\t\tin order to recalculate timeouts.\n\n\t\t- optional vector - default is own vector\n\t\t- optional range - default is own range\n\t*/\n\t__renewTimeout(vector, range) {\n\t\tthis.__timeout.clear();\n\t\tlet timeout_vector = this.__calculateTimeoutVector(vector, range);\n\t\tif (timeout_vector == undefined) {\n\t\t\treturn;\n\t\t}\n\t\tthis.__timeout.setTimeout(timeout_vector.timestamp, timeout_vector);\n\t};\n\n\n\t/*\n\t\tcalculate a vector that will be delivered to _process().\n\t\tthe timestamp in the vector determines when it is delivered.\n\n\t\t- optional vector - default is own vector\n\t\t- optional range - default is own range\n\t*/\n\t__calculateTimeoutVector(vector, range) {\n\t\tvector = vector || this.__vector;\n\t\trange = range || this.__range;\n\t\tlet now = this.clock.now();\n\t\tlet now_vector = motionutils.calculateVector(vector, now);\n\t\tlet [delta, pos] = motionutils.calculateDelta(now_vector, range);\n\t\tif (delta == undefined) {\n\t\t\treturn;\n\t\t}\n\t\t// vector when range restriction will be reached\n\t\tlet timeout_vector = motionutils.calculateVector(vector, now + delta);\n\t\t// possibly avoid rounding errors\n\t\ttimeout_vector.position = pos;\n\t\treturn timeout_vector;\n\t};\n\n\n\t/***************************************************************\n\n\t\tTIMINGSRC\n\n\t***************************************************************/\n\n\t/*\n\n\t\ttimingsrc property and switching on assignment\n\n\t*/\n\t__clear_timingsrc() {\n\t\t// clear timingsrc\n\t\tif (this.__timingsrc != undefined) {\n\t\t\tif (this.__timingsrc instanceof TimingObject) {\n\t\t\t\tthis.__timingsrc.off(this.__sub);\n\t\t\t\tthis.__sub = undefined;\n\t\t\t\tthis.__timingsrc = undefined;\n\t\t\t} else {\n\t\t\t\t// provider\n\t\t\t\tthis.__timingsrc.close();\n\t\t\t\tthis.__timingsrc = undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\t__set_timingsrc(timingsrc, options) {\n\t\t// set timingsrc\n\t\tlet callback = this.__handleEvent.bind(this);\n\t\tif (timingsrc instanceof TimingObject) {\n\t\t\t// timingsrc\n\t\t\tthis.__timingsrc = timingsrc;\n\t\t\tthis.__sub = this.__timingsrc.on(\"timingsrc\", callback);\n\t\t} else {\n\t\t\t// provider\n\t\t\tif (timingsrc == undefined) {\n\t\t\t\t// Internal Provider\n\t\t\t\tthis.__timingsrc = new InternalProvider(callback, options);\n\t\t\t} else {\n\t\t\t\t// External Provider\n\t\t\t\tthis.__timingsrc = new ExternalProvider(timingsrc, callback, options);\n\t\t\t}\n\t\t\t// emulating initial event from provider, causing\n\t\t\t// this timingobject to initialise\n\t\t\tif (this.__timingsrc.isReady()) {\n\t\t\t\tlet arg = {\n\t\t\t\t\trange: this.__timingsrc.range,\n\t\t\t\t\t...this.__timingsrc.vector,\n\t\t\t\t\tlive: false\n\t\t\t\t}\n\t\t\t\t// generate initial event\n\t\t\t\tcallback(arg);\n\t\t\t}\n\t\t}\n\t}\n\n\t__get_timingsrc() {\n\t\t// returns InternalProvider, ExternalProvider or TimingObject\n\t\treturn this.__timingsrc;\n\t}\n\n\tget timingsrc () {\n\t\t// returns TimingObject, Provider or undefined\n\t\tlet timingsrc = this.__get_timingsrc();\n\t\tif (timingsrc instanceof TimingObject) {\n\t\t\treturn timingsrc;\n\t\t} else if (timingsrc instanceof InternalProvider) {\n\t\t\treturn undefined;\n\t\t} else if (timingsrc instanceof ExternalProvider) {\n\t\t\treturn timingsrc._provider;\n\t\t} else {\n\t\t\tthrow new Error(\"illegal timingsrc\")\n\t\t}\n\t}\n\t\n\tset timingsrc(timingsrc) {\n\t\tthis.__clear_timingsrc();\n\t\tthis.__set_timingsrc(timingsrc);\n\t}\n\n}\n\neventify.eventifyPrototype(TimingObject.prototype);\n\nexport default TimingObject;\n\n\n\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\n/*\n\tLOOP CONVERTER\n\n\tThis is a modulo type transformation where the converter will be looping within\n\ta given range. Potentially one could create an associated timing object keeping track of the\n\tloop number.\n*/\n\n\nimport {calculateVector} from '../util/motionutils.js';\nimport TimingObject from './timingobject.js';\n\n\n// ovverride modulo to behave better for negative numbers\nfunction mod(n, m) {\n\treturn ((n % m) + m) % m;\n};\n\nfunction transform(x, range) {\n\tlet skew = range[0];\n\tlet length = range[1] - range[0];\n\treturn skew + mod(x-skew, length);\n}\n\n\n/*\n\tLOOP CONVERTER\n*/\n\nclass LoopConverter extends TimingObject {\n\n\tconstructor(timingsrc, range) {\n\t\tsuper(timingsrc, {timeout:true});\n\n\t\tif (!Array.isArray(range) || range.length != 2) {\n\t\t\tthrow new Error(`range must be array [low, high], ${range}`);\n\t\t}\n\t\tthis.__range = range;\n\t};\n\n\tupdate(arg) {\n\t\t// range change - only a local operation\n\t\tif (arg.range != undefined) {\n\t\t\t// implement local range update\n\t\t\tlet [low, high] = arg.range;\n\t\t\tif (low >= high) {\n\t\t\t\tthrow new Error(\"illegal range\", arg.range)\n\t\t\t}\n\t\t\tif (low != this.__range[0] || high != this.__range[1]) {\n\t\t\t\tthis.__range = [low, high];\n\t\t\t\tlet vector = this.__get_timingsrc().query();\n\t\t\t\tvector.position = transform(vector.position, this.__range);\n\t\t\t\tthis.__vector = vector;\n\t\t\t\t// trigger vector change\n\t\t\t\tlet _arg = {range: this.__range, ...this.__vector, live:true};\n\t\t\t\tthis.__dispatchEvents(_arg, true, true);\n\t\t\t}\n\t\t\tdelete arg.range;\n\t\t}\n\t\t// vector change\n\t\tif (arg.position != undefined) {\n\t\t\t// inverse transformation of position, from looper\n\t\t\t// coordinates to timingsrc coordinates\n\t\t\t// preserve relative position diff\n\t\t\tlet now = this.clock.now();\n\t\t\tlet now_vector = calculateVector(this.vector, now);\n\t\t\tlet diff = now_vector.position - arg.position;\n\t\t\tlet now_vector_src = calculateVector(this.__get_timingsrc().vector, now);\n\t\t\targ.position = now_vector_src.position - diff;\n\t\t}\n\t\treturn super.update(arg);\n\t};\n\n\t// overrides\n\tonRangeViolation(now_vector) {\n\t\tnow_vector.position = transform(now_vector.position, this.__range);\n\t\treturn now_vector;\n\t};\n\n\t// overrides\n\tonUpdateStart(arg) {\n if (arg.range != undefined) {\n // ignore range change from timingsrc\n // instead, insist that this._range is correct\n arg.range = this.__range;\n }\n if (arg.position != undefined) {\n \t// vector change\n \targ.position = transform(arg.position, this.__range);\n\t\t\t/* \n\t\t\tvector change must also apply to timestamp\n\t\t\tthis is handlet in onRangeViolation \n\t\t\t*/\n }\n\t\treturn arg;\n\t};\n\n}\nexport default LoopConverter;\n\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n/*\n\n\tRANGE CONVERTER\n\n\tThe converter enforce a range on position.\n\n\tIt only has effect if given range is a restriction on the range of the timingsrc.\n\tRange converter will pause on range endpoints if timingsrc leaves the range.\n\tRange converters will continue mirroring timingsrc once it comes into the range.\n*/\n\n\nimport {RangeState, correctRangeState, checkRange} from '../util/motionutils.js';\nimport TimingObject from './timingobject.js';\n\n\nfunction state() {\n\tvar _state = RangeState.INIT;\n\tvar _range = null;\n\tvar is_special_state_change = function (old_state, new_state) {\n\t\t// only state changes between INSIDE and OUTSIDE* are special state changes.\n\t\tif (old_state === RangeState.OUTSIDE_HIGH && new_state === RangeState.OUTSIDE_LOW) return false;\n\t\tif (old_state === RangeState.OUTSIDE_LOW && new_state === RangeState.OUTSIDE_HIGH) return false;\n\t\tif (old_state === RangeState.INIT) return false;\n\t\treturn true;\n\t}\n\tvar get = function () {return _state;};\n\tvar set = function (new_state, new_range) {\n\n\t\tvar absolute = false; // absolute change\n\t\tvar special = false; // special change\n\n\t\t// check absolute change\n\t\tif (new_state !== _state || new_range !== _range) {\n\t\t\tabsolute = true;\n\t\t}\n\t\t// check special change\n\t\tif (new_state !== _state) {\n\t\t\tspecial = is_special_state_change(_state, new_state);\n\t\t}\n\t\t// range change\n\t\tif (new_range !== _range) {\n\t\t\t_range = new_range;\n\t\t}\n\t\t// state change\n\t\tif (new_state !== _state) {\n\t\t\t_state = new_state;\n\t\t}\n\t\treturn {special:special, absolute:absolute};\n\n\t}\n\treturn {get: get, set:set};\n};\n\n\n/*\n\tRange converter allows a new (smaller) range to be specified.\n\n\t- ignores the range of its timingsrc\n\t- vector change from timingsrc\n\t - outside own range - drop - set timeout to inside\n\t - inside own range - normal processing\n\t- extra vector changes (compared to timingsrc)\n\t\t- enter inside\n\t\t- range violation own range\n\t- range updated locally\n\n*/\n\nclass RangeConverter extends TimingObject {\n\n\tconstructor (timingObject, range) {\n\t\tsuper(timingObject, {timeout:true});\n\t\tthis.__state = state();\n\t\tthis.__range = range;\n\t};\n\n\n\tupdate(arg) {\n\t\tthrow Error(\"Not Implemented!\");\n\t\t/*\n\t\t\trange change - only a local operation\n\n\t\t\t\t- need to trigger local processing of new range,\n\t\t\t\tso that range is changed and events triggered\n\t\t\t\t- also need to trigger a reevaluation of\n\t\t\t\tvector from timingsrc vector, for instance, if\n\t\t\t\trange grows while timingsrc is outside, the\n\t\t\t\tposition of the vector needs to change\n\t\t\t\t- cannot do both these things via emulation\n\t\t\t\tof timingsrc event - because rangeconverter\n\t\t\t\tis supposed to ignore range change from timingsrc\n\t\t\t\t- could do both locally, but this would effectively\n\t\t\t\trequire reimplementation of logic in __process\n\t\t\t\t- in addition, this could be a request to update\n\t\t\t\tboth range and vector at the same time, in which case\n\t\t\t\tit would be good to do them both at the same time\n\n\t\t\t- possible solution - somehow let range converter\n\t\t\t discriminate range changes based on origin?\n\n\t\t*/\n\t\tif (arg.range != undefined) {\n\n\t\t\t// local processing of range change\n\t\t\t// to trigger range change event\n\t\t\tlet _arg = {range: arg.range, ...this.__get_timingsrc().vector, live:true};\n\t\t\tthis.__process(_arg);\n\t\t\t// avoid that range change affects timingsrc\n\t\t\tdelete arg.range;\n\n\t\t}\n\t\treturn super.update(arg);\n\t};\n\n\n\n\t// overrides\n\tonUpdateStart(arg) {\n if (arg.range != undefined) {\n \t// ignore range change from timingsrc\n \t// delete causes update to be dropped\n delete arg.range;\n }\n if (arg.position != undefined) {\n \t// vector change from timingsrc\n \tlet {position, velocity, acceleration, timestamp} = arg;\n \tlet vector = {position, velocity, acceleration, timestamp};\n \tvector = this.onVectorChange(vector);\n \tif (vector == undefined) {\n \t\t// drop because motion is outside\n\t\t\t\t// create new timeout for entering inside\n\t\t\t\tthis.__renewTimeout(this.__get_timingsrc().vector, this.__range);\n\t\t\t\treturn;\n \t} else {\n \t\t// regular\n \t\targ.position = vector.position;\n \t\targ.velocity = vector.velocity;\n \t\targ.acceleration = vector.acceleration;\n \t\targ.timestamp = vector.timestamp;\n \t}\n }\n return arg;\n\t};\n\n\n\tonVectorChange(vector) {\n\t\tvar new_state = correctRangeState(vector, this.__range);\n\t\tvar state_changed = this.__state.set(new_state, this.__range);\n\t\tif (state_changed.special) {\n\t\t\t// state transition between INSIDE and OUTSIDE\n\t\t\tif (this.__state.get() === RangeState.INSIDE) {\n\t\t\t\t// OUTSIDE -> INSIDE, generate fake start event\n\t\t\t\t// vector delivered by timeout\n\t\t\t\t// forward event unchanged\n\t\t\t} else {\n\t\t\t\t// INSIDE -> OUTSIDE, generate fake stop event\n\t\t\t\tvector = checkRange(vector, this.__range);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t// no state transition between INSIDE and OUTSIDE\n\t\t\tif (this.__state.get() === RangeState.INSIDE) {\n\t\t\t\t// stay inside or first event inside\n\t\t\t\t// forward event unchanged\n\t\t\t} else {\n\t\t\t\t// stay outside or first event outside\n\t\t\t\t// forward if\n\t\t\t\t// - first event outside\n\t\t\t\t// - skip from outside-high to outside-low\n\t\t\t\t// - skip from outside-low to outside-high\n\t\t\t\t// - range change\n\t\t\t\t// else drop\n\t\t\t\t// - outside-high to outside-high (no range change)\n\t\t\t\t// - outside-low to outside-low (no range change)\n\t\t\t\tif (state_changed.absolute) {\n\t\t\t\t\tvector = checkRange(vector, this.__range);\n\t\t\t\t} else {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn vector;\n\t};\n}\n\nexport default RangeConverter;\n\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\n/**\n * Sampler for Timing Object\n * \n * - samples timing object position and emits a change event at certain frequency\n * - does not emit any events when timing object is paused\n * - options\n * - period (between samples) in ms\n * - frequency (sample frequency) in hz\n * if both given - period takes precedence\n * if none given - default period = 200 ms \n * \n * TODO\n - set refresh frequency to be sensitive\n to velocity - adapted to a fixed rate\n change in percent\n calculate percent velocity\n rate change in percent per second\n\n * \n * \n */\n\nimport eventify from '../util/eventify.js';\n\nconst DEFAULT_PERIOD = 200;\n\nclass TimingSampler {\n\n constructor (timingObject, options = {}) {\n this._to = timingObject;\n // timeout id\n this._tid;\n // period\n let {period, frequency} = options;\n this._period = DEFAULT_PERIOD;\n if (period != undefined) {\n this._period = period;\n } else if (frequency != undefined) {\n this._period = 1.0/frequency;\n } \n // Events\n eventify.eventifyInstance(this);\n\n this.eventifyDefine(\"change\", {init:true});\n // Handle timing object change event\n this._sub = this._to.on(\"change\", this._onChange.bind(this));\n }\n\n /*\n Eventify: immediate events\n */\n eventifyInitEventArgs(name) {\n if (name == \"change\" && this._to.isReady()) {\n return [this._to.pos];\n }\n }\n\n /**\n * Start/stop sampling\n */\n _onChange() {\n let v = this._to.query();\n let moving = (v.velocity != 0.0 || v.acceleration != 0.0);\n // start or stop sampling\n if (moving && this._tid == undefined) {\n this._tid = setInterval(function(){\n this._onSample();\n }.bind(this), this._period);\n }\n if (!moving && this._tid != undefined) {\n clearTimeout(this._tid);\n this._tid = undefined;\n }\n this._onSample(v.position);\n }\n\n /**\n * Sample timing object\n */\n _onSample(position) {\n position = (position != undefined) ? position : this._to.pos;\n this.eventifyTrigger(\"change\", position);\n }\n \n /**\n * Terminate sampler\n */\n clear() {\n // stop sampling\n if (this._tid) {\n clearTimeout(this._tid);\n this._tid = undefined;\n }\n // disconnect handler\n this._to.off(this._sub);\n }\n}\n\neventify.eventifyPrototype(TimingSampler.prototype);\n\nexport default TimingSampler;","\n\n\nimport Timeout from '../util/timeout.js';\nimport * as motionutils from '../util/motionutils.js';\n\n/*\n modify modulo operation\n*/\nfunction mod(n,m) {\n return ((n % m) + m) % m; \n}\n\n/*\n divide n by m, \n find q (integer) and r such that \n n = q*m + r \n*/\nfunction divmod(n, m) {\n let q = Math.floor(n/m);\n let r = mod(n, m);\n return [q,r];\n}\n\n/**\n * point n == offset + q*stride + r\n - given stride, offset\n represent point as [q, r]\n */\n\nfunction float2point(n, stride, offset) {\n return divmod(n-offset, stride);\n}\n\nfunction point2float(p, stride, offset) {\n let [q, r] = p;\n return offset + q*stride + r;\n}\n\n\n/*\n Given stride and offset, calculate nearest\n waypoints before and after given position.\n If position is exact match with waypoint,\n return [true, before, after]\n*/\nfunction stride_points(position, stride, offset) {\n let [q, r] = float2point(position, stride, offset);\n let after = [q+1, 0];\n let before = (r == 0) ? [q-1, 0]: [q, 0];\n before = point2float(before, stride, offset);\n after = point2float(after, stride, offset);\n return [(r==0), before, after];\n};\n\n\n\n/*\n \n Position callback\n\n - callback whenever the timing object position is x, \n where (x - offset) % stride === 0\n\n - analogy to setInterval - except callbacks are in position space, not\n in time space\n\n options : {\n stride - default 1\n offset - default 0\n }\n\n NOTE: pausing on x and later resuming from x triggers callback in both cases \n\n*/\n\nclass PositionCallback {\n\n constructor (timingObject, callback, options={}) {\n this._to = timingObject;\n let {stride=1, offset=0} = options;\n this._offset = offset;\n this._stride = stride;\n this._callback = callback;\n this._timeout = new Timeout(this._to, this._handleTimeout.bind(this));\n\n // timing object timingsrc event\n this._to.on(\"timingsrc\", this._onChange.bind(this));\n }\n\n _onChange(eArg, eInfo) {\n let pos = (eArg.live) ? eArg.position : this._to.pos; \n this._renewTimeout(pos);\n }\n\n _calculateTimeout(before, after) {\n let vector = this._to.query();\n let [delta, pos] = motionutils.calculateDelta(vector, [before, after]);\n if (delta == undefined) { \n return;\n } \n // check range violation\n let [rLow, rHigh] = this._to.range;\n if (pos < rLow || rHigh < pos ) {\n return [undefined, undefined];\n }\n return [vector.timestamp + delta, pos]; \n }\n\n _renewTimeout(pos) {\n this._timeout.clear();\n // find candidate points - before and after\n let [match, before, after] = stride_points(pos,\n this._stride, \n this._offset);\n // callback\n if (match) {\n this._callback(pos);\n }\n // calculate timeout to next\n let res = this._calculateTimeout(before, after);\n if (res == undefined) {\n return;\n }\n // set timeout\n let ts = res[0];\n this._timeout.setTimeout(ts, res);\n }\n \n _handleTimeout(now, arg) {\n let pos = arg[1];\n this._renewTimeout(pos);\n }\n}\n\n\nexport default PositionCallback;","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport * as utils from '../util/utils.js';\nimport eventify from '../util/eventify.js';\nimport endpoint from '../util/endpoint.js';\nimport Interval from '../util/interval.js';\nimport BinarySearch from '../util/binarysearch.js';\nimport CueCollection from './cuecollection.js';\n\nconst Relation = Interval.Relation;\n\n/*\n UTILITY\n*/\n\nfunction epoch() {\n return Date.now();\n}\n\n\nfunction asInterval(input) {\n if (input instanceof Interval || input == undefined) {\n return input;\n }\n else if (Array.isArray(input) ) {\n // support intervals as arrays\n let [low, high, lowInclude, highInclude] = input;\n return new Interval(low, high, lowInclude, highInclude);\n } else {\n throw new Error (\"input not an Interval\", input);\n }\n}\n\n\nfunction cue_to_string(cue) {\n if (cue) {\n return `${cue.interval.toString()} ${cue.data}`;\n } else {\n return `${cue}`;\n } \n}\n\n/*\n Add cue to array\n - does not add if cue already exists\n - returns array length\n*/\nfunction addCueToArray(arr, cue) {\n // cue equality defined by key property\n if (arr.length == 0) {\n arr.push(cue);\n } else {\n let idx = arr.findIndex(function (_cue) {\n return _cue.key == cue.key;\n });\n if (idx == -1) {\n arr.push(cue);\n }\n }\n return arr.length;\n};\n\n/*\n Remove cue from array\n - noop if cue does not exist\n - returns array empty\n*/\nfunction removeCueFromArray(arr, cue) {\n // cue equality defined by key property\n if (arr.length == 1) {\n if (arr[0].key == cue.key) {\n arr.shift();\n }\n return arr.length == 0;\n }\n else if (arr.length == 0) {\n return true;\n } else {\n let idx = arr.findIndex(function (_cue) {\n return _cue.key == cue.key;\n });\n if (idx > -1) {\n arr.splice(idx, 1);\n }\n return arr.length == 0;\n }\n};\n\n/*\n Replace cue in array\n - noop if cue does not exist in array\n - returns sucess\n*/\n\nfunction replaceCueInArray (arr, cue) {\n if (arr.length == 0) {\n return false;\n } else if (arr.length == 1) {\n if (arr[0].key == cue.key) {\n arr[0] = cue;\n return true;\n }\n } else {\n let idx = arr.findIndex(function (_cue) {\n return _cue.key == cue.key;\n });\n if (idx > -1) {\n arr[idx] = cue;\n return true;\n }\n }\n return false;\n}\n\n\n/*\n Setup ID's for cue buckets.\n*/\nconst CueBucketIds = [0, 10, 100, 1000, 10000, 100000, Infinity];\nvar getCueBucketId = function (length) {\n for (let i=0; i {\n return this._submit.bind(this)();\n });\n }\n\n _push(cue_args) {\n // append cue args\n let m = this._cues.length;\n let was_empty = m == 0;\n let n = cue_args.length;\n this._cues.length += n;\n for (let i=0; i 0) {\n // batch done immediately \n // will be submitted by donePromise in next microtask\n this._done.value = true;\n }\n }\n\n _submit() {\n let result = [];\n // carry out update if necessary\n if (this._cues.length > 0) {\n result = this._ds.update(this._cues, this._options); \n }\n // reset cue arg builder\n this._reset();\n // update result\n return result;\n } \n \n /*\n add or change single cue\n \n if both interval and data are undefined\n this is not interpreted as remove,\n but as a cue with no interval and a data value set\n to undefined\n */\n addCue(key, interval, data) {\n let cue_arg = {key:key};\n cue_arg.interval = interval; \n if (arguments.length > 2) {\n cue_arg.data = data;\n }\n cue_arg = cue_check(cue_arg)\n this._push([cue_arg]);\n return this;\n }\n\n /* remove single cue */\n removeCue(key) {\n this._push([{key:key}]);\n return this;\n }\n\n /* load array of cue args into argbuilder */\n update(cue_args) {\n cue_args = cue_args.map((cue_arg) => cue_check(cue_arg));\n this._push(cue_args);\n }\n\n /* clear args currently in argbuilder */\n clear() {\n this._cues = [];\n return this;\n }\n\n /* manually submit cue args from cue arg builder */\n submit() {\n if (this._options.autosubmit) {\n throw new Error(\"manual submit while options.autosubmit is true\");\n }\n // mark batch as done\n // will be submitted by donePromise in next microtask\n this._done.value = true;\n }\n}\n\n\n/*\n this implements Dataset, a data collection supporting\n efficient lookup of cues tied to intervals on the timeline\n\n - cues may be tied to one or two points on the timeline, this\n is expressed by an Interval.\n - cues are indexed both by key and by intervals\n - the interval index is divided into a set of CueBuckets,\n based on cue interval length, for efficient lookup\n*/\n\nclass Dataset extends CueCollection {\n\n constructor(options) {\n super(options);\n\n this._map = new Map();\n this._builder = new CueArgBuilder(this);\n\n /*\n Initialise set of CueBuckets\n Each CueBucket is responsible for cues of a certain length\n */\n this._cueBuckets = new Map(); // CueBucketId -> CueBucket\n for (let i=0; i -1) {\n this._update_callbacks.splice(index, 1);\n }\n };\n\n\n _notify_callbacks (batchMap, relevanceInterval) {\n this._update_callbacks.forEach(function(handle) {\n handle.handler(batchMap, relevanceInterval);\n });\n };\n\n /***************************************************************\n MAP METHODS\n */\n\n set (key, value) {\n throw new Error(\"not implemented\");\n }\n\n delete (key) {\n throw new Error(\"not implemented\");\n }\n\n\n /***************************************************************\n CUE ARG BUILDER\n */\n \n makeBuilder(options) {\n return new CueArgBuilder(this, options);\n }\n\n // not really useful (v2 complience)\n get builder () {return this._builder;};\n\n \n /***************************************************************\n ADD CUE, REMOVE CUE\n\n - COMPATIBILTY WITH V2\n - SAFE TO USE repeatedly (batched using promise)\n */\n\n addCue(key, interval, data) {\n if (arguments.length > 2) {\n this._builder.addCue(key, interval, data);\n } else {\n this._builder.addCue(key, interval);\n }\n return this;\n }\n\n removeCue(key) {\n this._builder.removeCue(key);\n return this;\n }\n\n get updateDone() {return this._builder.updateDone};\n\n /***************************************************************\n ADD CUE, REMOVE CUE - INTERACTIVE USE\n\n - CONVENIENCE for interactive use\n - COMPATIBILTY WITH V2\n - NOT RECOMMENDED TO USE repeatedly (batched using promise)\n */\n\n _addCue(key, interval, data, options) {\n let cue = {key:key, interval:interval, data:data};\n cue = cue_check(cue);\n return this.update(cue, options);\n }\n\n _removeCue(key, options) {\n return this.update({key:key}, options);\n }\n\n /***************************************************************\n UPDATE\n\n - insert, replace or delete cues\n\n update(cues, equals, check)\n\n ordered list of cues to be updated\n - equality function for data objects\n\n cue = {\n key:key,\n interval: Interval,\n data: data\n }\n\n required\n - cue.key property is defined and value is != undefined\n - if cue.interval != undefined, it must be instance of Interval\n\n EXAMPLES\n\n // INSERT (no pre-existing cue)\n\n cue = {key:1, interval: new Interval(3,4), data: {}}\n // insert cue with only interval\n cue = {key:1, interval: new Interval(3,4)}\n // insert cue with only data\n cue = {key:1, data: {}}\n\n\n // REPLACE (pre-existing cue)\n preexisting_cue = {key:1, interval: new Interval(3,4), data: {}}\n\n cue = {key:1, interval: new Interval(3,5), data: {foo:\"bar\"}}\n // replace interval, keep data\n cue = {key:1, interval: new Interval(3,5)}\n // replace interval, delete data\n cue = {key:1, interval: new Interval(3,5), data: undefined\n // replace data, keep interval\n cue = {key:1, data: {foo:\"bar\"}}\n // replace data, delete interval\n cue = {key:1, interval: undefined, data: {foo:\"bar\"}}\n\n // DELETE (pre-existing)\n cue = {key:1}\n // delete interval, keep data\n cue = {key:1, interval: undefined}\n // delete data, keep interval\n cue = {key:1, data: undefined}\n\n\n Update returns a list of event items - describes the effects of an update.\n {\n new: new_cue,\n old: old_cue,\n delta: {\n interval: Delta,\n data: Delta\n }\n }\n\n with independent delta values for interval and data:\n Delta.NOOP: 0\n Delta.INSERT: 1\n Delta.REPLACE: 2\n Delta.DELETE: 3\n\n Duplicates\n - if there are multiple cue operations for the same key,\n within the same batch of cues,\n these will be processed in order.\n\n - The old cue will always be the state of the cue,\n before the batch started.\n\n - The returned delta values will be calcultated relative to\n the cue before the batch started (old).\n\n This way, external mirroring observers may will be able to\n replicate the effects of the update operation.\n\n ***************************************************************/\n\n\n\n\n update(cues, options = {}) {\n const batchMap = new Map();\n let current_cue;\n let has_interval, has_data;\n\n // options\n let {debug=false, equals, check_needed=true} = options;\n\n // support single cue arg for convenience\n if (!utils.isIterable(cues)) {\n cues = [cues];\n }\n\n /***********************************************************\n process all cues\n ***********************************************************/\n const epoch_ts = epoch();\n const info = {\n ts: epoch_ts,\n author: options.author\n };\n\n for (let cue of cues) {\n\n /*******************************************************\n check validity of cue argument\n *******************************************************/\n if (check_needed) {\n try {\n cue = cue_check(cue)\n } catch (err) {\n console.log(err, cue)\n continue;\n }\n }\n has_interval = cue.hasOwnProperty(\"interval\");\n has_data = cue.hasOwnProperty(\"data\");\n\n /*******************************************************\n adjust cue so that it correctly represents\n the new cue to replace the current cue\n - includes preservation of values from current cue\n *******************************************************/\n\n current_cue = this._map.get(cue.key);\n if (current_cue == undefined) {\n // make sure properties are defined\n if (!has_interval) {\n cue.interval = undefined;\n }\n if (!has_data) {\n cue.data = undefined;\n }\n } else if (current_cue != undefined) {\n if (!has_interval && !has_data) {\n // make sure properties are defined\n cue.interval = undefined;\n cue.data = undefined;\n } else if (!has_data) {\n // REPLACE_INTERVAL, preserve data\n cue.data = current_cue.data;\n } else if (!has_interval) {\n // REPLACE_DATA, preserve interval\n cue.interval = current_cue.interval;\n } else {\n // REPLACE CUE\n }\n }\n\n /*******************************************************\n update cue\n - update _map\n - update cueBuckets\n - create batchMap\n *******************************************************/\n this._update_cue(batchMap, current_cue, cue, info, options);\n }\n\n // flush all buckets so updates take effect\n this._call_buckets(\"flush\");\n\n if (batchMap.size > 0) {\n\n /*\n create events without delta property\n and accumulate relevance interval for batch\n */\n let relevance = {low: Infinity, high: -Infinity};\n\n // create list of events and remove delta property\n let items = [...batchMap.values()].map(item => {\n if (item.new && item.new.interval) {\n relevance.low = endpoint.min(relevance.low, item.new.interval.endpointLow);\n relevance.high = endpoint.max(relevance.high, item.new.interval.endpointHigh);\n }\n if (item.old && item.old.interval) {\n relevance.low = endpoint.min(relevance.low, item.old.interval.endpointLow);\n relevance.high = endpoint.max(relevance.high, item.old.interval.endpointHigh);\n }\n return {key:item.key, new:item.new, old:item.old, info: item.info};\n });\n\n // extra filter items to remove NOOP transitions\n let event_items = items.filter((item) => {\n let delta = cue_delta(item.new, item.old, equals);\n return (delta.interval != Delta.NOOP || delta.data != Delta.NOOP);\n });\n\n // event notification\n this._notifyEvents(event_items);\n\n // create relevance Interval\n let relevanceInterval = undefined;\n if (relevance.low != Infinity) {\n relevanceInterval = Interval.fromEndpoints(relevance.low, relevance.high);\n }\n\n /*\n notify sequencer last so that change event\n from the dataset will be applied before change\n events from sequencers.\n */\n this._notify_callbacks(batchMap, relevanceInterval);\n \n // debug\n if (debug) {this.integrity();}\n return items;\n }\n // debug\n if (debug) {this.integrity();}\n return [];\n };\n\n\n\n /***************************************************************\n UPDATE CUE\n\n update operation for a single cue\n\n - update _map\n - generate entry for batchMap\n - update CueBucket\n ***************************************************************/\n\n _update_cue(batchMap, current_cue, cue, info, options) {\n\n let old_cue, new_cue;\n let item, _item;\n let oldCueBucket, newCueBucket;\n let low_changed, high_changed;\n let remove_needed, add_needed;\n\n // options\n let {chaining=true, safe=false, equals} = options;\n \n if (current_cue === cue) {\n throw Error(\"illegal cue arg: same object as current cue\");\n }\n\n // check for equality\n let delta = cue_delta(current_cue, cue, equals);\n\n // (NOOP, NOOP)\n if (delta.interval == Delta.NOOP && delta.data == Delta.NOOP) {\n item = {\n key:cue.key, new:current_cue,\n old:current_cue, delta: delta\n }\n batchMap.set(cue.key, item);\n return;\n }\n\n\n /***********************************************************\n update _map and batchMap\n ***********************************************************/\n\n if (current_cue == undefined) {\n // INSERT - add cue object to _map\n\n // cue info: add if missing\n if (cue.info == undefined) {\n cue.info = {\n ts: info.ts,\n change_ts: info.ts,\n change_id: 0\n }\n }\n\n old_cue = undefined;\n new_cue = (safe)? Object.freeze(cue) : cue;\n this._map.set(cue.key, new_cue);\n\n\n } else if (cue.interval == undefined && cue.data == undefined) {\n // DELETE - remove cue object from _map\n old_cue = current_cue;\n new_cue = undefined;\n this._map.delete(cue.key);\n\n // cue info: noop\n\n } else {\n // REPLACE\n\n // cue info - update if missing\n // preserve ts from current cue, update update_ts\n if (cue.info == undefined) {\n cue.info = {\n ts: current_cue.info.ts,\n change_ts: info.ts,\n change_id: current_cue.info.change_id + 1\n };\n }\n\n /*\n Solution used to be in-place modification\n of current cue.\n Now we instead implement replace by inserting\n a new cue object as current cue.\n Since current cue is referenced both in\n _map and in pointMap - it must be replaced both\n places.\n\n Adjustments to pointMap as a result of interval\n changes are handled further down\n\n Another design option would be to let point map\n manage only keys of cues. This however would \n impose an extra map lookup per item in lookup - \n so better to pay this modest price in update\n */\n old_cue = current_cue;\n new_cue = {\n key: cue.key,\n interval: cue.interval,\n data: cue.data,\n info: cue.info\n }\n\n if (safe) {\n new_cue = Object.freeze(new_cue);\n }\n\n // replace in cue map\n this._map.set(cue.key, new_cue);\n\n // replace in point map\n // - only necessary if old cue is in pointMap\n // i.e. if old_cue has interval\n if (old_cue.interval) {\n let bid = getCueBucketId(old_cue.interval.length);\n let cueBucket = this._cueBuckets.get(bid);\n // replace for low\n cueBucket.replace_endpoint(old_cue.interval.low, new_cue);\n // replace for high\n if (!old_cue.singular) {\n cueBucket.replace_endpoint(old_cue.interval.high, new_cue);\n }\n }\n }\n item = {key:cue.key, new:new_cue, old:old_cue, delta:delta, info};\n\n /*\n if this item has been set earlier in batchMap\n restore the correct old_cue by getting it from\n the previous batchMap item\n\n recalculate delta relative to old_cue\n - continue processing with the original (delta, old_cue) defined\n above, as this is required to correctly change cueBuckets\n which have already been affected by previous item.\n */\n if (chaining) {\n _item = batchMap.get(cue.key);\n if (_item != undefined) {\n item.old = _item.old;\n item.delta = cue_delta(new_cue, item.old, equals);\n }\n }\n\n batchMap.set(cue.key, item)\n\n //console.log(\"OLD:\", cue_to_string(old_cue));\n //console.log(\"NEW:\", cue_to_string(new_cue));\n\n /***********************************************************\n update cueBuckets\n\n - use delta.interval to avoid unnessesary changes\n\n - interval may change in several ways:\n - low changed\n - high changed\n - low and high changed\n - changed intervals may stay in bucket or change bucket:\n - changing to/from singular may require special consideration\n with respect to how many endpoints are being updated\n - singular -> singular\n - singular -> regular\n - regular -> singular\n - regular -> regular\n - changes to interval.lowInclude and interval highInclude\n do not require any changes to CueBuckets, as long\n as interval.low and interval.high values stay unchanged.\n ***********************************************************/\n\n if (delta.interval == Delta.NOOP) {\n // no changes to interval - no change needed in pointMap \n return;\n } else if (delta.interval == Delta.INSERT) {\n remove_needed = false;\n add_needed = true;\n low_changed = true;\n high_changed = true;\n } else if (delta.interval == Delta.DELETE) {\n remove_needed = true;\n add_needed = false;\n low_changed = true;\n high_changed = true;\n } else if (delta.interval == Delta.REPLACE) {\n remove_needed = true;\n add_needed = true;\n low_changed = new_cue.interval.low != old_cue.interval.low;\n high_changed = new_cue.interval.high != old_cue.interval.high;\n }\n\n /*\n old cue and new cue might not belong to the same cue bucket\n */\n if (remove_needed){\n let old_bid = getCueBucketId(old_cue.interval.length);\n oldCueBucket = this._cueBuckets.get(old_bid);\n }\n if (add_needed) {\n let new_bid = getCueBucketId(new_cue.interval.length);\n newCueBucket = this._cueBuckets.get(new_bid);\n }\n\n /*\n if old CueBucket is different from the new cue Buckets\n both low and high must be moved, even it one was not\n changed\n */\n if (oldCueBucket && newCueBucket) {\n if (oldCueBucket != newCueBucket) {\n remove_needed = true;\n add_needed = true;\n low_changed = true;\n high_changed = true;\n }\n }\n\n /*\n dispatch add and remove operations for interval points\n\n cues in CueBucket may be removed using a copy of the cue,\n because remove is by key.\n\n cues added to CueBucket must be the correct object\n (current_cue), so that later in-place modifications become\n reflected in CueBucket.\n */\n\n // update low point - if changed\n if (low_changed) {\n if (remove_needed) {\n oldCueBucket.del_endpoint(old_cue.interval.low, old_cue);\n }\n if (add_needed) {\n newCueBucket.add_endpoint(new_cue.interval.low, new_cue);\n }\n }\n // update high point - if changed\n if (high_changed) {\n if (remove_needed && !old_cue.interval.singular) {\n oldCueBucket.del_endpoint(old_cue.interval.high, old_cue);\n }\n if (add_needed && !new_cue.interval.singular) {\n newCueBucket.add_endpoint(new_cue.interval.high, new_cue);\n }\n }\n }\n\n\n /*\n INTERNAL FUNCTION\n execute method across all cue buckets\n and aggregate results\n */\n _call_buckets(method, ...args) {\n const arrays = [];\n for (let cueBucket of this._cueBuckets.values()) {\n let cues = cueBucket[method](...args);\n if (cues != undefined && cues.length > 0) {\n arrays.push(cues);\n }\n }\n return utils.array_concat(arrays);\n };\n\n\n /*\n LOOKUP ENDPOINTS\n\n returns (endpoint, cue) for all endpoints covered by given interval\n\n returns:\n - [{endpoint: endpoint, cue:cue}]\n */\n\n lookup_endpoints(interval) {\n interval = asInterval(interval);\n return this._call_buckets(\"lookup_endpoints\", interval);\n };\n\n\n /*\n LOOKUP\n */\n\n lookup(interval, mask) {\n interval = asInterval(interval);\n return this._call_buckets(\"lookup\", interval, mask);\n };\n\n\n /*\n REMOVE CUES BY INTERVAL\n */\n lookup_delete(interval, mask, options={}) {\n interval = asInterval(interval);\n const cues = this._call_buckets(\"lookup_delete\", interval, mask);\n // remove from _map and make event items\n const items = [];\n const info = {\n ts: epoch(),\n author: options.author\n };\n let cue;\n for (let i=0; i cue.interval == undefined);\n\n let count_buckets = cues.length;\n let count_no_interval = no_interval_cues.length;\n let count_map = this._map.size;\n let diff = count_map - count_buckets - count_no_interval;\n if (diff != 0) {\n console.log(\"count buckets\", count_buckets);\n console.log(\"count no intervals\", count_no_interval);\n console.log(\"count map\", count_map);\n console.log(\"count diff\", diff);\n throw new Error(\"inconsistent cue count\");\n }\n\n // check that cue maps are non overlapping\n let bucket_map = new Map(cues.map(cue => [cue.key, cue]));\n let map_map = new Map([...this._map.entries()].filter(([key, cue]) => {\n return (cue.interval != undefined);\n }));\n\n let missing = utils.map_difference(bucket_map, map_map);\n if (missing.size > 0) {\n console.log(\"buckets missing cues:\")\n console.log([...missing.keys()])\n throw new Error(`buckets missing cues: ${[...missing.keys()]}`);\n }\n \n missing = utils.map_difference(map_map, bucket_map);\n if (missing.size > 0) {\n throw new Error(`buckets too many cues: ${[...missing.keys()]}`);\n }\n\n return {\n cues: cues.length,\n points: points.length\n };\n };\n\n}\n\n\nDataset.Delta = Delta;\nDataset.cue_delta = cue_delta;\nDataset.cue_equals = cue_equals;\n\n\n/*\n CueBucket is a bucket of cues limited to specific length\n*/\n\n\nclass CueBucket {\n\n\n constructor(maxLength) {\n\n // max length of cues in this bucket\n this._maxLength = maxLength;\n\n /*\n pointMap maintains the associations between values (points on\n the timeline) and cues that reference such points. A single point value may be\n referenced by multiple cues, so one point value maps to a list of cues.\n\n value -> [cue, ....]\n */\n this._pointMap = new Map();\n\n\n /*\n pointIndex maintains a sorted list of numbers for efficient lookup.\n A large volume of insert and remove operations may be problematic\n with respect to performance, so the implementation seeks to\n do a single bulk update on this structure, for each batch of cue\n operations (i.e. each invocations of addCues). In order to do this\n all cue operations are processed to calculate a single batch\n of deletes and a single batch of inserts which then will be applied to\n the pointIndex in one atomic operation.\n\n [1.2, 3, 4, 8.1, ....]\n */\n this._pointIndex = new BinarySearch();\n\n // bookeeping during batch processing\n this._created = new Set(); // point\n this._dirty = new Set(); // point\n\n };\n\n\n /*\n\n ENDPOINT BATCH PROCESSING\n\n Needs to translate endpoint operations into a minimum set of\n operations on the pointIndex.\n\n To do this, we need to record points that are created and\n points that are removed.\n\n The total difference that the batch of cue operations\n amounts to is expressed as one list of values to be\n deleted, and and one list of values to be inserted.\n The update operation of the pointIndex will process both\n in one atomic operation.\n\n On flush both the pointMap and the pointIndex will be brought\n up to speed\n\n created and dirty are used for bookeeping during\n processing of a cue batch. They are needed to\n create the correct diff operation to be applied on pointIndex.\n\n created : includes values that were not in pointMap\n before current batch was processed\n\n dirty : includes values that were in pointMap\n before current batch was processed, and that\n have been become empty at least at one point during cue\n processing.\n\n created and dirty are used as temporary alternatives to pointMap.\n after the cue processing, pointmap will updated based on the\n contents of these two.\n\n process buffers operations for pointMap and index so that\n all operations may be applied in one batch. This happens in flush\n */\n\n add_endpoint(point, cue) {\n let init = (this._pointMap.size == 0);\n let cues = (init) ? undefined : this._pointMap.get(point);\n if (cues == undefined) {\n this._pointMap.set(point, [cue]);\n this._created.add(point);\n } else {\n cues.push(cue);\n //addCueToArray(cues, cue);\n }\n }\n\n del_endpoint(point, cue) {\n let init = (this._pointMap.size == 0);\n let cues = (init) ? undefined : this._pointMap.get(point);\n if (cues != undefined) {\n let empty = removeCueFromArray(cues, cue);\n if (empty) {\n this._dirty.add(point);\n }\n }\n };\n\n /* \n in case of data update without touching the interval\n the new cue needs to be insert in place of the old\n */\n replace_endpoint(point, cue) {\n let init = (this._pointMap.size == 0);\n let cues = (init) ? undefined : this._pointMap.get(point);\n if (cues != undefined) {\n let ok = replaceCueInArray (cues, cue);\n if (!ok) {\n console.log(\"WARNING: attempt to replace non-existent cue in pointMap\")\n }\n }\n }\n\n\n /*\n Batch processing is completed\n Commit changes to pointIndex and pointMap.\n\n pointMap\n - update with contents of created\n\n pointIndex\n - points to delete - dirty and empty\n - points to insert - created and non-empty\n\n it is possible that a cue ends up in both created and dirty\n\n */\n flush() {\n if (this._created.size == 0 && this._dirty.size == 0) {\n return;\n }\n\n // update pointIndex\n let to_remove = [];\n let to_insert = [];\n for (let point of this._created.values()) {\n let cues = this._pointMap.get(point);\n if (cues.length > 0) {\n to_insert.push(point);\n } else {\n this._pointMap.delete(point);\n }\n }\n for (let point of this._dirty.values()) {\n let cues = this._pointMap.get(point);\n if (cues == undefined) {\n // point already deleted from created set - ignore\n continue;\n }\n if (cues.length == 0) {\n to_remove.push(point);\n this._pointMap.delete(point);\n }\n }\n this._pointIndex.update(to_remove, to_insert);\n // cleanup\n this._created.clear();\n this._dirty.clear();\n };\n\n\n /*\n LOOKUP_ENDPOINTS\n\n returns all (endpoint, cue) pairs where\n - endpoint is a cue endpoint (cue.endpointLow or cue.endpointHigh)\n - endpoint is INSIDE search interval\n - [{endpoint:endpoint, cue: cue}]\n\n - a given endpoint may appear multiple times in the result,\n as multiple cues may be tied to the same endpoint\n - a given cue may appear two times in the result, if\n both cue.endpointLow and cue.endpointHigh are both INSIDE interval\n - a singular cue will appear only once\n - ordering: no specific order is guaranteed\n - results are concatenated from multiple CueBuckets\n - internally in a single CueBucket\n - no defined order for cues tied to the same endpoint\n - the natural order is endpoint order\n - but this can be added on the outside if needed\n - no order is defined if two cues have exactly the\n same endpoint\n\n */\n\n lookup_endpoints(interval) {\n if (this._pointMap.size == 0) {\n return [];\n }\n const broader_interval = new Interval(interval.low, interval.high, true, true);\n const points = this._pointIndex.lookup(broader_interval);\n const result = [];\n const len = points.length;\n let point, _endpoint;\n for (let i=0; i this._maxLength) {\n return cues;\n }\n\n /*\n handle match with COVERS separately\n\n search left of search interval for cues\n that covers the search interval\n search left is limited by CueBucket maxlength\n left_interval: [interval.high-maxLength, interval.low]\n\n it would be possible to search right too, but we\n have to choose one.\n */\n if (mask & Relation.COVERS) {\n\n let left_interval;\n if (this._maxLength == Infinity) {\n // no limitation on interval length\n // must search entire timeline to the left\n left_interval = new Interval(-Infinity, interval.low);\n } else {\n let low = interval.high - this._maxLength;\n let high = interval.low;\n // protect against float rounding effects creating\n // high < low by a very small margin\n [low, high] = [Math.min(low, high), Math.max(low, high)];\n left_interval = new Interval(low, high, true, true);\n }\n this._lookup_cues(left_interval)\n .forEach(function(cue){\n if (cue.interval.match(interval, Relation.COVERS)) {\n cues.push(cue);\n }\n });\n }\n\n return cues;\n }\n\n\n /*\n REMOVE CUES\n */\n lookup_delete(interval, mask) {\n /*\n update pointMap\n - remove all cues from pointMap\n - remove empty entries in pointMap\n - record points that became empty, as these need to be deleted in pointIndex\n - separate into two bucketes, inside and outside\n */\n const cues = this.lookup(interval, mask);\n const to_remove = [];\n let cue, point, points;\n for (let i=0; i 0) {\n throw new Error(`pointMap missing points: ${[...missing]}`);\n }\n \n missing = utils.set_difference(map_point_set, index_point_set);\n if (missing.size > 0) {\n throw new Error(`pointIndex missing points: ${[...missing]}`);\n }\n }\n\n /*\n invariable - pointIndex shall always be sorted and not contain duplicates\n */\n let points = [...this._pointIndex.values()];\n if (points.length != index_point_set.size) {\n throw new Error(\"pointIndex include duplicate points\");\n }\n for (let i=1; i= points[i]) {\n throw new Error(\"pointIndex not ordered\");\n } \n }\n\n /**\n * invariable - pointMap point -> cues \n * cues shall only include cues which are relevant to given point\n */\n for (let point of points) {\n let cues = this._pointMap.get(point);\n for (let cue of cues) {\n // figure out if point is endpoint low or high\n if (point == cue.interval.low) {\n continue;\n } else if (point == cue.interval.high) {\n continue;\n } else {\n console.log(\"POINT:\", point); \n console.log(\"CUE:\", cue.interval.toString());\n throw new Error(\"pointMap: wrong cue\");\n }\n } \n }\n\n\n /**\n * invariable - all endpoints from all cues from pointMap are found as points in pointMap\n */\n\n for (let _cue_list of [...this._pointMap.values()]) {\n for (let cue of _cue_list) {\n for (let p of [cue.interval.low, cue.interval.high]) {\n if (!this._pointMap.has(p)) {\n throw new Error(`cue found with low or high point not in pointMap ${p} -> ${cue.interval.toString()} `);\n }\n }\n }\n }\n\n\n /*\n invariable - all cues in pointMap with same key are same object\n */\n\n // collect all cues from pointMap\n let _cues = [];\n for (let _cue_list of this._pointMap.values()) {\n for (let cue of _cue_list) {\n _cues.push(cue);\n }\n }\n\n // remove and check duplicates\n let cueMap = new Map();\n for (let cue of _cues) {\n let _cue = cueMap.get(cue.key);\n if (_cue == undefined) {\n cueMap.set(cue.key, cue);\n } else {\n // duplicate\n if (cue !== _cue) {\n throw new Error(\"pointMap: different cue objects for same key\");\n }\n }\n }\n let cues = [...cueMap.values()];\n\n /**\n * invariable - all cues belong to this bucket\n */\n\n for (let cue of cues.values()) {\n // check that cue belongs to this bucket\n if (cue.interval.length > this._maxLength) {\n throw new Error(`cue in wrong cue bucket ${this._maxLength}, ${cue.interval.toString()}`);\n }\n }\n\n return [{\n maxLength: this._maxLength,\n points: [...this._pointMap.keys()],\n cues: cues\n }];\n };\n}\n\n// module definition\nexport default Dataset;\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n\nimport endpoint from '../util/endpoint.js';\nimport Interval from '../util/interval.js';\nimport Timeout from '../util/timeout.js';\nimport * as motionutils from '../util/motionutils.js';\n\nconst pft = motionutils.posInterval_from_timeInterval;\n\nfunction queueCmp(a,b) {\n return endpoint.cmp(a.tsEndpoint, b.tsEndpoint);\n};\n\n// Default lookahead in seconds\nconst LOOKAHEAD = 5\n\nclass Schedule {\n\n constructor(dataset, to, options) {\n // timingobject\n this.to = to;\n // current timeout\n this.timeout = new Timeout(to, this.run.bind(this));\n // current vector\n this.vector;\n // current time interval\n this.timeInterval;\n // current position interval\n this.posInterval;\n // dataset\n this.dataset = dataset;\n // task queue\n this.queue = [];\n // callbacks\n this.callbacks = [];\n // options\n options = options || {};\n options.lookahead = options.lookahead || LOOKAHEAD;\n this.options = options;\n }\n\n\n /***************************************************************\n CALLBACKS\n ***************************************************************/\n\n add_callback (handler) {\n let handle = {\n handler: handler\n }\n this.callbacks.push(handle);\n return handle;\n };\n\n del_callback (handle) {\n let index = this.callbacks.indexof(handle);\n if (index > -1) {\n this.callbacks.splice(index, 1);\n }\n };\n\n _notify_callbacks (...args) {\n this.callbacks.forEach(function(handle) {\n handle.handler(...args);\n });\n };\n\n /***************************************************************\n MOTION CHANGE\n ***************************************************************/\n\n /*\n update schedule with new motion vector\n */\n setVector(vector) {\n let now = vector.timestamp;\n // clean up current motion\n let current_vector = this.vector;\n if (this.vector != undefined) {\n this.timeout.clear();\n this.timeInterval = undefined;\n this.posInterval = undefined;\n this.queue = [];\n }\n // update vector\n this.vector = vector;\n // start scheduler if moving\n if (motionutils.isMoving(this.vector)) {\n this.run(now);\n }\n }\n\n\n /***************************************************************\n TASK QUEUE\n ***************************************************************/\n\n /*\n push eventItem onto queue\n */\n push(eventItems) {\n eventItems.forEach(function(item) {\n if (this.timeInterval.covers_endpoint(item.tsEndpoint)) {\n // note - this test has also been done within the load function\n this.queue.push(item);\n }\n }, this);\n // maintain ordering\n this.queue.sort(queueCmp);\n };\n\n /*\n pop due eventItems from queue\n */\n pop(now) {\n let eventItem, res = [];\n let len = this.queue.length;\n while (this.queue.length > 0 && this.queue[0].tsEndpoint[0] <= now) {\n res.push(this.queue.shift());\n }\n return res;\n };\n\n /*\n return timestamp of next eventItem\n */\n next() {\n return (this.queue.length > 0) ? this.queue[0].tsEndpoint[0]: undefined;\n }\n\n\n /***************************************************************\n ADVANCE TIMEINTERVAL/POSINTERVAL\n ***************************************************************/\n\n\n /*\n advance timeInterval and posInterval if needed\n */\n advance(now) {\n let start, delta = this.options.lookahead;\n let advance = false;\n if (this.timeInterval == undefined) {\n start = now;\n advance = true;\n } else if (endpoint.leftof(this.timeInterval.endpointHigh, now)) {\n start = this.timeInterval.high;\n advance = true\n }\n if (advance) {\n // advance intervals\n this.timeInterval = new Interval(start, start + delta, true, false);\n // calculate position interval\n // ensure that floats only have limited precision (10 decimals)\n // or else interval comparisons may not be safe.\n this.posInterval = pft(this.timeInterval, this.vector);\n // clear task queue\n this.queue = [];\n }\n return advance;\n }\n\n\n /***************************************************************\n LOAD\n ***************************************************************/\n\n /*\n load events\n */\n\n load(endpoints, minimum_tsEndpoint) {\n let endpointEvents = motionutils.endpointEvents(this.timeInterval,\n this.posInterval,\n this.vector,\n endpoints);\n\n\n /*\n ISSUE 1\n\n Range violation might occur within timeInterval.\n All endpointEvents with .tsEndpoint later or equal to range\n violation will be cancelled.\n */\n let range_ts = motionutils.rangeIntersect(this.vector, this.to.range)[0];\n\n /*\n ISSUE 2\n\n If load is used in response to dynamically added cues, the\n invocation of load might occor at any time during the timeInterval,\n as opposed to immediately after the start of timeInterval.\n This again implies that some of the endPointEvents we have found\n from the entire timeInterval might already be historic at time of\n invocation.\n\n Cancel endpointEvents with .tsEndpoint < minimum_ts.\n\n For regular loads this will have no effect since we\n do not specify a minimum_ts, but instead let it assume the\n default value of timeInterval.low.\n */\n if (minimum_tsEndpoint == undefined) {\n minimum_tsEndpoint = this.timeInterval.endpointLow;\n }\n\n /*\n ISSUE 3\n\n With acceleration the motion might change direction at\n some point, which might also be a cue endpoint. In this\n case, motion touches the cue endpoint but does not actually\n cross over it.\n\n For simplicity we say that this should not change the\n active state of that cue. The cue is either not activated\n or not inactivated by this occurrence. We might therefor\n simply drop such endpointEvents.\n\n To detect this, note that velocity will be exactly 0\n evaluated at the cue endpoint, but acceleration will be nonzero.\n\n Importantly, there is one exception. Dropping such events\n should only happen when 0 velocity is reached during motion,\n not at the start of a motion. For instance, in the case of\n starting with acceleration but no velocity, from a cue\n endpoint, this event should not be dropped.\n This is avoided by requiring that the tsEndpoint is not\n equal to timeInterval.endpointLow\n\n */\n\n return endpointEvents.filter(function(item) {\n // ISSUE 1\n if (range_ts <= item.tsEndpoint[0]) {\n return false;\n }\n\n // ISSUE 2\n if (endpoint.leftof(item.tsEndpoint, minimum_tsEndpoint)) {\n return false;\n }\n\n // ISSUE 3\n // checks every event. alternative approach would be\n // to calculate the ts of this event once, and compare\n // the result to the ts of all event\n if (this.vector.acceleration != 0.0) {\n let ts = item.tsEndpoint[0];\n if (ts > this.timeInterval.endpointLow[0]) {\n let v = motionutils.calculateVector(this.vector, ts);\n if (v.position == item.endpoint[0] && v.velocity == 0) {\n return false;\n }\n }\n }\n return true;\n }, this);\n }\n\n\n /***************************************************************\n RUN\n ***************************************************************/\n\n /*\n run schedule\n */\n run(now) {\n\n /*\n function events2string(events) {\n return events.map((e) => {\n return `${e.cue.key} -> ${endpoint.toString(e.endpoint)}`;\n });\n }\n */\n\n // process - due events\n let dueEvents = this.pop(now);\n\n /*\n if (dueEvents.length > 0) {\n console.log(\"due\", events2string(dueEvents));\n }\n */\n\n // advance schedule and load events if needed\n if (this.advance(now)) {\n // fetch cue endpoints for posInterval\n let endpointItems = this.dataset.lookup_endpoints(this.posInterval);\n\n /*\n if (endpointItmes.length > 0) {\n console.log(\"fetch\", events2string(endpointItems));\n }\n */\n\n // load events and push on queue\n let loaded = this.load(endpointItems);\n this.push(loaded);\n\n /*\n if (loaded.length > 0) {\n console.log(\"load\", events2string(loaded));\n }\n */\n\n // POP ADVANCE\n // process - possibly new due events\n let popped = this.pop(now);\n\n /*\n if (popped.length > 0) {\n console.log(\"due-immediate\", events2string(popped));\n }\n */\n dueEvents.push(...popped);\n }\n if (dueEvents.length > 0) {\n this._notify_callbacks(now, dueEvents, this);\n }\n // timeout - until next due event\n let ts = this.next() || this.timeInterval.high;\n this.timeout.setTimeout(Math.min(ts, this.timeInterval.high));\n }\n}\n\nexport default Schedule;\n\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport {map_intersect, map_difference} from '../util/utils.js';\nimport Interval from '../util/interval.js';\nimport CueCollection from '../dataset/cuecollection.js';\nimport Dataset from '../dataset/dataset.js';\n\n\nfunction isNoop(delta) {\n return (delta.interval == Dataset.Delta.NOOP && delta.data == Dataset.Delta.NOOP);\n}\n\n\n/*******************************************************************\n ACTIVE MAP\n*******************************************************************/\n/*\n\n This table describes cue changes to/from active state\n based on\n\n - to_role - the role of the timing object\n\n in the case of the double sequencer a timing object\n may be *LEFT* (L), *RIGHT* (R) or, in the corner case that\n the two timing objects are at the same position,\n *SINGULAR* (S)\n\n in the case of the single sequencer, the role is\n always *SINGULAR* (S)\n\n\n - to_direction - the direction of the movement of the\n timing object, either *RIGHT* (R) or *LEFT* (L)\n\n This map is only used when timing object is in a\n moving state, so *PAUSED* (P) is not needed.\n\n - endpoint_type - the type of endpoint which is\n passed by the timing object during motion, either\n *LEFT* (R) endpoint or *RIGHT* (R) endpoint, or\n *SINGULAR* (S) endpoint.\n\n - cue_change\n *ENTER* : cue changes from not active to active\n *EXIT*: cue changes from active to not active\n *STAY*: cue stays active\n *ENTER-EXIT*: cue changes from not active to active,\n and immediately back agoind to not active\n This only occurs when a *SINGULAR*\n timing object passed a *SINGULAR* cue.\n\n\n Table columns are:\n\n | to_role | to_direction | endpoint_type | cue change |\n\n left, right, left -> stay\n left, right, right -> exit\n left, right, singular -> exit\n\n left, left, left -> stay\n left, left, right -> enter\n left, left, singular -> enter\n\n right, right, left -> enter\n right, right, right -> stay\n right, right, singular -> enter\n\n right, left, left -> exit\n right, left, right -> stay\n right, left, singular -> exit\n\n // cornercase - timing objects are the same\n\n singular, right, left -> enter\n singular, right, right -> exit\n singular, right, singular -> enter, exit\n\n singular, left, left -> exit\n singular, left, right -> enter\n singular, left, singular -> enter, exit\n\n*/\n\nconst Active = Object.freeze({\n ENTER: 1,\n STAY: 0,\n EXIT: -1,\n ENTER_EXIT: 2\n});\n\nconst ActiveMap = new Map([\n [\"LRL\", Active.STAY],\n [\"LRR\", Active.EXIT],\n [\"LRS\", Active.EXIT],\n [\"LLL\", Active.STAY],\n [\"LLR\", Active.ENTER],\n [\"LLS\", Active.ENTER],\n [\"RRL\", Active.ENTER],\n [\"RRR\", Active.STAY],\n [\"RRS\", Active.ENTER],\n [\"RLL\", Active.EXIT],\n [\"RLR\", Active.STAY],\n [\"RLS\", Active.EXIT],\n [\"SRL\", Active.ENTER],\n [\"SRR\", Active.EXIT],\n [\"SRS\", Active.ENTER_EXIT],\n [\"SLL\", Active.EXIT],\n [\"SLR\", Active.ENTER],\n [\"SLS\", Active.ENTER_EXIT]\n]);\n\n\n\n/*******************************************************************\n DEFAULT EVENT ITEM ORDERING\n*******************************************************************/\n\nfunction cue_cmp_forwards (cue_a, cue_b) {\n return Interval.cmpLow(cue_a.interval, cue_b.interval);\n}\n\nfunction cue_cmp_backwards (cue_a, cue_b) {\n return -1 * Interval.cmpHigh(cue_a.interval, cue_b.interval);\n}\n\nfunction item_cmp_forwards (item_a, item_b) {\n let cue_a = (item_a.new) ? item_a.new : item_a.old;\n let cue_b = (item_b.new) ? item_b.new : item_b.old;\n return cue_cmp_forwards(cue_a, cue_b);\n}\n\nfunction item_cmp_backwards (item_a, item_b) {\n let cue_a = (item_a.new) ? item_a.new : item_a.old;\n let cue_b = (item_b.new) ? item_b.new : item_b.old;\n return cue_cmp_backwards(cue_a, cue_b);\n}\n\n/*******************************************************************\n BASE SEQUENCER\n*******************************************************************/\n\n/*\n This is an abstract base class for sequencers\n It implements common logic related to Dataset, events and activeCues.\n*/\n\nclass BaseSequencer extends CueCollection {\n\n\n constructor (dataset, options) {\n super(options);\n\n // Active cues\n this._map = new Map();\n\n // Dataset\n this._ds = dataset;\n let cb = this._onDatasetCallback.bind(this)\n this._ds_cb = this._ds.add_callback(cb);\n }\n\n /**\n * CueCollection (ObservableMap) needs access to map \n */\n get datasource () {\n return this._map;\n }\n\n /**\n * Access to dataset of sequencer\n */\n\n get dataset () { \n return this._ds;\n }\n\n /***************************************************************\n EVENTS\n ***************************************************************/\n\n /*\n Get the direction of movement\n To be implemented by subclass\n */\n _movementDirection() {\n throw new Error(\"not implemented\");\n }\n\n // override ObservableMap.sortValues to add special support for\n // direction sensitive ordering as default ordering\n sortValues(iter, options={}) {\n let order = this.sortOrder(options);\n if (typeof order == \"function\") {\n // use order specified by options\n return super.sortValues(iter, options)\n } else {\n // if iterable not array - convert into array ahead of sorting\n let cues = (Array.isArray(iter)) ? iter : [...iter];\n // default order is direction sensitive\n let direction = this._movementDirection();\n if (direction >= 0) {\n cues.sort(cue_cmp_forwards);\n } else {\n cues.sort(cue_cmp_backwards);\n }\n return cues\n } \n }\n\n\n // override ObservableMap.sortItems to add special support for\n // direction sensitive ordering as default ordering\n sortItems(items, direction) {\n let order = this.sortOrder(); \n if (typeof order == \"function\") {\n // use order specified by options\n return super.sortItems(items) \n } \n if (order == undefined) {\n // default order is direction sensitive\n if (direction == undefined) {\n direction = this._movementDirection();\n }\n if (direction >= 0) {\n items.sort(item_cmp_forwards);\n } else {\n items.sort(item_cmp_backwards);\n }\n }\n }\n\n /***************************************************************\n MAP METHODS\n ***************************************************************/\n\n set (key, value) {\n throw new Error(\"not implemented\");\n }\n\n delete (key) {\n throw new Error(\"not implemented\");\n }\n\n clear (key) {\n throw new Error(\"not implemented\");\n }\n\n /***************************************************************\n DATASET\n ***************************************************************/\n\n _onDatasetCallback(eventMap, relevanceInterval) {\n throw new Error(\"not implemented\");\n }\n\n /*\n make exit, change and enter events\n - based on eventMap\n */\n _items_from_dataset_events(eventMap, interval) {\n const enterEvents = [];\n const changeEvents = [];\n const exitEvents = [];\n const first = this._map.size == 0;\n let is_active, should_be_active, _item;\n for (let item of eventMap.values()) {\n if (isNoop(item.delta)) {\n continue;\n }\n // exit, change, enter events\n is_active = (first) ? false : this._map.has(item.key);\n should_be_active = false;\n if (item.new != undefined) {\n if (item.new.interval.match(interval)) {\n should_be_active = true;\n }\n }\n if (is_active && !should_be_active) {\n // exit\n _item = {key:item.key, new:undefined, old:item.old, info:item.info};\n exitEvents.push(_item);\n } else if (!is_active && should_be_active) {\n // enter\n _item = {key:item.key, new:item.new, old:undefined, info:item.info};\n enterEvents.push(_item);\n } else if (is_active && should_be_active) {\n // change\n _item = {key:item.key, new:item.new, old:item.old, info:item.info};\n changeEvents.push(_item);\n }\n };\n return [exitEvents, changeEvents, enterEvents];\n }\n\n /*\n make exit, change and enter events\n - based on dataset.lookup\n */\n _items_from_dataset_lookup(eventMap, interval) {\n\n /*\n Active cues\n\n find new set of active cues by querying the dataset\n */\n const _activeCues = new Map(this._ds.lookup(interval).map(function(cue) {\n return [cue.key, cue];\n }));\n\n let changeEvents = [];\n let exitEvents = [];\n let first = (this._map.size == 0);\n if (!first){\n\n /*\n Change Events\n\n change cues - cues which are modified, yet remain active cues\n */\n let remainCues = map_intersect(this._map, _activeCues);\n if (remainCues.size > 0) {\n /*\n Two approaches\n\n 1) large eventMap\n eventMap larger than remainCues\n - iterate remainCues\n - keep those that are found in eventMap\n\n 2) large remainCues\n remainCues larger than eventMap\n - iterate eventMap\n - keep those that are found in remainCues\n\n measurement shows that 2) is better\n */\n let cue, _item;\n for (let item of eventMap.values()) {\n cue = remainCues.get(item.key);\n if (cue != undefined && !isNoop(item.delta)) {\n _item = {key:item.key, new:item.new, old:item.old};\n changeEvents.push(_item);\n }\n }\n }\n\n /*\n Exit Events\n exit cues were in old active cues - but not in new\n */\n let exitCues = map_difference(this._map, _activeCues);\n exitEvents = [...exitCues.values()]\n .map(cue => {\n return {key:cue.key, new:undefined, old:cue};\n });\n }\n\n /*\n Enter Events\n enter cues were not in old active cues - but are in new\n */\n let enterCues;\n if (first) {\n enterCues = _activeCues\n } else {\n enterCues = map_difference(_activeCues, this._map);\n }\n let enterEvents = [...enterCues.values()]\n .map(cue => {\n return {key:cue.key, new:cue, old:undefined};\n });\n\n /*\n Preserve .info from eventMap\n */\n for (let eventList in [exitEvents, changeEvents, enterEvents]) {\n for (let item of eventList) {\n let _item = eventMap.get(item.key);\n if (_item != undefined) {\n item.info = _item.info;\n }\n } \n }\n\n return [exitEvents, changeEvents, enterEvents];\n }\n\n /***************************************************************\n V2 COMPATIBILTY\n\n Sequencers forward dataset operation to datase\n ***************************************************************/\n\n get builder() {\n return this.dataset.builder;\n }\n\n addCue(key, interval, data) {\n return this.dataset.addCue(key, interval, data);\n }\n\n removeCue(key) {\n return this.dataset.removeCue(key);\n }\n\n _addCue(key, interval, data) {\n return this.dataset._addCue(key, interval, data);\n }\n\n _removeCue(key) {\n return this.dataset._removeCue(key);\n }\n\n update(cues, options) {\n return this.dataset.update(cues, options);\n }\n\n clear() {\n return this.dataset.clear();\n }\n\n hasCue(key) {\n return this.dataset.has(key);\n }\n\n getCue(key) {\n return this.dataset.get(key);\n }\n\n getCues() {\n return this.dataset.cues();\n }\n\n getActiveKeys() {\n return [...this.keys()];\n }\n\n getActiveCues() {\n return this.cues();\n }\n\n isActive(key) {\n return this.has(key);\n }\n\n}\n\nBaseSequencer.Active = Active;\nBaseSequencer.ActiveMap = ActiveMap;\n\n\nexport default BaseSequencer;\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport {array_concat, map_difference} from '../util/utils.js';\nimport Interval from '../util/interval.js';\nimport * as motionutils from '../util/motionutils.js';\nimport Schedule from './schedule.js';\nimport BaseSequencer from './basesequencer.js';\n\nconst PosDelta = motionutils.MotionDelta.PosDelta;\nconst MoveDelta = motionutils.MotionDelta.MoveDelta;\nconst Active = BaseSequencer.Active;\nconst ActiveMap = BaseSequencer.ActiveMap;\n\nconst EVENTMAP_THRESHOLD = 5000;\nconst ACTIVECUES_THRESHOLD = 5000;\n\n\nclass PointModeSequencer extends BaseSequencer {\n\n constructor (dataset, to, options) {\n\n super(dataset, options);\n\n // Timing Object\n this._to = to;\n this._sub = this._to.on(\"timingsrc\", this._onTimingCallback.bind(this));\n\n // Schedule\n this._sched = new Schedule(this._ds, to);\n let cb = this._onScheduleCallback.bind(this);\n this._sched_cb = this._sched.add_callback(cb)\n }\n\n\n /*\n Implement movement direction from single timing object\n */\n _movementDirection() {\n const now = this._to.clock.now();\n return motionutils.calculateDirection(this._to.vector, now);\n }\n\n\n /***************************************************************\n DATASET CALLBACK\n ***************************************************************/\n\n /*\n Handling Dataset Update Callbacks\n */\n\n _onDatasetCallback(eventMap, relevanceInterval) {\n /*\n process dataset events which are relevant to the set\n of activeCues, or to the immediate future (schedule)\n\n enterCues - inactive -> active\n changeCues - active -> active, but changed\n exitCues - active -> inactive\n\n Two approaches\n - 1) EVENTS: filter list of events - compare to current active cues\n - 2) LOOKUP: regenerate new activeCues by looking up set of\n active cues from dataset, compare it to current active cues\n\n\n EventMap.size < about 1K-10K (5K)\n - EVENTS better or equal\n EventMap.size > about 5K\n - LOOKUP better\n - exception\n - If activeCues.size > 1K-10K (5K) - EVENTS BETTER\n\n If new cues are predominantly active cues, EVENTS are\n always better - and more so for larger sets of events.\n However, there is no information about this\n before making the choice, and also this is a somewhat\n unlikely scenario.\n\n So, the simple policy above works for typical workloads,\n where the majority of added cues are inactive.\n */\n\n if (!this._to.isReady()) {\n return;\n }\n\n if (relevanceInterval == undefined) {\n return;\n }\n\n const now = this._to.clock.now();\n const now_vector = motionutils.calculateVector(this._to.vector, now);\n\n // activeInterval\n const activeInterval = new Interval(now_vector.position);\n\n if (!activeInterval.match(relevanceInterval, Interval.Match.OUTSIDE)) {\n // relevanceInterval is NOT outside activeInterval\n // some events relevant for activeIntervale\n\n // choose approach to get events\n let get_items = this._items_from_dataset_events.bind(this);\n if (EVENTMAP_THRESHOLD < eventMap.size) {\n if (this._map.size < ACTIVECUES_THRESHOLD) {\n get_items = this._items_from_dataset_lookup.bind(this);\n }\n }\n\n // get items\n const [exit, change, enter] = get_items(eventMap, activeInterval);\n\n // update activeCues\n exit.forEach(item => {\n this._map.delete(item.key);\n });\n change.forEach(item => {\n this._map.set(item.key, item.new);\n });\n enter.forEach(item => {\n this._map.set(item.key, item.new);\n });\n\n // sort event items according to general movement direction\n let direction = motionutils.calculateDirection(now_vector);\n this.sortItems(exit, direction);\n this.sortItems(change, direction);\n this.sortItems(enter, direction);\n\n // notifications\n const items = array_concat([exit, change, enter], {copy:true, order:true});\n\n // event notification\n this._notifyEvents(items);\n }\n\n /*\n clear schedule\n\n This is only necessary if a cue interval is changed,\n and the change is relevant within the posInterval of\n of the schedule. RelevanceInterval to figure this out.\n */\n if (this._sched.posInterval) {\n if (!this._sched.posInterval.match(relevanceInterval, Interval.Match.OUTSIDE)) {\n // relevanceInterval is NOT outside schedule posInterval\n // refresh schedule\n this._sched.setVector(now_vector);\n }\n }\n }\n\n\n /***************************************************************\n TIMING OBJECT CALLBACK\n ***************************************************************/\n\n _onTimingCallback (eArg) {\n /*\n If update is the initial vector from the timing object,\n we set current time as the official time for the update.\n Else, the new vector is \"live\" and we use the timestamp\n when it was created as the official time for the update.\n This is represented by the new_vector.\n\n REMOVE SUPPOERT FOR LIVE\n */\n /*\n let new_vector;\n if (eArg.live) {\n new_vector = eArg;\n } else {\n // make a live vector from to vector\n new_vector = motionutils.calculateVector(eArg, this._to.clock.now());\n }\n */\n let new_vector = motionutils.calculateVector(eArg, this._to.clock.now());\n\n\n /*\n The nature of the vector change\n */\n let delta = new motionutils.MotionDelta(this._to.old_vector, new_vector);\n\n /*\n Reevaluate active state.\n This is required after any discontinuity of the position (jump),\n or if the motion stopped without jumping (pause or halt at range\n restriction)\n */\n if (delta.posDelta == PosDelta.CHANGE || delta.moveDelta == MoveDelta.STOP) {\n // make position interval\n let low = new_vector.position;\n let high = new_vector.position;\n let itv = new Interval(low, high, true, true);\n // new active cues\n let activeCues = new Map(this._ds.lookup(itv).map(cue => {\n return [cue.key, cue];\n }));\n // exit cues - in old activeCues but not in new activeCues\n let exitCues = map_difference(this._map, activeCues);\n // enter cues - not in old activeCues but in new activeCues\n let enterCues = map_difference(activeCues, this._map);\n // update active cues\n this._map = activeCues;\n\n // make event items\n let exitItems = [...exitCues.values()].map(cue => {\n return {key:cue.key, new:undefined, old:cue};\n });\n let enterItems = [...enterCues.values()].map(cue => {\n return {key:cue.key, new:cue, old:undefined};\n }); \n\n // sort event items according to general movement direction\n let direction = motionutils.calculateDirection(new_vector);\n this.sortItems(exitItems, direction);\n this.sortItems(enterItems, direction);\n\n // notifications\n const items = array_concat([exitItems, enterItems], {copy:true, order:true});\n\n // event notification\n this._notifyEvents(items);\n }\n\n /*\n Handle Timing Object Moving\n */\n this._sched.setVector(new_vector);\n };\n\n\n /***************************************************************\n SCHEDULE CALLBACK\n ***************************************************************/\n\n _onScheduleCallback = function(now, endpointItems, schedule) {\n\n if (!this._to.isReady()) {\n return;\n }\n\n\n const items = [];\n endpointItems.forEach(function (item) {\n let cue = item.cue;\n let has_cue = this._map.has(cue.key);\n let [value, right, closed, singular] = item.endpoint;\n\n /*\n Action Code - see sequenceutils\n */\n // to role\n let to_role = \"S\";\n // movement direction\n let to_dir = (item.direction > 0) ? \"R\" : \"L\";\n // endpoint type\n let ep_type = (singular) ? \"S\": (right) ? \"R\" : \"L\";\n // action code, enter, exit, stay, enter-exit\n let action_code = ActiveMap.get(`${to_role}${to_dir}${ep_type}`);\n\n if (action_code == Active.ENTER_EXIT) {\n if (has_cue) {\n // exit\n items.push({key:cue.key, new:undefined, old:cue});\n this._map.delete(cue.key);\n } else {\n // enter\n items.push({key:cue.key, new:cue, old:undefined});\n // exit\n items.push({key:cue.key, new:undefined, old:cue});\n // no need to both add and remove from activeCues\n }\n } else if (action_code == Active.ENTER) {\n if (!has_cue) {\n // enter\n items.push({key:cue.key, new:cue, old:undefined});\n this._map.set(cue.key, cue);\n }\n } else if (action_code == Active.EXIT) {\n if (has_cue) {\n // exit\n items.push({key:cue.key, new:undefined, old:cue});\n this._map.delete(cue.key);\n }\n }\n }, this);\n\n // Event items already sorted\n\n // event notification\n this._notifyEvents(items);\n };\n}\n\nexport default PointModeSequencer;\n\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport {array_concat, map_difference} from '../util/utils.js';\nimport Interval from '../util/interval.js';\nimport * as motionutils from '../util/motionutils.js';\nimport Schedule from './schedule.js';\nimport BaseSequencer from './basesequencer.js';\n\nconst PosDelta = motionutils.MotionDelta.PosDelta;\nconst MoveDelta = motionutils.MotionDelta.MoveDelta;\nconst Active = BaseSequencer.Active;\nconst ActiveMap = BaseSequencer.ActiveMap;\n\nconst EVENTMAP_THRESHOLD = 5000;\nconst ACTIVECUES_THRESHOLD = 5000;\n\n/*\n calculate general movement direction for double sequencer\n define movement direction as the aggregate movement direction\n for both timing objects\n*/\nfunction movement_direction (now_vector_A, now_vector_B) {\n let direction_A = motionutils.calculateDirection(now_vector_A);\n let direction_B = motionutils.calculateDirection(now_vector_B);\n let direction = direction_A + direction_B;\n return (direction > 0) ? 1 : (direction < 0) ? -1 : 0;\n}\n\n\nclass IntervalModeSequencer extends BaseSequencer {\n\n constructor (dataset, toA, toB, options) {\n\n super(dataset, options);\n\n // Timing objects\n this._toA = toA;\n this._toA_ready = false;\n this._toB = toB;\n this._toB_ready = false;\n let to_cb = this._onTimingCallback.bind(this);\n this._subA = this._toA.on(\"timingsrc\", to_cb);\n this._subB = this._toB.on(\"timingsrc\", to_cb);\n\n // Schedules\n let sched_cb = this._onScheduleCallback.bind(this);\n this._schedA = new Schedule(this._ds, toA);\n this._schedA_cb = this._schedA.add_callback(sched_cb);\n this._schedB = new Schedule(this._ds, toB);\n this._schedB_cb = this._schedB.add_callback(sched_cb);\n\n this._toA_vector;\n this._toB_vector;\n }\n\n\n _isReady() {\n return (this._toA_ready && this._toB_ready);\n }\n\n\n /*\n Implement movement direction from two timing objects\n */\n\n _movementDirection() {\n const now = this._toA.clock.now();\n const now_vector_A = motionutils.calculateVector(this._toA.vector, now);\n const now_vector_B = motionutils.calculateVector(this._toB.vector, now);\n return movement_direction(now_vector_A, now_vector_B);\n }\n\n /***************************************************************\n DATASET CALLBACK\n ***************************************************************/\n\n /*\n Handling Dataset Update Callbacks\n */\n _onDatasetCallback(eventMap, relevanceInterval) {\n if (!this._isReady()) {\n return;\n }\n\n if (relevanceInterval == undefined) {\n return;\n }\n\n // assuming both timing objects have the same clock\n const now = this._toA.clock.now();\n const now_vector_A = motionutils.calculateVector(this._toA_vector, now);\n const now_vector_B = motionutils.calculateVector(this._toB_vector, now);\n\n // active interval\n let [pos_A, pos_B] = [now_vector_A.position, now_vector_B.position];\n let [low, high] = (pos_A <= pos_B) ? [pos_A, pos_B] : [pos_B, pos_A];\n const activeInterval = new Interval(low, high, true, true);\n\n if (!activeInterval.match(relevanceInterval, Interval.Match.OUTSIDE)) {\n // relevanceInterval is NOT outside activeInterval\n // some events relevant for activeIntervale\n\n // choose approach to get events\n let get_items = this._items_from_dataset_events.bind(this);\n if (EVENTMAP_THRESHOLD < eventMap.size) {\n if (this._map.size < ACTIVECUES_THRESHOLD) {\n get_items = this._items_from_dataset_lookup.bind(this);\n }\n }\n\n // get items\n const [exit, change, enter] = get_items(eventMap, activeInterval);\n\n // update activeCues\n exit.forEach(item => {\n this._map.delete(item.key);\n });\n change.forEach(item => {\n this._map.set(item.key, item.new);\n });\n enter.forEach(item => {\n this._map.set(item.key, item.new);\n });\n\n // sort event items according to general movement direction\n let direction = movement_direction(now_vector_A, now_vector_B);\n this.sortItems(exit, direction);\n this.sortItems(change, direction);\n this.sortItems(enter, direction);\n\n // notifications\n const items = array_concat([exit, change, enter], {copy:true, order:true});\n \n // event notification\n this._notifyEvents(items, direction);\n }\n\n\n /*\n clear schedules\n\n This is only necessary if a cue interval is changed,\n and the change is relevant within the posInterval of\n one of the schedules. RelevanceInterval to figure this out.\n */\n\n if (this._schedA.posInterval) {\n if (!this._schedA.posInterval.match(relevanceInterval, Interval.Match.OUTSIDE)) {\n // relevanceInterval is NOT outside schedule posInterval\n // refresh schedule\n this._schedA.setVector(now_vector_A);\n }\n }\n\n if (this._schedB.posInterval) {\n if (!this._schedB.posInterval.match(relevanceInterval, Interval.Match.OUTSIDE)) {\n // relevanceInterval is NOT outside schedule posInterval\n // refresh schedule\n this._schedB.setVector(now_vector_B);\n }\n }\n }\n\n\n /***************************************************************\n TIMING OBJECT CALLBACK\n ***************************************************************/\n\n /*\n Handling Change Events from Timing Objects\n */\n _onTimingCallback (eArg, eInfo) {\n\n\n /*\n make sure both timingobjects are ready\n */\n let init = false;\n if (!this._isReady()) {\n if (eInfo.src == this._toA) {\n this._toA_ready = true;\n } else {\n this._toB_ready = true;\n }\n if (this._isReady()) {\n init = true;\n } else {\n return;\n }\n }\n\n // cache new vectors\n this._toA_vector = this._toA.vector;\n this._toB_vector = this._toB.vector;\n\n /*\n figure out which timing object was firing\n */\n const to = eInfo.src;\n const other_to = (to == this._toA) ? this._toB : this._toA;\n\n /*\n The nature of the vector change\n */\n let new_vector = motionutils.calculateVector(to.vector, to.clock.now());\n const delta = new motionutils.MotionDelta(to.old_vector, new_vector);\n\n /*\n Sample the state of the other timing object at same time.\n */\n let ts = new_vector.timestamp;\n let other_new_vector = motionutils.calculateVector(other_to.vector, ts);\n\n /*\n Reevaluate active state.\n This is required after any discontinuity of the position (jump),\n or if the motion stopped without jumping (pause or halt at range\n restriction)\n */\n if (delta.posDelta == PosDelta.CHANGE || delta.MoveDelta == MoveDelta.STOP) {\n\n // make position interval\n let low = Math.min(new_vector.position, other_new_vector.position);\n let high = Math.max(new_vector.position, other_new_vector.position);\n let itv = new Interval(low, high, true, true);\n\n // new active cues\n let activeCues = new Map(this._ds.lookup(itv).map(cue => {\n return [cue.key, cue];\n }));\n // exit cues - in old activeCues but not in new activeCues\n let exitCues = map_difference(this._map, activeCues);\n // enter cues - not in old activeCues but in new activeCues\n let enterCues = map_difference(activeCues, this._map);\n // update active cues\n this._map = activeCues;\n // make event items\n\n let exitItems = [...exitCues.values()].map(cue => {\n return {key:cue.key, new:undefined, old:cue};\n });\n let enterItems = [...enterCues.values()].map(cue => {\n return {key:cue.key, new:cue, old:undefined};\n }); \n // sort event items according to general movement direction\n let direction = movement_direction(new_vector, other_new_vector);\n this.sortItems(exitItems, direction);\n this.sortItems(enterItems, direction);\n\n // notifications\n const items = array_concat([exitItems, enterItems], {copy:true, order:true});\n\n // event notification\n this._notifyEvents(items);\n }\n\n /*\n Handle Timing Object Moving\n - on init both shedules must be updated\n */\n if (to == this._toA) {\n this._schedA.setVector(new_vector);\n } else if (to == this._toB) {\n this._schedB.setVector(new_vector);\n }\n if (init) {\n if (other_to == this._toA) {\n this._schedA.setVector(other_new_vector);\n } else if (other_to == this._toB) {\n this._schedB.setVector(other_new_vector);\n }\n }\n };\n\n\n /***************************************************************\n SCHEDULE CALLBACK\n ***************************************************************/\n\n /*\n Handling due Events from Schedules\n */\n _onScheduleCallback = function(now, endpointItems, schedule) {\n if (!this._isReady()) {\n return;\n }\n\n /*\n figure out which timing object was firing\n */\n const to = schedule.to;\n const other_to = (to == this._toA) ? this._toB : this._toA;\n\n const items = [];\n endpointItems.forEach(function (item) {\n\n /*\n figure out if to (event source) is lower than the other to\n at time of event\n */\n // endpoint\n let [pos, right, closed, singular] = item.endpoint;\n // position of other to at time of event\n let ts = item.tsEndpoint[0];\n let other_vector = motionutils.calculateVector(other_to.vector, ts);\n let pos_other = other_vector.position;\n\n /*\n Action Code - see sequenceutils\n */\n // to role\n let to_role = (pos < pos_other) ? \"L\" : (pos == pos_other) ? \"S\" : \"R\";\n // movement direction\n let to_dir = (item.direction > 0) ? \"R\" : \"L\";\n // endpoint type\n let ep_type = (singular) ? \"S\": (right) ? \"R\" : \"L\";\n // action code, enter, exit, stay, enter-exit\n let action_code = ActiveMap.get(`${to_role}${to_dir}${ep_type}`);\n\n /*\n state of cue\n */\n let cue = item.cue;\n let has_cue = this._map.has(cue.key);\n\n // filter action code\n if (action_code == Active.ENTER_EXIT) {\n /*\n both timing objects evaluated to same position\n either\n 1) to is moving and other_to is paused at this point,\n implying that the cue STAYS active\n or,\n 2) both are moving. if both are moving in the same\n direction - EXIT\n opposite direction - ENTER\n */\n let other_moving = motionutils.isMoving(other_vector);\n if (!other_moving) {\n // other not moving\n action_code = Active.ENTER;\n } else {\n // both moving\n let direction = motionutils.calculateDirection(other_vector); // movement direction\n action_code = (direction != item.direction) ? Active.ENTER : Active.EXIT;\n }\n }\n if (action_code == Active.STAY) {\n action_code = Active.ENTER;\n }\n if (action_code == Active.ENTER && has_cue) {\n return;\n }\n if (action_code == Active.EXIT && !has_cue) {\n return;\n }\n\n // enter or exit\n if (action_code == Active.ENTER) {\n // enter\n items.push({key:cue.key, new:cue, old:undefined});\n this._map.set(cue.key, cue);\n } else if (action_code == Active.EXIT) {\n // exit\n items.push({key:cue.key, new:undefined, old:cue});\n this._map.delete(cue.key);\n }\n }, this);\n\n // Event items already sorted\n\n // event notification\n this._notifyEvents(items);\n }\n}\n\nexport default IntervalModeSequencer;\n\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\nimport TimingSampler from \"../timingobject/timingsampler.js\";\n\n/*\n TODO\n\n - treat progress change as a speculative\n change, (with a timeout)\n implementation - ideally as speculative converter\n easy solution - just lock\n*/\n\nclass TimingProgress {\n\n static position2percent(position, range) {\n let [low, high] = range;\n\n let offset = position - low;\n let length = high - low;\n return 100.0*offset/length;\n };\n\n static percent2position(percent, range) {\n let [low, high] = range;\n // make sure percent is [0,100]\n percent = Math.max(0, percent);\n percent = Math.min(100, percent);\n let length = high - low;\n let offset = length*percent/100.0;\n return low + offset;\n };\n\n constructor (timingObject, progress_elem, options={}) {\n this._to = timingObject;\n this._sampler = options.sampler;\n this._progress_elem = progress_elem;\n this._lock = false;\n this._options = options;\n this._range = options.range || this._to.range;\n let [low, high] = this._range;\n if (low == -Infinity || high == Infinity) {\n throw new Error(\"illegal range\", this._range);\n }\n\n // subscribe to input event from progress elem\n this._progress_elem.addEventListener(\"input\", function() {\n // set lock\n // no updates on progress elem from timing object until lock is released\n this._lock_value = true;\n }.bind(this));\n\n // subscribe to change event from progress elem\n this._progress_elem.addEventListener(\"change\", function () { \n // clear lock\n this._lock_value = false;\n // update the timing object\n let percent = parseInt(this._progress_elem.value); \n let position = TimingProgress.percent2position(percent, this._range);\n this._to.update({position: position});\n }.bind(this));\n \n // sampler\n if (this._sampler) {\n this._sampler.on(\"change\", this.refresh.bind(this));\n }\n }\n\n refresh() {\n let position = this._to.pos;\n // update progress elem if unlocked\n if (!this._lock_value) {\n let percent = TimingProgress.position2percent(position, this._range);\n if (this._options.thumb) {\n // check if percent is legal\n if (percent < 0.0 || 100.0 < percent) {\n // hide\n this._options.thumb.hide();\n return;\n }\n } else {\n percent = (percent < 0.0) ? 0.0 : percent;\n percent = (100.0 < percent) ? 100.0: percent;\n }\n this._progress_elem.value = `${percent}`;\n if (this._options.thumb) {\n this._options.thumb.show(); \n }\n }\n }\n}\n\nexport default TimingProgress;","\n/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n// utils\nexport * as utils from './util/utils.js';\nexport * as motionutils from './util/motionutils.js';\nexport {default as BinarySearch} from './util/binarysearch.js';\nexport {default as endpoint} from './util/endpoint.js';\nexport {default as eventify} from './util/eventify.js';\nexport {default as Interval} from './util/interval.js';\nexport {default as CueCollection} from './dataset/cuecollection.js';\nexport {default as Timeout} from './util/timeout.js';\n\n// timing object\nimport {default as TimingObject} from './timingobject/timingobject.js';\nexport {TimingObject};\nexport {default as SkewConverter} from './timingobject/skewconverter.js';\nexport {default as DelayConverter} from './timingobject/delayconverter.js';\nexport {default as ScaleConverter} from './timingobject/scaleconverter.js';\nexport {default as LoopConverter} from './timingobject/loopconverter.js';\nexport {default as RangeConverter} from './timingobject/rangeconverter.js';\nexport {default as TimeshiftConverter} from './timingobject/timeshiftconverter.js';\nexport {default as TimingSampler} from './timingobject/timingsampler.js';\nexport {default as PositionCallback} from './timingobject/positioncallback.js';\n\n// timed data\nimport {default as Dataset} from './dataset/dataset.js';\nexport {Dataset};\nexport {default as Subset} from './dataset/subset.js';\nimport {default as PointModeSequencer} from './sequencing/pointsequencer.js';\nimport {default as IntervalModeSequencer} from './sequencing/intervalsequencer.js';\n\n// create single sequencer factory function\nexport function Sequencer() {\n // find datasets in arguments\n let ds_list = [...arguments].filter((e) => (e instanceof Dataset));\n let ds = (ds_list.length > 0) ? ds_list[0] : new Dataset();\n // find timing objects in arguments\n let to_list = [...arguments].filter((e) => (e instanceof TimingObject));\n // find options (plain objects) in arguments\n let obj_list = [...arguments].filter((e) => (Object.getPrototypeOf(e) === Object.prototype));\n let options = (obj_list.length > 0) ? obj_list[0] : {};\n if (to_list.length == 0) {\n throw new Error(\"no timingobject in arguments\");\n } else if (to_list.length == 1) {\n return new PointModeSequencer(ds, to_list[0], options);\n } else {\n return new IntervalModeSequencer(ds, to_list[0], to_list[1], options);\n }\n};\n\n// Add clone functions for backwards compatibility\nPointModeSequencer.prototype.clone = function () {\n let args = [this.dataset];\n args.push.apply(args, [...arguments]);\n return Sequencer(...args);\n};\n\n// Add clone functions for backwards compatibility\nIntervalModeSequencer.prototype.clone = function () {\n let args = [this.dataset];\n args.push.apply(args, [...arguments]);\n return Sequencer(...args);\n};\n\n// ui\nexport {default as DatasetViewer} from './ui/datasetviewer.js';\nexport {default as TimingProgress} from './ui/timingprogress.js';\n\nexport const version = \"v3.0\";\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport {random_string} from '../util/utils.js';\n\nclass DatasetViewer {\n\n constructor(ds, elem) {\n this.ds = ds;\n this.elem = elem;\n this.nonce = random_string(4);\n this.ds.on(\"change\", this.onchange.bind(this));\n this.ds.on(\"remove\", this.onremove.bind(this));\n }\n\n cue2string(cue) {\n let itv = (cue.interval) ? cue.interval.toString() : \"undefined\";\n let data = JSON.stringify(cue.data); \n return `${cue.key}, ${itv}, ${data}`;\n }\n\n onchange(eItem) {\n let _id = `${this.nonce}-${eItem.key}`;\n let node = this.elem.querySelector(`#${_id}`);\n if (node) {\n // update existing node\n node.innerHTML = this.cue2string(eItem.new);\n } else {\n // create new node\n let node = document.createElement(\"div\");\n node.innerHTML = this.cue2string(eItem.new);\n node.setAttribute(\"id\", _id);\n this.elem.appendChild(node);\n }\n }\n\n onremove(eItem) {\n // remove node\n let _id = `${this.nonce}-${eItem.key}`;\n let node = document.getElementById(_id);\n if (node) {\n node.parentNode.removeChild(node);\n }\n }\n}\n\nexport default DatasetViewer;","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\n/*\n\tDELAY CONVERTER\n\n\tDelay Converter introduces a positive time delay on a source timing object.\n\n\tGenerally - if the source timing object has some value at time t,\n\tthen the delayConverter will provide the same value at time t + delay.\n\n\tSince the delay Converter is effectively replaying past events after the fact,\n\tit is not LIVE and not open to interactivity (i.e. update)\n\n*/\n\nimport TimingObject from './timingobject.js';\nimport Timeout from '../util/timeout.js';\n\n\nclass DelayConverter extends TimingObject {\n\tconstructor (timingObject, delay) {\n\t\tif (delay < 0) {throw new Error (\"negative delay not supported\");}\n\t\tif (delay === 0) {throw new Error (\"zero delay makes delayconverter pointless\");}\n\t\tsuper(timingObject);\n\t\t// fixed delay\n\t\tthis._delay = delay;\n\t\t// buffer\n\t\tthis._buffer = [];\n\t\t// timeoutid\n\t\tthis._timeout = new Timeout(this, this.__handleDelayed.bind(this));\n this.eventifyDefine(\"delaychange\", {init:true});\n\t};\n\n // extend\n eventifyInitEventArgs(name) {\n if (name == \"delaychange\") {\n return [this._delay];\n } else {\n return super.eventifyInitEventArgs(name)\n }\n }\n\n\t// overrides\n\tonUpdateStart(arg) {\n\t\t/*\n\t\t\tVector's timestamp always time-shifted (back-dated) by delay\n\n\t\t\tNormal operation is to delay every incoming vector update.\n\t\t\tThis implies returning null to abort further processing at this time,\n\t\t\tand instead trigger a later continuation.\n\n\t\t\tHowever, delay is calculated based on the timestamp of the vector (age), not when the vector is\n\t\t\tprocessed in this method. So, for small small delays the age of the vector could already be\n\t\t\tgreater than delay, indicating that the vector is immediately valid and do not require delayed processing.\n\n\t\t\tThis is particularly true for the first vector, which may be old.\n\n\t\t\tSo we generally check the age to figure out whether to apply the vector immediately or to delay it.\n\t\t*/\n\n\t\tthis._buffer.push(arg);\n\t\t// if timeout for next already defined, nothing to do\n\t\tif (!this._timeout.isSet()) {\n\t\t\tthis.__handleDelayed();\n\t\t}\n\t\treturn;\n\t};\n\n\t__handleDelayed() {\n\t\t// run through buffer and apply vectors that are due\n\t\tlet now = this.clock.now();\n\t\tlet arg, due;\n\t\twhile (this._buffer.length > 0) {\n\t\t\tdue = this._buffer[0].timestamp + this._delay;\n\t\t\tif (now < due) {\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\targ = this._buffer.shift();\n\t\t\t\t// apply\n\t\t\t\targ.timestamp = due;\n\t\t\t\tthis.__process(arg);\n\t\t\t}\n\t\t}\n\t\t// set new timeout\n\t\tif (this._buffer.length > 0) {\n\t\t\tdue = this._buffer[0].timestamp + this._delay;\n\t\t\tthis._timeout.setTimeout(due);\n\t\t}\n\t};\n\n\tupdate(arg) {\n\t\t// Updates are prohibited on delayed timingobjects\n\t\tthrow new Error (\"update is not legal on delayed (non-live) timingobject\");\n\t};\n\n get delay() {return this._delay;};\n\n\tset delay(delay) {\n if (delay != this._delay) {\n // set delay and emulate new event from timingsrc\n this._delay = delay;\n this._timeout.clear();\n this.__handleDelayed();\n this.eventifyTrigger(\"delaychange\", delay);\n }\n }\n}\n\nexport default DelayConverter;\n\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n/*\n\tSCALE CONVERTER\n\n\tScaling by a factor 2 means that values of the timing object (position, velocity and acceleration) are multiplied by two.\n\tFor example, if the timing object represents a media offset in seconds, scaling it to milliseconds implies a scaling factor of 1000.\n\n*/\n\nimport TimingObject from './timingobject.js';\n\n\nclass ScaleConverter extends TimingObject {\n constructor (timingsrc, factor) {\n\t\tsuper(timingsrc);\n\t\tthis._factor = factor;\n this.eventifyDefine(\"scalechange\", {init:true});\n\t};\n\n // extend\n eventifyInitEventArgs(name) {\n if (name == \"scalechange\") {\n return [this._factor];\n } else {\n return super.eventifyInitEventArgs(name)\n }\n }\n\n\t// overrides\n onUpdateStart(arg) {\n if (arg.range != undefined) {\n arg.range = [arg.range[0]*this._factor, arg.range[1]*this._factor];\n }\n if (arg.position != undefined) {\n arg.position *= this._factor;\n }\n if (arg.velocity != undefined) {\n arg.velocity *= this._factor;\n }\n if (arg.acceleration != undefined) {\n arg.acceleration *= this._factor;\n }\n return arg;\n }\n\n\tupdate(arg) {\n\t\tif (arg.position != undefined) {\n arg.position /= this._factor;\n }\n\t\tif (arg.velocity != undefined) {\n arg.velocity /= this._factor;\n }\n\t\tif (arg.acceleration != undefined) {\n arg.acceleration /= this._factor;\n }\n\t\treturn super.update(arg);\n\t};\n\n get scale() {return this._factor;};\n\n set scale(factor) {\n if (factor != this._factor) {\n // set scale and emulate new event from timingsrc\n this._factor = factor;\n this.__handleEvent({\n ...this.__get_timingsrc().vector,\n range: this.__get_timingsrc().range\n });\n this.eventifyTrigger(\"scalechange\", factor);\n }\n }\n}\nexport default ScaleConverter;\n\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n\n/*\n\tSKEW CONVERTER\n\n\tSkewing the timeline by 2 means that the timeline position 0 of the timingsrc becomes position 2 of Converter.\n\n*/\n\n\nimport TimingObject from './timingobject.js';\n\n\nclass SkewConverter extends TimingObject {\n\n\tconstructor (timingsrc, skew, options) {\n\t\tsuper(timingsrc, options);\n\t\tthis._skew = skew;\n this.eventifyDefine(\"skewchange\", {init:true});\n\t}\n\n // extend\n eventifyInitEventArgs(name) {\n if (name == \"skewchange\") {\n return [this._skew];\n } else {\n return super.eventifyInitEventArgs(name)\n }\n }\n\n\t// overrides\n\tonUpdateStart(arg) {\n if (arg.range != undefined) {\n arg.range[0] += this._skew;\n arg.range[1] += this._skew;\n }\n if (arg.position != undefined) {\n\t\t\targ.position += this._skew;\n }\n return arg;\n\t};\n\n\t// overrides\n\tupdate(arg) {\n if (arg.position != undefined) {\n\t\t\targ.position -= this._skew;\n }\n if (arg.range != undefined) {\n let [low, high] = arg.range;\n arg.range = [low - this._skew, high - this._skew];\n }\n\t\treturn super.update(arg);\n\t};\n\n\tget skew() {return this._skew;};\n\n\tset skew(skew) {\n if (skew != this._skew) {\n // set skew and emulate new event from timingsrc\n\t\t\tthis._skew = skew;\n\t\t\tthis.__handleEvent({\n ...this.__get_timingsrc().vector,\n range: this.__get_timingsrc().range\n });\n this.eventifyTrigger(\"skewchange\", skew);\n }\n\t}\n};\n\nexport default SkewConverter;\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport CueCollection from './cuecollection.js';\nimport {array_concat, map_difference} from '../util/utils.js';\nimport Interval from '../util/interval.js';\n\n/*\n Subset provides read-only access to subset of a source Dataset\n\n - \n - : if defined only include cues that match the interval\n - : filter by cue key\n function keep(key) returns boolena\n - : filter by cue data\n function keep(data) returns boolean\n - : change cue data\n function convert(data) returns data\n NOTE: filtering occurs BEFORE convert\n and only impacts the presentation of cues\n WARNING: it is possible to change the value\n in such a way that filtering appears incorrect\n\n This subset implementation is STATELESS\n It does not manage its own state, only implements a\n stateless frontend over its source dataset.\n\n*/\n\nclass Subset extends CueCollection {\n\n constructor(dataset, options={}) {\n super(options);\n this._key_filter = options.key_filter;\n this._data_filter = options.data_filter;\n this._interval = options.interval;\n this._data_convert = options.data_convert;\n this._size = 0;\n\n // Callbacks\n this._callbacks = [];\n\n // Source Dataset\n this._src_ds = dataset;\n let cb = this._onDatasetCallback.bind(this)\n this._src_ds_cb = this._src_ds.add_callback(cb);\n }\n\n\n /***************************************************************\n ACCESSORS\n ***************************************************************/\n\n get datasource () {\n return this._src_ds;\n }\n\n get dataset () {\n return this._src_ds;\n }\n\n\n get interval () {\n return this._interval;\n }\n\n set interval (itv) {\n this._setInterval(itv);\n }\n\n\n /***************************************************************\n EVENT CALLBACKS - FOR SEQUENCERS\n ***************************************************************/\n\n add_callback (handler) {\n let handle = {\n handler: handler\n }\n this._callbacks.push(handle);\n return handle;\n };\n\n\n del_callback (handle) {\n let index = this._callbacks.indexof(handle);\n if (index > -1) {\n this._callbacks.splice(index, 1);\n }\n };\n\n\n _notify_callbacks (batchMap, relevanceInterval) {\n this._callbacks.forEach(function(handle) {\n handle.handler(batchMap, relevanceInterval);\n });\n };\n\n\n /***************************************************************\n FILTER & CONVER\n ***************************************************************/\n\n /* \n Keep cue \n */\n\n _cue_keep(cue) {\n if (cue == undefined) {\n return false;\n }\n // check if cue matches interval\n if (this._interval) {\n if (!this._interval.match(cue.interval)) {\n return false;\n }\n }\n // check key filter\n if (this._key_filter) {\n if (!this._key_filter(cue.key)) {\n return false;\n }\n }\n // check data filter\n if (this._data_filter) {\n if (!this._data_filter(cue.data)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Convert cue\n */\n _cue_convert(cue) {\n if (cue != undefined && this._data_convert) {\n // copy\n return {\n key: cue.key,\n interval: cue.interval,\n data: this._data_convert(cue.data)\n }\n }\n return cue;\n }\n\n /**\n * Filter (and modify) event items based on key_filter and data_filter\n */\n\n _items_filter_convert(items) {\n let _items = [];\n for (let item of items) {\n if (item.new == undefined && item.old == undefined) {\n continue;\n }\n /* \n use cue filter function to check relevance of both old and new\n consider change of unrelevant cue into relevant cue.\n old cue would be non-relevant, new cue would be relevant\n Since old cue was not part of the subset before, it needs\n to be removed from the item - effectively turning the change\n operation into an add operation. \n */\n let _old = (this._cue_keep(item.old)) ? item.old : undefined;\n let _new = (this._cue_keep(item.new)) ? item.new : undefined;\n if (_old == undefined && _new == undefined) {\n continue;\n }\n // convert\n _old = this._cue_convert(_old);\n _new = this._cue_convert(_new);\n // push\n _items.push({key:item.key, new: _new, old: _old});\n }\n return _items;\n }\n\n\n /***************************************************************\n LOOKUP\n ***************************************************************/\n\n _check_interval(interval) {\n if (this._interval) {\n // subset interval\n if (interval) {\n // lookup interval - find intersection\n let intersects = Interval.intersect(interval, this._interval);\n if (intersects.length == 0) {\n console.log(`warning - lookup interval ${interval.toString()} outside the subset interval ${this._interval.toString()}`);\n return [];\n } else {\n interval = intersects[0];\n }\n } else {\n // no lookup interval - use subset interval \n interval = this._interval;\n }\n }\n return interval;\n }\n\n /** \n * lookup cues\n */\n\n lookup(interval, mask) {\n let _interval = this._check_interval(interval);\n let cues;\n if (_interval) {\n cues = this.datasource.lookup(_interval, mask);\n } else {\n cues = [...this.datasource.values()];\n }\n // filter & convert cues\n return cues.filter(this._cue_keep, this)\n .map(this._cue_convert, this);\n }\n\n /* \n lookup endpoints\n used by sequencers\n */\n\n lookup_endpoints(interval) {\n let _interval = this._check_interval(interval);\n let items = this.datasource.lookup_endpoints(_interval);\n // filter and convert\n return items.filter((item) => {\n return this._cue_keep(item.cue);\n }, this).map((item) => {\n return {endpoint: item.endpoint, cue: this._cue_convert(item.cue)};\n }, this);\n }\n\n /***************************************************************\n INITIAL STATE\n ***************************************************************/\n\n eventifyInitEventArgs(name) {\n if (name == \"batch\" || name == \"change\") {\n // find cues\n let cues = this.lookup();\n // make event items\n let items = cues.map((cue) => {\n return {key:cue.key, new:cue, old:undefined};\n });\n // sort\n this.sortItems(items);\n return (name == \"batch\") ? [items] : items;\n }\n }\n\n /***************************************************************\n DATASET CALLBACK\n ***************************************************************/\n\n _onDatasetCallback(eventMap, relevanceInterval) {\n let items = [...eventMap.values()];\n items = this._items_filter_convert(items);\n // update size\n for (let item of items) {\n if (item.new != undefined && item.old == undefined) {\n // add\n this._size += 1;\n } else if (item.new == undefined && item.old != undefined) {\n // remove\n this._size -= 1;\n } \n } \n // forward as events\n super._notifyEvents(items);\n // forward as callbacks\n let batchMap = new Map(items.map((item) => {\n return [item.key, item];\n }));\n if (this._interval) {\n relevanceInterval = Interval.intersect(this._inverval, relevanceInterval);\n }\n this._notify_callbacks(batchMap, relevanceInterval);\n }\n\n\n /***************************************************************\n SET INTERVAL\n ***************************************************************/\n\n _setInterval (itv) {\n if (!itv instanceof Interval) {\n throw new Error(\"must be interval\", itv.toString());\n }\n if (!this._interval || !this._interval.equals(itv)) {\n // current cues (before interval update)\n let current_cues = this.lookup();\n // update interval\n this._interval = itv;\n // cues (after interval update)\n let new_cues = this.datasource.lookup(itv);\n // filter & convert cues\n new_cues = new_cues\n .filter(this._cue_keep, this)\n .map(this._cue_convert, this);\n // switch to map representation\n let currentCueMap = new Map([...current_cues].map((cue) => {\n return [cue.key, cue];\n }));\n let newCueMap = new Map([...new_cues].map((cue) => {\n return [cue.key, cue];\n }));\n // exit and enter cues\n let exitCueMap = map_difference(currentCueMap, newCueMap);\n let enterCueMap = map_difference(newCueMap, currentCueMap);\n // make list of event items\n let exitItems = [...exitCueMap.values()].map((cue) => {\n return {key: cue.key, new:undefined, old: cue}\n });\n let enterItems = [...enterCueMap.values()].map((cue) => {\n return {key: cue.key, new:cue, old: undefined}\n });\n // update size\n this._size -= exitItems.length;\n this._size += enterItems.length; \n // event notification\n const items = array_concat([exitItems, enterItems], {copy:false, order:true});\n this._notifyEvents(items);\n }\n }\n\n /***************************************************************\n MAP ACCESSORS\n ***************************************************************/\n\n get size () {\n return this._size;\n }\n\n has(key) {\n return (this.get(key) != undefined);\n };\n\n get(key) {\n let cue = super.get(key);\n if (cue != undefined && this._cue_keep(cue)) {\n return this._cue_convert(cue);\n }\n };\n\n keys() {\n return this.values().map((cue => {\n return cue.key;\n }));\n };\n\n values() {\n return [...super.values()]\n .filter((cue) => {\n return this._cue_keep(cue);\n }, this)\n .map((cue) => {\n return this._cue_convert(cue);\n }, this);\n };\n\n entries() {\n return this.values().map((cue) => {\n return [cue.key, cue];\n });\n };\n\n\n /***************************************************************\n MAP MODIFICATION METHODS\n ***************************************************************/\n\n update(cues, options) {\n throw new Error(\"not implemented\");\n }\n\n set (key, value) {\n throw new Error(\"not implemented\");\n }\n\n delete (key) {\n throw new Error(\"not implemented\");\n }\n\n clear (key) {\n throw new Error(\"not implemented\");\n }\n\n}\n\n// module definition\nexport default Subset;","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n/*\n\tTIMESHIFT CONVERTER\n\n\tTimeshift Converter timeshifts a timing object by timeoffset.\n\tPositive timeoffset means that the converter will run ahead of the source timing object.\n\tNegative timeoffset means that the converter will run behind the source timing object.\n\n\tUpdates affect the converter immediately.\n This means that update vector must be re-calculated\n\tto the value it would have at time-shifted time.\n Timestamps are not time-shifted, since the motion is still live.\n\tFor instance, (0, 1, ts) becomes (0+(1*timeshift), 1, ts)\n\n\tHowever, this transformation may cause range violation\n\t\t- this happens only when timing object is moving.\n\t\t- implementation requires range converter logic\n\n\t- range is infinite\n*/\n\nimport TimingObject from './timingobject.js';\nimport {calculateVector} from '../util/motionutils.js';\n\n\nclass TimeshiftConverter extends TimingObject {\n\n constructor (timingsrc, offset) {\n\t\tsuper(timingsrc);\n\t\tthis._offset = offset;\n this.eventifyDefine(\"offsetchange\", {init:true});\n\t};\n\n // extend\n eventifyInitEventArgs(name) {\n if (name == \"offsetchange\") {\n return [this._offset];\n } else {\n return super.eventifyInitEventArgs(name)\n }\n }\n\n // overrides\n onUpdateStart(arg) {\n if (arg.range != undefined) {\n arg.range = [-Infinity, Infinity];\n }\n if (arg.position != undefined) {\n // calculate timeshifted vector\n let ts = arg.timestamp;\n let new_vector = calculateVector(arg, ts + this._offset);\n arg.position = new_vector.position;\n arg.velocity = new_vector.velocity;\n arg.acceleration = new_vector.acceleration;\n arg.timestamp = ts;\n }\n return arg;\n };\n\n get offset() {return this._offset;};\n\n set offset(offset) {\n if (offset != this._offset) {\n // set offset and emulate new event from timingsrc\n this._offset = offset;\n this.__handleEvent({\n ...this.__get_timingsrc().vector,\n range: this.__get_timingsrc().range\n });\n this.eventifyTrigger(\"offsetchange\", offset);\n }\n }\n\n}\n\nexport default TimeshiftConverter;\n"],"names":["random_string","length","text","possible","i","charAt","Math","floor","random","eqSet","as","bs","size","all","isIn","pred","a","has","set_difference","Set","filter","e","map_difference","b","Map","key","value","map_intersect","isIterable","obj","Symbol","iterator","array_concat","arrays","options","copy","order","total_len","reduce","acc","cur","sort","end","len","first","shift","start","arr","object_equals","propName","aProps","Object","getOwnPropertyNames","bProps","docready","Promise","resolve","document","readyState","onReady","removeEventListener","window","addEventListener","array_of_maps","Array","isArray","Error","map","o","every","m","val","entries","set","n","d","r","isNumber","N","parseFloat","isNaN","create","right","closed","singular","Infinity","get_mode","undefined","get_order","e1","e2","cmp","order1","order2","diff","toString","mode","equals","rightof","leftof","min","max","IntervalError","[object Object]","message","super","this","name","Relation","freeze","OUTSIDE_LEFT","OVERLAP_LEFT","COVERED","EQUALS","COVERS","OVERLAP_RIGHT","OUTSIDE_RIGHT","MATCH_OUTSIDE","MATCH_INSIDE","MATCH_OVERLAP","MATCH_COVERS","MATCH_ALL","Match","OUTSIDE","INSIDE","OVERLAP","ALL","compare","Interval","endpoint","endpointLow","endpointHigh","includes","_make_interval_cmp","low","lowInclude","high","highInclude","_low","_high","_lowInclude","_highInclude","_length","_singular","_finite","isFinite","_endpointLow","_endpointHigh","finite","p","other","mask","relation","Boolean","cmpLow","cmpHigh","fromEndpoints","low_right","low_closed","low_singular","high_right","high_closed","high_singular","intersect","rel","union","intersectAll","intervals","result","prev","pop","next","push","unionAll","decimalAdjust","type","exp","NaN","split","round10","floor10","ceil10","equalVectors","vector_a","vector_b","pos","position","vel","velocity","acceleration","ts","timestamp","calculateVector","vector","deltaSec","calculateDirection","freshVector","direction","isMoving","RangeState","INIT","OUTSIDE_LOW","OUTSIDE_HIGH","correctRangeState","range","v","detectRangeViolation","now_vector","checkRange","state","rangeIntersect","t0","deltaLeft","calculateMinPositiveRealSolution","deltaRight","hasRealSolution","x","pow","calculateRealSolutions","sqrt","d1","d2","res","calculatePositiveRealSolutions","calculateDelta","deltaBeforeSec","deltaAfterSec","posInterval_from_timeInterval","timeInterval","t1","vector0","p0","v0","a0","p1","t_extrem","covers_endpoint","p_extrem","timeEndpoint_from_posEndpoint","posEndpoint","close","endpointEvents","posInterval","endpointItems","deltas","tsEndpoint","eventItems","forEach","item","delta","console","log","PosDelta","NOOP","CHANGE","MoveDelta","NOOP_MOVING","START","STOP","MotionDelta","old_vector","new_vector","is_moving","_mc","mct","was_moving","end_vector","start_vector","pct","vel_changed","acc_changed","posDelta","moveDelta","str","BinarySearchError","BinarySearch","array","searchElement","currentIndex","currentElement","minIndex","maxIndex","index","binaryIndexOf","isFound","elements","indexes","indexOf","to_remove","to_insert","indexOfElements","splice","abs","concat","A","approach","arrayLength","batchLength","_update_splice","_update_sort","idx","interval","start_index","end_index","geIndexOf","gtIndexOf","leIndexOf","ltIndexOf","lookupIndexes","slice","removeList","rd_ptr","wr_ptr","rm_ptr","rd_elem","rm_elem","values","Event","publisher","init","subscriptions","callback","sub","Subscription","init_pending","self","then","eArgs","eventifyInitEventArgs","eArg","trigger","subs","eInfo","ctx","terminated","src","call","err","terminate","event","unsubscribe","eventifyInstance","object","__eventify_eventMap","__eventify_buffer","eventifyPrototype","_prototype","eventifyGetEvent","get","eventifyDefine","eventifyTrigger","eventifyTriggerAll","eventifyTriggerAlike","triggerItems","ev","buf","buf_len","eventifySubscriptions","on","subscribe","off","EventVariable","_value","prototype","EventBoolean","makePromise","eventObject","conditionFunc","reject","ObservableMap","eventify","datasource","iter","sortOrder","items","item_a","item_b","cue_a","new","old","cue_b","sortItems","has_update_subs","has_remove_subs","has_change_subs","keys","_notifyEvents","delete","clear","CueCollection","cues","sortValues","Timeout","timingObject","tid","to","target_ts","arg","now","clock","delay","setTimeout","onTimeout","bind","clearTimeout","performance","offset","Date","getTime","local_clock","tsSec","MasterClock","_vector","adjust","nowVector","query","skew","rate","InternalProvider","_clock","_range","_callback","_process_update","rest","_old_vector","ExternalProvider","provider","required","prop","checkTimingProvider","_provider","_ready","_provider_clock","_onVectorChange","_onSkewChange","local_ts","current_skew","skew_delta","update","TimingObject","timingsrc","isTimingProvider","__options","timeout","__old_vector","__vector","__range","__timeout","__handleTimeout","__tid","__timingsrc","__sub","__update_events","__ready","__set_timingsrc","live","ready","motionutils.MotionDelta","version","motionutils.calculateVector","isSet","__process","__update","ok","tunnel","promise","_arg","onUpdateStart","timeout_vector","range_change","vector_change","motionutils.detectRangeViolation","onRangeViolation","motionutils.equalVectors","__dispatchEvents","__renewTimeout","onUpdateDone","moving","motionutils.isMoving","setInterval","motionutils.checkRange","__calculateTimeoutVector","motionutils.calculateDelta","__handleEvent","isReady","__get_timingsrc","__clear_timingsrc","transform","_state","new_state","new_range","absolute","special","old_state","is_special_state_change","TimingSampler","_to","_tid","period","frequency","_period","_sub","_onChange","_onSample","float2point","stride","mod","divmod","point2float","q","epoch","asInterval","input","removeCueFromArray","cue","findIndex","_cue","CueBucketIds","getCueBucketId","Delta","INSERT","REPLACE","DELETE","cue_delta","interval_delta","data_delta","eq","a_interval_defined","b_interval_defined","a_data_defined","data","b_data_defined","utils.object_equals","cue_check","hasOwnProperty","CueArgBuilder","dataset","_ds","_options","assign","autosubmit","check_needed","_cues","_done","updateDone","_reset","_submit","cue_args","was_empty","cue_arg","arguments","_push","Dataset","_map","_builder","_cueBuckets","cueBucketId","CueBucket","_update_callbacks","handler","handle","indexof","batchMap","relevanceInterval","builder","addCue","removeCue","current_cue","has_interval","has_data","debug","utils.isIterable","info","author","_update_cue","_call_buckets","relevance","event_items","_notify_callbacks","integrity","old_cue","new_cue","_item","oldCueBucket","newCueBucket","low_changed","high_changed","remove_needed","add_needed","chaining","safe","change_ts","change_id","bid","cueBucket","replace_endpoint","old_bid","new_bid","del_endpoint","add_endpoint","method","args","utils.array_concat","points","bucketInfo","no_interval_cues","count_buckets","count_no_interval","count_map","bucket_map","map_map","missing","utils.map_difference","cue_equals","maxLength","_maxLength","_pointMap","_pointIndex","_created","_dirty","point","add","replaceCueInArray","broader_interval","lookup","_endpoint","cueSet","match","_mask","_lookup_cues","left_interval","j","removeInSlice","index_point_set","map_point_set","utils.eqSet","utils.set_difference","_cue_list","cueMap","pft","motionutils.posInterval_from_timeInterval","queueCmp","Schedule","run","queue","callbacks","lookahead","advance","endpoints","minimum_tsEndpoint","motionutils.endpointEvents","range_ts","motionutils.rangeIntersect","dueEvents","lookup_endpoints","loaded","load","popped","isNoop","Active","ENTER","STAY","EXIT","ENTER_EXIT","ActiveMap","cue_cmp_forwards","cue_cmp_backwards","item_cmp_forwards","item_cmp_backwards","BaseSequencer","cb","_onDatasetCallback","_ds_cb","add_callback","_movementDirection","eventMap","enterEvents","changeEvents","exitEvents","is_active","should_be_active","_activeCues","enterCues","remainCues","eventList","_addCue","_removeCue","PointModeSequencer","_onTimingCallback","_sched","_onScheduleCallback","_sched_cb","motionutils.calculateDirection","activeInterval","get_items","_items_from_dataset_events","_items_from_dataset_lookup","exit","change","enter","setVector","itv","activeCues","exitCues","exitItems","enterItems","schedule","has_cue","to_dir","ep_type","action_code","movement_direction","now_vector_A","now_vector_B","IntervalModeSequencer","toA","toB","_toA","_toA_ready","_toB","_toB_ready","to_cb","_subA","_subB","sched_cb","_schedA","_schedA_cb","_schedB","_schedB_cb","_toA_vector","_toB_vector","_isReady","pos_A","pos_B","other_to","other_new_vector","other_vector","pos_other","to_role","TimingProgress","percent","progress_elem","_sampler","sampler","_progress_elem","_lock","_lock_value","parseInt","percent2position","refresh","position2percent","thumb","hide","show","Sequencer","ds_list","ds","to_list","obj_list","getPrototypeOf","clone","apply","elem","nonce","onchange","onremove","JSON","stringify","eItem","_id","node","querySelector","innerHTML","cue2string","createElement","setAttribute","appendChild","getElementById","parentNode","removeChild","_delay","_buffer","_timeout","__handleDelayed","due","now_vector_src","_offset","_stride","_handleTimeout","_renewTimeout","before","after","rLow","rHigh","stride_points","_calculateTimeout","__state","onVectorChange","state_changed","factor","_factor","scale","_skew","_key_filter","key_filter","_data_filter","data_filter","_interval","_data_convert","data_convert","_size","_callbacks","_src_ds","_src_ds_cb","_setInterval","_items","_old","_cue_keep","_new","_cue_convert","intersects","_check_interval","_items_filter_convert","_inverval","current_cues","new_cues","currentCueMap","newCueMap","exitCueMap","enterCueMap"],"mappings":"uCAqBO,SAASA,EAAcC,GAG1B,IAFA,IAAIC,EAAO,GACPC,EAAW,uDACPC,EAAI,EAAGA,EAAIH,EAAQG,IACvBF,GAAQC,EAASE,OAAOC,KAAKC,MAAMD,KAAKE,SAAWL,EAASF,SAEhE,OAAOC,EAKJ,SAASO,EAAMC,EAAIC,GACtB,OAAOD,EAAGE,OAASD,EAAGC,MAAQC,EAAIC,EAAKH,GAAKD,GAGzC,SAASG,EAAIE,EAAML,GACtB,IAAK,IAAIM,KAAKN,EAAI,IAAKK,EAAKC,GAAI,OAAO,EACvC,OAAO,EAGJ,SAASF,EAAKJ,GACjB,OAAO,SAAUM,GACb,OAAON,EAAGO,IAAID,IAIf,SAASE,EAAeR,EAAIC,GAC/B,OAAO,IAAIQ,IAAI,IAAIT,GAAIU,OAAQC,IAAOV,EAAGM,IAAII,KAW1C,MAAMC,EAAiB,SAAUN,EAAGO,GACvC,OAAc,GAAVP,EAAEJ,KACK,IAAIY,IACM,GAAVD,EAAEX,KACFI,EAEA,IAAIQ,IAAI,IAAIR,GAAGI,QAAO,UAAWK,EAAKC,IACzC,OAAQH,EAAEN,IAAIQ,QASbE,EAAgB,SAAUX,EAAGO,GAEtC,OADCP,EAAGO,GAAMP,EAAEJ,MAAQW,EAAEX,KAAQ,CAACI,EAAEO,GAAK,CAACA,EAAEP,GAC3B,GAAVA,EAAEJ,KAEK,IAAIY,IAER,IAAIA,IAAI,IAAIR,GAAGI,QAAO,UAAWK,EAAKC,IACzC,OAAOH,EAAEN,IAAIQ,QA6Dd,SAASG,EAAWC,GAEvB,OAAW,MAAPA,GAGmC,mBAAzBA,EAAIC,OAAOC,UActB,SAASC,EAAaC,EAAQC,EAAU,IAC3C,IAAIC,KAACA,GAAK,EAAKC,MAAEA,GAAM,GAASF,EAChC,GAAqB,GAAjBD,EAAOhC,OACP,MAAO,GAEX,GAAqB,GAAjBgC,EAAOhC,OACP,OAAOgC,EAAO,GAElB,IAAII,EAAYJ,EAAOK,OAAO,CAACC,EAAKC,IAAQD,EAAMC,EAAIvC,OAAQ,GAEzDmC,GAEDH,EAAOQ,KAAK,CAACzB,EAAGO,IAAMA,EAAEtB,OAASe,EAAEf,QAGvC,IAKIyC,EAAKC,EALLC,EAAQ,EAAS,GAAKX,EAAOY,QAC7BC,EAAQF,EAAM3C,OAElB2C,EAAM3C,OAASoC,EAGf,IAAK,IAAIU,KAAOd,EAAQ,CACpBU,EAAMI,EAAI9C,OACVyC,EAAMI,EAAQH,EACd,IAAK,IAAIvC,EAAE,EAAGA,EAAEuC,EAAKvC,IACjBwC,EAAME,EAAQ1C,GAAK2C,EAAI3C,GAE3B0C,EAAQJ,EAEZ,OAAOE,EAQJ,SAASI,EAAchC,EAAGO,GAE7B,IAGI0B,EAHAC,EAASC,OAAOC,oBAAoBpC,GACpCqC,EAASF,OAAOC,oBAAoB7B,GACpCoB,EAAMO,EAAOjD,OAGjB,GAAIiD,EAAOjD,QAAUoD,EAAOpD,OACxB,OAAO,EAEX,IAAK,IAAIG,EAAE,EAAGA,EAAEuC,EAAKvC,IAGjB,GAFA6C,EAAWC,EAAO9C,GAEdY,EAAEiC,KAAc1B,EAAE0B,GAClB,OAAO,EAIf,OAAO,EAKJ,MAAMK,EAAW,IAAIC,SAAQ,SAASC,GACzC,GAA4B,aAAxBC,SAASC,WACTF,QACG,CACH,IAAIG,EAAU,WACVH,IACAC,SAASG,oBAAoB,mBAAoBD,GAAS,GAC1DE,OAAOD,oBAAoB,OAAQD,GAAS,IAEhDF,SAASK,iBAAiB,mBAAoBH,GAAS,GACvDE,OAAOC,iBAAiB,OAAQH,GAAS,4IAnI1C,SAAmBI,EAAe7B,EAAQ,IAC7C,IAAIC,KAACA,GAAK,EAAKC,MAAEA,GAAM,GAASF,EAEhC,GAAI6B,aAAyBvC,IACzB,OAAOuC,EAEX,IAAKC,MAAMC,QAAQF,GACf,MAAM,IAAIG,MAAM,8BAA+BH,GAEnD,GAA4B,GAAxBA,EAAc9D,OACd,MAAM,IAAIiE,MAAM,uBAKpB,IAHcH,EAAcI,IAAKC,GACrBA,aAAa5C,KAEZ6C,MAAOhD,GAAW,GAALA,GACtB,MAAM,IAAI6C,MAAM,4CAA6CH,GAG5D3B,GAED2B,EAActB,KAAK,CAACzB,EAAGO,IAAMA,EAAEX,KAAOI,EAAEJ,MAG5C,IAAIgC,EAAQ,EAAS,IAAIpB,IAAQuC,EAAclB,QAE/C,IAAK,IAAIyB,KAAKP,EACV,IAAK,IAAKtC,EAAK8C,KAAQD,EAAEE,UACrB5B,EAAM6B,IAAIhD,EAAK8C,GAGvB,OAAO3B,UAIJ,SAAiB8B,EAAGC,GACvB,IAAIC,EAAIF,EAAIC,EAEZ,MAAO,EADED,EAAEE,GAAGD,EACHC,6DCtHf,MAAMC,EAAW,SAASH,GACzB,IAAII,EAAIC,WAAWL,GAChB,OAAQA,IAAII,IAAME,MAAMF,IAwB5B,SAASG,EAAOV,EAAKW,EAAOC,EAAQC,GAEnC,GAAIb,GAAOc,EAAAA,IACG,GAATH,GAA4B,GAAVC,GACrB,MAAM,IAAIjB,MAAM,sDAGlB,GAAIK,IAAQc,EAAAA,IACE,GAATH,GAA2B,GAAVC,GACpB,MAAM,IAAIjB,MAAM,sDAGlB,MAAO,CAACK,EAAKW,EAAOC,EAAQC,GAO7B,SAASE,EAASjE,GAGjB,IAAKkD,EAAKW,EAAOC,EAAQC,GAAY/D,EACrC,OAAI+D,GAAqBG,MAATL,EA5BK,EA8BVA,EACNC,EA9BoB,EAHF,EAuClBA,EAtCmB,EAGF,EAmEvB,SAASK,EAAUC,EAAIC,GAEtB,QAAkBH,IAAdE,EAAGxF,OAAsB,CAC5B,IAAK4E,EAASY,GACb,MAAM,IAAIvB,MAAM,kBAAmBuB,GAEpCA,EAAKR,EAAOQ,OAAIF,OAAWA,GAAW,GAEvC,QAAkBA,IAAdG,EAAGzF,OAAsB,CAC5B,IAAK4E,EAASa,GACb,MAAM,IAAIxB,MAAM,kBAAmBwB,GAEpCA,EAAKT,EAAOS,OAAIH,OAAWA,GAAW,GAEvC,OAAIE,EAAG,IAAMC,EAAG,GAER,CAACD,EAAG,GAAIC,EAAG,IAGX,CAACJ,EAASG,GAAKH,EAASI,IAuCjC,SAASC,EAAIF,EAAIC,GAChB,IAAKE,EAAQC,GAAUL,EAAUC,EAAIC,GACjCI,EAAOF,EAASC,EACpB,OAAY,GAARC,EAAkB,EACdA,EAAO,EAAK,GAAK,QAyCX,CACdH,IAAAA,EACAI,SA1BD,SAAkB1E,GACjB,QAAiBkE,IAAblE,EAAEpB,OACL,OAAOoB,EAAE0E,WACH,CACN,IAAIC,EAAOV,EAASjE,GAChBkD,EAAMlD,EAAE,GAIZ,GAHIkD,GAAOc,EAAAA,GAAYd,IAAQc,EAAAA,IAC9Bd,EAAM,MA7Je,GA+JlByB,EACH,OAAUzB,EAAH,IACD,GAhKgB,GAgKZyB,EACV,MAAO,IAAIzB,EACL,GAjKa,GAiKTyB,EACV,MAAO,IAAIzB,KACL,GAlKiB,GAkKbyB,EACV,OAAUzB,EAAH,IACD,GAnKc,GAmKVyB,EACV,MAAO,IAAIzB,IASb0B,OA3DD,SAAgBR,EAAIC,GACnB,IAAKE,EAAQC,GAAUL,EAAUC,EAAIC,GACrC,OAAQE,GAAUC,GA0DlBK,QArED,SAAiBT,EAAIC,GACpB,IAAKE,EAAQC,GAAUL,EAAUC,EAAIC,GACrC,OAAQE,EAASC,GAoEjBM,OAhFD,SAAgBV,EAAIC,GACnB,IAAKE,EAAQC,GAAUL,EAAUC,EAAIC,GACrC,OAAQE,EAASC,GA+EjBZ,OAAAA,EACAmB,IA5CD,SAAaX,EAAIC,GACb,OAAQC,EAAIF,EAAIC,IAAO,EAAKD,EAAKC,GA4CpCW,IAxCD,SAAaZ,EAAIC,GACb,OAAQC,EAAIF,EAAIC,IAAO,EAAKA,EAAKD,IC/JrC,MAAMZ,EAAW,SAASH,GACzB,IAAII,EAAIC,WAAWL,GAChB,OAAQA,IAAII,IAAME,MAAMF,IAO5B,MAAMwB,UAAsBpC,MAC3BqC,YAAYC,GACXC,MAAMD,GACNE,KAAKC,MAUP,MAAMC,EAAWzD,OAAO0D,OAAO,CAC9BC,aAAc,GACdC,aAAc,GACdC,QAAS,GACTC,OAAQ,EACRC,OAAQ,EACRC,cAAe,EACfC,cAAe,IAMVC,EAAgBT,EAASE,aAAeF,EAASQ,cACjDE,EAAeV,EAASK,OAASL,EAASI,QAC1CO,EAAgBD,EACrBV,EAASG,aAAeH,EAASO,cAC5BK,EAAeD,EAAgBX,EAASM,OACxCO,EAAYD,EAAeH,EAE3BK,EAAQvE,OAAO0D,OAAO,CAC3Bc,QAASN,EACTO,OAAQN,EACRO,QAASN,EACTL,OAAQM,EACRM,IAAKL,IAoCN,SAASM,EAAQ/G,EAAGO,GACnB,IAAMP,aAAagH,EAAU,CAE5B,IAAInD,EAAS7D,GAGZ,MAAM,IAAIsF,EAAc,iBAAkBtF,GAF1CA,EAAI,IAAIgH,EAAShH,GAKnB,IAAMO,aAAayG,EAAU,CAE5B,IAAInD,EAAStD,GAGZ,MAAM,IAAI+E,EAAc,iBAAkB/E,GAF1CA,EAAI,IAAIyG,EAASzG,GAMnB,IAEIE,EAAY,GAFJwG,EAAStC,IAAI3E,EAAEkH,YAAa3G,EAAE2G,aAC9BD,EAAStC,IAAI3E,EAAEmH,aAAc5G,EAAE4G,cAG3C,OAAW,IAAP1G,EAECwG,EAAS9B,OAAO5E,EAAE4G,aAAcnH,EAAEkH,aAC9BtB,EAASQ,cAETR,EAASO,cAEP,EAAE,EAAG,EAAG,IAAIiB,SAAS3G,GACxBmF,EAASI,QACN,CAAC,GAAI,GAAI,IAAIoB,SAAS3G,GACzBmF,EAASM,OACC,GAAPzF,EACHmF,EAASK,OAIZgB,EAAS/B,QAAQ3E,EAAE2G,YAAalH,EAAEmH,cAC9BvB,EAASE,aAETF,EAASG,aAgBnB,SAASsB,EAAmBC,GAC3B,OAAO,SAActH,EAAGO,GACvB,IAAIkE,EAAIC,EAQR,OAPI4C,GACH7C,EAAK,CAACzE,EAAEsH,KAAK,EAAOtH,EAAEuH,WAAYvH,EAAEoE,UACpCM,EAAK,CAACnE,EAAE+G,KAAK,EAAO/G,EAAEgH,WAAYvH,EAAEoE,YAEpCK,EAAK,CAACzE,EAAEwH,MAAM,EAAMxH,EAAEyH,YAAazH,EAAEoE,UACrCM,EAAK,CAACnE,EAAEiH,MAAM,EAAMjH,EAAEkH,YAAazH,EAAEoE,WAE/B6C,EAAStC,IAAIF,EAAIC,IAkH1B,MAAMsC,EAQLzB,YAAa+B,EAAKE,EAAMD,EAAYE,GAInC,GAHkB5D,EAASyD,SAEC/C,IAATiD,IAAoBA,EAAOF,IACzCzD,EAASyD,GAAM,MAAM,IAAIhC,EAAc,qBAAqBgC,GACjE,IAAKzD,EAAS2D,GAAO,MAAM,IAAIlC,EAAc,sBAAsBkC,GACnE,GAAIF,EAAME,EAAM,MAAM,IAAIlC,EAAc,eAAegC,MAAQE,KAS/D,GARIF,IAAQE,IACXD,GAAa,EACbE,GAAc,GAEXH,KAASjD,EAAAA,IAAUkD,GAAa,GAChCC,IAASnD,EAAAA,IAAUoD,GAAc,QAClBlD,IAAfgD,IAA0BA,GAAa,QACvBhD,IAAhBkD,IAA2BA,GAAc,GACnB,kBAAfF,EACV,MAAM,IAAIjC,EAAc,2BAA2BiC,GAEpD,GAA2B,kBAAhBE,EACV,MAAM,IAAInC,EAAc,4BAA4BmC,GAErD/B,KAAKgC,KAAOJ,EACZ5B,KAAKiC,MAAQH,EACb9B,KAAKkC,YAAcL,EACnB7B,KAAKmC,aAAeJ,EACpB/B,KAAKoC,QAAUpC,KAAKiC,MAAQjC,KAAKgC,KACjChC,KAAKqC,UAAarC,KAAKgC,OAAShC,KAAKiC,MACrCjC,KAAKsC,QAAWC,SAASvC,KAAKgC,OAASO,SAASvC,KAAKiC,OAQrDjC,KAAKwC,aAAejB,EAAShD,OAAOyB,KAAKgC,MAAM,EAAOhC,KAAKkC,YAAalC,KAAKqC,WAC7ErC,KAAKyC,cAAgBlB,EAAShD,OAAOyB,KAAKiC,OAAO,EAAMjC,KAAKmC,aAAcnC,KAAKqC,WAIhFT,UAAY,OAAO5B,KAAKgC,KACxBF,WAAa,OAAO9B,KAAKiC,MACzBJ,iBAAmB,OAAO7B,KAAKkC,YAC/BH,kBAAoB,OAAO/B,KAAKmC,aAChC5I,aAAe,OAAOyG,KAAKoC,QAC3B1D,eAAiB,OAAOsB,KAAKqC,UAC7BK,aAAe,OAAO1C,KAAKsC,QAC3Bd,kBAAoB,OAAOxB,KAAKwC,aAChCf,mBAAqB,OAAOzB,KAAKyC,cAMjC5C,WAEC,GAAIG,KAAKqC,UAAW,CAEnB,MAAO,IADCrC,KAAKwC,aAAa,MAK1B,MAAO,GAFGjB,EAASlC,SAASW,KAAKwC,iBACtBjB,EAASlC,SAASW,KAAKyC,iBAMpC5C,UACC,MAAO,CAACG,KAAKgC,KAAMhC,KAAKiC,MAAOjC,KAAKkC,YAAalC,KAAKmC,cAGvDtC,gBAAiB8C,GAChB,IAAIlD,EAAS8B,EAAS9B,OAAOkD,EAAG3C,KAAKwC,cACjChD,EAAU+B,EAAS/B,QAAQmD,EAAG3C,KAAKyC,eACvC,OAAQhD,IAAWD,EAGpBK,QAAS+C,GACR,OAAOvB,EAAQrB,KAAM4C,GAGtB/C,OAAQ+C,GACP,OAAOvB,EAAQrB,KAAM4C,IAAU1C,EAASK,OAOzCV,MAAO+C,EAAOC,EAAK/B,GAClB,IAAIgC,EAAWzB,EAAQrB,KAAM4C,GAC7B,OAAOG,QAAQF,EAAOC,IAQxBxB,EAASpB,SAAWA,EACpBoB,EAASN,MAAQA,EACjBM,EAAS0B,OAASrB,GAAmB,GACrCL,EAAS2B,QAAUtB,GAAmB,GACtCL,EAAS4B,cAvNT,SAAuB1B,EAAaC,GACnC,IAAKG,EAAKuB,EAAWC,EAAYC,GAAgB7B,GAC5CM,EAAMwB,EAAYC,EAAaC,GAAiB/B,EACrD,GAAI0B,EACH,MAAM,IAAIvD,EAAc,8CAEzB,IAAK0D,EACJ,MAAM,IAAI1D,EAAc,gDAEzB,OAAO,IAAI0B,EAASM,EAAKE,EAAMsB,EAAYG,IA+M5CjC,EAASmC,UA1MT,SAAmBnJ,EAAGO,GACrB,IAAI6I,EAAMrC,EAAQ/G,EAAGO,GACrB,OAAI6I,GAAOxD,EAASE,aACZ,GACGsD,GAAOxD,EAASG,aACnB,CAACiB,EAAS4B,cAAcrI,EAAE2G,YAAalH,EAAEmH,eACtCiC,GAAOxD,EAASM,OACnB,CAAC3F,GACE6I,GAAOxD,EAASK,QAEhBmD,GAAOxD,EAASI,QADnB,CAAChG,GAGEoJ,GAAOxD,EAASO,cACnB,CAACa,EAAS4B,cAAc5I,EAAEkH,YAAa3G,EAAE4G,eACtCiC,GAAOxD,EAASQ,cACnB,QADD,GA6LRY,EAASqC,MAvLT,SAAerJ,EAAGO,GACjB,IAAI6I,EAAMrC,EAAQ/G,EAAGO,GACrB,OAAI6I,GAAOxD,EAASE,aAGf9F,EAAEwH,MAAQjH,EAAE+G,MAAStH,EAAEyH,cAAgBlH,EAAEgH,WAErC,CAACvH,EAAGO,GAGJ,CAACyG,EAAS4B,cAAc5I,EAAEkH,YAAa3G,EAAE4G,eAEvCiC,GAAOxD,EAASG,aACnB,CAACiB,EAAS4B,cAAc5I,EAAEkH,YAAa3G,EAAE4G,eACtCiC,GAAOxD,EAASM,QAEhBkD,GAAOxD,EAASK,OADnB,CAACjG,GAGEoJ,GAAOxD,EAASI,QACnB,CAACzF,GACE6I,GAAOxD,EAASO,cACnB,CAACa,EAAS4B,cAAcrI,EAAE2G,YAAalH,EAAEmH,eACtCiC,GAAOxD,EAASQ,cAGtB7F,EAAEiH,MAAQxH,EAAEsH,MAAS/G,EAAEkH,cAAgBzH,EAAEuH,WAErC,CAAChH,EAAGP,GAGJ,CAACgH,EAAS4B,cAAcrI,EAAE2G,YAAalH,EAAEmH,oBAR3C,GAkKRH,EAASsC,aApJT,SAAsBC,GAErB,GADAA,EAAU9H,KAAKuF,EAAS0B,QACpBa,EAAUtK,QAAU,EACvB,OAAOsK,EAER,MAAMC,EAAS,CAACD,EAAU1H,SAC1B,KAAO0H,EAAUtK,OAAS,GAAG,CAC5B,IAAIwK,EAAOD,EAAOE,MACdC,EAAOJ,EAAU1H,QACrB2H,EAAOI,QAAQ5C,EAASmC,UAAUM,EAAME,IAEzC,OAAOH,GA0IRxC,EAAS6C,SAtIT,SAAkBN,GAEjB,GADAA,EAAU9H,KAAKuF,EAAS0B,QACpBa,EAAUtK,QAAU,EACvB,OAAOsK,EAER,MAAMC,EAAS,CAACD,EAAU1H,SAC1B,KAAO0H,EAAUtK,OAAS,GAAG,CAC5B,IAAIwK,EAAOD,EAAOE,MACdC,EAAOJ,EAAU1H,QACrB2H,EAAOI,QAAQ5C,EAASqC,MAAMI,EAAME,IAErC,OAAOH,GChQR,WASE,SAASM,EAAcC,EAAMrJ,EAAOsJ,GAElC,YAAmB,IAARA,GAAgC,IAARA,EAC1B1K,KAAKyK,GAAMrJ,IAEpBA,GAASA,EACTsJ,GAAOA,EAEHhG,MAAMtD,IAA2B,iBAARsJ,GAAoBA,EAAM,GAAM,EACpDC,KAGTvJ,EAAQA,EAAMqE,WAAWmF,MAAM,QAG/BxJ,GAFAA,EAAQpB,KAAKyK,KAAQrJ,EAAM,GAAK,KAAOA,EAAM,IAAOA,EAAM,GAAKsJ,GAAQA,MAEzDjF,WAAWmF,MAAM,MAChB,GAAK,KAAOxJ,EAAM,IAAOA,EAAM,GAAKsJ,EAAOA,MAIvD1K,KAAK6K,UACR7K,KAAK6K,QAAU,SAASzJ,EAAOsJ,GAC7B,OAAOF,EAAc,QAASpJ,EAAOsJ,KAIpC1K,KAAK8K,UACR9K,KAAK8K,QAAU,SAAS1J,EAAOsJ,GAC7B,OAAOF,EAAc,QAASpJ,EAAOsJ,KAIpC1K,KAAK+K,SACR/K,KAAK+K,OAAS,SAAS3J,EAAOsJ,GAC5B,OAAOF,EAAc,OAAQpJ,EAAOsJ,KA3C1C,GAkDA,MAAMrF,EAAM,SAAU3E,EAAGO,GAAI,OAAOP,EAAIO,GAMjC,SAAS+J,EAAaC,EAAUC,GACnC,IAAIC,EAAMF,EAASG,UAAYF,EAASE,SACpCC,EAAMJ,EAASK,UAAYJ,EAASI,SACpCrJ,EAAMgJ,EAASM,cAAgBL,EAASK,aACxCC,EAAKP,EAASQ,WAAaP,EAASO,UACxC,OAAON,GAAOE,GAAOpJ,GAAOuJ,EAoBzB,SAASE,EAAgBC,EAAQH,GACvC,QAAWvG,IAAPuG,EACA,MAAM,IAAI5H,MAAO,sCAErB,MAAMgI,EAAWJ,EAAKG,EAAOF,UAC7B,MAAO,CACNL,SAAWO,EAAOP,SAAWO,EAAOL,SAASM,EAAW,GAAID,EAAOJ,aAAaK,EAASA,EACzFN,SAAWK,EAAOL,SAAWK,EAAOJ,aAAaK,EACjDL,aAAeI,EAAOJ,aACtBE,UAAYD,GASP,SAASK,EAAmBF,EAAQH,GAOvC,IAAIM,EAEAA,EADM7G,MAANuG,EACcG,EAEAD,EAAgBC,EAAQH,GAG1C,IAAIO,EAAY1G,EAAIyG,EAAYR,SAAU,GAK1C,OAJkB,IAAdS,IAEAA,EAAY1G,EAAIsG,EAAOJ,aAAc,IAElCQ,EASJ,SAASC,EAASL,GACrB,OAA4B,IAApBA,EAAOL,UAA4C,IAAxBK,EAAOJ,aASvC,MAAMU,EAAapJ,OAAO0D,OAAO,CACpC2F,KAAO,OACP5E,OAAQ,SACR6E,YAAa,aACbC,aAAc,gBAOX,SAASC,EAAkBV,EAAQW,GACtC,MAAOlB,SAAUrC,EAAGuC,SAAUiB,EAAGhB,aAAc7K,GAAKiL,EACvD,GAAI5C,EAAIuD,EAAM,GAAI,OAAOL,EAAWG,aACpC,GAAIrD,EAAIuD,EAAM,GAAI,OAAOL,EAAWE,YAEpC,GAAIpD,IAAMuD,EAAM,GAAI,CACnB,GAAIC,EAAI,EAAK,OAAON,EAAWG,aAC/B,GAAU,IAANG,GAAa7L,EAAI,EAAK,OAAOuL,EAAWG,kBACtC,GAAIrD,IAAMuD,EAAM,GAAI,CACvB,GAAIC,EAAI,EAAK,OAAON,EAAWE,YAC/B,GAAS,GAALI,GAAY7L,EAAI,EAAK,OAAOuL,EAAWG,aAE/C,OAAOH,EAAW3E,OAQZ,SAASkF,EAAqBC,EAAYH,GAC7C,OAAQD,EAAkBI,EAAYH,IAAUL,EAAW3E,OAUxD,SAASoF,EAAWf,EAAQW,GAClC,MAAMK,EAAQN,EAAkBV,EAAQW,GASxC,OARIK,IAAUV,EAAW3E,SAExBqE,EAAOL,SAAW,EAClBK,EAAOJ,aAAe,EAClBoB,IAAUV,EAAWG,aACxBT,EAAOP,SAAWkB,EAAM,GAClBX,EAAOP,SAAWkB,EAAM,IAEzBX,EAOD,SAASiB,EAAejB,EAAQW,GACnC,IAAIO,EAAKlB,EAAOF,UAEZqB,EAAYC,EAAiCpB,EAAQW,EAAM,IAE3DU,EAAaD,EAAiCpB,EAAQW,EAAM,IAEhE,YAAkBrH,IAAd6H,QAA0C7H,IAAf+H,EACvBF,EAAYE,EACL,CAACH,EAAKC,EAAWR,EAAM,IAGvB,CAACO,EAAKG,EAAYV,EAAM,SAEhBrH,IAAd6H,EACE,CAACD,EAAKC,EAAWR,EAAM,SACVrH,IAAf+H,EACE,CAACH,EAAKG,EAAYV,EAAM,IACvB,MAACrH,OAAWA,GAgB5B,SAASgI,EAAiBlE,EAAEwD,EAAE7L,EAAEwM,GAC/B,OAAKlN,KAAKmN,IAAIZ,EAAE,GAAK,EAAE7L,GAAGqI,EAAEmE,IAAO,EAcpC,SAASE,EAAuBrE,EAAEwD,EAAE7L,EAAEwM,GAErC,GAAU,IAANxM,GAAmB,IAAN6L,EACb,OAAIxD,GAAKmE,EAAU,GACP,CAAC,GAGjB,GAAU,IAANxM,EAAW,MAAO,EAAEwM,EAAEnE,GAAGwD,GAE7B,IAAiC,IAA7BU,EAAgBlE,EAAEwD,EAAE7L,EAAEwM,GAAc,MAAO,GAG/C,GAAqB,IADAX,EAAEA,EAAI,EAAE7L,GAAGqI,EAAEmE,GAE9B,MAAO,EAAEX,EAAE7L,GAEf,MAAM2M,EAAOrN,KAAKqN,KAAKrN,KAAKmN,IAAIZ,EAAE,GAAK,EAAE7L,GAAGqI,EAAEmE,IACxCI,IAAOf,EAAIc,GAAM3M,EACjB6M,IAAOhB,EAAIc,GAAM3M,EACvB,MAAO,CAACV,KAAK8F,IAAIwH,EAAGC,GAAIvN,KAAK+F,IAAIuH,EAAGC,IAwC9B,SAASR,EAAiCpB,EAAQuB,GACrD,MAAO9B,SAAUrC,EAAGuC,SAAUiB,EAAGhB,aAAc7K,GAAKiL,EACjD6B,EA7BP,SAAwCzE,EAAEwD,EAAE7L,EAAEwM,GAC7C,MAAMM,EAAMJ,EAAuBrE,EAAEwD,EAAE7L,EAAEwM,GACzC,OAAmB,IAAfM,EAAI7N,OAAqB,GACN,GAAd6N,EAAI7N,OACL6N,EAAI,GAAK,EACR,CAACA,EAAI,IAEE,GAEO,GAAdA,EAAI7N,OACL6N,EAAI,GAAK,EAAY,GACrBA,EAAI,GAAK,EAAY,CAACA,EAAI,GAAIA,EAAI,IAClCA,EAAI,GAAK,EAAY,CAACA,EAAI,IACvB,GAEC,GAcAC,CAA+B1E,EAAEwD,EAAE7L,EAAEwM,GACjD,OAAmB,IAAfM,EAAI7N,YACD,EAEK6N,EAAI,GAmBV,SAASE,EAAe/B,EAAQW,GAEtC,IAAIqB,EAAiBZ,EAAiCpB,EAAQW,EAAM,IAEhEsB,EAAgBb,EAAiCpB,EAAQW,EAAM,IASnE,OAPOqB,GAAkB5I,EAAAA,IAClB4I,OAAiB1I,GAEjB2I,GAAiB7I,EAAAA,IACjB6I,OAAgB3I,QAGAA,IAAnB0I,QAAkD1I,IAAlB2I,EAC5BD,EAAiBC,EAChB,CAACD,EAAgBrB,EAAM,IAEvB,CAACsB,EAAetB,EAAM,SAEHrH,IAAnB0I,EACE,CAACA,EAAgBrB,EAAM,SACPrH,IAAlB2I,EACE,CAACA,EAAetB,EAAM,IACrB,MAACrH,OAAWA,GAuBlB,SAAS4I,EAA+BC,EAAcnC,GAKzD,IAAKK,EAASL,IAAWmC,EAAahJ,SAClC,OAAO,IAAI4C,EAASiE,EAAOP,UAG/B,IAWIpD,EAAKE,EAXL2E,EAAKiB,EAAa9F,IAClB+F,EAAKD,EAAa5F,KAIlB8F,GAHYF,EAAa7F,WACb6F,EAAa3F,YAEfuD,EAAgBC,EAAQkB,IAClCoB,EAAKD,EAAQ5C,SACb8C,EAAKF,EAAQ1C,SACb6C,EAAKH,EAAQzC,aACb6C,EAAK1C,EAAgBC,EAAQoC,GAAI3C,SAIrC,GAAU,GAAN+C,EAAS,CA4BT,IAAIE,GAAYH,EAAGC,EAAKtB,EACxB,GAAIiB,EAAaQ,gBAAgBD,GAAW,CACxC,IAAIE,GAAYL,EAAGA,GAAI,EAAIC,GAAMF,EAE7BE,EAAK,EAGDF,EAAKG,GACLpG,EAAMuG,EACNrG,EAAOkG,IAEPpG,EAAMuG,EACNrG,EAAO+F,GAKPA,EAAKG,GACLpG,EAAMiG,EACN/F,EAAOqG,IAEPvG,EAAMoG,EACNlG,EAAOqG,IAwCvB,OAvBIN,EAAKG,GAELpG,EAAMiG,EACN/F,EAAOkG,IAGPpG,EAAMoG,EACNlG,EAAO+F,GAcXjG,EAAMhI,KAAK8K,QAAQ9C,GAAM,GACzBE,EAAOlI,KAAK+K,OAAO7C,GAAO,GACnB,IAAIR,EAASM,EAAKE,GAAM,GAAM,GAiBlC,SAASsG,EAA8BC,EAAajD,EAAIO,GAC3D,IAAKZ,EAAKvG,EAAO8J,EAAO5J,GAAY2J,EAKpC,OAHI1C,EAAY,QAAe9G,IAAVL,IACjBA,GAASA,GAEN,CAAC4G,EAAI5G,EAAO8J,EAAO5J,GAsDvB,SAAS6J,EAAgBb,EAAcc,EAAajD,EAAQkD,GAK/D,GAAIf,EAAahJ,SACb,MAAM,IAAIlB,MAAM,4CAEpB,IAAKoI,EAASL,GACV,MAAM,IAAI/H,MAAM,6BAGpB,IAKIxC,EAAOoK,EAAIsD,EACXC,EAAYhD,EANZkC,EAAKtC,EAAOP,SACZ8C,EAAKvC,EAAOL,SACZ6C,EAAKxC,EAAOJ,aACZsB,EAAKlB,EAAOF,UAIZuD,EAAa,GAEjBH,EAAcI,SAAQ,SAASC,GAEtBN,EAAYN,gBAAgBY,EAAKvH,WAItCvG,EAAQ8N,EAAKvH,SAAS,GAEjBsF,EAAgBgB,EAAIC,EAAIC,EAAI/M,IAOjC0N,EAAS1B,EAAuBa,EAAGC,EAAGC,EAAI/M,GAE1C0N,EAAOG,SAAQ,SAASE,GACpB3D,EAAKqB,EAAKsC,EACVpD,EAAYF,EAAmBF,EAAQH,GACvCuD,EAAaP,EAA8BU,EAAKvH,SAAU6D,EAAIO,GAC1D+B,EAAaQ,gBAAgBS,KAC7BG,EAAKH,WAAaA,EAClBG,EAAKnD,UAAYA,EACjBiD,EAAW1E,KAAK4E,QAfpBE,QAAQC,IAAI,WANZD,QAAQC,IAAI,aA0CpB,OAZAL,EAAW7M,MAHC,SAAUzB,EAAEO,GACpB,OAAO0G,EAAStC,IAAI3E,EAAEqO,WAAY9N,EAAE8N,eAcjCC,EAkCX,MAAMM,EAAWzM,OAAO0D,OAAO,CAC3BgJ,KAAM,EACNC,OAAQ,IAINC,EAAY5M,OAAO0D,OAAO,CAC5BgJ,KAAM,EACNG,YAAa,EACbC,MAAO,EACPH,OAAQ,EACRI,KAAM,IAIH,MAAMC,EAET5J,YAAa6J,EAAYC,GACrB,IAAIvE,EAAKuE,EAAWtE,UAChBuE,EAAYhE,EAAS+D,GAGzB,GAF0B9K,MAAd6K,GAAkD7K,MAAvB6K,EAAW1E,SAS1ChF,KAAK6J,IADLD,EACW,CAACV,EAASE,OAAQC,EAAUE,OAE5B,CAACL,EAASE,OAAQC,EAAUF,UAExC,CACH,IASIW,EATAC,EAAanE,EAAS8D,GACtBM,EAAa1E,EAAgBoE,EAAYtE,GACzC6E,EAAe3E,EAAgBqE,EAAYvE,GAI3C8E,EADeF,EAAWhF,UAAYiF,EAAajF,SAC7BkE,EAASE,OAASF,EAASC,KAIrD,GAAIY,GAAcH,EAAW,CACzB,IAAIO,EAAeH,EAAW9E,UAAY+E,EAAa/E,SACnDkF,EAAeJ,EAAW7E,cAAgB8E,EAAa9E,aAGvD2E,EAFgBK,GAAeC,EAEzBf,EAAUD,OAEVC,EAAUC,iBAEZS,GAAcH,EACtBE,EAAMT,EAAUE,MACTQ,IAAeH,EACtBE,EAAMT,EAAUG,KACRO,GAAeH,IACvBE,EAAMT,EAAUF,MAEpBnJ,KAAK6J,IAAM,CAACK,EAAKJ,IAIzBO,eACI,OAAOrK,KAAK6J,IAAI,GAGpBS,gBACI,OAAOtK,KAAK6J,IAAI,GAGpBhK,WACI,MAAMqJ,EAAWO,EAAYP,SACvBG,EAAYI,EAAYJ,UAC9B,IAAIkB,EAAOvK,KAAKqK,UAAYnB,EAASE,OAAU,SAAW,GAY1D,OAXIpJ,KAAKsK,WAAajB,EAAUE,MAC5BgB,GAAO,mBACAvK,KAAKsK,WAAajB,EAAUD,OACnCmB,GAAO,mBACAvK,KAAKsK,WAAajB,EAAUG,KACnCe,GAAO,mBACAvK,KAAKsK,WAAajB,EAAUC,YACnCiB,GAAO,yBACAvK,KAAKsK,WAAajB,EAAUF,OACnCoB,GAAO,8BAEJA,GAKfd,EAAYP,SAAWA,EACvBO,EAAYJ,UAAYA,gEAnrBjB,SAAoB9D,GACvB,MAAO,CACHP,SAAUO,EAAOP,SACjBE,SAAUK,EAAOL,SACjBC,aAAcI,EAAOJ,aACrBE,UAAWE,EAAOF,ySCxC1B,MAAMmF,UAA0BhN,MAE5BqC,YAAYC,GACRC,MAAMD,GACNE,KAAKC,KAAO,qBA4BpB,SAAShB,EAAI3E,EAAGO,GAAI,OAAOP,EAAEO,EAG7B,MAAM4P,GAEF5K,YAAYrE,GACRwE,KAAK0K,MAAQ,GACb1K,KAAKxE,QAAUA,GAAW,GAS9BqE,cAAc8K,GACV,IAEIC,EACAC,EAHAC,EAAW,EACXC,EAAW/K,KAAK0K,MAAMnR,OAAS,EAGnC,KAAOuR,GAAYC,GAGf,GAFNH,GAAgBE,EAAWC,GAAY,EAAI,EAC3CF,EAAiB7K,KAAK0K,MAAME,GAClBC,EAAiBF,EACjBG,EAAWF,EAAe,MACvB,CAAA,KAAIC,EAAiBF,GAI9B,OAAOC,EAHDG,EAAWH,EAAe,EAOrC,OAAQG,EAqBTlL,QAAQmL,EAAOlE,GACX,OAAIkE,EAAQ,GAGC,GAATA,GAAchL,KAAK0K,MAAMnR,OAAS,GAAKyG,KAAK0K,MAAM,IAAM5D,EAShEjH,QAAQiH,GACJ,IAAIkE,EAAQhL,KAAKiL,cAAcnE,GAC/B,OAAQ9G,KAAKkL,QAAQF,EAAOlE,GAAMkE,GAAS,EAG/CnL,gBAAgBsL,GACZ,IAAIrE,EAAGkE,EACHI,EAAU,GACd,IAAK,IAAI1R,EAAE,EAAGA,EAAEyR,EAAS5R,OAAQG,IAC7BoN,EAAIqE,EAASzR,GACbsR,EAAQhL,KAAKqL,QAAQvE,GACjBkE,GAAS,GACTI,EAAQlH,KAAK8G,GAGrB,OAAOI,EAMXvL,IAAIiH,GACA,OAAQ9G,KAAKqL,QAAQvE,IAAM,EAG/BjH,IAAImL,GACA,OAAOhL,KAAK0K,MAAMM,GAkBtBnL,eAAeyL,EAAWC,EAAW/P,GAGjC,GAAIwE,KAAK0K,MAAMnR,OAAS,EAAG,CACvB,IAAI6R,EAAUpL,KAAKwL,gBAAgBF,GAOnCF,EAAQrP,MAAK,SAASzB,EAAEO,GAAG,OAAOP,EAAEO,KACpC,IAAK,IAAInB,EAAE0R,EAAQ7R,OAAO,EAAGG,GAAK,EAAGA,IACjCsG,KAAK0K,MAAMe,OAAOL,EAAQ1R,GAAI,GAKtC,IAAIoN,EAAGkE,EACH/O,EAAMsP,EAAUhS,OACpB,IAAK,IAAIG,EAAE,EAAGA,EAAEuC,EAAKvC,IACjBoN,EAAIyE,EAAU7R,GACdsR,EAAQhL,KAAKiL,cAAcnE,GACtB9G,KAAKkL,QAAQF,EAAOlE,IAErB9G,KAAK0K,MAAMe,OAAO7R,KAAK8R,IAAIV,GAAQ,EAAGlE,GAmBlDjH,aAAayL,EAAWC,EAAW/P,GAE/B,GAAIwE,KAAK0K,MAAMnR,OAAS,GAAK+R,EAAU/R,OAAS,EAAG,CAG/C,IAAI6R,EAAUpL,KAAKwL,gBAAgBF,GACnC,IAAK,IAAI5R,EAAE,EAAGA,EAAE0R,EAAQ7R,OAAOG,IAC3BsG,KAAK0K,MAAMU,EAAQ1R,SAAMmF,EASjC,GAJAmB,KAAK0K,MAAQ1K,KAAK0K,MAAMiB,OAAOJ,GAE/BvL,KAAK0K,MAAM3O,KAAKkD,GAEZqM,EAAU/R,OAAS,EAAG,CACtB,IAAIyR,EAAQhL,KAAK0K,MAAMW,aAAQxM,GAC3BmM,GAAS,GACThL,KAAK0K,MAAMe,OAAOT,EAAOhL,KAAK0K,MAAMnR,OAAOyR,GArO3D,IAAgBY,EAyOR5L,KAAK0K,OAzOGkB,EAyOY5L,KAAK0K,MAxOtB,IAAI,IAAIjQ,IAAImR,KAuPnB/L,OAAOyL,EAAWC,EAAW/P,GACzB,IAAItB,EAAOoR,EAAU/R,OAASgS,EAAUhS,OACxC,GAAY,GAARW,EACA,OAIJ,IAAI2R,GAjPcC,EAiPc9L,KAAK0K,MAAMnR,OAjPZwS,EAiPoB7R,EAhPpC,GAAf4R,EACO,OAEHC,GAAe,IAAO,SAAW,QAJ7C,IAA0BD,EAAaC,EAkPf,UAAZF,EACA7L,KAAKgM,eAAeV,EAAWC,EAAW/P,GACvB,QAAZqQ,GACP7L,KAAKiM,aAAaX,EAAWC,EAAW/P,GAShDqE,aACI,OAAQG,KAAK0K,MAAMnR,OAAS,EAAKyG,KAAK0K,MAAM,QAAK7L,EAGrDgB,WAAa,WACT,OAAQG,KAAK0K,MAAMnR,OAAS,EAAKyG,KAAK0K,MAAM1K,KAAK0K,MAAMnR,OAAS,QAAKsF,GAYzEgB,UAAUiH,GACN,IAAIpN,EAAIsG,KAAKiL,cAAcnE,GAC3B,OAAI9G,KAAKkL,QAAQxR,EAAGoN,GAOZpN,EAAI,EACGA,EAAE,GAED,EAOLE,KAAK8R,IAAIhS,GAAG,EAQ3BmG,UAAUiH,GACN,IAAIpN,EAAIsG,KAAKiL,cAAcnE,GAC3B,OAAI9G,KAAKkL,QAAQxR,EAAGoN,KAOhBpN,EAAIE,KAAK8R,IAAIhS,GAAK,IACL,EAJNA,GAIgB,EAS/BmG,UAAUiH,GACN,IAAIpN,EAAIsG,KAAKiL,cAAcnE,GAC3B,GAAI9G,KAAKkL,QAAQxR,EAAGoN,GAKhB,OAAIpN,EAAIsG,KAAK0K,MAAMnR,OAAQ,EAChBG,EAAE,GAED,EAET,CAOH,IAAIwS,EAAMtS,KAAK8R,IAAIhS,GACnB,OAAQwS,EAAMlM,KAAK0K,MAAMnR,OAAU2S,GAAO,GAUlDrM,UAAUiH,GACN,IAAIpN,EAAIsG,KAAKiL,cAAcnE,GAC3B,OAAI9G,KAAKkL,QAAQxR,EAAGoN,KAOhBpN,EAAIE,KAAK8R,IAAIhS,IACHsG,KAAK0K,MAAMnR,OAJdG,GAI6B,EAS5CmG,cAAcsM,GAGV,QAFiBtN,IAAbsN,IACAA,EAAW,IAAI7K,GAAU3C,EAAAA,EAAUA,EAAAA,GAAU,GAAM,IACnDwN,aAAoB7K,IAAa,EACjC,MAAM,IAAIkJ,EAAkB,qCAGhC,GAAI2B,EAASzN,SAAU,CACnB,IAAIsM,EAAQhL,KAAKqL,QAAQc,EAASvK,KAClC,OAAIoJ,GAAS,EACF,CAACA,EAAOA,EAAQ,GAEhB,MAACnM,OAAWA,GAK3B,IAAIuN,GAAe,EAAGC,GAAa,EAMnC,OAAqB,KAJjBD,EADAD,EAAStK,WACK7B,KAAKsM,UAAUH,EAASvK,KAExB5B,KAAKuM,UAAUJ,EAASvK,QAUvB,KAJfyK,EADAF,EAASpK,YACG/B,KAAKwM,UAAUL,EAASrK,MAExB9B,KAAKyM,UAAUN,EAASrK,OAL7B,MAACjD,OAAWA,GAUhB,CAACuN,EAAaC,EAAY,GAOrCxM,OAAOsM,GACH,IAAK/P,EAAOJ,GAAOgE,KAAK0M,cAAcP,GACtC,OAAiBtN,MAATzC,EAAsB4D,KAAK0K,MAAMiC,MAAMvQ,EAAOJ,GAAO,GAMjE6D,OAAOsM,GACH,IAAK/P,EAAOJ,GAAOgE,KAAK0M,cAAcP,GACtC,OAAiBtN,MAATzC,EAAsB4D,KAAK0K,MAAMe,OAAOrP,EAAOJ,EAAII,GAAS,GAIxEyD,MAAMzD,EAAOJ,GACT,OAAOgE,KAAK0K,MAAMiC,MAAMvQ,EAAOJ,GAGnC6D,OAAOzD,EAAO7C,GACV,OAAOyG,KAAK0K,MAAMe,OAAOrP,EAAO7C,GAapCsG,cAAc+M,GACV,GAAyB,GAArBA,EAAWrT,OACX,OAEJ,MAAMqI,EAAMgL,EAAW,GACjB9K,EAAO8K,EAAWA,EAAWrT,OAAO,GAC1C,IAAK6C,EAAOJ,GAAOgE,KAAK0M,cAAc,IAAIpL,EAASM,EAAKE,GAAM,GAAM,IAEhE+K,EAASzQ,EACT0Q,EAAS1Q,EACT2Q,EAAS,EAEb,KAAOF,EAAS7Q,GAAK,CACjB,IAAIgR,EAAUhN,KAAK0K,MAAMmC,GACrBI,EAAUL,EAAWG,GAYzB,GAXIC,EAAUC,GACVjN,KAAK0K,MAAMoC,GAAU9M,KAAK0K,MAAMmC,GAChCC,IACAD,KACOG,GAAWC,GAClBJ,IACAE,KAGAA,IAEAA,GAAUH,EAAWrT,OACrB,MAGRyG,KAAK0K,MAAMe,OAAOqB,EAAQD,EAAOC,GAIrCjN,SACI,OAAOG,KAAK0K,MAAMwC,SAGtBrN,QACIG,KAAK0K,MAAQ,GAGjBnR,aACI,OAAOyG,KAAK0K,MAAMnR,QCjf1B,MAAM4T,GAELtN,YAAauN,EAAWnN,EAAMzE,GAC7BA,EAAUA,GAAW,GACrBwE,KAAKoN,UAAYA,EACjBpN,KAAKC,KAAOA,EACZD,KAAKqN,UAAyBxO,IAAjBrD,EAAQ6R,MAA8B7R,EAAQ6R,KAC3DrN,KAAKsN,cAAgB,GAUtBzN,UAAW0N,EAAU/R,GACpB,IAAK+R,GAAgC,mBAAbA,EACvB,MAAM,IAAI/P,MAAM,0BAA2B+P,GAE5C,MAAMC,EAAM,IAAIC,GAAazN,KAAMuN,EAAU/R,GAG1C,GAFHwE,KAAKsN,cAAcpJ,KAAKsJ,GAEjBxN,KAAKqN,MAAQG,EAAIH,KAAM,CAC1BG,EAAIE,cAAe,EACnB,IAAIC,EAAO3N,KACXnD,QAAQC,UAAU8Q,MAAK,WACtB,MAAMC,EAAQF,EAAKP,UAAUU,sBAAsBH,EAAK1N,OAAS,GACjEuN,EAAIE,cAAe,EACnB,IAAK,IAAIK,KAAQF,EAChBF,EAAKK,QAAQD,EAAM,CAACP,IAAM,MAIhC,OAAOA,EASR3N,QAASkO,EAAME,EAAMZ,GACpB,IAAIa,EAAOC,EACX,IAAK,MAAMX,KAAOS,EAEjB,IAAIT,EAAIY,WAAR,CAGAF,EAAQ,CACPG,IAAKrO,KAAKoN,UACVnN,KAAMD,KAAKC,KACXuN,IAAKA,EACLH,KAAMA,GAEPc,EAAMX,EAAIW,KAAOnO,KAAKoN,UACtB,IACCI,EAAID,SAASe,KAAKH,EAAKJ,EAAMG,GAC5B,MAAOK,GACRvF,QAAQC,IAAI,YAAYjJ,KAAKC,SAASuN,EAAID,YAAYgB,OASzD1O,YAAY2N,GACX,IAAItB,EAAMlM,KAAKsN,cAAcjC,QAAQmC,GACjCtB,GAAO,IACVlM,KAAKsN,cAAc7B,OAAOS,EAAK,GAC/BsB,EAAIgB,cAUP,MAAMf,GAEL5N,YAAY4O,EAAOlB,EAAU/R,GAC5BA,EAAUA,GAAW,GACrBwE,KAAKyO,MAAQA,EACbzO,KAAKC,KAAOwO,EAAMxO,KAClBD,KAAKuN,SAAWA,EAChBvN,KAAKqN,UAAyBxO,IAAjBrD,EAAQ6R,KAAsBrN,KAAKyO,MAAMpB,KAAO7R,EAAQ6R,KACrErN,KAAK0N,cAAe,EACpB1N,KAAKoO,YAAa,EAClBpO,KAAKmO,IAAM3S,EAAQ2S,IAGpBtO,YACCG,KAAKoO,YAAa,EAClBpO,KAAKuN,cAAW1O,EAChBmB,KAAKyO,MAAMC,YAAY1O,OAsBlB,SAAS2O,GAAkBC,GAGjC,OAFAA,EAAOC,oBAAsB,IAAI/T,IACjC8T,EAAOE,kBAAoB,GACpBF,EAUD,SAASG,GAAkBC,GAEjC,SAASC,EAAiBL,EAAQ3O,GACjC,MAAMwO,EAAQG,EAAOC,oBAAoBK,IAAIjP,GAC7C,GAAapB,MAAT4P,EACH,MAAM,IAAIjR,MAAM,kBAAmByC,GAEpC,OAAOwO,EA2GRO,EAAWG,eAlGX,SAAwBlP,EAAMzE,GAE7B,GAAIwE,KAAK6O,oBAAoBtU,IAAI0F,GAChC,MAAM,IAAIzC,MAAM,wBAAyByC,GAE1CD,KAAK6O,oBAAoB9Q,IAAIkC,EAAM,IAAIkN,GAAMnN,KAAMC,EAAMzE,KA8F1DwT,EAAWI,gBALX,SAAyBnP,EAAM8N,GAC9B,OAAO/N,KAAKqP,mBAAmB,CAAC,CAACpP,KAAAA,EAAM8N,KAAAA,MAKxCiB,EAAWM,qBAfX,SAA8BrP,EAAM4N,GACnC,OAAO7N,KAAKqP,mBAAmBxB,EAAMpQ,IAAIsQ,IACjC,CAAC9N,KAAAA,EAAM8N,KAAAA,OAchBiB,EAAWK,mBA3DX,SAA4BzG,GAC3B,GAAyB,GAArBA,EAAWrP,OACd,OAQD,IAAIgW,EAAe3G,EAAWnL,IAAKqL,IAClC,IAAI7I,KAACA,EAAI8N,KAAEA,GAAQjF,EACf0G,EAAKP,EAAiBjP,KAAMC,GAC5BgO,EAAOuB,EAAGlC,cAAc5S,OAAO8S,GAA2B,GAApBA,EAAIE,cAC9C,MAAO,CAAC8B,EAAIzB,EAAME,IAChBjO,MAGH,MAAM/D,EAAMsT,EAAahW,OACnBkW,EAAMzP,KAAK8O,kBACXY,EAAU1P,KAAK8O,kBAAkBvV,OAEvCyG,KAAK8O,kBAAkBvV,OAASmW,EAAUzT,EAE1C,IAAK,IAAIvC,EAAE,EAAGA,EAAEuC,EAAKvC,IACpB+V,EAAIC,EAAQhW,GAAK6V,EAAa7V,GAG/B,GAAe,GAAXgW,EAAc,CACjB,IAAI/B,EAAO3N,KACXnD,QAAQC,UAAU8Q,MAAK,WACtB,IAAK,IAAK4B,EAAIzB,EAAME,KAASN,EAAKmB,kBAEjCU,EAAGxB,QAAQD,EAAME,GAAM,GAExBN,EAAKmB,kBAAoB,QAyB5BE,EAAWW,sBA3EX,SAA+B1P,GAC9B,OAAOgP,EAAiBjP,KAAMC,GAAMqN,eA2ErC0B,EAAWY,GA1FX,SAAY3P,EAAMsN,EAAU/R,GAC3B,OAAOyT,EAAiBjP,KAAMC,GAAM4P,UAAUtC,EAAU/R,IA0FzDwT,EAAWc,IAlFX,SAAatC,GACZ,OAAOyB,EAAiBjP,KAAMwN,EAAIvN,MAAMyO,YAAYlB,IA2F/C,MAAMuC,GAEZlQ,YAAa7E,GACZ2T,GAAiB3O,MACjBA,KAAKgQ,OAAShV,EACdgF,KAAKmP,eAAe,SAAU,CAAC9B,MAAK,IAGrCxN,sBAAsBI,GACrB,GAAY,UAARA,EACH,MAAO,CAACD,KAAKgQ,QAIfhV,YAAc,OAAOgF,KAAKgQ,OAC1BhV,UAAWA,GACNA,GAASgF,KAAKgQ,SACjBhQ,KAAKgQ,OAAShV,EACdgF,KAAKoP,gBAAgB,SAAUpU,KAIlC+T,GAAkBgB,GAAcE,kBAwCjB,CACdlB,kBAAAA,GACAJ,iBAAAA,GACAoB,cAAAA,GACAG,aAjCM,cAA2BH,GACjClQ,YAAY7E,GACX+E,MAAMgD,QAAQ/H,IAGfA,UAAWA,GACV+E,MAAM/E,MAAQ+H,QAAQ/H,GAEvBA,YAAc,OAAO+E,MAAM/E,QA0B3BmV,YAlBM,SAAqBC,EAAaC,GAExC,OADAA,EAAgBA,GAAiB,SAASxS,GAAM,OAAc,GAAPA,GAChD,IAAIhB,SAAS,SAAUC,EAASwT,GACtC,IAAI9C,EAAM4C,EAAYR,GAAG,UAAU,SAAU5U,GACxCqV,EAAcrV,KACjB8B,EAAQ9B,GACRoV,EAAYN,IAAItC,YCjUpB,MAAM+C,GAEF1Q,YAAarE,EAAQ,IAEjBwE,KAAKxE,QAAUA,EAGfgV,GAAS7B,iBAAiB3O,MAC1BA,KAAKmP,eAAe,QAAS,CAAC9B,MAAK,IACnCrN,KAAKmP,eAAe,SAAU,CAAC9B,MAAK,IACpCrN,KAAKmP,eAAe,SAAU,CAAC9B,MAAK,IAUxCoD,iBACI,MAAM,IAAIjT,MAAM,mBAOpBqC,UAAUrE,EAAQ,IAEd,IAAIE,MAACA,EAAMsE,KAAKxE,QAAQE,OAASF,EACjC,GAAoB,mBAATE,EACP,OAAOA,EAUfmE,WAAW6Q,EAAMlV,EAAQ,IACrB,IAAIE,EAAQsE,KAAK2Q,UAAUnV,GAC3B,GAAoB,mBAATE,EAAqB,CAI5B,OADW4B,MAAMC,QAAQmT,GAASA,EAAO,IAAIA,IAClC3U,KAAKL,GAGhB,OAAOgV,EAQf7Q,UAAU+Q,GACN,IAAIlV,EAAQsE,KAAK2Q,YACG,mBAATjV,GACPkV,EAAM7U,MAAK,SAAS8U,EAAQC,GACxB,IAAIC,EAASF,EAAU,IAAIA,EAAOG,IAAMH,EAAOI,IAC3CC,EAASJ,EAAU,IAAIA,EAAOE,IAAMF,EAAOG,IAC/C,OAAOvV,EAAMqV,EAAOG,MAYhCrR,sBAAsBI,GAClB,GAAY,SAARA,GAA2B,UAARA,EAAkB,CACrC,IAAI2Q,EAAQ,IAAI5Q,KAAKyQ,WAAW3S,WAAWL,IAAI,EAAE1C,EAAK8C,MAC3C,CAAC9C,IAAIA,EAAKiW,IAAInT,EAAKoT,SAAIpS,KAIlC,OADAmB,KAAKmR,UAAUP,GACC,SAAR3Q,EAAmB,CAAC2Q,GAASA,GAO7C/Q,cAAc+Q,GAEV,GAAoB,GAAhBA,EAAMrX,OACN,OAEJ,MAAM6X,EAAkBpR,KAAK2P,sBAAsB,SAASpW,OAAS,EAC/D8X,EAAkBrR,KAAK2P,sBAAsB,UAAUpW,OAAS,EAChE+X,EAAkBtR,KAAK2P,sBAAsB,UAAUpW,OAAS,EAMtE,GAJI6X,GACApR,KAAKoP,gBAAgB,QAASwB,GAG9BS,GAAmBC,EACnB,IAAK,IAAIxI,KAAQ8H,EACG/R,MAAZiK,EAAKkI,KAAgCnS,MAAZiK,EAAKmI,IAC1BI,GACArR,KAAKoP,gBAAgB,SAAUtG,GAG/BwI,GACAtR,KAAKoP,gBAAgB,SAAUtG,GAYnD5O,WACI,OAAO8F,KAAKyQ,WAAWvW,KAG3B2F,IAAI9E,GACA,OAAOiF,KAAKyQ,WAAWlW,IAAIQ,GAG/B8E,IAAI9E,GACA,OAAOiF,KAAKyQ,WAAWvB,IAAInU,GAG/B8E,OACI,OAAOG,KAAKyQ,WAAWc,OAG3B1R,SACI,OAAOG,KAAKyQ,WAAWvD,SAG3BrN,UACI,OAAOG,KAAKyQ,WAAW3S,UAQ3B+B,IAAI9E,EAAKC,GACL,IAAIiW,OAAMpS,EAMV,OALImB,KAAKyQ,WAAWlW,IAAIQ,KACpBkW,EAAMjR,KAAKyQ,WAAWvB,IAAInU,IAE9BiF,KAAKyQ,WAAW1S,IAAIhD,EAAKC,GACzBgF,KAAKwR,cAAc,CAAC,CAACzW,IAAKA,EAAKiW,IAAIhW,EAAOiW,IAAKA,KACxCjR,KAGXH,OAAO9E,GACH,IAAI+I,GAAS,EACTmN,OAAMpS,EAOV,OANImB,KAAKyQ,WAAWlW,IAAIQ,KACpBkW,EAAMjR,KAAKyQ,WAAWvB,IAAInU,GAC1BiF,KAAKyQ,WAAWgB,OAAO1W,GACvB+I,GAAS,GAEb9D,KAAKwR,cAAc,CAAC,CAACzW,IAAKA,EAAKiW,SAAInS,EAAWoS,IAAKA,KAC5CnN,EAGXjE,QAEI,MAAM+Q,EAAQ,IAAI5Q,KAAKyQ,WAAW3S,WAAWL,IAAI,EAAE1C,EAAK8C,MAC7C,CAAC9C,IAAKA,EAAKiW,SAAKnS,EAAWoS,IAAKpT,KAG3CmC,KAAKyQ,WAAWiB,QAEhB1R,KAAKwR,cAAcZ,IAK3BJ,GAASzB,kBAAkBwB,GAAcN,WC7LzC,MAAM0B,WAAsBpB,GAExB1Q,cAAckR,EAAOG,GACjB,OAAO5P,EAAS0B,OAAO+N,EAAM5E,SAAU+E,EAAM/E,UAGjDtM,eAAekR,EAAOG,GAClB,OAAO5P,EAAS2B,QAAQ8N,EAAM5E,SAAU+E,EAAM/E,UAIlDtM,UAAUrE,EAAQ,IACd,IAAIE,EAAQF,EAAQE,OAASqE,MAAM4Q,UAAUnV,GAC7C,MAAa,OAATE,EACOiW,GAAc3O,OACL,QAATtH,EACAiW,GAAc1O,QAED,mBAATvH,EAIRA,OAJH,EAQRmE,KAAMrE,EAAU,IACZ,IAAIoW,EAAO5R,KAAK6R,WAAW7R,KAAKkN,SAAU1R,GAE1C,OAAQ8B,MAAMC,QAAQqU,GAASA,EAAO,IAAIA,ICzBlD,MAAME,GAEFjS,YAAakS,EAAcxE,GACvBvN,KAAKgS,SAAMnT,EACXmB,KAAKiS,GAAKF,EACV/R,KAAKuN,SAAWA,EAGpB1N,QACI,OAAmBhB,MAAZmB,KAAKgS,IAMhBnS,WAAWqS,EAAWC,GAClB,GAAgBtT,MAAZmB,KAAKgS,IACL,MAAM,IAAIxU,MAAM,sBAEpB,IAAI4U,EAAMpS,KAAKiS,GAAGI,MAAMD,MACpBE,EAAuC,IAA/B1Y,KAAK+F,IAAIuS,EAAYE,EAAK,GACtCpS,KAAKgS,IAAMO,WAAWvS,KAAKwS,UAAUC,KAAKzS,MAAOsS,EAAOJ,EAAWC,GAMvEtS,UAAUqS,EAAWC,GACjB,GAAgBtT,MAAZmB,KAAKgS,IAAkB,CACvBhS,KAAKgS,SAAMnT,EAEX,IAAIuT,EAAMpS,KAAKiS,GAAGI,MAAMD,MACpBA,EAAMF,EAENlS,KAAKuS,WAAWL,EAAWC,GAG3BnS,KAAKuN,SAAS6E,EAAKD,IAQ/BtS,QACoBhB,MAAZmB,KAAKgS,MACLU,aAAa1S,KAAKgS,KAClBhS,KAAKgS,SAAMnT,ICvBf,gBAAiB1B,QAAW,IAC5BA,OAAOwV,YAAc,GACrBxV,OAAOwV,YAAYC,QAAS,IAAIC,MAAOC,WAEvC,QAAS3V,OAAOwV,aAAgB,IAClCxV,OAAOwV,YAAYP,IAAM,WACvB,OAAO,IAAIS,MAAOC,UAAY3V,OAAOwV,YAAYC,SAMzD,MAAMG,GACC,WAAa,OAAOJ,YAAYP,MAAM,KAG7C,SAAS9M,GAAgBC,EAAQyN,QAClBnU,IAAVmU,IAAqBA,EAAQD,MACjC,IAAIvN,EAAWwN,EAAQzN,EAAOF,UAC9B,MAAO,CACNL,SAAWO,EAAOP,SAAWO,EAAOL,SAASM,EAC7CN,SAAWK,EAAOL,SAClBG,UAAY2N,GAId,MAAMC,GAELpT,YAAarE,GACZ,IAAI4W,EAAMW,KACVvX,EAAUA,GAAW,GACrBwE,KAAKkT,QAAW,CAAClO,SAAUoN,EAAKlN,SAAU,EAAKG,UAAW+M,GAE1D5B,GAAS7B,iBAAiB3O,MAC1BA,KAAKmP,eAAe,SAAU,CAAC9B,MAAK,IAEpCrN,KAAKmT,OAAO3X,GASbqE,OAAOrE,GACNA,EAAUA,GAAW,GACrB,IAAI4W,EAAMW,KACNK,EAAYpT,KAAKqT,MAAMjB,QACNvT,IAAjBrD,EAAQ8X,WAAuCzU,IAAjBrD,EAAQ+X,OAG1CvT,KAAKkT,QAAU,CACdlO,cAA6BnG,IAAjBrD,EAAQ8X,KAAsBlB,EAAM5W,EAAQ8X,KAAOF,EAAUpO,SACzEE,cAA6BrG,IAAjBrD,EAAQ+X,KAAsB/X,EAAQ+X,KAAOH,EAAUlO,SACnEG,UAAY+N,EAAU/N,WAEvBrF,KAAKoP,gBAAgB,WAQtBvP,MACC,OAAOyF,GAAgBtF,KAAKkT,QAASH,MAAmB/N,SAQzDnF,MAAMuS,GACL,OAAO9M,GAAgBtF,KAAKkT,QAASd,IAIvC5B,GAASzB,kBAAkBkE,GAAYhD,WCxGvC,MAAMuD,GAEL3T,YAAa0N,EAAU/R,GACtBA,EAAUA,GAAW,GAErBwE,KAAKyT,OAAS,IAAIR,GAAY,CAACK,KAAK,IACpCtT,KAAK0T,OAAS,EAAE/U,EAAAA,EAAUA,EAAAA,GAC1BqB,KAAKkT,QACLlT,KAAK2T,UAAYpG,EAEjB/R,EAAQ6J,UAAY7J,EAAQ6J,WAAarF,KAAKyT,OAAOrB,MACrDpS,KAAK4T,gBAAgBpY,GAItB6W,YAAa,OAAOrS,KAAKyT,OACzBvN,YAAa,OAAOlG,KAAK0T,OACzBnO,aAAc,OAAOvF,KAAKkT,QAE1BrT,UAAW,OAAO,EAGlBA,gBAAgBsS,GAEf,IACCnN,SAAUD,EACVG,SAAUD,EACVE,aAActJ,EACdwJ,UAAWD,EACXc,MAAOA,KACJ2N,GACA1B,EAGAxP,EAAI,EAAGwD,EAAI,EAAG7L,EAAI,EACtB,GAAoBuE,MAAhBmB,KAAKkT,QAAsB,CAC9B,IAAIE,EAAY9N,EAAgBtF,KAAKkT,QAAS9N,GAC9CgO,EAAY9M,EAAW8M,EAAWpT,KAAK0T,QACvC/Q,EAAIyQ,EAAUpO,SACdmB,EAAIiN,EAAUlO,SACd5K,EAAI8Y,EAAUjO,aAIf,IAAII,EAAS,CACZP,SAAmBnG,MAAPkG,EAAoBA,EAAMpC,EACtCuC,SAAmBrG,MAAPoG,EAAoBA,EAAMkB,EACtChB,aAAuBtG,MAAPhD,EAAoBA,EAAMvB,EAC1C+K,UAAYD,GAIb,GAAavG,MAATqH,EAAoB,CACvB,IAAKtE,EAAKE,GAAQoE,EACdtE,EAAME,IACLF,GAAO5B,KAAK0T,OAAO,IAAM5R,GAAQ9B,KAAK0T,OAAO,KAChD1T,KAAK0T,OAAS,CAAC9R,EAAKE,KAWvB,OALAyD,EAASe,EAAWf,EAAQvF,KAAK0T,QAEjC1T,KAAK8T,YAAc9T,KAAKkT,QAExBlT,KAAKkT,QAAU3N,EACR,CAACW,MAAAA,KAAUX,KAAWsO,GAI9BhU,OAAOsS,GAEN,OADAA,EAAMnS,KAAK4T,gBAAgBzB,GACpBnS,KAAK2T,UAAUxB,GAGvBtS,QACCG,KAAK2T,eAAY9U,GC7DnB,MAAMkV,GAELlU,YAAYmU,EAAUzG,EAAU/R,IAzBjC,SAA6BL,GAC5B,IAAI8Y,EAAW,CAAC,KAAM,OAAQ,SAAU,QAAS,UACjD,IAAK,IAAIC,KAAQD,EAChB,KAAMC,KAAQ/Y,GACb,MAAM,IAAIqC,MAAM,kBAAkBrC,sBAAwB+Y,KAsB3DC,CAAoBH,GAGpBhU,KAAKoU,UAAYJ,EACjBhU,KAAK2T,UAAYpG,EACjBvN,KAAK0T,OACL1T,KAAKkT,QACLlT,KAAKqU,QAAS,EAKdrU,KAAKsU,gBAMLtU,KAAKyT,OAGLzT,KAAKoU,UAAUxE,GAAG,eAAgB5P,KAAKuU,gBAAgB9B,KAAKzS,OAC5DA,KAAKoU,UAAUxE,GAAG,aAAc5P,KAAKwU,cAAc/B,KAAKzS,OAG7BnB,MAAvBmB,KAAKoU,UAAUd,MAElBtT,KAAKwU,eAAc,GAIrB3U,UAAW,OAAOG,KAAKqU,OAGvBhC,YAAa,OAAOrS,KAAKyT,OACzBvN,YAAa,OAAOlG,KAAK0T,OAczBnO,aAEC,IAAIkP,EAAWzU,KAAKkT,QAAQ7N,UAAYrF,KAAKoU,UAAUd,KACvD,MAAO,CACNtO,SAAWhF,KAAKkT,QAAQlO,SACxBE,SAAWlF,KAAKkT,QAAQhO,SACxBC,aAAenF,KAAKkT,QAAQ/N,aAC5BE,UAAYoP,GAMdT,eAAgB,OAAOhU,KAAKoU,UAG5BvU,cAAcwN,GAAK,GAClB,GAAKrN,KAAKyT,OAGH,CACNzT,KAAKsU,gBAAgBnB,OAAO,CAACG,KAAMtT,KAAKoU,UAAUd,OAGlD,IAAIoB,EAAe1U,KAAKsU,gBAAgBlC,MAAQpS,KAAKyT,OAAOrB,MAExDuC,EAAa3U,KAAKoU,UAAUd,KAAOoB,EACvC1U,KAAKyT,OAAON,OAAO,CAACG,KAAMqB,SAT1B3U,KAAKsU,gBAAkB,IAAIrB,GAAY,CAACK,KAAMtT,KAAKoU,UAAUd,OAC7DtT,KAAKyT,OAAS,IAAIR,GAAY,CAACK,KAAK,IAatCzT,kBACC,GAAIG,KAAKyT,SAEHzT,KAAKqU,QAAmCxV,MAAzBmB,KAAKoU,UAAU7O,SAElCvF,KAAKqU,QAAS,GAEXrU,KAAKqU,QAAQ,CACXrU,KAAK0T,SACT1T,KAAK0T,OAAS1T,KAAKoU,UAAUlO,OAE9BlG,KAAKkT,QAAUlT,KAAKoU,UAAU7O,OAC9B,IAAIwI,EAAO,CACV7H,MAAOlG,KAAKkG,SACTlG,KAAKuF,QAELvF,KAAK2T,WACR3T,KAAK2T,UAAU5F,IAYnBlO,OAAOsS,GACN,IAAI5M,EAAS,CACZP,SAAUmN,EAAInN,SACdE,SAAUiN,EAAIjN,SACdC,aAAcgN,EAAIhN,aAClBE,UAAW8M,EAAI9M,WAIhBE,EAAOF,UAAYE,EAAOF,UAAYrF,KAAKoU,UAAUd,KAC3CtT,KAAKoU,UAAUQ,OAAOrP,GAEhC,OAAO,EAGR1F,QACCG,KAAK2T,eAAY9U,GCpGnB,MAAMgW,GAELhV,YAAaiV,EAAWtZ,GAKNqD,MAAbiW,GAAqCjW,MAAXrD,IACvBsZ,aAAqBD,IArD9B,SAA0B1Z,GACzB,IAAI8Y,EAAW,CAAC,KAAM,OAAQ,SAAU,QAAS,UACjD,IAAK,IAAIC,KAAQD,EAChB,KAAMC,KAAQ/Y,GACb,OAAO,EAGT,OAAO,EA8CwC4Z,CAAiBD,KAG7DtZ,EAAUsZ,EACVA,OAAYjW,EACRrD,EAAQwY,SACXc,EAAYtZ,EAAQwY,SACVxY,EAAQsZ,YAClBA,EAAYtZ,EAAQsZ,aAMvBtZ,EAAUA,GAAW,GACrBwE,KAAKgV,UAAYxZ,EAIMqD,MAAnBrD,EAAQyZ,UACXzZ,EAAQyZ,SAAU,GAInBjV,KAAKkV,aACLlV,KAAKmV,SACLnV,KAAKoV,QAAU,EAAEzW,EAAAA,EAAUA,EAAAA,GAG3BqB,KAAKqV,UAAY,IAAIvD,GAAQ9R,KAAMA,KAAKsV,gBAAgB7C,KAAKzS,OAG7DA,KAAKuV,WAAQ1W,EAGbmB,KAAKwV,YACLxV,KAAKyV,MAGLzV,KAAK0V,gBAAkB,IAAI5a,IAG3BkF,KAAK2V,QAAU,IAAInF,GAASN,aAG5BM,GAAS7B,iBAAiB3O,MAC1BA,KAAKmP,eAAe,YAAa,CAAC9B,MAAK,IACvCrN,KAAKmP,eAAe,SAAU,CAAC9B,MAAK,IACpCrN,KAAKmP,eAAe,cAAe,CAAC9B,MAAK,IACzCrN,KAAKmP,eAAe,aAAc,CAAC9B,MAAK,IAGxCrN,KAAK4V,gBAAgBd,EAAWtZ,GAejCqE,sBAAsBI,GACrB,GAAID,KAAK2V,QAAQ3a,MAAO,CACvB,GAAY,aAARiF,EAAqB,CAMxB,MAAO,CALI,IACPD,KAAKmV,SACRjP,MAAOlG,KAAKoV,QACZS,MAAK,IAGA,GAAY,cAAR5V,EACV,MAAO,MAACpB,GACF,GAAY,UAARoB,EACV,MAAO,CAACD,KAAKmV,UACP,GAAY,eAARlV,EACV,MAAO,CAACD,KAAKoV,UAahBvV,UAAW,OAAOG,KAAK2V,QAAQ3a,MAG5B8a,YAAa,OAAOtF,GAASL,YAAYnQ,KAAK2V,SAG9CzP,YAEC,MAAO,CAAClG,KAAKoV,QAAQ,GAAIpV,KAAKoV,QAAQ,IAIvC7P,aAEF,MAAO,CACNP,SAAWhF,KAAKmV,SAASnQ,SACzBE,SAAWlF,KAAKmV,SAASjQ,SACzBC,aAAenF,KAAKmV,SAAShQ,aAC7BE,UAAYrF,KAAKmV,SAAS9P,WAKzBqE,iBAAkB,OAAO1J,KAAKkV,aAG9BnM,YACC,OAAO,IAAIgN,EAAwB/V,KAAKkV,aAAclV,KAAKmV,UAI/D9C,YAAa,OAAOrS,KAAKwV,YAAYnD,MAErC2D,cAAe,OAAO,EAUtBnW,QACC,GAA0B,GAAtBG,KAAK2V,QAAQ3a,MAChB,MAAM,IAAIwC,MAAM,uCAGjB,IAAI+H,EAAS0Q,EAA4BjW,KAAKmV,SAAUnV,KAAKqS,MAAMD,OAEnE,OAAIpS,KAAKqV,UAAUa,UACd3Q,EAAOP,SAAWhF,KAAKoV,QAAQ,IAAMpV,KAAKoV,QAAQ,GAAK7P,EAAOP,WAEjEhF,KAAKmW,UAAU,IAAI5Q,IAGb0Q,EAA4BjW,KAAKmV,SAAUnV,KAAKqS,MAAMD,QAEvD7M,EAIRR,UAAW,OAAO/E,KAAKqT,QAAQrO,SAC/BC,UAAW,OAAOjF,KAAKqT,QAAQnO,SAC/BrJ,UAAW,OAAOmE,KAAKqT,QAAQlO,aAU/BtF,SAASsS,GACR,OAAInS,KAAKwV,uBAAuBX,GACxB7U,KAAKwV,YAAYY,SAASjE,GAG1BnS,KAAKwV,YAAYZ,OAAOzC,GAKjCtS,OAAOsS,GAEN,IAAIkE,EAAmBxX,MAAbsT,EAAIjM,MAId,GAHAmQ,EAAKA,GAAuBxX,MAAhBsT,EAAInN,SAChBqR,EAAKA,GAAuBxX,MAAhBsT,EAAIjN,SAChBmR,EAAKA,GAA2BxX,MAApBsT,EAAIhN,cACXkR,EACJ,OAAOxZ,QAAQC,QAAQqV,GAExBA,EAAImE,OAnPG1c,KAAKC,MAHI,IAGED,KAAKE,UAoPF+E,MAAjBsT,EAAI9M,YACP8M,EAAI9M,UAAYrF,KAAKqS,MAAMD,OAE5B,IAAI3D,EAAQ,IAAI+B,GAAST,cACzB/P,KAAK0V,gBAAgB3X,IAAIoU,EAAImE,OAAQ7H,GACrC,IAAI8H,EAAU/F,GAASL,YAAY1B,EAAO5Q,GAAegB,MAAPhB,GAElD,OADAmC,KAAKoW,SAASjE,GACPoE,EAmBR1W,cAAcsS,GACb,IAAIjM,MACHA,EAAK2P,KACLA,GAAO,KACJhC,GACA1B,EAEStT,MAATqH,IACHA,EAAQ,CAACA,EAAM,GAAIA,EAAM,KAG1B,IAAIsQ,EAAO,CACVtQ,MAAAA,EACA2P,KAAAA,KACGhC,GAGJ,GADA2C,EAAOxW,KAAKyW,cAAcD,GACd3X,MAAR2X,EACH,OAAOxW,KAAKmW,UAAUK,GAQxB3W,gBAAgBuS,EAAKsE,GACpB1W,KAAKmW,UAAU,IAAIO,IAOpB7W,UAAUsS,GACT,IAAIjM,MACHA,EAAKlB,SACLA,EAAQE,SACRA,EAAQC,aACRA,EAAYE,UACZA,EAASwQ,KACTA,GAAK,KACFhC,GACA1B,EAIAwE,GAAe,EACnB,GAAa9X,MAATqH,EAAoB,CACvB,IAAKtE,EAAKE,GAAQoE,EACdtE,EAAME,IACLF,GAAO5B,KAAKoV,QAAQ,IAAMtT,GAAQ9B,KAAKoV,QAAQ,KAClDpV,KAAKoV,QAAU,CAACxT,EAAKE,GACrBoE,EAAQ,CAACtE,EAAKE,GACd6U,GAAe,IAUlB,IAeIpR,EAfAqR,EAA6B/X,MAAZmG,EAChB4R,GAAkBD,GACtB3N,QAAQC,IAAI,6DAgBZ1D,EAFGqR,EAEM,CAAC5R,SAAAA,EAAUE,SAAAA,EAAUC,aAAAA,EAAcE,UAAAA,GAEnC,IAAIrF,KAAKmV,UAEnB,IAmBIqB,EAlBAnQ,EAAa4P,EAA4B1Q,EADnCvF,KAAKqS,MAAMD,OAsCrB,GApCgByE,EAAiCxQ,EAAYrG,KAAKoV,WAEjE7P,EAASvF,KAAK8W,iBAAiBzQ,GAC/BwP,GAAO,GAIRe,EAAgBA,IAAkBG,EAAyBxR,EAAQvF,KAAKmV,UAGpEyB,IAEH5W,KAAKkV,aAAelV,KAAKmV,SAEzBnV,KAAKmV,SAAW5P,GAKhBiR,EADGG,GAAgBC,EACZ,CAAC1Q,MAAAA,KAAUX,EAAQsQ,KAAAA,KAAShC,GACzB8C,EACH,CAACzQ,MAAAA,EAAO2P,KAAAA,KAAShC,GACd+C,EACH,IAAIrR,EAAQsQ,KAAAA,KAAShC,GAErB,CAACgC,KAAAA,KAAShC,GAIlB7T,KAAK2V,QAAQ3a,OAAQ,EACrBgF,KAAKgX,iBAAiBR,EAAMG,EAAcC,GAEtC5W,KAAKgV,UAAUC,SAClBjV,KAAKiX,iBAGapY,MAAf2X,EAAKF,OAAqB,CAC7B,IAAI7H,EAAQzO,KAAK0V,gBAAgBxG,IAAIsH,EAAKF,QACtC7H,IACHzO,KAAK0V,gBAAgBjE,OAAO+E,EAAKF,eAC1BE,EAAKF,OACZ7H,EAAMzT,MAAQwb,GAMhB,IAAK,IAAI/H,KAASzO,KAAK0V,gBAAgBxI,SACtCuB,EAAMzT,MAAQ,GAGf,OADAgF,KAAKkX,aAAaV,GACXA,EAQR3W,iBAAiBsS,EAAKwE,EAAcC,GACnC,IAAI1Q,MACHA,EAAKlB,SACLA,EAAQE,SACRA,EAAQC,aACRA,EAAYE,UACZA,GACG8M,EAIJ,GAFAnS,KAAKoP,gBAAgB,YAAa+C,GAE9ByE,EAAe,CAClB,IAAIrR,EAAS,CAACP,SAAAA,EAAUE,SAAAA,EAAUC,aAAAA,EAAcE,UAAAA,GAChDrF,KAAKoP,gBAAgB,SAAU7J,GAE5BoR,GACH3W,KAAKoP,gBAAgB,cAAelJ,GAGrClG,KAAKoP,gBAAgB,cACrB,IAAI+H,EAASC,EAAqBpX,KAAKmV,UACvC,GAAIgC,QAAyBtY,IAAfmB,KAAKuV,MAAqB,CACvC,IAAI5H,EAAO3N,KACXA,KAAKuV,MAAQ8B,aAAY,WACxB1J,EAAKyB,gBAAgB,gBACnB,UACQ+H,QAAyBtY,IAAfmB,KAAKuV,QAC1B7C,aAAa1S,KAAKuV,OAClBvV,KAAKuV,WAAQ1W,GAcfgB,iBAAiBwG,GAChB,OAAOiR,EAAuBjR,EAAYrG,KAAKoV,SAMhDvV,cAAcsS,GAAM,OAAOA,EAK3BtS,aAAasS,IAgBbtS,eAAe0F,EAAQW,GACtBlG,KAAKqV,UAAU3D,QACf,IAAIgF,EAAiB1W,KAAKuX,yBAAyBhS,EAAQW,GACrCrH,MAAlB6X,GAGJ1W,KAAKqV,UAAU9C,WAAWmE,EAAerR,UAAWqR,GAWrD7W,yBAAyB0F,EAAQW,GAChCX,EAASA,GAAUvF,KAAKmV,SACxBjP,EAAQA,GAASlG,KAAKoV,QACtB,IAAIhD,EAAMpS,KAAKqS,MAAMD,MACjB/L,EAAa4P,EAA4B1Q,EAAQ6M,IAChDrJ,EAAOhE,GAAOyS,EAA2BnR,EAAYH,GAC1D,GAAarH,MAATkK,EACH,OAGD,IAAI2N,EAAiBT,EAA4B1Q,EAAQ6M,EAAMrJ,GAG/D,OADA2N,EAAe1R,SAAWD,EACnB2R,EAeR7W,oBAEyBhB,MAApBmB,KAAKwV,cACJxV,KAAKwV,uBAAuBX,IAC/B7U,KAAKwV,YAAY1F,IAAI9P,KAAKyV,OAC1BzV,KAAKyV,WAAQ5W,EACbmB,KAAKwV,iBAAc3W,IAGnBmB,KAAKwV,YAAYlN,QACjBtI,KAAKwV,iBAAc3W,IAKtBgB,gBAAgBiV,EAAWtZ,GAE1B,IAAI+R,EAAWvN,KAAKyX,cAAchF,KAAKzS,MACvC,GAAI8U,aAAqBD,GAExB7U,KAAKwV,YAAcV,EACnB9U,KAAKyV,MAAQzV,KAAKwV,YAAY5F,GAAG,YAAarC,QAY9C,GAPCvN,KAAKwV,YAFW3W,MAAbiW,EAEgB,IAAItB,GAAiBjG,EAAU/R,GAG/B,IAAIuY,GAAiBe,EAAWvH,EAAU/R,GAI1DwE,KAAKwV,YAAYkC,UAAW,CAO/BnK,EANU,CACTrH,MAAOlG,KAAKwV,YAAYtP,SACrBlG,KAAKwV,YAAYjQ,OACpBsQ,MAAM,KAQVhW,kBAEC,OAAOG,KAAKwV,YAGbV,gBAEC,IAAIA,EAAY9U,KAAK2X,kBACrB,GAAI7C,aAAqBD,GACxB,OAAOC,EACD,KAAIA,aAAqBtB,IAAzB,CAEA,GAAIsB,aAAqBf,GAC/B,OAAOe,EAAUV,UAEjB,MAAM,IAAI5W,MAAM,sBAIlBsX,cAAcA,GACb9U,KAAK4X,oBACL5X,KAAK4V,gBAAgBd,IAKvBtE,GAASzB,kBAAkB8F,GAAa5E,WCllBxC,SAAS4H,GAAU/Q,EAAGZ,GACrB,IAAIoN,EAAOpN,EAAM,GACb3M,EAAS2M,EAAM,GAAKA,EAAM,GAC9B,OAAOoN,IAAWxM,EAAEwM,IAPL1V,EAOWrE,GANRqE,GAAKA,EADxB,IAAgBA,ECChB,SAAS2I,KACR,IAAIuR,EAASjS,EAAWC,KACpB4N,EAAS,KAiCb,MAAO,CAACxE,IAzBE,WAAa,OAAO4I,GAyBZ/Z,IAxBR,SAAUga,EAAWC,GAE9B,IAAIC,GAAW,EACXC,GAAU,EAkBd,OAfIH,IAAcD,GAAUE,IAActE,IACzCuE,GAAW,GAGRF,IAAcD,IACjBI,EAnB4B,SAAUC,EAAWJ,GAElD,OAAII,IAActS,EAAWG,cAAgB+R,IAAclS,EAAWE,gBAClEoS,IAActS,EAAWE,aAAegS,IAAclS,EAAWG,eACjEmS,IAActS,EAAWC,MAelBsS,CAAwBN,EAAQC,IAGvCC,IAActE,IACjBA,EAASsE,GAGND,IAAcD,IACjBA,EAASC,GAEH,CAACG,QAAQA,EAASD,SAASA,KCrBpC,MAAMI,GAEFxY,YAAakS,EAAcvW,EAAU,IACjCwE,KAAKsY,IAAMvG,EAEX/R,KAAKuY,KAEL,IAAIC,OAACA,EAAMC,UAAEA,GAAajd,EAC1BwE,KAAK0Y,QAVU,IAWD7Z,MAAV2Z,EACAxY,KAAK0Y,QAAUF,EACK3Z,MAAb4Z,IACPzY,KAAK0Y,QAAU,EAAID,GAGvBjI,GAAS7B,iBAAiB3O,MAE1BA,KAAKmP,eAAe,SAAU,CAAC9B,MAAK,IAEpCrN,KAAK2Y,KAAO3Y,KAAKsY,IAAI1I,GAAG,SAAU5P,KAAK4Y,UAAUnG,KAAKzS,OAM1DH,sBAAsBI,GAClB,GAAY,UAARA,GAAoBD,KAAKsY,IAAIZ,UAC7B,MAAO,CAAC1X,KAAKsY,IAAIvT,KAOzBlF,YACI,IAAIsG,EAAInG,KAAKsY,IAAIjF,QACb8D,EAAwB,GAAdhR,EAAEjB,UAAqC,GAAlBiB,EAAEhB,aAEjCgS,GAAuBtY,MAAbmB,KAAKuY,OACfvY,KAAKuY,KAAOlB,YAAY,WACpBrX,KAAK6Y,aACPpG,KAAKzS,MAAOA,KAAK0Y,UAElBvB,GAAuBtY,MAAbmB,KAAKuY,OAChB7F,aAAa1S,KAAKuY,MAClBvY,KAAKuY,UAAO1Z,GAEhBmB,KAAK6Y,UAAU1S,EAAEnB,UAMrBnF,UAAUmF,GACNA,EAAwBnG,MAAZmG,EAAyBA,EAAWhF,KAAKsY,IAAIvT,IACzD/E,KAAKoP,gBAAgB,SAAUpK,GAMnCnF,QAEQG,KAAKuY,OACL7F,aAAa1S,KAAKuY,MAClBvY,KAAKuY,UAAO1Z,GAGhBmB,KAAKsY,IAAIxI,IAAI9P,KAAK2Y,OCrF1B,SAASG,GAAY9a,EAAG+a,EAAQnG,GAC5B,OAbJ,SAAgB5U,EAAGJ,GAGf,MAAO,CAFChE,KAAKC,MAAMmE,EAAEJ,GAVzB,SAAaI,EAAEJ,GACX,OAASI,EAAIJ,EAAKA,GAAKA,EAUfob,CAAIhb,EAAGJ,IAWRqb,CAAOjb,EAAE4U,EAAQmG,GAG5B,SAASG,GAAYvW,EAAGoW,EAAQnG,GAC5B,IAAKuG,EAAGjb,GAAKyE,EACb,OAAOiQ,EAASuG,EAAEJ,EAAS7a,EDmF/BsS,GAASzB,kBAAkBsJ,GAAcpI,WE5FzC,MAAM/P,GAAWoB,EAASpB,SAM1B,SAASkZ,KACL,OAAOvG,KAAKT,MAIhB,SAASiH,GAAWC,GAChB,GAAIA,aAAiBhY,GAAqBzC,MAATya,EAC7B,OAAOA,EAEN,GAAIhc,MAAMC,QAAQ+b,GAAS,CAE5B,IAAK1X,EAAKE,EAAMD,EAAYE,GAAeuX,EAC3C,OAAO,IAAIhY,EAASM,EAAKE,EAAMD,EAAYE,GAE3C,MAAM,IAAIvE,MAAO,wBAAyB8b,GAsClD,SAASC,GAAmBld,EAAKmd,GAE7B,GAAkB,GAAdnd,EAAI9C,OAIJ,OAHI8C,EAAI,GAAGtB,KAAOye,EAAIze,KAClBsB,EAAIF,QAEa,GAAdE,EAAI9C,OAEV,GAAkB,GAAd8C,EAAI9C,OACT,OAAO,EACJ,CACH,IAAI2S,EAAM7P,EAAIod,WAAU,SAAUC,GAC9B,OAAOA,EAAK3e,KAAOye,EAAIze,OAK3B,OAHImR,GAAO,GACP7P,EAAIoP,OAAOS,EAAK,GAEC,GAAd7P,EAAI9C,QAkCnB,MAAMogB,GAAe,CAAC,EAAG,GAAI,IAAK,IAAM,IAAO,IAAQhb,EAAAA,GACvD,IAAIib,GAAiB,SAAUrgB,GAC3B,IAAK,IAAIG,EAAE,EAAGA,EAAEigB,GAAapgB,OAAQG,IACjC,GAAIH,GAAUogB,GAAajgB,GACvB,OAAOigB,GAAajgB,IAYhC,MAAMmgB,GAAQpd,OAAO0D,OAAO,CACxBgJ,KAAM,EACN2Q,OAAQ,EACRC,QAAS,EACTC,OAAQ,IA8BZ,SAASC,GAAUlJ,EAAOG,EAAO3R,GAC7B,IAAI2a,EAAgBC,EAAYC,EAE5BC,EAA8Bxb,MAATkS,GAAwClS,MAAlBkS,EAAM5E,SACjDmO,EAA8Bzb,MAATqS,GAAwCrS,MAAlBqS,EAAM/E,SAChDkO,GAAuBC,EAEhBD,EAEAC,GAIRF,EAAKrJ,EAAM5E,SAAS5M,OAAO2R,EAAM/E,UACjC+N,EAAiB,EAAOL,GAAM1Q,KAAO0Q,GAAME,SAJ3CG,EAAiBL,GAAMG,OAFvBE,EAAiBL,GAAMC,OAFvBI,EAAiBL,GAAM1Q,KAW3B,IAAIoR,EAA0B1b,MAATkS,GAAoClS,MAAdkS,EAAMyJ,KAC7CC,EAA0B5b,MAATqS,GAAoCrS,MAAdqS,EAAMsJ,KAgBjD,OAfKD,GAAmBE,EAEZF,EAEAE,GAKJL,EADA7a,EACKA,EAAOwR,EAAMyJ,KAAMtJ,EAAMsJ,MAEzBE,EAAoB3J,EAAMyJ,KAAMtJ,EAAMsJ,MAE/CL,EAAa,EAAON,GAAM1Q,KAAO0Q,GAAME,SARvCI,EAAaN,GAAMG,OAFnBG,EAAaN,GAAMC,OAFnBK,EAAaN,GAAM1Q,KAchB,CAACgD,SAAU+N,EAAgBM,KAAML,GAgB5C,SAASQ,GAAUnB,GACf,GAAW3a,MAAP2a,IAAqBA,EAAIoB,eAAe,QAAqB/b,MAAX2a,EAAIze,IAAkB,CACxE,GAAW8D,MAAP2a,EACA,MAAM,IAAIhc,MAAM,oBACb,IAAKgc,EAAIoB,eAAe,OAC3B,MAAM,IAAIpd,MAAM,2BAA4Bgc,GACzC,GAAe3a,MAAX2a,EAAIze,IACX,MAAM,IAAIyC,MAAM,uBAAwBgc,GAMhD,OAHIA,EAAIoB,eAAe,cACnBpB,EAAIrN,SAAWkN,GAAWG,EAAIrN,WAE3BqN,EAkBX,MAAMqB,GAEFhb,YAAaib,EAAStf,EAAQ,IAE1BwE,KAAK+a,IAAMD,EAGX9a,KAAKgb,SAAWve,OAAOwe,OAAO,GADf,CAACC,YAAW,EAAMC,cAAa,GACF3f,GAE5CwE,KAAKob,MAELpb,KAAKqb,MAELrb,KAAKsb,WAELtb,KAAKub,SAGT1b,SACIG,KAAKob,MAAQ,GAEbpb,KAAKqb,MAAQ,IAAI7K,GAASN,aAC1BlQ,KAAKsb,WAAa9K,GAASL,YAAYnQ,KAAKqb,OAAOzN,KAAK,IAC7C5N,KAAKwb,QAAQ/I,KAAKzS,KAAlBA,IAIfH,MAAM4b,GAEF,IAAI7d,EAAIoC,KAAKob,MAAM7hB,OACfmiB,EAAiB,GAAL9d,EACZI,EAAIyd,EAASliB,OACjByG,KAAKob,MAAM7hB,QAAUyE,EACrB,IAAK,IAAItE,EAAE,EAAGA,EAAEsE,EAAGtE,IACfsG,KAAKob,MAAMxd,KAAO6d,EAAS/hB,GAE3BsG,KAAKgb,SAASE,YAAcQ,GAAa1d,EAAI,IAG7CgC,KAAKqb,MAAMrgB,OAAQ,GAI3B6E,UACI,IAAIiE,EAAS,GAQb,OANI9D,KAAKob,MAAM7hB,OAAS,IACpBuK,EAAS9D,KAAK+a,IAAInG,OAAO5U,KAAKob,MAAOpb,KAAKgb,WAG9Chb,KAAKub,SAEEzX,EAWXjE,OAAO9E,EAAKoR,EAAUqO,GAClB,IAAImB,EAAU,CAAC5gB,IAAIA,GAOnB,OANA4gB,EAAQxP,SAAWA,EACfyP,UAAUriB,OAAS,IACnBoiB,EAAQnB,KAAOA,GAEnBmB,EAAUhB,GAAUgB,GACpB3b,KAAK6b,MAAM,CAACF,IACL3b,KAIXH,UAAU9E,GAEN,OADAiF,KAAK6b,MAAM,CAAC,CAAC9gB,IAAIA,KACViF,KAIXH,OAAO4b,GACHA,EAAWA,EAAShe,IAAKke,GAAYhB,GAAUgB,IAC/C3b,KAAK6b,MAAMJ,GAIf5b,QAEI,OADAG,KAAKob,MAAQ,GACNpb,KAIXH,SACI,GAAIG,KAAKgb,SAASE,WACd,MAAM,IAAI1d,MAAM,kDAIpBwC,KAAKqb,MAAMrgB,OAAQ,GAgB3B,MAAM8gB,WAAgBnK,GAElB9R,YAAYrE,GACRuE,MAAMvE,GAENwE,KAAK+b,KAAO,IAAIjhB,IAChBkF,KAAKgc,SAAW,IAAInB,GAAc7a,MAMlCA,KAAKic,YAAc,IAAInhB,IACvB,IAAK,IAAIpB,EAAE,EAAGA,EAAEigB,GAAapgB,OAAQG,IAAK,CACtC,IAAIwiB,EAAcvC,GAAajgB,GAC/BsG,KAAKic,YAAYle,IAAIme,EAAa,IAAIC,GAAUD,IAIpDlc,KAAKoc,kBAAoB,GAM7B3L,iBACI,OAAOzQ,KAAK+b,KAOhBlc,aAAcwc,GACV,IAAIC,EAAS,CACTD,QAASA,GAGb,OADArc,KAAKoc,kBAAkBlY,KAAKoY,GACrBA,EAIXzc,aAAcyc,GACV,IAAItR,EAAQhL,KAAKoc,kBAAkBG,QAAQD,GACvCtR,GAAS,GACThL,KAAKoc,kBAAkB3Q,OAAOT,EAAO,GAK7CnL,kBAAmB2c,EAAUC,GACzBzc,KAAKoc,kBAAkBvT,SAAQ,SAASyT,GACpCA,EAAOD,QAAQG,EAAUC,MAQjC5c,IAAK9E,EAAKC,GACN,MAAM,IAAIwC,MAAM,mBAGpBqC,OAAQ9E,GACJ,MAAM,IAAIyC,MAAM,mBAQpBqC,YAAYrE,GACR,OAAO,IAAIqf,GAAc7a,KAAMxE,GAInCkhB,cAAgB,OAAO1c,KAAKgc,SAU5Bnc,OAAO9E,EAAKoR,EAAUqO,GAMlB,OALIoB,UAAUriB,OAAS,EACnByG,KAAKgc,SAASW,OAAO5hB,EAAKoR,EAAUqO,GAEpCxa,KAAKgc,SAASW,OAAO5hB,EAAKoR,GAEvBnM,KAGXH,UAAU9E,GAEN,OADAiF,KAAKgc,SAASY,UAAU7hB,GACjBiF,KAGXsb,iBAAkB,OAAOtb,KAAKgc,SAASV,WAUvCzb,QAAQ9E,EAAKoR,EAAUqO,EAAMhf,GACzB,IAAIge,EAAM,CAACze,IAAIA,EAAKoR,SAASA,EAAUqO,KAAKA,GAE5C,OADAhB,EAAMmB,GAAUnB,GACTxZ,KAAK4U,OAAO4E,EAAKhe,GAG5BqE,WAAW9E,EAAKS,GACZ,OAAOwE,KAAK4U,OAAO,CAAC7Z,IAAIA,GAAMS,GA0FlCqE,OAAO+R,EAAMpW,EAAU,IACnB,MAAMghB,EAAW,IAAI1hB,IACrB,IAAI+hB,EACAC,EAAcC,GAGdC,MAACA,GAAM,EAAKzd,OAAEA,EAAM4b,aAAEA,GAAa,GAAQ3f,EAG1CyhB,EAAiBrL,KAClBA,EAAO,CAACA,IAMZ,MACMsL,EAAO,CACT9X,GAFagU,KAGb+D,OAAQ3hB,EAAQ2hB,QAGpB,IAAK,IAAI3D,KAAO5H,EAAM,CAKlB,GAAIuJ,EACA,IACI3B,EAAMmB,GAAUnB,GAClB,MAAOjL,GACLvF,QAAQC,IAAIsF,EAAKiL,GACjB,SAGRsD,EAAetD,EAAIoB,eAAe,YAClCmC,EAAWvD,EAAIoB,eAAe,QAQ9BiC,EAAc7c,KAAK+b,KAAK7M,IAAIsK,EAAIze,KACb8D,MAAfge,GAEKC,IACDtD,EAAIrN,cAAWtN,GAEdke,IACDvD,EAAIgB,UAAO3b,IAEOA,MAAfge,IACFC,GAAiBC,EAIVA,EAGAD,IAERtD,EAAIrN,SAAW0Q,EAAY1Q,UAH3BqN,EAAIgB,KAAOqC,EAAYrC,MAJvBhB,EAAIrN,cAAWtN,EACf2a,EAAIgB,UAAO3b,IAkBnBmB,KAAKod,YAAYZ,EAAUK,EAAarD,EAAK0D,EAAM1hB,GAMvD,GAFAwE,KAAKqd,cAAc,SAEfb,EAAStiB,KAAO,EAAG,CAMnB,IAAIojB,EAAY,CAAC1b,IAAKjD,EAAAA,EAAUmD,MAAOnD,EAAAA,GAGnCiS,EAAQ,IAAI4L,EAAStP,UAAUzP,IAAIqL,IAC/BA,EAAKkI,KAAOlI,EAAKkI,IAAI7E,WACrBmR,EAAU1b,IAAML,EAAS7B,IAAI4d,EAAU1b,IAAKkH,EAAKkI,IAAI7E,SAAS3K,aAC9D8b,EAAUxb,KAAOP,EAAS5B,IAAI2d,EAAUxb,KAAMgH,EAAKkI,IAAI7E,SAAS1K,eAEhEqH,EAAKmI,KAAOnI,EAAKmI,IAAI9E,WACrBmR,EAAU1b,IAAML,EAAS7B,IAAI4d,EAAU1b,IAAKkH,EAAKmI,IAAI9E,SAAS3K,aAC9D8b,EAAUxb,KAAOP,EAAS5B,IAAI2d,EAAUxb,KAAMgH,EAAKmI,IAAI9E,SAAS1K,eAE7D,CAAC1G,IAAI+N,EAAK/N,IAAKiW,IAAIlI,EAAKkI,IAAKC,IAAInI,EAAKmI,IAAKiM,KAAMpU,EAAKoU,QAI7DK,EAAc3M,EAAMlW,OAAQoO,IAC5B,IAAIC,EAAQkR,GAAUnR,EAAKkI,IAAKlI,EAAKmI,IAAK1R,GAC1C,OAAQwJ,EAAMoD,UAAY0N,GAAM1Q,MAAQJ,EAAMyR,MAAQX,GAAM1Q,OAIhEnJ,KAAKwR,cAAc+L,GAGnB,IAAId,OAAoB5d,EAcxB,OAbIye,EAAU1b,KAAOjD,EAAAA,IACjB8d,EAAoBnb,EAAS4B,cAAcoa,EAAU1b,IAAK0b,EAAUxb,OAQxE9B,KAAKwd,kBAAkBhB,EAAUC,GAG7BO,GAAQhd,KAAKyd,YACV7M,EAIX,OADIoM,GAAQhd,KAAKyd,YACV,GAeX5d,YAAY2c,EAAUK,EAAarD,EAAK0D,EAAM1hB,GAE1C,IAAIkiB,EAASC,EACT7U,EAAM8U,EACNC,EAAcC,EACdC,EAAaC,EACbC,EAAeC,GAGfC,SAACA,GAAS,EAAIC,KAAEA,GAAK,EAAK7e,OAAEA,GAAU/D,EAE1C,GAAIqhB,IAAgBrD,EAChB,MAAMhc,MAAM,+CAIhB,IAAIuL,EAAQkR,GAAU4C,EAAarD,EAAKja,GAGxC,GAAIwJ,EAAMoD,UAAY0N,GAAM1Q,MAAQJ,EAAMyR,MAAQX,GAAM1Q,KAMpD,OALAL,EAAO,CACH/N,IAAIye,EAAIze,IAAKiW,IAAI6L,EACjB5L,IAAI4L,EAAa9T,MAAOA,QAE5ByT,EAASze,IAAIyb,EAAIze,IAAK+N,GAS1B,GAAmBjK,MAAfge,EAIgBhe,MAAZ2a,EAAI0D,OACJ1D,EAAI0D,KAAO,CACP9X,GAAI8X,EAAK9X,GACTiZ,UAAWnB,EAAK9X,GAChBkZ,UAAW,IAInBZ,OAAU7e,EACV8e,EAAU,EAAQlhB,OAAO0D,OAAOqZ,GAAOA,EACvCxZ,KAAK+b,KAAKhe,IAAIyb,EAAIze,IAAK4iB,QAGpB,GAAoB9e,MAAhB2a,EAAIrN,UAAqCtN,MAAZ2a,EAAIgB,KAExCkD,EAAUb,EACVc,OAAU9e,EACVmB,KAAK+b,KAAKtK,OAAO+H,EAAIze,UAoDrB,GA3CgB8D,MAAZ2a,EAAI0D,OACJ1D,EAAI0D,KAAO,CACP9X,GAAIyX,EAAYK,KAAK9X,GACrBiZ,UAAWnB,EAAK9X,GAChBkZ,UAAWzB,EAAYK,KAAKoB,UAAY,IAqBhDZ,EAAUb,EACVc,EAAU,CACN5iB,IAAKye,EAAIze,IACToR,SAAUqN,EAAIrN,SACdqO,KAAMhB,EAAIgB,KACV0C,KAAM1D,EAAI0D,MAGVkB,IACAT,EAAUlhB,OAAO0D,OAAOwd,IAI5B3d,KAAK+b,KAAKhe,IAAIyb,EAAIze,IAAK4iB,GAKnBD,EAAQvR,SAAU,CAClB,IAAIoS,EAAM3E,GAAe8D,EAAQvR,SAAS5S,QACtCilB,EAAYxe,KAAKic,YAAY/M,IAAIqP,GAErCC,EAAUC,iBAAiBf,EAAQvR,SAASvK,IAAK+b,GAE5CD,EAAQhf,UACT8f,EAAUC,iBAAiBf,EAAQvR,SAASrK,KAAM6b,GAkD9D,GA9CA7U,EAAO,CAAC/N,IAAIye,EAAIze,IAAKiW,IAAI2M,EAAS1M,IAAIyM,EAAS3U,MAAMA,EAAOmU,KAAAA,GAYxDiB,IACAP,EAAQpB,EAAStN,IAAIsK,EAAIze,KACZ8D,MAAT+e,IACA9U,EAAKmI,IAAM2M,EAAM3M,IACjBnI,EAAKC,MAAQkR,GAAU0D,EAAS7U,EAAKmI,IAAK1R,KAIlDid,EAASze,IAAIyb,EAAIze,IAAK+N,GA0BlBC,EAAMoD,UAAY0N,GAAM1Q,KAA5B,CAuBA,GApBWJ,EAAMoD,UAAY0N,GAAMC,QAC/BmE,GAAgB,EAChBC,GAAa,EACbH,GAAc,EACdC,GAAe,GACRjV,EAAMoD,UAAY0N,GAAMG,QAC/BiE,GAAgB,EAChBC,GAAa,EACbH,GAAc,EACdC,GAAe,GACRjV,EAAMoD,UAAY0N,GAAME,UAC/BkE,GAAgB,EAChBC,GAAa,EACbH,EAAcJ,EAAQxR,SAASvK,KAAO8b,EAAQvR,SAASvK,IACvDoc,EAAeL,EAAQxR,SAASrK,MAAQ4b,EAAQvR,SAASrK,MAMzDmc,EAAc,CACd,IAAIS,EAAU9E,GAAe8D,EAAQvR,SAAS5S,QAC9CskB,EAAe7d,KAAKic,YAAY/M,IAAIwP,GAExC,GAAIR,EAAY,CACZ,IAAIS,EAAU/E,GAAe+D,EAAQxR,SAAS5S,QAC9CukB,EAAe9d,KAAKic,YAAY/M,IAAIyP,GAQpCd,GAAgBC,GACZD,GAAgBC,IAChBG,GAAgB,EAChBC,GAAa,EACbH,GAAc,EACdC,GAAe,GAgBnBD,IACIE,GACAJ,EAAae,aAAalB,EAAQvR,SAASvK,IAAK8b,GAEhDQ,GACAJ,EAAae,aAAalB,EAAQxR,SAASvK,IAAK+b,IAIpDK,IACIC,IAAkBP,EAAQvR,SAASzN,UACnCmf,EAAae,aAAalB,EAAQvR,SAASrK,KAAM4b,GAEjDQ,IAAeP,EAAQxR,SAASzN,UAChCof,EAAae,aAAalB,EAAQxR,SAASrK,KAAM6b,KAW7D9d,cAAcif,KAAWC,GACrB,MAAMxjB,EAAS,GACf,IAAK,IAAIijB,KAAaxe,KAAKic,YAAY/O,SAAU,CAC7C,IAAI0E,EAAO4M,EAAUM,MAAWC,GACpBlgB,MAAR+S,GAAqBA,EAAKrY,OAAS,GACnCgC,EAAO2I,KAAK0N,GAGpB,OAAOoN,EAAmBzjB,GAa9BsE,iBAAiBsM,GAEb,OADAA,EAAWkN,GAAWlN,GACfnM,KAAKqd,cAAc,mBAAoBlR,GAQlDtM,OAAOsM,EAAUtJ,GAEb,OADAsJ,EAAWkN,GAAWlN,GACfnM,KAAKqd,cAAc,SAAUlR,EAAUtJ,GAOlDhD,cAAcsM,EAAUtJ,EAAMrH,EAAQ,IAClC2Q,EAAWkN,GAAWlN,GACtB,MAAMyF,EAAO5R,KAAKqd,cAAc,gBAAiBlR,EAAUtJ,GAErD+N,EAAQ,GACRsM,EAAO,CACT9X,GAAIgU,KACJ+D,OAAQ3hB,EAAQ2hB,QAEpB,IAAI3D,EACJ,IAAK,IAAI9f,EAAE,EAAGA,EAAEkY,EAAKrY,OAAQG,IACzB8f,EAAM5H,EAAKlY,GACXsG,KAAK+b,KAAKtK,OAAO+H,EAAIze,KAErB6V,EAAM1M,KAAK,CAACnJ,IAAIye,EAAIze,IAAKiW,SAAKnS,EAAWoS,IAAKuI,EAAK0D,KAAAA,IAIvD,OADAld,KAAKwR,cAAcZ,GACZA,EAMX/Q,MAAMrE,EAAQ,IAEVwE,KAAKqd,cAAc,SAEnB,IAAItB,EAAO/b,KAAK+b,KAChB/b,KAAK+b,KAAO,IAAIjhB,IAEhB,MAAM8V,EAAQ,GACRsM,EAAO,CACT9X,GAAIgU,KACJ+D,OAAQ3hB,EAAQ2hB,QAEpB,IAAK,IAAI3D,KAAOuC,EAAK7O,SACjB0D,EAAM1M,KAAK,CAACnJ,IAAKye,EAAIze,IAAKiW,SAAKnS,EAAWoS,IAAKuI,EAAK0D,KAAAA,IAIxD,OADAld,KAAKwR,cAAcZ,GACZA,EAOX/Q,YAEI,MAAMuH,EAAMpH,KAAKqd,cAAc,aAG/B,IAAIzL,EAAO,GACPqN,EAAS,GACb,IAAK,IAAIC,KAAc9X,EAAI8F,SACvB0E,EAAK1N,KAAKgb,EAAWtN,MACrBqN,EAAO/a,KAAKgb,EAAWD,QAE3BrN,EAAO,GAAGjG,UAAUiG,GACpBqN,EAAS,GAAGtT,UAAUsT,GAEtBA,EAAS,IAAI,IAAIxkB,IAAIwkB,IAIrB,IAAIE,EAAmB,IAAInf,KAAK+b,KAAK7O,UAAUxS,OAAO8e,GAAuB3a,MAAhB2a,EAAIrN,UAE7DiT,EAAgBxN,EAAKrY,OACrB8lB,EAAoBF,EAAiB5lB,OACrC+lB,EAAYtf,KAAK+b,KAAK7hB,KACtBkF,EAAOkgB,EAAYF,EAAgBC,EACvC,GAAY,GAARjgB,EAKA,MAJA4J,QAAQC,IAAI,gBAAiBmW,GAC7BpW,QAAQC,IAAI,qBAAsBoW,GAClCrW,QAAQC,IAAI,YAAaqW,GACzBtW,QAAQC,IAAI,aAAc7J,GACpB,IAAI5B,MAAM,0BAIpB,IAAI+hB,EAAa,IAAIzkB,IAAI8W,EAAKnU,IAAI+b,GAAO,CAACA,EAAIze,IAAKye,KAC/CgG,EAAU,IAAI1kB,IAAI,IAAIkF,KAAK+b,KAAKje,WAAWpD,OAAO,EAAEK,EAAKye,KACjC3a,MAAhB2a,EAAIrN,WAGZsT,EAAUC,EAAqBH,EAAYC,GAC/C,GAAIC,EAAQvlB,KAAO,EAGf,MAFA8O,QAAQC,IAAI,yBACZD,QAAQC,IAAI,IAAIwW,EAAQlO,SAClB,IAAI/T,MAAM,yBAAyB,IAAIiiB,EAAQlO,SAIzD,GADAkO,EAAUC,EAAqBF,EAASD,GACpCE,EAAQvlB,KAAO,EACf,MAAM,IAAIsD,MAAM,0BAA0B,IAAIiiB,EAAQlO,SAG1D,MAAO,CACHK,KAAMA,EAAKrY,OACX0lB,OAAQA,EAAO1lB,SAO3BuiB,GAAQjC,MAAQA,GAChBiC,GAAQ7B,UAAYA,GACpB6B,GAAQ6D,WA34BR,SAAoB5O,EAAOG,GACvB,IAAInI,EAAQkR,GAAUlJ,EAAOG,GAC7B,OAAOnI,EAAMoD,UAAY0N,GAAM1Q,MAAQJ,EAAMyR,MAAQX,GAAM1Q,MAi5B/D,MAAMgT,GAGFtc,YAAY+f,GAGR5f,KAAK6f,WAAaD,EASlB5f,KAAK8f,UAAY,IAAIhlB,IAerBkF,KAAK+f,YAAc,IAAItV,GAGvBzK,KAAKggB,SAAW,IAAIvlB,IACpBuF,KAAKigB,OAAS,IAAIxlB,IA4CtBoF,aAAaqgB,EAAO1G,GAChB,IACI5H,EAD+B,GAAvB5R,KAAK8f,UAAU5lB,UACP2E,EAAYmB,KAAK8f,UAAU5Q,IAAIgR,GACvCrhB,MAAR+S,GACA5R,KAAK8f,UAAU/hB,IAAImiB,EAAO,CAAC1G,IAC3BxZ,KAAKggB,SAASG,IAAID,IAElBtO,EAAK1N,KAAKsV,GAKlB3Z,aAAaqgB,EAAO1G,GAChB,IACI5H,EAD+B,GAAvB5R,KAAK8f,UAAU5lB,UACP2E,EAAYmB,KAAK8f,UAAU5Q,IAAIgR,GACnD,GAAYrhB,MAAR+S,EAAmB,CACP2H,GAAmB3H,EAAM4H,IAEjCxZ,KAAKigB,OAAOE,IAAID,IAS5BrgB,iBAAiBqgB,EAAO1G,GACpB,IACI5H,EAD+B,GAAvB5R,KAAK8f,UAAU5lB,UACP2E,EAAYmB,KAAK8f,UAAU5Q,IAAIgR,GACnD,GAAYrhB,MAAR+S,EAAmB,EA/mC/B,SAA4BvV,EAAKmd,GAC7B,GAAkB,GAAdnd,EAAI9C,OACJ,OAAO,EACJ,GAAkB,GAAd8C,EAAI9C,QACX,GAAI8C,EAAI,GAAGtB,KAAOye,EAAIze,IAElB,OADAsB,EAAI,GAAKmd,GACF,MAER,CACH,IAAItN,EAAM7P,EAAIod,WAAU,SAAUC,GAC9B,OAAOA,EAAK3e,KAAOye,EAAIze,OAE3B,GAAImR,GAAO,EAEP,OADA7P,EAAI6P,GAAOsN,GACJ,EAGf,OAAO,GA+lCU4G,CAAmBxO,EAAM4H,IAE9BxQ,QAAQC,IAAI,6DAoBxBpJ,QACI,GAA0B,GAAtBG,KAAKggB,SAAS9lB,MAAiC,GAApB8F,KAAKigB,OAAO/lB,KACvC,OAIJ,IAAIoR,EAAY,GACZC,EAAY,GAChB,IAAK,IAAI2U,KAASlgB,KAAKggB,SAAS9S,SAAU,CAC3BlN,KAAK8f,UAAU5Q,IAAIgR,GACrB3mB,OAAS,EACdgS,EAAUrH,KAAKgc,GAEflgB,KAAK8f,UAAUrO,OAAOyO,GAG9B,IAAK,IAAIA,KAASlgB,KAAKigB,OAAO/S,SAAU,CACpC,IAAI0E,EAAO5R,KAAK8f,UAAU5Q,IAAIgR,GAClBrhB,MAAR+S,IAIe,GAAfA,EAAKrY,SACL+R,EAAUpH,KAAKgc,GACflgB,KAAK8f,UAAUrO,OAAOyO,KAG9BlgB,KAAK+f,YAAYnL,OAAOtJ,EAAWC,GAEnCvL,KAAKggB,SAAStO,QACd1R,KAAKigB,OAAOvO,QA4BhB7R,iBAAiBsM,GACb,GAA2B,GAAvBnM,KAAK8f,UAAU5lB,KACf,MAAO,GAEX,MAAMmmB,EAAmB,IAAI/e,EAAS6K,EAASvK,IAAKuK,EAASrK,MAAM,GAAM,GACnEmd,EAASjf,KAAK+f,YAAYO,OAAOD,GACjCvc,EAAS,GACT7H,EAAMgjB,EAAO1lB,OACnB,IAAI2mB,EAAOK,EACX,IAAK,IAAI7mB,EAAE,EAAGA,EAAEuC,EAAKvC,IACjBwmB,EAAQjB,EAAOvlB,GACfsG,KAAK8f,UAAU5Q,IAAIgR,GACdrX,SAAQ,SAAU2Q,GAKf,GAAI0G,GAAS1G,EAAIrN,SAASvK,IACtB2e,EAAY/G,EAAIrN,SAAS3K,gBACtB,CAAA,GAAI0e,GAAS1G,EAAIrN,SAASrK,KAS7B,MANAkH,QAAQC,IAAI,kBACZD,QAAQC,IAAI,aAAcjJ,KAAK6f,YAC/B7W,QAAQC,IAAI,+BAAgCoX,EAAiBhhB,YAC7D2J,QAAQC,IAAI,SAAUiX,GACtBlX,QAAQC,IAAI,OAAQuQ,EAAIrN,SAAS9M,YACjCW,KAAKyd,YACC,IAAIjgB,MAAM,6BARhB+iB,EAAY/G,EAAIrN,SAAS1K,aAUzB0K,EAASjE,gBAAgBqY,IACzBzc,EAAOI,KAAK,CAAC3C,SAASgf,EAAW/G,IAAIA,MAE1CxZ,MAEX,OAAO8D,EAsBXjE,aAAasM,GACT,GAA2B,GAAvBnM,KAAK8f,UAAU5lB,KACf,MAAO,GAEX,MAAMmmB,EAAmB,IAAI/e,EAAS6K,EAASvK,IAAKuK,EAASrK,MAAM,GAAM,GACnEmd,EAASjf,KAAK+f,YAAYO,OAAOD,GACjCpkB,EAAMgjB,EAAO1lB,OACbinB,EAAS,IAAI/lB,IACbqJ,EAAS,GAEf,IAAK,IAAIpK,EAAE,EAAGA,EAAEuC,EAAKvC,IACjBsG,KAAK8f,UAAU5Q,IAAI+P,EAAOvlB,IACrBmP,SAAQ,SAAS2Q,GAEVgH,EAAOjmB,IAAIif,EAAIze,OAGfylB,EAAOL,IAAI3G,EAAIze,KAEnB+I,EAAOI,KAAKsV,OAGxB,OAAO1V,EAsBXjE,OAAOsM,EAAUtJ,EAAKvB,EAASN,MAAMR,QAEjC,GAA2B,GAAvBR,KAAK8f,UAAU5lB,KACf,MAAO,GAGX,IAAI0X,EAAO,GAMX,IAHA/O,GAAQvB,EAASN,MAAMR,SAGXN,GAASK,OACjB,OAAOP,KAAK8f,UAAU5Q,IAAI/C,EAASvK,KAAKlH,QAAO,SAAS8e,GACpD,OAAOA,EAAIrN,SAASsU,MAAMtU,EAAUjM,GAASK,WAMrD,IAAImgB,EAAQ7d,EAAOvB,EAASN,MAAMG,QAclC,GAbIuf,IAEA9O,EAAO5R,KAAK2gB,aAAaxU,GACpBzR,QAAO,SAAS8e,GACb,OAAOA,EAAIrN,SAASsU,MAAMtU,EAAUuU,OAS5CvU,EAAS5S,OAASyG,KAAK6f,WACvB,OAAOjO,EAcX,GAAI/O,EAAO3C,GAASM,OAAQ,CAExB,IAAIogB,EACJ,GAAI5gB,KAAK6f,YAAclhB,EAAAA,EAGnBiiB,EAAgB,IAAItf,GAAU3C,EAAAA,EAAUwN,EAASvK,SAC9C,CACH,IAAIA,EAAMuK,EAASrK,KAAO9B,KAAK6f,WAC3B/d,EAAOqK,EAASvK,KAGnBA,EAAKE,GAAQ,CAAClI,KAAK8F,IAAIkC,EAAKE,GAAOlI,KAAK+F,IAAIiC,EAAKE,IAClD8e,EAAgB,IAAItf,EAASM,EAAKE,GAAM,GAAM,GAElD9B,KAAK2gB,aAAaC,GACb/X,SAAQ,SAAS2Q,GACVA,EAAIrN,SAASsU,MAAMtU,EAAUjM,GAASM,SACtCoR,EAAK1N,KAAKsV,MAK1B,OAAO5H,EAOX/R,cAAcsM,EAAUtJ,GAQpB,MAAM+O,EAAO5R,KAAKsgB,OAAOnU,EAAUtJ,GAC7ByI,EAAY,GAClB,IAAIkO,EAAK0G,EAAOjB,EAChB,IAAK,IAAIvlB,EAAE,EAAGA,EAAEkY,EAAKrY,OAAQG,IAAK,CAC9B8f,EAAM5H,EAAKlY,GAGPulB,EADAzF,EAAIrN,SAASzN,SACJ,CAAC8a,EAAIrN,SAASvK,KAEd,CAAC4X,EAAIrN,SAASvK,IAAK4X,EAAIrN,SAASrK,MAE7C,IAAK,IAAI+e,EAAE,EAAGA,EAAE5B,EAAO1lB,OAAQsnB,IAAK,CAChCX,EAAQjB,EAAO4B,GAGHtH,GAAmBvZ,KAAK8f,UAAU5Q,IAAIgR,GAAQ1G,KAEtDxZ,KAAK8f,UAAUrO,OAAOyO,GACtB5U,EAAUpH,KAAKgc,KA4B3B,OARA5U,EAAUvP,MAAK,SAASzB,EAAEO,GAAG,OAAOP,EAAEO,KACtCmF,KAAK+f,YAAYe,cAAcxV,GAOxBsG,EAaX/R,QACIG,KAAK8f,UAAUpO,QACf1R,KAAK+f,YAAc,IAAItV,GACvBzK,KAAKggB,SAAStO,QACd1R,KAAKigB,OAAOvO,QAQhB7R,YAKI,MAAMkhB,EAAkB,IAAItmB,IAAI,IAAIuF,KAAK+f,YAAY7S,WAC/C8T,EAAgB,IAAIvmB,IAAI,IAAIuF,KAAK8f,UAAUvO,SAEjD,IAAK0P,EAAYF,EAAiBC,GAAgB,CAC9C,IAAIvB,EAAUyB,EAAqBH,EAAiBC,GACpD,GAAIvB,EAAQvlB,KAAO,EACf,MAAM,IAAIsD,MAAM,4BAA4B,IAAIiiB,IAIpD,GADAA,EAAUyB,EAAqBF,EAAeD,GAC1CtB,EAAQvlB,KAAO,EACf,MAAM,IAAIsD,MAAM,8BAA8B,IAAIiiB,IAO1D,IAAIR,EAAS,IAAIjf,KAAK+f,YAAY7S,UAClC,GAAI+R,EAAO1lB,QAAUwnB,EAAgB7mB,KACjC,MAAM,IAAIsD,MAAM,uCAEpB,IAAK,IAAI9D,EAAE,EAAGA,EAAEulB,EAAO1lB,OAAQG,IAC3B,GAAIulB,EAAOvlB,EAAE,IAAMulB,EAAOvlB,GACtB,MAAM,IAAI8D,MAAM,0BAQxB,IAAK,IAAI0iB,KAASjB,EAAQ,CACtB,IAAIrN,EAAO5R,KAAK8f,UAAU5Q,IAAIgR,GAC9B,IAAK,IAAI1G,KAAO5H,EAEZ,GAAIsO,GAAS1G,EAAIrN,SAASvK,KAEfse,GAAS1G,EAAIrN,SAASrK,KAK7B,MAFAkH,QAAQC,IAAI,SAAUiX,GACtBlX,QAAQC,IAAI,OAAQuQ,EAAIrN,SAAS9M,YAC3B,IAAI7B,MAAM,uBAU5B,IAAK,IAAI2jB,IAAa,IAAInhB,KAAK8f,UAAU5S,UACrC,IAAK,IAAIsM,KAAO2H,EACZ,IAAK,IAAIxe,IAAK,CAAC6W,EAAIrN,SAASvK,IAAK4X,EAAIrN,SAASrK,MAC1C,IAAK9B,KAAK8f,UAAUvlB,IAAIoI,GACpB,MAAM,IAAInF,MAAM,oDAAoDmF,QAAQ6W,EAAIrN,SAAS9M,eAYzG,IAAI+b,EAAQ,GACZ,IAAK,IAAI+F,KAAanhB,KAAK8f,UAAU5S,SACjC,IAAK,IAAIsM,KAAO2H,EACZ/F,EAAMlX,KAAKsV,GAKnB,IAAI4H,EAAS,IAAItmB,IACjB,IAAK,IAAI0e,KAAO4B,EAAO,CACnB,IAAI1B,EAAO0H,EAAOlS,IAAIsK,EAAIze,KAC1B,GAAY8D,MAAR6a,EACA0H,EAAOrjB,IAAIyb,EAAIze,IAAKye,QAGpB,GAAIA,IAAQE,EACR,MAAM,IAAIlc,MAAM,gDAI5B,IAAIoU,EAAO,IAAIwP,EAAOlU,UAMtB,IAAK,IAAIsM,KAAO5H,EAAK1E,SAEjB,GAAIsM,EAAIrN,SAAS5S,OAASyG,KAAK6f,WAC3B,MAAM,IAAIriB,MAAM,4BAA4BwC,KAAK6f,eAAerG,EAAIrN,SAAS9M,cAIrF,MAAO,CAAC,CACJugB,UAAW5f,KAAK6f,WAChBZ,OAAQ,IAAIjf,KAAK8f,UAAUvO,QAC3BK,KAAMA,KCvoDlB,MAAMyP,GAAMC,EAEZ,SAASC,GAASjnB,EAAEO,GAChB,OAAO0G,EAAStC,IAAI3E,EAAEqO,WAAY9N,EAAE8N,YAMxC,MAAM6Y,GAEF3hB,YAAYib,EAAS7I,EAAIzW,GAErBwE,KAAKiS,GAAKA,EAEVjS,KAAKiV,QAAU,IAAInD,GAAQG,EAAIjS,KAAKyhB,IAAIhP,KAAKzS,OAE7CA,KAAKuF,OAELvF,KAAK0H,aAEL1H,KAAKwI,YAELxI,KAAK8a,QAAUA,EAEf9a,KAAK0hB,MAAQ,GAEb1hB,KAAK2hB,UAAY,IAEjBnmB,EAAUA,GAAW,IACbomB,UAAYpmB,EAAQomB,WAvBlB,EAwBV5hB,KAAKxE,QAAUA,EAQnBqE,aAAcwc,GACV,IAAIC,EAAS,CACTD,QAASA,GAGb,OADArc,KAAK2hB,UAAUzd,KAAKoY,GACbA,EAGXzc,aAAcyc,GACV,IAAItR,EAAQhL,KAAK2hB,UAAUpF,QAAQD,GAC/BtR,GAAS,GACThL,KAAK2hB,UAAUlW,OAAOT,EAAO,GAIrCnL,qBAAsBkf,GAClB/e,KAAK2hB,UAAU9Y,SAAQ,SAASyT,GAC5BA,EAAOD,WAAW0C,MAW1Blf,UAAU0F,GACN,IAAI6M,EAAM7M,EAAOF,UAEIrF,KAAKuF,OACP1G,MAAfmB,KAAKuF,SACLvF,KAAKiV,QAAQvD,QACb1R,KAAK0H,kBAAe7I,EACpBmB,KAAKwI,iBAAc3J,EACnBmB,KAAK0hB,MAAQ,IAGjB1hB,KAAKuF,OAASA,EAEV6R,EAAqBpX,KAAKuF,SAC1BvF,KAAKyhB,IAAIrP,GAYjBvS,KAAK+I,GACDA,EAAWC,SAAQ,SAASC,GACpB9I,KAAK0H,aAAaQ,gBAAgBY,EAAKH,aAEvC3I,KAAK0hB,MAAMxd,KAAK4E,KAErB9I,MAEHA,KAAK0hB,MAAM3lB,KAAKwlB,IAMpB1hB,IAAIuS,GACG,IAAYhL,EAAM,GACXpH,KAAK0hB,MAAMnoB,OACrB,KAAOyG,KAAK0hB,MAAMnoB,OAAS,GAAKyG,KAAK0hB,MAAM,GAAG/Y,WAAW,IAAMyJ,GAC3DhL,EAAIlD,KAAKlE,KAAK0hB,MAAMvlB,SAExB,OAAOiL,EAMXvH,OACI,OAAQG,KAAK0hB,MAAMnoB,OAAS,EAAKyG,KAAK0hB,MAAM,GAAG/Y,WAAW,QAAI9J,EAYlEgB,QAAQuS,GACJ,IAAIhW,EAAO2M,EAAQ/I,KAAKxE,QAAQomB,UAC5BC,GAAU,EAkBd,OAjByBhjB,MAArBmB,KAAK0H,cACLtL,EAAQgW,EACRyP,GAAU,GACHtgB,EAAS9B,OAAOO,KAAK0H,aAAajG,aAAc2Q,KACvDhW,EAAQ4D,KAAK0H,aAAa5F,KAC1B+f,GAAU,GAEVA,IAEA7hB,KAAK0H,aAAe,IAAIpG,EAASlF,EAAOA,EAAQ2M,GAAO,GAAM,GAI7D/I,KAAKwI,YAAc6Y,GAAIrhB,KAAK0H,aAAc1H,KAAKuF,QAE/CvF,KAAK0hB,MAAQ,IAEVG,EAYXhiB,KAAKiiB,EAAWC,GACZ,IAAIxZ,EAAiByZ,EAA2BhiB,KAAK0H,aACL1H,KAAKwI,YACLxI,KAAKuF,OACLuc,GAU5CG,EAAWC,EAA2BliB,KAAKuF,OAAQvF,KAAKiS,GAAG/L,OAAO,GAgDtE,OA9B0BrH,MAAtBkjB,IACAA,EAAqB/hB,KAAK0H,aAAalG,aA6BpC+G,EAAe7N,QAAO,SAASoO,GAElC,GAAImZ,GAAYnZ,EAAKH,WAAW,GAC5B,OAAO,EAIX,GAAIpH,EAAS9B,OAAOqJ,EAAKH,WAAYoZ,GACjC,OAAO,EAOX,GAAgC,GAA5B/hB,KAAKuF,OAAOJ,aAAqB,CACjC,IAAIC,EAAK0D,EAAKH,WAAW,GACzB,GAAIvD,EAAKpF,KAAK0H,aAAalG,YAAY,GAAI,CACvC,IAAI2E,EAAI8P,EAA4BjW,KAAKuF,OAAQH,GACjD,GAAIe,EAAEnB,UAAY8D,EAAKvH,SAAS,IAAoB,GAAd4E,EAAEjB,SACpC,OAAO,GAInB,OAAO,IACRlF,MAWPH,IAAIuS,GAWA,IAAI+P,EAAYniB,KAAKgE,IAAIoO,GASzB,GAAIpS,KAAK6hB,QAAQzP,GAAM,CAEnB,IAAI3J,EAAgBzI,KAAK8a,QAAQsH,iBAAiBpiB,KAAKwI,aASnD6Z,EAASriB,KAAKsiB,KAAK7Z,GACvBzI,KAAKkE,KAAKme,GAUV,IAAIE,EAASviB,KAAKgE,IAAIoO,GAOtB+P,EAAUje,QAAQqe,GAElBJ,EAAU5oB,OAAS,GACnByG,KAAKwd,kBAAkBpL,EAAK+P,EAAWniB,MAG3C,IAAIoF,EAAKpF,KAAKiE,QAAUjE,KAAK0H,aAAa5F,KAC1C9B,KAAKiV,QAAQ1C,WAAW3Y,KAAK8F,IAAI0F,EAAIpF,KAAK0H,aAAa5F,QC9T/D,SAAS0gB,GAAOzZ,GACZ,OAAQA,EAAMoD,UAAY2P,GAAQjC,MAAM1Q,MAAQJ,EAAMyR,MAAQsB,GAAQjC,MAAM1Q,KA4EhF,MAAMsZ,GAAShmB,OAAO0D,OAAO,CACzBuiB,MAAO,EACPC,KAAM,EACNC,MAAO,EACPC,WAAY,IAGVC,GAAY,IAAIhoB,IAAI,CACtB,CAAC,MAAO2nB,GAAOE,MACf,CAAC,MAAOF,GAAOG,MACf,CAAC,MAAOH,GAAOG,MACf,CAAC,MAAOH,GAAOE,MACf,CAAC,MAAOF,GAAOC,OACf,CAAC,MAAOD,GAAOC,OACf,CAAC,MAAOD,GAAOC,OACf,CAAC,MAAOD,GAAOE,MACf,CAAC,MAAOF,GAAOC,OACf,CAAC,MAAOD,GAAOG,MACf,CAAC,MAAOH,GAAOE,MACf,CAAC,MAAOF,GAAOG,MACf,CAAC,MAAOH,GAAOC,OACf,CAAC,MAAOD,GAAOG,MACf,CAAC,MAAOH,GAAOI,YACf,CAAC,MAAOJ,GAAOG,MACf,CAAC,MAAOH,GAAOC,OACf,CAAC,MAAOD,GAAOI,cASnB,SAASE,GAAkBhS,EAAOG,GAC9B,OAAO5P,EAAS0B,OAAO+N,EAAM5E,SAAU+E,EAAM/E,UAGjD,SAAS6W,GAAmBjS,EAAOG,GAC/B,OAAQ,EAAI5P,EAAS2B,QAAQ8N,EAAM5E,SAAU+E,EAAM/E,UAGvD,SAAS8W,GAAmBpS,EAAQC,GAGhC,OAAOiS,GAFMlS,EAAU,IAAIA,EAAOG,IAAMH,EAAOI,IAClCH,EAAU,IAAIA,EAAOE,IAAMF,EAAOG,KAInD,SAASiS,GAAoBrS,EAAQC,GAGjC,OAAOkS,GAFMnS,EAAU,IAAIA,EAAOG,IAAMH,EAAOI,IAClCH,EAAU,IAAIA,EAAOE,IAAMF,EAAOG,KAanD,MAAMkS,WAAsBxR,GAGxB9R,YAAaib,EAAStf,GAClBuE,MAAMvE,GAGNwE,KAAK+b,KAAO,IAAIjhB,IAGhBkF,KAAK+a,IAAMD,EACX,IAAIsI,EAAKpjB,KAAKqjB,mBAAmB5Q,KAAKzS,MACtCA,KAAKsjB,OAAStjB,KAAK+a,IAAIwI,aAAaH,GAMxC3S,iBACI,OAAOzQ,KAAK+b,KAOhBjB,cACI,OAAO9a,KAAK+a,IAWhBlb,qBACI,MAAM,IAAIrC,MAAM,mBAKpBqC,WAAW6Q,EAAMlV,EAAQ,IAErB,GAAoB,mBADRwE,KAAK2Q,UAAUnV,GAGvB,OAAOuE,MAAM8R,WAAWnB,EAAMlV,GAC3B,CAEH,IAAIoW,EAAQtU,MAAMC,QAAQmT,GAASA,EAAO,IAAIA,GAQ9C,OANgB1Q,KAAKwjB,sBACJ,EACb5R,EAAK7V,KAAKgnB,IAEVnR,EAAK7V,KAAKinB,IAEPpR,GAOf/R,UAAU+Q,EAAOjL,GACb,IAAIjK,EAAQsE,KAAK2Q,YACjB,GAAoB,mBAATjV,EAEP,OAAOqE,MAAMoR,UAAUP,GAEd/R,MAATnD,IAEiBmD,MAAb8G,IACAA,EAAY3F,KAAKwjB,sBAEjB7d,GAAa,EACbiL,EAAM7U,KAAKknB,IAEXrS,EAAM7U,KAAKmnB,KASvBrjB,IAAK9E,EAAKC,GACN,MAAM,IAAIwC,MAAM,mBAGpBqC,OAAQ9E,GACJ,MAAM,IAAIyC,MAAM,mBAGpBqC,MAAO9E,GACH,MAAM,IAAIyC,MAAM,mBAOpBqC,mBAAmB4jB,EAAUhH,GACzB,MAAM,IAAIjf,MAAM,mBAOpBqC,2BAA2B4jB,EAAUtX,GACjC,MAAMuX,EAAc,GACdC,EAAe,GACfC,EAAa,GACb1nB,EAA0B,GAAlB8D,KAAK+b,KAAK7hB,KACxB,IAAI2pB,EAAWC,EAAkBlG,EACjC,IAAK,IAAI9U,KAAQ2a,EAASvW,SAClBsV,GAAO1Z,EAAKC,SAIhB8a,GAAY,GAAkB7jB,KAAK+b,KAAKxhB,IAAIuO,EAAK/N,KACjD+oB,GAAmB,EACHjlB,MAAZiK,EAAKkI,KACDlI,EAAKkI,IAAI7E,SAASsU,MAAMtU,KACxB2X,GAAmB,GAGvBD,IAAcC,GAEdlG,EAAQ,CAAC7iB,IAAI+N,EAAK/N,IAAKiW,SAAInS,EAAWoS,IAAInI,EAAKmI,IAAKiM,KAAKpU,EAAKoU,MAC9D0G,EAAW1f,KAAK0Z,KACRiG,GAAaC,GAErBlG,EAAQ,CAAC7iB,IAAI+N,EAAK/N,IAAKiW,IAAIlI,EAAKkI,IAAKC,SAAIpS,EAAWqe,KAAKpU,EAAKoU,MAC9DwG,EAAYxf,KAAK0Z,IACViG,GAAaC,IAEpBlG,EAAQ,CAAC7iB,IAAI+N,EAAK/N,IAAKiW,IAAIlI,EAAKkI,IAAKC,IAAInI,EAAKmI,IAAKiM,KAAKpU,EAAKoU,MAC7DyG,EAAazf,KAAK0Z,KAG1B,MAAO,CAACgG,EAAYD,EAAcD,GAOtC7jB,2BAA2B4jB,EAAUtX,GAOjC,MAAM4X,EAAc,IAAIjpB,IAAIkF,KAAK+a,IAAIuF,OAAOnU,GAAU1O,KAAI,SAAS+b,GAC/D,MAAO,CAACA,EAAIze,IAAKye,OAGrB,IAoDIwK,EApDAL,EAAe,GACfC,EAAa,GACb1nB,EAA2B,GAAlB8D,KAAK+b,KAAK7hB,KACvB,IAAKgC,EAAM,CAOP,IAAI+nB,EAAahpB,EAAc+E,KAAK+b,KAAMgI,GAC1C,GAAIE,EAAW/pB,KAAO,EAAG,CAgBrB,IAAIsf,EAAKoE,EACT,IAAK,IAAI9U,KAAQ2a,EAASvW,SACtBsM,EAAMyK,EAAW/U,IAAIpG,EAAK/N,KACf8D,MAAP2a,GAAqBgJ,GAAO1Z,EAAKC,SACjC6U,EAAQ,CAAC7iB,IAAI+N,EAAK/N,IAAKiW,IAAIlI,EAAKkI,IAAKC,IAAInI,EAAKmI,KAC9C0S,EAAazf,KAAK0Z,IAU9BgG,EAAa,IADEhpB,EAAeoF,KAAK+b,KAAMgI,GACf7W,UACrBzP,IAAI+b,IACM,CAACze,IAAIye,EAAIze,IAAKiW,SAAInS,EAAWoS,IAAIuI,KAUhDwK,EADA9nB,EACY6nB,EAEAnpB,EAAempB,EAAa/jB,KAAK+b,MAEjD,IAAI2H,EAAc,IAAIM,EAAU9W,UAC3BzP,IAAI+b,IACM,CAACze,IAAIye,EAAIze,IAAKiW,IAAIwI,EAAKvI,SAAIpS,KAM1C,IAAK,IAAIqlB,IAAa,CAACN,EAAYD,EAAcD,GAC7C,IAAK,IAAI5a,KAAQob,EAAW,CACxB,IAAItG,EAAQ6F,EAASvU,IAAIpG,EAAK/N,KACjB8D,MAAT+e,IACA9U,EAAKoU,KAAOU,EAAMV,MAK9B,MAAO,CAAC0G,EAAYD,EAAcD,GAStChH,cACI,OAAO1c,KAAK8a,QAAQ4B,QAGxB7c,OAAO9E,EAAKoR,EAAUqO,GAClB,OAAOxa,KAAK8a,QAAQ6B,OAAO5hB,EAAKoR,EAAUqO,GAG9C3a,UAAU9E,GACN,OAAOiF,KAAK8a,QAAQ8B,UAAU7hB,GAGlC8E,QAAQ9E,EAAKoR,EAAUqO,GACnB,OAAOxa,KAAK8a,QAAQqJ,QAAQppB,EAAKoR,EAAUqO,GAG/C3a,WAAW9E,GACP,OAAOiF,KAAK8a,QAAQsJ,WAAWrpB,GAGnC8E,OAAO+R,EAAMpW,GACT,OAAOwE,KAAK8a,QAAQlG,OAAOhD,EAAMpW,GAGrCqE,QACI,OAAOG,KAAK8a,QAAQpJ,QAGxB7R,OAAO9E,GACH,OAAOiF,KAAK8a,QAAQvgB,IAAIQ,GAG5B8E,OAAO9E,GACH,OAAOiF,KAAK8a,QAAQ5L,IAAInU,GAG5B8E,UACI,OAAOG,KAAK8a,QAAQlJ,OAGxB/R,gBACI,MAAO,IAAIG,KAAKuR,QAGpB1R,gBACI,OAAOG,KAAK4R,OAGhB/R,SAAS9E,GACL,OAAOiF,KAAKzF,IAAIQ,IAKxBooB,GAAcV,OAASA,GACvBU,GAAcL,UAAYA,GC1b1B,MAAM5Z,GAAW6M,EAAwB7M,SACnCG,GAAY0M,EAAwB1M,UACpCoZ,GAASU,GAAcV,OACvBK,GAAYK,GAAcL,UAMhC,MAAMuB,WAA2BlB,GAE7BtjB,YAAaib,EAAS7I,EAAIzW,GAEtBuE,MAAM+a,EAAStf,GAGfwE,KAAKsY,IAAMrG,EACXjS,KAAK2Y,KAAO3Y,KAAKsY,IAAI1I,GAAG,YAAa5P,KAAKskB,kBAAkB7R,KAAKzS,OAGjEA,KAAKukB,OAAS,IAAI/C,GAASxhB,KAAK+a,IAAK9I,GACrC,IAAImR,EAAKpjB,KAAKwkB,oBAAoB/R,KAAKzS,MACvCA,KAAKykB,UAAYzkB,KAAKukB,OAAOhB,aAAaH,GAO9CvjB,qBACI,MAAMuS,EAAMpS,KAAKsY,IAAIjG,MAAMD,MAC3B,OAAOsS,EAA+B1kB,KAAKsY,IAAI/S,OAAQ6M,GAY3DvS,mBAAmB4jB,EAAUhH,GAgCzB,IAAKzc,KAAKsY,IAAIZ,UACV,OAGJ,GAAyB7Y,MAArB4d,EACA,OAGJ,MAAMrK,EAAMpS,KAAKsY,IAAIjG,MAAMD,MACrB/L,EAAa4P,EAA4BjW,KAAKsY,IAAI/S,OAAQ6M,GAG1DuS,EAAiB,IAAIrjB,EAAS+E,EAAWrB,UAE/C,IAAK2f,EAAelE,MAAMhE,EAAmBnb,EAASN,MAAMC,SAAU,CAKlE,IAAI2jB,EAAY5kB,KAAK6kB,2BAA2BpS,KAAKzS,MAzFtC,IA0FUyjB,EAASvpB,MAC1B8F,KAAK+b,KAAK7hB,KA1FD,MA2FT0qB,EAAY5kB,KAAK8kB,2BAA2BrS,KAAKzS,OAKzD,MAAO+kB,EAAMC,EAAQC,GAASL,EAAUnB,EAAUkB,GAGlDI,EAAKlc,QAAQC,IACT9I,KAAK+b,KAAKtK,OAAO3I,EAAK/N,OAE1BiqB,EAAOnc,QAAQC,IACX9I,KAAK+b,KAAKhe,IAAI+K,EAAK/N,IAAK+N,EAAKkI,OAEjCiU,EAAMpc,QAAQC,IACV9I,KAAK+b,KAAKhe,IAAI+K,EAAK/N,IAAK+N,EAAKkI,OAIjC,IAAIrL,EAAY+e,EAA+Bre,GAC/CrG,KAAKmR,UAAU4T,EAAMpf,GACrB3F,KAAKmR,UAAU6T,EAAQrf,GACvB3F,KAAKmR,UAAU8T,EAAOtf,GAGtB,MAAMiL,EAAQtV,EAAa,CAACypB,EAAMC,EAAQC,GAAQ,CAACxpB,MAAK,EAAMC,OAAM,IAGpEsE,KAAKwR,cAAcZ,GAUnB5Q,KAAKukB,OAAO/b,cACPxI,KAAKukB,OAAO/b,YAAYiY,MAAMhE,EAAmBnb,EAASN,MAAMC,UAGjEjB,KAAKukB,OAAOW,UAAU7e,IAUlCxG,kBAAmBkO,GAmBf,IAAIpE,EAAasM,EAA4BlI,EAAM/N,KAAKsY,IAAIjG,MAAMD,OAM9DrJ,EAAQ,IAAIgN,EAAwB/V,KAAKsY,IAAI5O,WAAYC,GAQ7D,GAAIZ,EAAMsB,UAAYnB,GAASE,QAAUL,EAAMuB,WAAajB,GAAUG,KAAM,CAExE,IAAI5H,EAAM+H,EAAW3E,SACjBlD,EAAO6H,EAAW3E,SAClBmgB,EAAM,IAAI7jB,EAASM,EAAKE,GAAM,GAAM,GAEpCsjB,EAAa,IAAItqB,IAAIkF,KAAK+a,IAAIuF,OAAO6E,GAAK1nB,IAAI+b,GACvC,CAACA,EAAIze,IAAKye,KAGjB6L,EAAWzqB,EAAeoF,KAAK+b,KAAMqJ,GAErCpB,EAAYppB,EAAewqB,EAAYplB,KAAK+b,MAEhD/b,KAAK+b,KAAOqJ,EAGZ,IAAIE,EAAY,IAAID,EAASnY,UAAUzP,IAAI+b,IAChC,CAACze,IAAIye,EAAIze,IAAKiW,SAAInS,EAAWoS,IAAIuI,KAExC+L,EAAa,IAAIvB,EAAU9W,UAAUzP,IAAI+b,IAClC,CAACze,IAAIye,EAAIze,IAAKiW,IAAIwI,EAAKvI,SAAIpS,KAIlC8G,EAAY+e,EAA+B/a,GAC/C3J,KAAKmR,UAAUmU,EAAW3f,GAC1B3F,KAAKmR,UAAUoU,EAAY5f,GAG3B,MAAMiL,EAAQtV,EAAa,CAACgqB,EAAWC,GAAa,CAAC9pB,MAAK,EAAMC,OAAM,IAGtEsE,KAAKwR,cAAcZ,GAMvB5Q,KAAKukB,OAAOW,UAAUvb,GAQ1B9J,oBAAsB,SAASuS,EAAK3J,EAAe+c,GAE/C,IAAKxlB,KAAKsY,IAAIZ,UACV,OAIJ,MAAM9G,EAAQ,GACdnI,EAAcI,SAAQ,SAAUC,GAC5B,IAAI0Q,EAAM1Q,EAAK0Q,IACXiM,EAAUzlB,KAAK+b,KAAKxhB,IAAIif,EAAIze,MAC3BC,EAAOwD,EAAOC,EAAQC,GAAYoK,EAAKvH,SAQxCmkB,EAAU5c,EAAKnD,UAAY,EAAK,IAAM,IAEtCggB,EAAU,EAAa,IAAK,EAAU,IAAM,IAE5CC,EAAc9C,GAAU5T,IAAI,IAAawW,IAASC,KAElDC,GAAenD,GAAOI,WAClB4C,GAEA7U,EAAM1M,KAAK,CAACnJ,IAAIye,EAAIze,IAAKiW,SAAInS,EAAWoS,IAAIuI,IAC5CxZ,KAAK+b,KAAKtK,OAAO+H,EAAIze,OAGrB6V,EAAM1M,KAAK,CAACnJ,IAAIye,EAAIze,IAAKiW,IAAIwI,EAAKvI,SAAIpS,IAEtC+R,EAAM1M,KAAK,CAACnJ,IAAIye,EAAIze,IAAKiW,SAAInS,EAAWoS,IAAIuI,KAGzCoM,GAAenD,GAAOC,MACxB+C,IAED7U,EAAM1M,KAAK,CAACnJ,IAAIye,EAAIze,IAAKiW,IAAIwI,EAAKvI,SAAIpS,IACtCmB,KAAK+b,KAAKhe,IAAIyb,EAAIze,IAAKye,IAEpBoM,GAAenD,GAAOG,MACzB6C,IAEA7U,EAAM1M,KAAK,CAACnJ,IAAIye,EAAIze,IAAKiW,SAAInS,EAAWoS,IAAIuI,IAC5CxZ,KAAK+b,KAAKtK,OAAO+H,EAAIze,QAG9BiF,MAKHA,KAAKwR,cAAcZ,IC5R3B,MAAM1H,GAAW6M,EAAwB7M,SACnCG,GAAY0M,EAAwB1M,UACpCoZ,GAASU,GAAcV,OACvBK,GAAYK,GAAcL,UAUhC,SAAS+C,GAAoBC,EAAcC,GACvC,IAEIpgB,EAFc+e,EAA+BoB,GAC/BpB,EAA+BqB,GAEjD,OAAQpgB,EAAY,EAAK,EAAKA,EAAY,GAAM,EAAI,EAIxD,MAAMqgB,WAA8B7C,GAEhCtjB,YAAaib,EAASmL,EAAKC,EAAK1qB,GAE5BuE,MAAM+a,EAAStf,GAGfwE,KAAKmmB,KAAOF,EACZjmB,KAAKomB,YAAa,EAClBpmB,KAAKqmB,KAAOH,EACZlmB,KAAKsmB,YAAa,EAClB,IAAIC,EAAQvmB,KAAKskB,kBAAkB7R,KAAKzS,MACxCA,KAAKwmB,MAAQxmB,KAAKmmB,KAAKvW,GAAG,YAAa2W,GACvCvmB,KAAKymB,MAAQzmB,KAAKqmB,KAAKzW,GAAG,YAAa2W,GAGvC,IAAIG,EAAW1mB,KAAKwkB,oBAAoB/R,KAAKzS,MAC7CA,KAAK2mB,QAAU,IAAInF,GAASxhB,KAAK+a,IAAKkL,GACtCjmB,KAAK4mB,WAAa5mB,KAAK2mB,QAAQpD,aAAamD,GAC5C1mB,KAAK6mB,QAAU,IAAIrF,GAASxhB,KAAK+a,IAAKmL,GACtClmB,KAAK8mB,WAAa9mB,KAAK6mB,QAAQtD,aAAamD,GAE5C1mB,KAAK+mB,YACL/mB,KAAKgnB,YAITnnB,WACI,OAAQG,KAAKomB,YAAcpmB,KAAKsmB,WAQpCzmB,qBACI,MAAMuS,EAAMpS,KAAKmmB,KAAK9T,MAAMD,MAG5B,OAAOyT,GAFc5P,EAA4BjW,KAAKmmB,KAAK5gB,OAAQ6M,GAC9C6D,EAA4BjW,KAAKqmB,KAAK9gB,OAAQ6M,IAWvEvS,mBAAmB4jB,EAAUhH,GACzB,IAAKzc,KAAKinB,WACN,OAGJ,GAAyBpoB,MAArB4d,EACA,OAIJ,MAAMrK,EAAMpS,KAAKmmB,KAAK9T,MAAMD,MACtB0T,EAAe7P,EAA4BjW,KAAK+mB,YAAa3U,GAC7D2T,EAAe9P,EAA4BjW,KAAKgnB,YAAa5U,GAGnE,IAAK8U,EAAOC,GAAS,CAACrB,EAAa9gB,SAAU+gB,EAAa/gB,WACrDpD,EAAKE,GAASolB,GAASC,EAAS,CAACD,EAAOC,GAAS,CAACA,EAAOD,GAC9D,MAAMvC,EAAiB,IAAIrjB,EAASM,EAAKE,GAAM,GAAM,GAErD,IAAK6iB,EAAelE,MAAMhE,EAAmBnb,EAASN,MAAMC,SAAU,CAKlE,IAAI2jB,EAAY5kB,KAAK6kB,2BAA2BpS,KAAKzS,MA1FtC,IA2FUyjB,EAASvpB,MAC1B8F,KAAK+b,KAAK7hB,KA3FD,MA4FT0qB,EAAY5kB,KAAK8kB,2BAA2BrS,KAAKzS,OAKzD,MAAO+kB,EAAMC,EAAQC,GAASL,EAAUnB,EAAUkB,GAGlDI,EAAKlc,QAAQC,IACT9I,KAAK+b,KAAKtK,OAAO3I,EAAK/N,OAE1BiqB,EAAOnc,QAAQC,IACX9I,KAAK+b,KAAKhe,IAAI+K,EAAK/N,IAAK+N,EAAKkI,OAEjCiU,EAAMpc,QAAQC,IACV9I,KAAK+b,KAAKhe,IAAI+K,EAAK/N,IAAK+N,EAAKkI,OAIjC,IAAIrL,EAAYkgB,GAAmBC,EAAcC,GACjD/lB,KAAKmR,UAAU4T,EAAMpf,GACrB3F,KAAKmR,UAAU6T,EAAQrf,GACvB3F,KAAKmR,UAAU8T,EAAOtf,GAGtB,MAAMiL,EAAQtV,EAAa,CAACypB,EAAMC,EAAQC,GAAQ,CAACxpB,MAAK,EAAMC,OAAM,IAGpEsE,KAAKwR,cAAcZ,EAAOjL,GAY1B3F,KAAK2mB,QAAQne,cACRxI,KAAK2mB,QAAQne,YAAYiY,MAAMhE,EAAmBnb,EAASN,MAAMC,UAGlEjB,KAAK2mB,QAAQzB,UAAUY,IAI3B9lB,KAAK6mB,QAAQre,cACRxI,KAAK6mB,QAAQre,YAAYiY,MAAMhE,EAAmBnb,EAASN,MAAMC,UAGlEjB,KAAK6mB,QAAQ3B,UAAUa,IAanClmB,kBAAmBkO,EAAMG,GAMrB,IAAIb,GAAO,EACX,IAAKrN,KAAKinB,WAAY,CAMlB,GALI/Y,EAAMG,KAAOrO,KAAKmmB,KAClBnmB,KAAKomB,YAAa,EAElBpmB,KAAKsmB,YAAa,GAElBtmB,KAAKinB,WAGL,OAFA5Z,GAAO,EAOfrN,KAAK+mB,YAAc/mB,KAAKmmB,KAAK5gB,OAC7BvF,KAAKgnB,YAAchnB,KAAKqmB,KAAK9gB,OAK7B,MAAM0M,EAAK/D,EAAMG,IACX+Y,EAAYnV,GAAMjS,KAAKmmB,KAAQnmB,KAAKqmB,KAAOrmB,KAAKmmB,KAKtD,IAAIxc,EAAasM,EAA4BhE,EAAG1M,OAAQ0M,EAAGI,MAAMD,OACjE,MAAMrJ,EAAQ,IAAIgN,EAAwB9D,EAAGvI,WAAYC,GAKzD,IAAIvE,EAAKuE,EAAWtE,UAChBgiB,EAAmBpR,EAA4BmR,EAAS7hB,OAAQH,GAQpE,GAAI2D,EAAMsB,UAAYnB,GAASE,QAAUL,EAAMM,WAAaA,GAAUG,KAAM,CAGxE,IAAI5H,EAAMhI,KAAK8F,IAAIiK,EAAW3E,SAAUqiB,EAAiBriB,UACrDlD,EAAOlI,KAAK+F,IAAIgK,EAAW3E,SAAUqiB,EAAiBriB,UACtDmgB,EAAM,IAAI7jB,EAASM,EAAKE,GAAM,GAAM,GAGpCsjB,EAAa,IAAItqB,IAAIkF,KAAK+a,IAAIuF,OAAO6E,GAAK1nB,IAAI+b,GACvC,CAACA,EAAIze,IAAKye,KAGjB6L,EAAWzqB,EAAeoF,KAAK+b,KAAMqJ,GAErCpB,EAAYppB,EAAewqB,EAAYplB,KAAK+b,MAEhD/b,KAAK+b,KAAOqJ,EAGZ,IAAIE,EAAY,IAAID,EAASnY,UAAUzP,IAAI+b,IAChC,CAACze,IAAIye,EAAIze,IAAKiW,SAAInS,EAAWoS,IAAIuI,KAExC+L,EAAa,IAAIvB,EAAU9W,UAAUzP,IAAI+b,IAClC,CAACze,IAAIye,EAAIze,IAAKiW,IAAIwI,EAAKvI,SAAIpS,KAGlC8G,EAAYkgB,GAAmBlc,EAAY0d,GAC/CrnB,KAAKmR,UAAUmU,EAAW3f,GAC1B3F,KAAKmR,UAAUoU,EAAY5f,GAG3B,MAAMiL,EAAQtV,EAAa,CAACgqB,EAAWC,GAAa,CAAC9pB,MAAK,EAAMC,OAAM,IAGtEsE,KAAKwR,cAAcZ,GAOnBqB,GAAMjS,KAAKmmB,KACXnmB,KAAK2mB,QAAQzB,UAAUvb,GAChBsI,GAAMjS,KAAKqmB,MAClBrmB,KAAK6mB,QAAQ3B,UAAUvb,GAEvB0D,IACI+Z,GAAYpnB,KAAKmmB,KACjBnmB,KAAK2mB,QAAQzB,UAAUmC,GAChBD,GAAYpnB,KAAKqmB,MACxBrmB,KAAK6mB,QAAQ3B,UAAUmC,IAanCxnB,oBAAsB,SAASuS,EAAK3J,EAAe+c,GAC/C,IAAKxlB,KAAKinB,WACN,OAMJ,MACMG,EADK5B,EAASvT,IACIjS,KAAKmmB,KAAQnmB,KAAKqmB,KAAOrmB,KAAKmmB,KAEhDvV,EAAQ,GACdnI,EAAcI,SAAQ,SAAUC,GAO5B,IAAK/D,EAAKvG,EAAOC,EAAQC,GAAYoK,EAAKvH,SAEtC6D,EAAK0D,EAAKH,WAAW,GACrB2e,EAAerR,EAA4BmR,EAAS7hB,OAAQH,GAC5DmiB,EAAYD,EAAatiB,SAMzBwiB,EAAWziB,EAAMwiB,EAAa,IAAOxiB,GAAOwiB,EAAa,IAAM,IAE/D7B,EAAU5c,EAAKnD,UAAY,EAAK,IAAM,IAEtCggB,EAAU,EAAa,IAAK,EAAU,IAAM,IAE5CC,EAAc9C,GAAU5T,IAAI,GAAGsY,IAAU9B,IAASC,KAKlDnM,EAAM1Q,EAAK0Q,IACXiM,EAAUzlB,KAAK+b,KAAKxhB,IAAIif,EAAIze,KAGhC,GAAI6qB,GAAenD,GAAOI,WAAY,CAYlC,GADmBzL,EAAqBkQ,GAIjC,CAGH1B,EADgBlB,EAA+B4C,IACnBxe,EAAKnD,UAAa8c,GAAOC,MAAQD,GAAOG,UAJpEgD,EAAcnD,GAAOC,MAOzBkD,GAAenD,GAAOE,OACtBiD,EAAcnD,GAAOC,OAErBkD,GAAenD,GAAOC,OAAS+C,IAG/BG,GAAenD,GAAOG,MAAS6C,KAK/BG,GAAenD,GAAOC,OAEtB9R,EAAM1M,KAAK,CAACnJ,IAAIye,EAAIze,IAAKiW,IAAIwI,EAAKvI,SAAIpS,IACtCmB,KAAK+b,KAAKhe,IAAIyb,EAAIze,IAAKye,IAChBoM,GAAenD,GAAOG,OAE7BhS,EAAM1M,KAAK,CAACnJ,IAAIye,EAAIze,IAAKiW,SAAInS,EAAWoS,IAAIuI,IAC5CxZ,KAAK+b,KAAKtK,OAAO+H,EAAIze,SAE1BiF,MAKHA,KAAKwR,cAAcZ,ICvW3B,MAAM6W,GAEF5nB,wBAAwBmF,EAAUkB,GAC9B,IAAKtE,EAAKE,GAAQoE,EAIlB,OAAO,KAFMlB,EAAWpD,IACXE,EAAOF,GAIxB/B,wBAAwB6nB,EAASxhB,GAC7B,IAAKtE,EAAKE,GAAQoE,EAMlB,OAJAwhB,EAAU9tB,KAAK+F,IAAI,EAAG+nB,GAIf9lB,GAFME,EAAOF,IADpB8lB,EAAU9tB,KAAK8F,IAAI,IAAKgoB,IAEI,IAIhC7nB,YAAakS,EAAc4V,EAAensB,EAAQ,IAC9CwE,KAAKsY,IAAMvG,EACX/R,KAAK4nB,SAAWpsB,EAAQqsB,QACxB7nB,KAAK8nB,eAAiBH,EACtB3nB,KAAK+nB,OAAQ,EACb/nB,KAAKgb,SAAWxf,EAChBwE,KAAK0T,OAASlY,EAAQ0K,OAASlG,KAAKsY,IAAIpS,MACxC,IAAKtE,EAAKE,GAAQ9B,KAAK0T,OACvB,GAAI9R,IAAQjD,EAAAA,GAAYmD,GAAQnD,EAAAA,EAC5B,MAAM,IAAInB,MAAM,gBAAiBwC,KAAK0T,QAI1C1T,KAAK8nB,eAAe1qB,iBAAiB,QAAS,WAG1C4C,KAAKgoB,aAAc,GACrBvV,KAAKzS,OAGPA,KAAK8nB,eAAe1qB,iBAAiB,SAAU,WAE3C4C,KAAKgoB,aAAc,EAEnB,IAAIN,EAAUO,SAASjoB,KAAK8nB,eAAe9sB,OACvCgK,EAAWyiB,GAAeS,iBAAiBR,EAAS1nB,KAAK0T,QAC7D1T,KAAKsY,IAAI1D,OAAO,CAAC5P,SAAUA,KAC7ByN,KAAKzS,OAGHA,KAAK4nB,UACL5nB,KAAK4nB,SAAShY,GAAG,SAAU5P,KAAKmoB,QAAQ1V,KAAKzS,OAIrDH,UACI,IAAImF,EAAWhF,KAAKsY,IAAIvT,IAExB,IAAK/E,KAAKgoB,YAAa,CACnB,IAAIN,EAAUD,GAAeW,iBAAiBpjB,EAAUhF,KAAK0T,QAC7D,GAAI1T,KAAKgb,SAASqN,OAEd,GAAIX,EAAU,GAAO,IAAQA,EAGzB,YADA1nB,KAAKgb,SAASqN,MAAMC,YAIxBZ,EAAWA,EAAU,EAAO,EAAMA,EAClCA,EAAW,IAAQA,EAAW,IAAOA,EAEzC1nB,KAAK8nB,eAAe9sB,MAAQ,GAAG0sB,EAC3B1nB,KAAKgb,SAASqN,OACdroB,KAAKgb,SAASqN,MAAME,SCrD7B,SAASC,KAEZ,IAAIC,EAAU,IAAI7M,WAAWlhB,OAAQC,GAAOA,aAAamhB,IACrD4M,EAAMD,EAAQlvB,OAAS,EAAKkvB,EAAQ,GAAK,IAAI3M,GAE7C6M,EAAU,IAAI/M,WAAWlhB,OAAQC,GAAOA,aAAaka,IAErD+T,EAAW,IAAIhN,WAAWlhB,OAAQC,GAAO8B,OAAOosB,eAAeluB,KAAO8B,OAAOwT,WAC7EzU,EAAWotB,EAASrvB,OAAS,EAAKqvB,EAAS,GAAK,GACpD,GAAsB,GAAlBD,EAAQpvB,OACR,MAAM,IAAIiE,MAAM,gCACb,OAAsB,GAAlBmrB,EAAQpvB,OACR,IAAI8qB,GAAmBqE,EAAIC,EAAQ,GAAIntB,GAEvC,IAAIwqB,GAAsB0C,EAAIC,EAAQ,GAAIA,EAAQ,GAAIntB,GAKrE6oB,GAAmBpU,UAAU6Y,MAAQ,WACjC,IAAI/J,EAAO,CAAC/e,KAAK8a,SAEjB,OADAiE,EAAK7a,KAAK6kB,MAAMhK,EAAM,IAAInD,YACnB4M,MAAazJ,IAIxBiH,GAAsB/V,UAAU6Y,MAAQ,WACpC,IAAI/J,EAAO,CAAC/e,KAAK8a,SAEjB,OADAiE,EAAK7a,KAAK6kB,MAAMhK,EAAM,IAAInD,YACnB4M,MAAazJ,6EC1DxB,MAEIlf,YAAY6oB,EAAIM,GACZhpB,KAAK0oB,GAAKA,EACV1oB,KAAKgpB,KAAOA,EACZhpB,KAAKipB,MAAQ3vB,EAAc,GAC3B0G,KAAK0oB,GAAG9Y,GAAG,SAAU5P,KAAKkpB,SAASzW,KAAKzS,OACxCA,KAAK0oB,GAAG9Y,GAAG,SAAU5P,KAAKmpB,SAAS1W,KAAKzS,OAG5CH,WAAW2Z,GACP,IAAI2L,EAAO3L,EAAY,SAAIA,EAAIrN,SAAS9M,WAAa,YACjDmb,EAAO4O,KAAKC,UAAU7P,EAAIgB,MAC9B,MAAO,GAAGhB,EAAIze,QAAQoqB,MAAQ3K,IAGlC3a,SAASypB,GACL,IAAIC,EAAM,GAAGvpB,KAAKipB,SAASK,EAAMvuB,MAC7ByuB,EAAOxpB,KAAKgpB,KAAKS,cAAc,IAAIF,GACvC,GAAIC,EAEAA,EAAKE,UAAY1pB,KAAK2pB,WAAWL,EAAMtY,SACpC,CAEH,IAAIwY,EAAOzsB,SAAS6sB,cAAc,OAClCJ,EAAKE,UAAY1pB,KAAK2pB,WAAWL,EAAMtY,KACvCwY,EAAKK,aAAa,KAAMN,GACxBvpB,KAAKgpB,KAAKc,YAAYN,IAI9B3pB,SAASypB,GAEL,IAAIC,EAAM,GAAGvpB,KAAKipB,SAASK,EAAMvuB,MAC7ByuB,EAAOzsB,SAASgtB,eAAeR,GAC/BC,GACAA,EAAKQ,WAAWC,YAAYT,sBCpBxC,cAA6B3U,GAC5BhV,YAAakS,EAAcO,GAC1B,GAAIA,EAAQ,EAAI,MAAM,IAAI9U,MAAO,gCACjC,GAAc,IAAV8U,EAAc,MAAM,IAAI9U,MAAO,6CACnCuC,MAAMgS,GAEN/R,KAAKkqB,OAAS5X,EAEdtS,KAAKmqB,QAAU,GAEfnqB,KAAKoqB,SAAW,IAAItY,GAAQ9R,KAAMA,KAAKqqB,gBAAgB5X,KAAKzS,OACtDA,KAAKmP,eAAe,cAAe,CAAC9B,MAAK,IAI7CxN,sBAAsBI,GAClB,MAAY,eAARA,EACO,CAACD,KAAKkqB,QAENnqB,MAAM+N,sBAAsB7N,GAK9CJ,cAAcsS,GAiBbnS,KAAKmqB,QAAQjmB,KAAKiO,GAEbnS,KAAKoqB,SAASlU,SAClBlW,KAAKqqB,kBAKPxqB,kBAEC,IACIsS,EAAKmY,EADLlY,EAAMpS,KAAKqS,MAAMD,MAErB,KAAOpS,KAAKmqB,QAAQ5wB,OAAS,IAC5B+wB,EAAMtqB,KAAKmqB,QAAQ,GAAG9kB,UAAYrF,KAAKkqB,SACnC9X,EAAMkY,KAGTnY,EAAMnS,KAAKmqB,QAAQhuB,QAEnBgW,EAAI9M,UAAYilB,EAChBtqB,KAAKmW,UAAUhE,GAIbnS,KAAKmqB,QAAQ5wB,OAAS,IACzB+wB,EAAMtqB,KAAKmqB,QAAQ,GAAG9kB,UAAYrF,KAAKkqB,OACvClqB,KAAKoqB,SAAS7X,WAAW+X,IAI3BzqB,OAAOsS,GAEN,MAAM,IAAI3U,MAAO,0DAGf8U,YAAa,OAAOtS,KAAKkqB,OAE5B5X,UAAUA,GACCA,GAAStS,KAAKkqB,SAEdlqB,KAAKkqB,OAAS5X,EACdtS,KAAKoqB,SAAS1Y,QACd1R,KAAKqqB,kBACLrqB,KAAKoP,gBAAgB,cAAekD,mCZxEhD,cAA4BuC,GAE3BhV,YAAYiV,EAAW5O,GAGtB,GAFAnG,MAAM+U,EAAW,CAACG,SAAQ,KAErB3X,MAAMC,QAAQ2I,IAA0B,GAAhBA,EAAM3M,OAClC,MAAM,IAAIiE,MAAM,oCAAoC0I,GAErDlG,KAAKoV,QAAUlP,EAGhBrG,OAAOsS,GAEN,GAAiBtT,MAAbsT,EAAIjM,MAAoB,CAE3B,IAAKtE,EAAKE,GAAQqQ,EAAIjM,MACtB,GAAItE,GAAOE,EACV,MAAM,IAAItE,MAAM,gBAAiB2U,EAAIjM,OAEtC,GAAItE,GAAO5B,KAAKoV,QAAQ,IAAMtT,GAAQ9B,KAAKoV,QAAQ,GAAI,CACtDpV,KAAKoV,QAAU,CAACxT,EAAKE,GACrB,IAAIyD,EAASvF,KAAK2X,kBAAkBtE,QACpC9N,EAAOP,SAAW6S,GAAUtS,EAAOP,SAAUhF,KAAKoV,SAClDpV,KAAKmV,SAAW5P,EAEhB,IAAIiR,EAAO,CAACtQ,MAAOlG,KAAKoV,WAAYpV,KAAKmV,SAAUU,MAAK,GACxD7V,KAAKgX,iBAAiBR,GAAM,GAAM,UAE5BrE,EAAIjM,MAGZ,GAAoBrH,MAAhBsT,EAAInN,SAAuB,CAI9B,IAAIoN,EAAMpS,KAAKqS,MAAMD,MAEjBhT,EADakG,EAAgBtF,KAAKuF,OAAQ6M,GACxBpN,SAAWmN,EAAInN,SACjCulB,EAAiBjlB,EAAgBtF,KAAK2X,kBAAkBpS,OAAQ6M,GACpED,EAAInN,SAAWulB,EAAevlB,SAAW5F,EAE1C,OAAOW,MAAM6U,OAAOzC,GAIrBtS,iBAAiBwG,GAEhB,OADAA,EAAWrB,SAAW6S,GAAUxR,EAAWrB,SAAUhF,KAAKoV,SACnD/O,EAIRxG,cAAcsS,GAcb,OAbuBtT,MAAbsT,EAAIjM,QAGJiM,EAAIjM,MAAQlG,KAAKoV,SAEDvW,MAAhBsT,EAAInN,WAEPmN,EAAInN,SAAW6S,GAAU1F,EAAInN,SAAUhF,KAAKoV,UAM5CjD,uBGvCT,MAEItS,YAAakS,EAAcxE,EAAU/R,EAAQ,IACzCwE,KAAKsY,IAAMvG,EACX,IAAIgH,OAACA,EAAO,EAACnG,OAAEA,EAAO,GAAKpX,EAC3BwE,KAAKwqB,QAAU5X,EACf5S,KAAKyqB,QAAU1R,EACf/Y,KAAK2T,UAAYpG,EACjBvN,KAAKoqB,SAAW,IAAItY,GAAQ9R,KAAKsY,IAAKtY,KAAK0qB,eAAejY,KAAKzS,OAG/DA,KAAKsY,IAAI1I,GAAG,YAAa5P,KAAK4Y,UAAUnG,KAAKzS,OAGjDH,UAAUkO,EAAMG,GACZ,IAAInJ,EAAOgJ,EAAS,KAAIA,EAAK/I,SAAWhF,KAAKsY,IAAIvT,IACjD/E,KAAK2qB,cAAc5lB,GAGvBlF,kBAAkB+qB,EAAQC,GACtB,IAAItlB,EAASvF,KAAKsY,IAAIjF,SACjBtK,EAAOhE,GAAOyS,EAA2BjS,EAAQ,CAACqlB,EAAQC,IAC/D,GAAahsB,MAATkK,EACA,OAGJ,IAAK+hB,EAAMC,GAAS/qB,KAAKsY,IAAIpS,MAC7B,OAAInB,EAAM+lB,GAAQC,EAAQhmB,EACf,MAAClG,OAAWA,GAEhB,CAAC0G,EAAOF,UAAY0D,EAAOhE,GAGtClF,cAAckF,GACV/E,KAAKoqB,SAAS1Y,QAEd,IAAK+O,EAAOmK,EAAQC,GAlE5B,SAAuB7lB,EAAU+T,EAAQnG,GACrC,IAAKuG,EAAGjb,GAAK4a,GAAY9T,EAAU+T,EAAQnG,GACvCiY,EAAQ,CAAC1R,EAAE,EAAG,GACdyR,EAAe,GAAL1sB,EAAU,CAACib,EAAE,EAAG,GAAI,CAACA,EAAG,GAGtC,OAFAyR,EAAS1R,GAAY0R,EAAQ7R,EAAQnG,GACrCiY,EAAQ3R,GAAY2R,EAAO9R,EAAQnG,GAC5B,CAAK,GAAH1U,EAAO0sB,EAAQC,GA4DUG,CAAcjmB,EACA/E,KAAKyqB,QACLzqB,KAAKwqB,SAE7C/J,GACAzgB,KAAK2T,UAAU5O,GAGnB,IAAIqC,EAAMpH,KAAKirB,kBAAkBL,EAAQC,GACzC,GAAWhsB,MAAPuI,EACA,OAGJ,IAAIhC,EAAKgC,EAAI,GACbpH,KAAKoqB,SAAS7X,WAAWnN,EAAIgC,GAGjCvH,eAAeuS,EAAKD,GAChB,IAAIpN,EAAMoN,EAAI,GACdnS,KAAK2qB,cAAc5lB,sBF1C3B,cAA6B8P,GAE5BhV,YAAakS,EAAc7L,GAC1BnG,MAAMgS,EAAc,CAACkD,SAAQ,IAC7BjV,KAAKkrB,QAAU3kB,KACfvG,KAAKoV,QAAUlP,EAIhBrG,OAAOsS,GACN,MAAM3U,MAAM,oBAuCbqC,cAAcsS,GAMP,GALiBtT,MAAbsT,EAAIjM,cAGGiM,EAAIjM,MAEKrH,MAAhBsT,EAAInN,SAAuB,CAE9B,IAAIA,SAACA,EAAQE,SAAEA,EAAQC,aAAEA,EAAYE,UAAEA,GAAa8M,EAChD5M,EAAS,CAACP,SAAAA,EAAUE,SAAAA,EAAUC,aAAAA,EAAcE,UAAAA,GAEhD,GADAE,EAASvF,KAAKmrB,eAAe5lB,GACf1G,MAAV0G,EAIT,YADAvF,KAAKiX,eAAejX,KAAK2X,kBAAkBpS,OAAQvF,KAAKoV,SAIlDjD,EAAInN,SAAWO,EAAOP,SACtBmN,EAAIjN,SAAWK,EAAOL,SACtBiN,EAAIhN,aAAeI,EAAOJ,aAC1BgN,EAAI9M,UAAYE,EAAOF,UAGzB,OAAO8M,EAIdtS,eAAe0F,GACd,IAAIwS,EAAY9R,EAAkBV,EAAQvF,KAAKoV,SAC3CgW,EAAgBprB,KAAKkrB,QAAQntB,IAAIga,EAAW/X,KAAKoV,SACrD,GAAIgW,EAAclT,QAEblY,KAAKkrB,QAAQhc,QAAUrJ,EAAW3E,SAMrCqE,EAASe,EAAWf,EAAQvF,KAAKoV,eAKlC,GAAIpV,KAAKkrB,QAAQhc,QAAUrJ,EAAW3E,YAG/B,CAUN,IAAIkqB,EAAcnT,SAGjB,OAFA1S,EAASe,EAAWf,EAAQvF,KAAKoV,SAMpC,OAAO7P,qBY3KT,cAA6BsP,GACzBhV,YAAaiV,EAAWuW,GAC1BtrB,MAAM+U,GACN9U,KAAKsrB,QAAUD,EACTrrB,KAAKmP,eAAe,cAAe,CAAC9B,MAAK,IAI7CxN,sBAAsBI,GAClB,MAAY,eAARA,EACO,CAACD,KAAKsrB,SAENvrB,MAAM+N,sBAAsB7N,GAK3CJ,cAAcsS,GAaV,OAZiBtT,MAAbsT,EAAIjM,QACJiM,EAAIjM,MAAQ,CAACiM,EAAIjM,MAAM,GAAGlG,KAAKsrB,QAASnZ,EAAIjM,MAAM,GAAGlG,KAAKsrB,UAE1CzsB,MAAhBsT,EAAInN,WACJmN,EAAInN,UAAYhF,KAAKsrB,SAELzsB,MAAhBsT,EAAIjN,WACJiN,EAAIjN,UAAYlF,KAAKsrB,SAEDzsB,MAApBsT,EAAIhN,eACJgN,EAAIhN,cAAgBnF,KAAKsrB,SAEtBnZ,EAGdtS,OAAOsS,GAUN,OAToBtT,MAAhBsT,EAAInN,WACEmN,EAAInN,UAAYhF,KAAKsrB,SAEXzsB,MAAhBsT,EAAIjN,WACEiN,EAAIjN,UAAYlF,KAAKsrB,SAEPzsB,MAApBsT,EAAIhN,eACEgN,EAAIhN,cAAgBnF,KAAKsrB,SAE5BvrB,MAAM6U,OAAOzC,GAGlBoZ,YAAa,OAAOvrB,KAAKsrB,QAEzBC,UAAUF,GACFA,GAAUrrB,KAAKsrB,UAEftrB,KAAKsrB,QAAUD,EACfrrB,KAAKyX,cAAc,IACZzX,KAAK2X,kBAAkBpS,OAC1BW,MAAOlG,KAAK2X,kBAAkBzR,QAElClG,KAAKoP,gBAAgB,cAAeic,qCCvDhD,cAA4BxW,GAE3BhV,YAAaiV,EAAWxB,EAAM9X,GAC7BuE,MAAM+U,EAAWtZ,GACjBwE,KAAKwrB,MAAQlY,EACPtT,KAAKmP,eAAe,aAAc,CAAC9B,MAAK,IAI5CxN,sBAAsBI,GAClB,MAAY,cAARA,EACO,CAACD,KAAKwrB,OAENzrB,MAAM+N,sBAAsB7N,GAK9CJ,cAAcsS,GAQP,OAPiBtT,MAAbsT,EAAIjM,QACJiM,EAAIjM,MAAM,IAAMlG,KAAKwrB,MACrBrZ,EAAIjM,MAAM,IAAMlG,KAAKwrB,OAEL3sB,MAAhBsT,EAAInN,WACbmN,EAAInN,UAAYhF,KAAKwrB,OAETrZ,EAIdtS,OAAOsS,GAIA,GAHoBtT,MAAhBsT,EAAInN,WACbmN,EAAInN,UAAYhF,KAAKwrB,OAEC3sB,MAAbsT,EAAIjM,MAAoB,CACxB,IAAKtE,EAAKE,GAAQqQ,EAAIjM,MACtBiM,EAAIjM,MAAQ,CAACtE,EAAM5B,KAAKwrB,MAAO1pB,EAAO9B,KAAKwrB,OAErD,OAAOzrB,MAAM6U,OAAOzC,GAGrBmB,WAAY,OAAOtT,KAAKwrB,MAExBlY,SAASA,GACEA,GAAQtT,KAAKwrB,QAEtBxrB,KAAKwrB,MAAQlY,EACbtT,KAAKyX,cAAc,IACHzX,KAAK2X,kBAAkBpS,OAC1BW,MAAOlG,KAAK2X,kBAAkBzR,QAElClG,KAAKoP,gBAAgB,aAAckE,eCrC/C,cAAqB3B,GAEjB9R,YAAYib,EAAStf,EAAQ,IACzBuE,MAAMvE,GACNwE,KAAKyrB,YAAcjwB,EAAQkwB,WAC3B1rB,KAAK2rB,aAAenwB,EAAQowB,YAC5B5rB,KAAK6rB,UAAYrwB,EAAQ2Q,SACzBnM,KAAK8rB,cAAgBtwB,EAAQuwB,aAC7B/rB,KAAKgsB,MAAQ,EAGbhsB,KAAKisB,WAAa,GAGlBjsB,KAAKksB,QAAUpR,EACf,IAAIsI,EAAKpjB,KAAKqjB,mBAAmB5Q,KAAKzS,MACtCA,KAAKmsB,WAAansB,KAAKksB,QAAQ3I,aAAaH,GAQhD3S,iBACI,OAAOzQ,KAAKksB,QAGhBpR,cACI,OAAO9a,KAAKksB,QAIhB/f,eACI,OAAOnM,KAAK6rB,UAGhB1f,aAAcgZ,GACVnlB,KAAKosB,aAAajH,GAQtBtlB,aAAcwc,GACV,IAAIC,EAAS,CACTD,QAASA,GAGb,OADArc,KAAKisB,WAAW/nB,KAAKoY,GACdA,EAIXzc,aAAcyc,GACV,IAAItR,EAAQhL,KAAKisB,WAAW1P,QAAQD,GAChCtR,GAAS,GACThL,KAAKisB,WAAWxgB,OAAOT,EAAO,GAKtCnL,kBAAmB2c,EAAUC,GACzBzc,KAAKisB,WAAWpjB,SAAQ,SAASyT,GAC7BA,EAAOD,QAAQG,EAAUC,MAajC5c,UAAU2Z,GACN,OAAW3a,MAAP2a,MAIAxZ,KAAK6rB,YACA7rB,KAAK6rB,UAAUpL,MAAMjH,EAAIrN,eAK9BnM,KAAKyrB,cACAzrB,KAAKyrB,YAAYjS,EAAIze,SAK1BiF,KAAK2rB,eACA3rB,KAAK2rB,aAAanS,EAAIgB,SAUnC3a,aAAa2Z,GACT,OAAW3a,MAAP2a,GAAoBxZ,KAAK8rB,cAElB,CACH/wB,IAAKye,EAAIze,IACToR,SAAUqN,EAAIrN,SACdqO,KAAMxa,KAAK8rB,cAActS,EAAIgB,OAG9BhB,EAOX3Z,sBAAsB+Q,GAClB,IAAIyb,EAAS,GACb,IAAK,IAAIvjB,KAAQ8H,EAAO,CACpB,GAAgB/R,MAAZiK,EAAKkI,KAAgCnS,MAAZiK,EAAKmI,IAC9B,SAUJ,IAAIqb,EAAQtsB,KAAKusB,UAAUzjB,EAAKmI,KAAQnI,EAAKmI,SAAMpS,EAC/C2tB,EAAQxsB,KAAKusB,UAAUzjB,EAAKkI,KAAQlI,EAAKkI,SAAMnS,EACvCA,MAARytB,GAA6BztB,MAAR2tB,IAIzBF,EAAOtsB,KAAKysB,aAAaH,GACzBE,EAAOxsB,KAAKysB,aAAaD,GAEzBH,EAAOnoB,KAAK,CAACnJ,IAAI+N,EAAK/N,IAAKiW,IAAKwb,EAAMvb,IAAKqb,KAE/C,OAAOD,EAQXxsB,gBAAgBsM,GACZ,GAAInM,KAAK6rB,UAEN,GAAI1f,EAAU,CAEV,IAAIugB,EAAaprB,EAASmC,UAAU0I,EAAUnM,KAAK6rB,WACnD,GAAyB,GAArBa,EAAWnzB,OAEX,OADAyP,QAAQC,IAAI,6BAA6BkD,EAAS9M,0CAA0CW,KAAK6rB,UAAUxsB,cACpG,GAEN8M,EAAWugB,EAAW,QAI1BvgB,EAAWnM,KAAK6rB,UAGxB,OAAO1f,EAOXtM,OAAOsM,EAAUtJ,GACb,IACI+O,EADAia,EAAY7rB,KAAK2sB,gBAAgBxgB,GAQrC,OALIyF,EADAia,EACO7rB,KAAKyQ,WAAW6P,OAAOuL,EAAWhpB,GAElC,IAAI7C,KAAKyQ,WAAWvD,UAGxB0E,EAAKlX,OAAOsF,KAAKusB,UAAWvsB,MAC9BvC,IAAIuC,KAAKysB,aAAczsB,MAQhCH,iBAAiBsM,GACb,IAAI0f,EAAY7rB,KAAK2sB,gBAAgBxgB,GAGrC,OAFYnM,KAAKyQ,WAAW2R,iBAAiByJ,GAEhCnxB,OAAQoO,GACV9I,KAAKusB,UAAUzjB,EAAK0Q,KAC5BxZ,MAAMvC,IAAKqL,IACH,CAACvH,SAAUuH,EAAKvH,SAAUiY,IAAKxZ,KAAKysB,aAAa3jB,EAAK0Q,OAC9DxZ,MAOPH,sBAAsBI,GAClB,GAAY,SAARA,GAA2B,UAARA,EAAkB,CAErC,IAEI2Q,EAFO5Q,KAAKsgB,SAEC7iB,IAAK+b,IACX,CAACze,IAAIye,EAAIze,IAAKiW,IAAIwI,EAAKvI,SAAIpS,KAItC,OADAmB,KAAKmR,UAAUP,GACC,SAAR3Q,EAAmB,CAAC2Q,GAASA,GAQ7C/Q,mBAAmB4jB,EAAUhH,GACzB,IAAI7L,EAAQ,IAAI6S,EAASvW,UACzB0D,EAAQ5Q,KAAK4sB,sBAAsBhc,GAEnC,IAAK,IAAI9H,KAAQ8H,EACG/R,MAAZiK,EAAKkI,KAAgCnS,MAAZiK,EAAKmI,IAE9BjR,KAAKgsB,OAAS,EACKntB,MAAZiK,EAAKkI,KAAgCnS,MAAZiK,EAAKmI,MAErCjR,KAAKgsB,OAAS,GAItBjsB,MAAMyR,cAAcZ,GAEpB,IAAI4L,EAAW,IAAI1hB,IAAI8V,EAAMnT,IAAKqL,GACvB,CAACA,EAAK/N,IAAK+N,KAElB9I,KAAK6rB,YACLpP,EAAoBnb,EAASmC,UAAUzD,KAAK6sB,UAAWpQ,IAE3Dzc,KAAKwd,kBAAkBhB,EAAUC,GAQrC5c,aAAcslB,GACV,IAAKA,aAAe7jB,EAChB,MAAM,IAAI9D,MAAM,mBAAoB2nB,EAAI9lB,YAE5C,IAAKW,KAAK6rB,YAAc7rB,KAAK6rB,UAAUtsB,OAAO4lB,GAAM,CAEhD,IAAI2H,EAAe9sB,KAAKsgB,SAExBtgB,KAAK6rB,UAAY1G,EAEjB,IAAI4H,EAAW/sB,KAAKyQ,WAAW6P,OAAO6E,GAEtC4H,EAAWA,EACNryB,OAAOsF,KAAKusB,UAAWvsB,MACvBvC,IAAIuC,KAAKysB,aAAczsB,MAE5B,IAAIgtB,EAAgB,IAAIlyB,IAAI,IAAIgyB,GAAcrvB,IAAK+b,GACxC,CAACA,EAAIze,IAAKye,KAEjByT,EAAY,IAAInyB,IAAI,IAAIiyB,GAAUtvB,IAAK+b,GAChC,CAACA,EAAIze,IAAKye,KAGjB0T,EAAatyB,EAAeoyB,EAAeC,GAC3CE,EAAcvyB,EAAeqyB,EAAWD,GAExC1H,EAAY,IAAI4H,EAAWhgB,UAAUzP,IAAK+b,IACnC,CAACze,IAAKye,EAAIze,IAAKiW,SAAInS,EAAWoS,IAAKuI,KAE1C+L,EAAa,IAAI4H,EAAYjgB,UAAUzP,IAAK+b,IACrC,CAACze,IAAKye,EAAIze,IAAKiW,IAAIwI,EAAKvI,SAAKpS,KAGxCmB,KAAKgsB,OAAS1G,EAAU/rB,OACxByG,KAAKgsB,OAASzG,EAAWhsB,OAEzB,MAAMqX,EAAQtV,EAAa,CAACgqB,EAAWC,GAAa,CAAC9pB,MAAK,EAAOC,OAAM,IACvEsE,KAAKwR,cAAcZ,IAQ3B1W,WACI,OAAO8F,KAAKgsB,MAGhBnsB,IAAI9E,GACA,OAAyB8D,MAAjBmB,KAAKkP,IAAInU,GAGrB8E,IAAI9E,GACA,IAAIye,EAAMzZ,MAAMmP,IAAInU,GACpB,GAAW8D,MAAP2a,GAAoBxZ,KAAKusB,UAAU/S,GACnC,OAAOxZ,KAAKysB,aAAajT,GAIjC3Z,OACI,OAAOG,KAAKkN,SAASzP,IAAK+b,GACfA,EAAIze,KAInB8E,SACI,MAAO,IAAIE,MAAMmN,UACZxS,OAAQ8e,GACExZ,KAAKusB,UAAU/S,GACvBxZ,MACFvC,IAAK+b,GACKxZ,KAAKysB,aAAajT,GAC1BxZ,MAGXH,UACI,OAAOG,KAAKkN,SAASzP,IAAK+b,GACf,CAACA,EAAIze,IAAKye,IASzB3Z,OAAO+R,EAAMpW,GACT,MAAM,IAAIgC,MAAM,mBAGpBqC,IAAK9E,EAAKC,GACN,MAAM,IAAIwC,MAAM,mBAGpBqC,OAAQ9E,GACJ,MAAM,IAAIyC,MAAM,mBAGpBqC,MAAO9E,GACH,MAAM,IAAIyC,MAAM,uDC1WxB,cAAiCqX,GAE7BhV,YAAaiV,EAAWlC,GAC1B7S,MAAM+U,GACN9U,KAAKwqB,QAAU5X,EACT5S,KAAKmP,eAAe,eAAgB,CAAC9B,MAAK,IAI9CxN,sBAAsBI,GAClB,MAAY,gBAARA,EACO,CAACD,KAAKwqB,SAENzqB,MAAM+N,sBAAsB7N,GAK3CJ,cAAcsS,GAIV,GAHiBtT,MAAbsT,EAAIjM,QACJiM,EAAIjM,MAAQ,EAAEvH,EAAAA,EAAUA,EAAAA,IAERE,MAAhBsT,EAAInN,SAAuB,CAE3B,IAAII,EAAK+M,EAAI9M,UACTsE,EAAarE,EAAgB6M,EAAK/M,EAAKpF,KAAKwqB,SAChDrY,EAAInN,SAAW2E,EAAW3E,SAC1BmN,EAAIjN,SAAWyE,EAAWzE,SAC1BiN,EAAIhN,aAAewE,EAAWxE,aAC9BgN,EAAI9M,UAAYD,EAEpB,OAAO+M,EAGXS,aAAc,OAAO5S,KAAKwqB,QAE1B5X,WAAWA,GACHA,GAAU5S,KAAKwqB,UAEfxqB,KAAKwqB,QAAU5X,EACf5S,KAAKyX,cAAc,IACZzX,KAAK2X,kBAAkBpS,OAC1BW,MAAOlG,KAAK2X,kBAAkBzR,QAElClG,KAAKoP,gBAAgB,eAAgBwD,8HND1B"}
\ No newline at end of file
diff --git a/docs/lib/timingsrc-module-v3.js.map b/docs/lib/timingsrc-module-v3.js.map
new file mode 100644
index 0000000..4786148
--- /dev/null
+++ b/docs/lib/timingsrc-module-v3.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"timingsrc-module-v3.js","sources":["../../v3/util/utils.js","../../v3/util/endpoint.js","../../v3/util/interval.js","../../v3/util/motionutils.js","../../v3/util/binarysearch.js","../../v3/util/eventify.js","../../v3/util/observablemap.js","../../v3/dataset/cuecollection.js","../../v3/util/timeout.js","../../v3/timingobject/masterclock.js","../../v3/timingobject/internalprovider.js","../../v3/timingobject/externalprovider.js","../../v3/timingobject/timingobject.js","../../v3/timingobject/skewconverter.js","../../v3/timingobject/delayconverter.js","../../v3/timingobject/scaleconverter.js","../../v3/timingobject/loopconverter.js","../../v3/timingobject/rangeconverter.js","../../v3/timingobject/timeshiftconverter.js","../../v3/timingobject/timingsampler.js","../../v3/timingobject/positioncallback.js","../../v3/dataset/dataset.js","../../v3/dataset/subset.js","../../v3/sequencing/schedule.js","../../v3/sequencing/basesequencer.js","../../v3/sequencing/pointsequencer.js","../../v3/sequencing/intervalsequencer.js","../../v3/ui/datasetviewer.js","../../v3/ui/timingprogress.js","../../v3/index.js"],"sourcesContent":["/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n\nexport function random_string(length) {\n var text = \"\";\n var possible = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n for(var i = 0; i < length; i++) {\n text += possible.charAt(Math.floor(Math.random() * possible.length));\n }\n return text;\n}\n\n\n/* Set Comparison */\nexport function eqSet(as, bs) {\n return as.size === bs.size && all(isIn(bs), as);\n}\n\nexport function all(pred, as) {\n for (var a of as) if (!pred(a)) return false;\n return true;\n}\n\nexport function isIn(as) {\n return function (a) {\n return as.has(a);\n };\n}\n\nexport function set_difference(as, bs) {\n return new Set([...as].filter((e) => !bs.has(e)));\n}\n\n\n\n\n\n/*\n get the difference of two Maps\n key in a but not in b\n*/\nexport const map_difference = function (a, b) {\n if (a.size == 0) {\n return new Map();\n } else if (b.size == 0) {\n return a;\n } else {\n return new Map([...a].filter(function ([key, value]) {\n return !b.has(key)\n }));\n }\n};\n\n/*\n get the intersection of two Maps\n key in a and b\n*/\nexport const map_intersect = function (a, b) {\n [a, b] = (a.size <= b.size) ? [a,b] : [b,a];\n if (a.size == 0) {\n // No intersect\n return new Map();\n }\n return new Map([...a].filter(function ([key, value]) {\n return b.has(key)\n }));\n};\n\n/*\n\nNOTE : just as good to do \n let merged = new Map(...map0, ...map1, ...)\n\neffective concatenation of multiple arrays\n- order - if true preserves ordering of input arrays\n - else sorts input arrays (longest first)\n - default false is more effective\n- copy - if true leaves input arrays unchanged, copy\n values into new array\n - if false copies remainder arrays into the first\n array\n - default false is more effective\n*/\nexport function map_merge(array_of_maps, options={}) {\n let {copy=false, order=false} = options;\n // check input\n if (array_of_maps instanceof Map) {\n return array_of_maps;\n }\n if (!Array.isArray(array_of_maps)) {\n throw new Error(\"illegal input array_of_maps\", array_of_maps);\n }\n if (array_of_maps.length == 0) {\n throw new Error(\"empty array_of_maps\");\n }\n let is_maps = array_of_maps.map((o) => {\n return (o instanceof Map);\n });\n if (!is_maps.every((e) => e == true)) {\n throw new Error(\"some object in array_of_maps is not a Map\", array_of_maps);\n }\n // order\n if (!order) {\n // sort array_of_maps according to size - longest first\n array_of_maps.sort((a, b) => b.size - a.size);\n }\n // copy\n let first = (copy) ? new Map() : array_of_maps.shift(); \n // fill up first Map with entries from other Maps\n for (let m of array_of_maps) {\n for (let [key, val] of m.entries()) {\n first.set(key, val);\n }\n }\n return first;\n}\n\n\nexport function divmod (n, d) {\n let r = n % d;\n let q = (n-r)/d;\n return [q, r];\n}\n\n\nexport function isIterable(obj) {\n // checks for null and undefined\n if (obj == null) {\n return false;\n }\n return typeof obj[Symbol.iterator] === 'function';\n}\n\n/*\n effective concatenation of multiple arrays\n - order - if true preserves ordering of input arrays\n - else sorts input arrays (longest first)\n - default false is more effective\n - copy - if true leaves input arrays unchanged, copy\n values into new array\n - if false copies remainder arrays into the first\n array\n - default false is more effective\n*/\nexport function array_concat(arrays, options = {}) {\n let {copy=false, order=false} = options;\n if (arrays.length == 0) {\n return [];\n }\n if (arrays.length == 1) {\n return arrays[0];\n }\n let total_len = arrays.reduce((acc, cur) => acc + cur.length, 0);\n // order\n if (!order) {\n // sort arrays according to length - longest first\n arrays.sort((a, b) => b.length - a.length);\n }\n // copy\n let first = (copy) ? [] : arrays.shift();\n let start = first.length;\n // reserve memory total length\n first.length = total_len;\n // fill up first with entries from other arrays\n let end, len;\n for (let arr of arrays) {\n len = arr.length;\n end = start + len;\n for (let i=0; i not equal\n if (aProps.length != bProps.length) {\n return false;\n }\n for (let i=0; i not equal\n if (a[propName] !== b[propName]) {\n return false;\n }\n }\n // equal\n return true;\n}\n\n\n/* document readypromise */\nexport const docready = new Promise(function(resolve) {\n if (document.readyState === 'complete') {\n resolve();\n } else {\n let onReady = function () {\n resolve();\n document.removeEventListener('DOMContentLoaded', onReady, true);\n window.removeEventListener('load', onReady, true);\n };\n document.addEventListener('DOMContentLoaded', onReady, true);\n window.addEventListener('load', onReady, true);\n }\n});\n\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\nconst isNumber = function(n) {\n\tlet N = parseFloat(n);\n return (n===N && !isNaN(N));\n};\n\n\n/*********************************************************\n\nENDPOINT\n\nUtilities for interval endpoints comparison\n\n**********************************************************/\n\n/*\n\tendpoint modes - in endpoint order\n\tendpoint order\n\tp), [p, [p], p], (p\n*/\nconst MODE_RIGHT_OPEN = 0;\nconst MODE_LEFT_CLOSED = 1;\nconst MODE_SINGULAR = 2;\nconst MODE_RIGHT_CLOSED = 3;\nconst MODE_LEFT_OPEN = 4;\n\n// create endpoint\nfunction create(val, right, closed, singular) {\n\t// make sure infinity endpoints are legal\n\tif (val == Infinity) {\n\t\tif (right == false || closed == false) {\n\t\t\tthrow new Error(\"Infinity endpoint must be right-closed or singular\");\n\t\t}\n\t}\n\tif (val == -Infinity) {\n\t\tif (right == true || closed == false) {\n\t\t\tthrow new Error(\"-Infinity endpoint must be left-closed or singular\")\n\t\t}\n\t}\n\treturn [val, right, closed, singular];\n}\n\n\n/*\n\tresolve endpoint mode\n*/\nfunction get_mode(e) {\n\t// if right, closed is given\n\t// use that instead of singular\n\tlet [val, right, closed, singular] = e;\n\tif (right == undefined) {\n\t\treturn MODE_SINGULAR;\n\t} else if (right) {\n\t\tif (closed) {\n\t\t\treturn MODE_RIGHT_CLOSED;\n\t\t} else {\n\t\t\treturn MODE_RIGHT_OPEN;\n\t\t}\n\t} else {\n\t\tif (closed) {\n\t\t\treturn MODE_LEFT_CLOSED;\n\t\t} else {\n\t\t\treturn MODE_LEFT_OPEN;\n\t\t}\n\t}\n}\n\n/*\n\tget order\n\n\tgiven two endpoints\n\treturn two numbers representing their order\n\n\talso accepts regular numbers as endpoints\n\tregular number are represented as singular endpoints\n\n\tfor endpoint values that are not\n\tequal, these values convey order directly,\n\totherwise endpoint mode numbers 0-4 are returned\n\n\tparameters are either\n\t- point: Number\n\tor,\n\t- endpoint: [\n\t\tvalue (number),\n\t\tright (bool),\n\t\tclosed (bool),\n\t\tsingular (bool)\n\t ]\n*/\n\nfunction get_order(e1, e2) {\n\t// support plain numbers (not endpoints)\n\tif (e1.length === undefined) {\n\t\tif (!isNumber(e1)) {\n\t\t\tthrow new Error(\"e1 not a number\", e1);\n\t\t}\n\t\te1 = create(e1, undefined, undefined, true);\n\t}\n\tif (e2.length === undefined) {\n\t\tif (!isNumber(e2)) {\n\t\t\tthrow new Error(\"e2 not a number\", e2);\n\t\t}\n\t\te2 = create(e2, undefined, undefined, true);\n\t}\n\tif (e1[0] != e2[0]) {\n\t\t// different values\n\t\treturn [e1[0], e2[0]];\n\t} else {\n\t\t// equal values\n\t\treturn [get_mode(e1), get_mode(e2)];\n\t}\n}\n\n/*\n\treturn true if e1 is ordered before e2\n\tfalse if equal\n*/\n\nfunction leftof(e1, e2) {\n\tlet [order1, order2] = get_order(e1, e2);\n\treturn (order1 < order2);\n}\n\n/*\n\treturn true if e1 is ordered after e2\n\tfalse is equal\n*/\n\nfunction rightof(e1, e2) {\n\tlet [order1, order2] = get_order(e1, e2);\n\treturn (order1 > order2);\n}\n\n/*\n\treturn true if e1 is ordered equal to e2\n*/\n\nfunction equals(e1, e2) {\n\tlet [order1, order2] = get_order(e1, e2);\n\treturn (order1 == order2);\n}\n\n/*\n\treturn -1 if ordering e1, e2 is correct\n\treturn 0 if e1 and e2 is equal\n\treturn 1 if ordering e1, e2 is incorrect\n*/\n\nfunction cmp(e1, e2) {\n\tlet [order1, order2] = get_order(e1, e2);\n\tlet diff = order1 - order2;\n\tif (diff == 0) return 0;\n\treturn (diff > 0) ? 1 : -1;\n}\n\n\nfunction min(e1, e2) {\n return (cmp(e1, e2) <= 0) ? e1 : e2;\n}\n\n\nfunction max(e1, e2) {\n return (cmp(e1, e2) <= 0) ? e2 : e1;\n}\n\n\n/*\n\thuman friendly endpoint representation\n*/\nfunction toString(e) {\n\tif (e.length === undefined) {\n\t\treturn e.toString();\n\t} else {\n\t\tlet mode = get_mode(e);\n\t\tlet val = e[0];\n\t\tif (val == Infinity || val == -Infinity) {\n\t\t\tval = \"--\";\n\t\t}\n\t\tif (mode == MODE_RIGHT_OPEN) {\n\t\t\treturn `${val})`\n\t\t} else if (mode == MODE_LEFT_CLOSED) {\n\t\t\treturn `[${val}`\n\t\t} else if (mode == MODE_SINGULAR){\n\t\t\treturn `[${val}]`\n\t\t} else if (mode == MODE_RIGHT_CLOSED) {\n\t\t\treturn `${val}]`\n\t\t} else if (mode == MODE_LEFT_OPEN) {\n\t\t\treturn `(${val}`\n\t\t}\n\t}\n}\n\n\nexport default {\n\tcmp,\n\ttoString,\n\tequals,\n\trightof,\n\tleftof,\n\tcreate,\n\tmin,\n\tmax\n};\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\nimport endpoint from './endpoint.js';\n\n\nconst isNumber = function(n) {\n\tlet N = parseFloat(n);\n return (n===N && !isNaN(N));\n};\n\n/*********************************************************\nINTERVAL ERROR\n**********************************************************/\n\nclass IntervalError extends Error {\n\tconstructor(message) {\n\t\tsuper(message);\n\t\tthis.name == \"IntervalError\";\n\t}\n};\n\n\n/*********************************************************\nINTERVAL\n**********************************************************/\n\n// Interval Relations\nconst Relation = Object.freeze({\n\tOUTSIDE_LEFT: 64, \t// 0b1000000\n\tOVERLAP_LEFT: 32, \t// 0b0100000\n\tCOVERED: 16,\t\t// 0b0010000\n\tEQUALS: 8,\t\t\t// 0b0001000\n\tCOVERS: 4,\t\t\t// 0b0000100\n\tOVERLAP_RIGHT: 2,\t// 0b0000010\n\tOUTSIDE_RIGHT: 1\t// 0b0000001\n});\n\n/*\n Masks for Interval matching\n*/\nconst MATCH_OUTSIDE = Relation.OUTSIDE_LEFT + Relation.OUTSIDE_RIGHT;\nconst MATCH_INSIDE = Relation.EQUALS + Relation.COVERED;\nconst MATCH_OVERLAP = MATCH_INSIDE +\n\tRelation.OVERLAP_LEFT + Relation.OVERLAP_RIGHT;\nconst MATCH_COVERS = MATCH_OVERLAP + Relation.COVERS;\nconst MATCH_ALL = MATCH_COVERS + MATCH_OUTSIDE;\n\nconst Match = Object.freeze({\n\tOUTSIDE: MATCH_OUTSIDE,\n\tINSIDE: MATCH_INSIDE,\n\tOVERLAP: MATCH_OVERLAP,\n\tCOVERS: MATCH_COVERS,\n\tALL: MATCH_ALL\n});\n\n\n/*********************************************************\nCOMPARE INTERVALS\n**********************************************************\n\ncompare (a, b)\nparam a Interval\nparam b Interval\nreturns IntervalRelation\n\ncompares interval b to interval a\ne.g. return value COVERED reads b is covered by a.\n\ncmp_1 = endpoint_compare(b_low, a_low);\ncmp_2 = endpoint_compare(b_high, a_high);\n\nkey = 10*cmp_1 + cmp_2\n\ncmp_1 cmp_2 key relation\n===== ===== === ============================\n-1 -1 -11 OUTSIDE_LEFT, PARTIAL_LEFT\n-1 \t 0 -10 COVERS\n-1 1 -9 COVERS\n0\t -1 -1 COVERED\n0 0 0 EQUAL\n0 \t 1 1 COVERS\n1 -1 9 COVERED\n1 \t 0 10 COVERED\n1 \t 1 11 OUTSIDE_RIGHT, OVERLAP_RIGHT\n===== ===== === ============================\n\n**********************************************************/\n\nfunction compare(a, b) {\n\tif (! a instanceof Interval) {\n\t\t// could be a number\n\t\tif (isNumber(a)) {\n\t\t\ta = new Interval(a);\n\t\t} else {\n\t\t\tthrow new IntervalError(\"a not interval\", a);\n\t\t}\n\t}\n\tif (! b instanceof Interval) {\n\t\t// could be a number\n\t\tif (isNumber(b)) {\n\t\t\tb = new Interval(b);\n\t\t} else {\n\t\t\tthrow new IntervalError(\"b not interval\", b);\n\t\t}\n\t}\n\n\tlet cmp_1 = endpoint.cmp(a.endpointLow, b.endpointLow);\n\tlet cmp_2 = endpoint.cmp(a.endpointHigh, b.endpointHigh);\n\tlet key = cmp_1*10 + cmp_2;\n\n\tif (key == 11) {\n\t\t// OUTSIDE_LEFT or PARTIAL_LEFT\n\t\tif (endpoint.leftof(b.endpointHigh, a.endpointLow)) {\n\t\t\treturn Relation.OUTSIDE_RIGHT;\n\t\t} else {\n\t\t\treturn Relation.OVERLAP_RIGHT;\n\t\t}\n\t} else if ([-1, 9, 10].includes(key)) {\n\t\treturn Relation.COVERED;\n\t} else if ([1, -9, -10].includes(key)) {\n\t\treturn Relation.COVERS;\n\t} else if (key == 0) {\n\t\treturn Relation.EQUALS;\n\t} else {\n\t\t// key == -11\n\t\t// OUTSIDE_RIGHT, PARTIAL_RIGHT\n\t\tif (endpoint.rightof(b.endpointLow, a.endpointHigh)) {\n\t\t\treturn Relation.OUTSIDE_LEFT;\n\t\t} else {\n\t\t\treturn Relation.OVERLAP_LEFT;\n\t\t}\n\t}\n}\n\n/*********************************************************\nCOMPARE INTERVALS BY ENDPOINT\n**********************************************************\n\ncmp functions for sorting intervals (ascending) based on\nendpoint low or high\n\nuse with array.sort()\n\n**********************************************************/\n\nfunction _make_interval_cmp(low) {\n\treturn function cmp (a, b) {\n\t\tlet e1, e2;\n\t\tif (low) {\n\t\t\te1 = [a.low, false, a.lowInclude, a.singular];\n\t\t\te2 = [b.low, false, b.lowInclude, a.singular];\n\t\t} else {\n\t\t\te1 = [a.high, true, a.highInclude, a.singular];\n\t\t\te2 = [b.high, true, b.highInclude, a.singular];\n\t\t}\n\t\treturn endpoint.cmp(e1, e2);\n\t}\n}\n\n\n\n/**\n * Create interval from two endpoints\n */\n\nfunction fromEndpoints(endpointLow, endpointHigh) {\n\tlet [low, low_right, low_closed, low_singular] = endpointLow;\n\tlet [high, high_right, high_closed, high_singular] = endpointHigh;\n\tif (low_right) {\n\t\tthrow new IntervalError(\"illegal endpointLow - bracket must be left\");\n\t}\n\tif (!high_right) {\n\t\tthrow new IntervalError(\"illegal endpointHigh - bracket must be right\");\n\t}\n\treturn new Interval(low, high, low_closed, high_closed);\n};\n\n\n// intersect two intervals\nfunction intersect(a, b) {\n\tlet rel = compare(a, b);\n\tif (rel == Relation.OUTSIDE_LEFT) {\n\t\treturn [];\n\t} else if (rel == Relation.OVERLAP_LEFT) {\n\t\treturn [Interval.fromEndpoints(b.endpointLow, a.endpointHigh)];\n\t} else if (rel == Relation.COVERS) {\n\t\treturn [b];\n\t} else if (rel == Relation.EQUALS) {\n\t\treturn [a]; // or b\n\t} else if (rel == Relation.COVERED) {\n\t\treturn [a];\n\t} else if (rel == Relation.OVERLAP_RIGHT) {\n\t\treturn [Interval.fromEndpoints(a.endpointLow, b.endpointHigh)];\n\t} else if (rel == Relation.OUTSIDE_RIGHT) {\n\t\treturn [];\n\t}\n}\n\n// union of two intervals\nfunction union(a, b) {\n\tlet rel = compare(a, b);\n\tif (rel == Relation.OUTSIDE_LEFT) {\n\t\t// merge\n\t\t// [aLow,aHigh)[bLow, bHigh] or [aLow,aHigh](bLow, bHigh]\n\t\tif (a.high != b.low || (!a.highInclude && !b.lowInclude)) {\n\t\t\t// no merge\n\t\t\treturn [a, b];\n\t\t} else {\n\t\t\t// merge\n\t\t\treturn [Interval.fromEndpoints(a.endpointLow, b.endpointHigh)]; \n\t\t}\n\t} else if (rel == Relation.OVERLAP_LEFT) {\n\t\treturn [Interval.fromEndpoints(a.endpointLow, b.endpointHigh)];\n\t} else if (rel == Relation.COVERS) {\n\t\treturn [a];\n\t} else if (rel == Relation.EQUALS) {\n\t\treturn [a]; // or b\n\t} else if (rel == Relation.COVERED) {\n\t\treturn [b];\n\t} else if (rel == Relation.OVERLAP_RIGHT) {\n\t\treturn [Interval.fromEndpoints(b.endpointLow, a.endpointHigh)];\n\t} else if (rel == Relation.OUTSIDE_RIGHT) {\n\t\t// merge\n\t\t// [bLow,bHigh)[aLow, aHigh] or [bLow,bHigh](aLow, aHigh]\n\t\tif (b.high != a.low || (!b.highInclude && !a.lowInclude)) {\n\t\t\t// no merge\n\t\t\treturn [b, a];\n\t\t} else {\n\t\t\t// merge\n\t\t\treturn [Interval.fromEndpoints(b.endpointLow, a.endpointHigh)];\n\t\t}\n\t}\n}\n\n// intersection of multiple intervals\nfunction intersectAll(intervals) {\n\tintervals.sort(Interval.cmpLow);\n\tif (intervals.length <= 1) {\n\t\treturn intervals;\n\t}\n\tconst result = [intervals.shift()];\n\twhile (intervals.length > 0) {\n\t\tlet prev = result.pop();\n\t\tlet next = intervals.shift()\n\t\tresult.push(...Interval.intersect(prev, next));\n\t}\n\treturn result;\n}\n\n// union of multiple interval\nfunction unionAll(intervals) {\n\tintervals.sort(Interval.cmpLow);\n\tif (intervals.length <= 1) {\n\t\treturn intervals;\n\t}\n\tconst result = [intervals.shift()];\n\twhile (intervals.length > 0) {\n\t\tlet prev = result.pop();\n\t\tlet next = intervals.shift()\n\t\tresult.push(...Interval.union(prev, next));\n\t}\n\treturn result;\n}\n\n\n/*********************************************************\nINTERVAL CLASS\n**********************************************************/\n\nclass Interval {\n\n\n\t// private variables\n\n\t/*\n\t\tConstructor\n\t*/\n\tconstructor (low, high, lowInclude, highInclude) {\n\t\tvar lowIsNumber = isNumber(low);\n\t\t// new Interval(3.0) defines singular - low === high\n\t\tif (lowIsNumber && high === undefined) high = low;\n\t\tif (!isNumber(low)) throw new IntervalError(\"low not a number\");\n\t\tif (!isNumber(high)) throw new IntervalError(\"high not a number\");\n\t\tif (low > high) throw new IntervalError(\"low > high\");\n\t\tif (low === high) {\n\t\t\tlowInclude = true;\n\t\t\thighInclude = true;\n\t\t}\n\t\tif (low === -Infinity) lowInclude = true;\n\t\tif (high === Infinity) highInclude = true;\n\t\tif (lowInclude === undefined) lowInclude = true;\n\t\tif (highInclude === undefined) highInclude = false;\n\t\tif (typeof lowInclude !== \"boolean\") throw new IntervalError(\"lowInclude not boolean\");\n\t\tif (typeof highInclude !== \"boolean\") throw new IntervalError(\"highInclude not boolean\");\n\t\tthis._low = low;\n\t\tthis._high = high;\n\t\tthis._lowInclude = lowInclude;\n\t\tthis._highInclude = highInclude;\n\t\tthis._length = this._high - this._low;\n\t\tthis._singular = (this._low === this._high);\n\t\tthis._finite = (isFinite(this._low) && isFinite(this._high));\n\n\t\t/*\n\t\t\tAccessors for full endpoint representationo\n\t\t\t[value (number), right (bool), closed (bool)]\n\n\t\t\t- use with inside(endpoint, interval)\n\t\t*/\n\t\tthis._endpointLow = endpoint.create(this._low, false, this._lowInclude, this._singular);\n\t\tthis._endpointHigh = endpoint.create(this._high, true, this._highInclude, this._singular);\n\t}\n\n\t// accessors\n\tget low () {return this._low;}\n\tget high () {return this._high;}\n\tget lowInclude () {return this._lowInclude;}\n\tget highInclude () {return this._highInclude;}\n\tget length () {return this._length;}\n\tget singular () {return this._singular;}\n\tget finite () {return this._finite;}\n\tget endpointLow () {return this._endpointLow;}\n\tget endpointHigh () {return this._endpointHigh;}\n\t\n\t/**\n\t * Instance methods\n\t */\n\n\ttoString () {\n\t\tconst toString = endpoint.toString;\n\t\tif (this._singular) {\n\t\t\tlet p = this._endpointLow[0];\n\t\t\treturn `[${p}]`;\n\t\t} else {\n\t\t\tlet low = endpoint.toString(this._endpointLow);\n\t\t\tlet high = endpoint.toString(this._endpointHigh);\n\t\t\treturn `${low},${high}`;\n\t\t}\n\t};\n\n\n\tasArray() {\n\t\treturn [this._low, this._high, this._lowInclude, this._highInclude];\n\t}\n\n\tcovers_endpoint (p) {\n\t\tlet leftof = endpoint.leftof(p, this._endpointLow);\n\t\tlet rightof = endpoint.rightof(p, this._endpointHigh);\n\t\treturn !leftof && !rightof;\n\t}\n\n\tcompare (other) {\n\t\treturn compare(this, other);\n\t}\n\n\tequals (other) {\n\t\treturn compare(this, other) == Relation.EQUALS;\n\t}\n\n\t/*\n\t\tdefault mode - all except outside\n\t\t2+4+8+16+32 = 62\n\t*/\n\tmatch (other, mask=MATCH_COVERS) {\n\t\tlet relation = compare(this, other);\n\t\treturn Boolean(mask & relation);\n\t}\n}\n\n/*\n\tAdd static properties to Interval class.\n*/\n\nInterval.Relation = Relation;\nInterval.Match = Match;\nInterval.cmpLow = _make_interval_cmp(true);\nInterval.cmpHigh = _make_interval_cmp(false);\nInterval.fromEndpoints = fromEndpoints;\nInterval.intersect = intersect;\nInterval.union = union;\nInterval.intersectAll = intersectAll;\nInterval.unionAll = unionAll;\n\n\nexport default Interval;\n\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport endpoint from './endpoint.js';\nimport Interval from './interval.js';\n\n\n// sort func\nconst cmp = function (a, b) {return a - b;};\n\n/*******************************************************************\n BASIC\n*******************************************************************/\n\nexport function equalVectors(vector_a, vector_b) {\n let pos = vector_a.position == vector_b.position;\n let vel = vector_a.velocity == vector_b.velocity;\n let acc = vector_a.acceleration == vector_b.acceleration;\n let ts = vector_a.timestamp == vector_b.timestamp;\n return pos && vel && acc && ts;\n};\n\n\nexport function copyVector(vector) {\n return {\n position: vector.position,\n velocity: vector.velocity,\n acceleration: vector.acceleration,\n timestamp: vector.timestamp\n }\n};\n\n/*\n Calculate vector snapshot for motion defined by vector at time ts\n\n vector: [p0,v0,a0,t0]\n t0 and ts are absolute time from same clock, in seconds\n*/\n\nexport function calculateVector(vector, ts) {\n\tif (ts === undefined) {\n\t throw new Error (\"no ts provided for calculateVector\");\n\t}\n\tconst deltaSec = ts - vector.timestamp;\n\treturn {\n\t\tposition : vector.position + vector.velocity*deltaSec + 0.5*vector.acceleration*deltaSec*deltaSec,\n\t\tvelocity : vector.velocity + vector.acceleration*deltaSec,\n\t\tacceleration : vector.acceleration,\n\t\ttimestamp : ts\n\t};\n};\n\n\n/*\n Calculate direction of motion at time ts\n 1 : forwards, -1 : backwards: 0, no movement\n*/\nexport function calculateDirection(vector, ts) {\n /*\n Given initial vector calculate direction of motion at time t\n (Result is valid only if (t > vector[T]))\n Return Forwards:1, Backwards -1 or No-direction (i.e. no-motion) 0.\n If t is undefined - t is assumed to be now.\n */\n let freshVector;\n if (ts == undefined) {\n freshVector = vector;\n } else {\n freshVector = calculateVector(vector, ts);\n }\n // check velocity\n let direction = cmp(freshVector.velocity, 0.0);\n if (direction === 0) {\n // check acceleration\n direction = cmp(vector.acceleration, 0.0);\n }\n return direction;\n};\n\n\n/*\n isMoving\n\n returns true if motion is moving else false\n*/\nexport function isMoving(vector) {\n return (vector.velocity !== 0.0 || vector.acceleration !== 0.0);\n};\n\n\n/*******************************************************************\n RANGE\n*******************************************************************/\n\n//\tRANGE STATE is used for managing/detecting range violations.\nexport const RangeState = Object.freeze({\n INIT : \"init\",\n INSIDE: \"inside\",\n OUTSIDE_LOW: \"outsidelow\",\n OUTSIDE_HIGH: \"outsidehigh\"\n});\n\n/*\n\tA snapshot vector is checked with respect to range,\n\tcalclulates correct RangeState (i.e. INSIDE|OUTSIDE)\n*/\nexport function correctRangeState(vector, range) {\n const {position: p, velocity: v, acceleration: a} = vector;\n\tif (p > range[1]) return RangeState.OUTSIDE_HIGH;\n\tif (p < range[0]) return RangeState.OUTSIDE_LOW;\n\t// corner cases\n\tif (p === range[1]) {\n\t\tif (v > 0.0) return RangeState.OUTSIDE_HIGH;\n\t\tif (v === 0.0 && a > 0.0) return RangeState.OUTSIDE_HIGH;\n\t} else if (p === range[0]) {\n\t if (v < 0.0) return RangeState.OUTSIDE_LOW;\n\t if (v == 0.0 && a < 0.0) return RangeState.OUTSIDE_HIGH;\n\t}\n\treturn RangeState.INSIDE;\n};\n\n\n/* \n detect range violation\n vector assumed to be valid now\n*/\nexport function detectRangeViolation(now_vector, range) {\n return (correctRangeState(now_vector, range) != RangeState.INSIDE);\n}\n\n\n/*\n\tA snapshot vector is checked with respect to range.\n\tReturns vector corrected for range violations, or input vector unchanged.\n\n vector assumed to be valid now\n*/\nexport function checkRange(vector, range) {\n\tconst state = correctRangeState(vector, range);\n\tif (state !== RangeState.INSIDE) {\n\t\t// protect from range violation\n\t\tvector.velocity = 0.0;\n\t\tvector.acceleration = 0.0;\n\t\tif (state === RangeState.OUTSIDE_HIGH) {\n\t\t\tvector.position = range[1];\n\t\t} else vector.position = range[0];\n\t}\n\treturn vector;\n};\n\n\n/*\n Return tsEndpoint of (first) range intersect if any.\n*/\nexport function rangeIntersect(vector, range) {\n let t0 = vector.timestamp;\n // Time delta to hit rangeLeft\n let deltaLeft = calculateMinPositiveRealSolution(vector, range[0]);\n // Time delta to hit rangeRight\n let deltaRight = calculateMinPositiveRealSolution(vector, range[1]);\n // Pick the appropriate solution\n if (deltaLeft !== undefined && deltaRight !== undefined) {\n if (deltaLeft < deltaRight) {\n return [t0 + deltaLeft, range[0]];\n }\n else\n return [t0 + deltaRight, range[1]];\n }\n else if (deltaLeft !== undefined)\n return [t0 + deltaLeft, range[0]];\n else if (deltaRight !== undefined)\n return [t0 + deltaRight, range[1]];\n else return [undefined, undefined];\n}\n\n\n/*******************************************************************\n EQUATIONS\n*******************************************************************/\n\n/*\n hasRealSolution\n\n Given motion determined from p,v,a,t.\n Determine if equation p(t) = p + vt + 0.5at^2 = x\n has solutions for some real number t.\n*/\n\nfunction hasRealSolution (p,v,a,x) {\n\tif ((Math.pow(v,2) - 2*a*(p-x)) >= 0.0) return true;\n\telse return false;\n};\n\n\n/*\n calculateRealSolution\n\n Given motion determined from p,v,a,t.\n Determine if equation p(t) = p + vt + 0.5at^2 = x\n has solutions for some real number t.\n Calculate and return real solutions, in ascending order.\n*/\n\nfunction calculateRealSolutions(p,v,a,x) {\n\t// Constant Position\n\tif (a === 0.0 && v === 0.0) {\n\t if (p != x) return [];\n\t else return [0.0];\n\t}\n\t// Constant non-zero Velocity\n\tif (a === 0.0) return [(x-p)/v];\n\t// Constant Acceleration\n\tif (hasRealSolution(p,v,a,x) === false) return [];\n\t// Exactly one solution\n\tconst discriminant = v*v - 2*a*(p-x);\n\tif (discriminant === 0.0) {\n\t return [-v/a];\n\t}\n\tconst sqrt = Math.sqrt(Math.pow(v,2) - 2*a*(p-x));\n\tconst d1 = (-v + sqrt)/a;\n\tconst d2 = (-v - sqrt)/a;\n\treturn [Math.min(d1,d2),Math.max(d1,d2)];\n};\n\n\n/*\n calculatePositiveRealSolutions\n\n Given motion determined from p,v,a,t.\n Determine if equation p(t) = p + vt + 0.5at^2 = x\n has solutions for some real number t.\n Calculate and return positive real solutions, in ascending order.\n*/\n\nfunction calculatePositiveRealSolutions(p,v,a,x) {\n\tconst res = calculateRealSolutions(p,v,a,x);\n\tif (res.length === 0) return [];\n\telse if (res.length == 1) {\n\t if (res[0] > 0.0) {\n\t\t\treturn [res[0]];\n\t }\n\t else return [];\n\t}\n\telse if (res.length == 2) {\n\t if (res[1] < 0.0) return [];\n\t if (res[0] > 0.0) return [res[0], res[1]];\n\t if (res[1] > 0.0) return [res[1]];\n\t return [];\n\t}\n\telse return [];\n};\n\n\n/*\n calculateMinPositiveRealSolution\n\n Given motion determined from p,v,a,t.\n Determine if equation p(t) = p + vt + 0.5at^2 = x\n has solutions for some real number t.\n Calculate and return the least positive real solution.\n*/\nfunction calculateMinPositiveRealSolution(vector, x) {\n const {position: p, velocity: v, acceleration: a} = vector;\n\tconst res = calculatePositiveRealSolutions(p,v,a,x);\n\tif (res.length === 0) {\n return;\n }\n\telse return res[0];\n};\n\n\n/*\n calculateDelta\n\n\n Given motion determined from p0,v0,a0 (initial conditions or snapshot),\n Supply two posisions, posBefore < p0 < posAfter.\n Calculate which of these positions will be reached first,\n if any, by the movement described by the vector.\n In addition, calculate when this position will be reached.\n Result will be expressed as time delta relative to t0, if solution exists,\n and a flag to indicate Before (false) or After (true)\n Note: t1 == (delta + t0) is only guaranteed to be in the\n future as long as the function\n is evaluated at time t0 or immediately after.\n*/\nexport function calculateDelta(vector, range) {\n\t// Time delta to hit posBefore\n\tlet deltaBeforeSec = calculateMinPositiveRealSolution(vector, range[0]);\n\t// Time delta to hit posAfter\n\tlet deltaAfterSec = calculateMinPositiveRealSolution(vector, range[1]);\n // Infinity is no good solution\n if (deltaBeforeSec == Infinity) {\n deltaBeforeSec = undefined;\n }\n if (deltaAfterSec == Infinity) {\n deltaAfterSec = undefined;\n }\n // Pick the appropriate solution\n\tif (deltaBeforeSec !== undefined && deltaAfterSec !== undefined) {\n\t if (deltaBeforeSec < deltaAfterSec)\n\t\t\treturn [deltaBeforeSec, range[0]];\n\t else\n\t\t\treturn [deltaAfterSec, range[1]];\n\t}\n\telse if (deltaBeforeSec !== undefined)\n\t return [deltaBeforeSec, range[0]];\n\telse if (deltaAfterSec !== undefined)\n\t return [deltaAfterSec, range[1]];\n\telse return [undefined, undefined];\n};\n\n\n/*******************************************************************\n TIME_INTERVAL POS_INTERVAL\n*******************************************************************/\n\n/*\n posInterval_from_timeInterval\n\n given\n - a time interval\n - a vector describing motion within the time interval\n figure out the smallest interval (of positions)\n that covers all possible positions during the time interval\n*/\n\nexport function posInterval_from_timeInterval (timeInterval, vector) {\n\n /*\n no motion or singular time interval\n */\n if (!isMoving(vector) || timeInterval.singular) {\n return new Interval(vector.position);\n }\n\n let t0 = timeInterval.low;\n let t1 = timeInterval.high;\n let t0_closed = timeInterval.lowInclude;\n let t1_closed = timeInterval.highInclude;\n\n let vector0 = calculateVector(vector, t0);\n let p0 = vector0.position;\n let v0 = vector0.velocity;\n let a0 = vector0.acceleration;\n let p1 = calculateVector(vector, t1).position;\n\n if (a0 != 0) {\n\n /*\n motion, with acceleration\n\n position over time is a parabola\n figure out if extrema happens to occor within\n timeInterval. If it does, extreme point is endpoint in\n position Interval. p0 or p1 will be the other\n interval endpoint.\n\n I extreme point is not occuring within timeInterval,\n interval endpoint will be p0 and p1.\n\n general parabola\n y = Ax*x + Bx + C\n extrema (x,y) : x = - B/2A, y = -B*B/4A + C\n\n where t0 <= t <= t1\n p(t) = 0.5*a0*(t-t0)*(t-t0) + v0*(t-t0) + p0,\n\n A = a0/2, B = v0, C = p0\n\n extrema (t_extrema, p_extrema):\n t_extrem = -v0/a0 + t0\n p_extrem = -v0*v0/(2*a0) + p0\n\n */\n let t_extrem = -v0/a0 + t0;\n if (timeInterval.covers_endpoint(t_extrem)) {\n let p_extrem = -v0*v0/(2.0*a0) + p0;\n // maximal point reached in time interval\n if (a0 > 0.0) {\n // p_extrem is minimum\n // figure out if p0 or p1 is maximum\n if (p0 < p1) {\n return new Interval(p_extrem, p1, true, t1_closed);\n } else {\n return new Interval(p_extrem, p0, true, t0_closed);\n }\n } else {\n // p_extrem is maximum\n // figure out if p0 or p1 is minimum\n if (p0 < p1) {\n return new Interval(p0, p_extrem, t0_closed, true);\n } else {\n return new Interval(p1, p_extrem, t1_closed, true);\n }\n }\n }\n }\n\n /*\n Motion, with or without acceleration,\n yet with no extreme points within interval\n\n positition monotonic increasing (forward velocity)\n or decreasing (backward velocity)\n\n extrem positions are associated with p0 and p1.\n */\n\n if (p0 < p1) {\n // forward\n return new Interval(p0, p1, t0_closed, t1_closed);\n } else {\n // backward\n return new Interval(p1, p0, t1_closed, t0_closed);\n }\n}\n\n\n/*\n time endpoint and pos endpoints.\n\n time is always increasing even when position\n is decreasing. When making a timeEndpoint from\n a posEndpoin the right/left aspect of the endpoint\n needs to be flipped.\n\n ts - the value of the timeEndpoint, ie. the time when\n motion will pass over posEndpoing\n direction - direction of motion at time ts\n*/\n\nexport function timeEndpoint_from_posEndpoint(posEndpoint, ts, direction) {\n let [pos, right, close, singular] = posEndpoint;\n // flip right/left if direction is backwards\n if (direction < 0 && right !== undefined) {\n right = !right\n }\n return [ts, right, close, singular];\n}\n\n\n/*******************************************************************\n ENDPOINT EVENTS\n*******************************************************************/\n\n/*\n endpointEvents\n\n Given a motion and a set of endpoing, calculate when\n the motion will pass by each endpoing.\n\n Given\n - timeInterval\n - posInterval\n - vector describing motion within timeInterval\n - list of endpointItems\n\n endpointItem\n {\n endpoint: [value, high, closed, singular],\n cue: {\n key: \"mykey\",\n interval: new Interval(...),\n data: {...}\n }\n }\n\n Creates eventItem by adding to endpointItem\n - tsEndpoint : timestamp endpoint (future) when motion will pass the endpoint\n - direction: true if motion passes endpoint while moving forward\n\n EventItems will be sorted by ts\n\n Issue:\n\n timeInterval [t0, t1)\n posinterval [p0, p1)\n\n Consider event at time t1 concerning endpoint p1)\n This will be outside the timeInterval, but inside\n the posInterval.\n\n Conversely, it will be inside the next timeInterval,\n but not the next posInterval.\n\n This is a problem - like falling between chairs.\n\n Resolve this by representing timestamps as endpoints too\n\n*/\n\nexport function endpointEvents (timeInterval, posInterval, vector, endpointItems) {\n\n /*\n no motion or singular time interval\n */\n if (timeInterval.singular) {\n throw new Error(\"getEventItems: timeInterval is singular\");\n }\n if (!isMoving(vector)) {\n throw new Error(\"getEventItems: no motion\")\n }\n\n let p0 = vector.position;\n let v0 = vector.velocity;\n let a0 = vector.acceleration;\n let t0 = vector.timestamp;\n\n let value, ts, deltas;\n let tsEndpoint, direction;\n let eventItems = [];\n\n endpointItems.forEach(function(item) {\n // check that endpoint is inside given posInterval\n if (!posInterval.covers_endpoint(item.endpoint)) {\n return;\n }\n value = item.endpoint[0];\n // check if equation has any solutions\n if (!hasRealSolution(p0, v0, a0, value)) {\n return;\n }\n // find time when motion will pass value\n // time delta is relative to t0\n // could be both in history or future\n deltas = calculateRealSolutions(p0,v0,a0, value);\n // include any timestamp within the timeinterval\n deltas.forEach(function(delta) {\n ts = t0 + delta;\n direction = calculateDirection(vector, ts);\n tsEndpoint = timeEndpoint_from_posEndpoint(item.endpoint, ts, direction);\n if (timeInterval.covers_endpoint(tsEndpoint)){\n item.tsEndpoint = tsEndpoint;\n item.direction = direction;\n eventItems.push(item);\n }\n });\n });\n\n // sort eventItems according to tsEndpoints\n const cmp = function (a,b) {\n return endpoint.cmp(a.tsEndpoint, b.tsEndpoint);\n };\n eventItems.sort(cmp);\n return eventItems;\n};\n\n\n/*******************************************************************\n MOTION TRANSITION\n*******************************************************************/\n\n/*\n Figure the nature of the transition from one motion to another,\n i.e. when old_vector is replaced by new_vector.\n\n The time when this transition occured is given bey\n new_vector.timestamp, by definition.\n\n - was moving (boolean) - true if moving before change\n - is moving (boolean) - true if moving after change\n - pos changed (boolean) - true if position was changed instantaneously\n - move changed (boolean) - true if movement was changed instantaneously\n\n report changed in two independent aspects\n - change in position (i.e. discontinuity in position)\n - change in movement (i.e. starting, stopping, changed)\n\n These are represented as\n - PosDelta\n - MoveDelta\n\n return [PosDelta, MoveDelta]\n*/\n\n\n/* Static properties */\n\nconst PosDelta = Object.freeze({\n NOOP: 0, // no change in position\n CHANGE: 1 // change in position\n});\n\n\nconst MoveDelta = Object.freeze({\n NOOP: 0, // no change in movement, not moving\n NOOP_MOVING: 1, // no change in movement, moving\n START: 2, // not moving -> moving\n CHANGE: 3, // keep moving, movement changed\n STOP: 4 // moving -> not moving\n});\n\n\nexport class MotionDelta {\n\n constructor (old_vector, new_vector) {\n let ts = new_vector.timestamp;\n let is_moving = isMoving(new_vector)\n let init = (old_vector == undefined || old_vector.position == undefined);\n\n if (init) {\n /*\n Possible to introduce\n PosDelta.INIT here instead of PosDelta.CHANGE\n Not sure if this is needed.\n */\n if (is_moving) {\n this._mc = [PosDelta.CHANGE, MoveDelta.START];\n } else {\n this._mc = [PosDelta.CHANGE, MoveDelta.NOOP];\n }\n } else {\n let was_moving = isMoving(old_vector);\n let end_vector = calculateVector(old_vector, ts);\n let start_vector = calculateVector(new_vector, ts);\n\n // position change\n let pos_changed = (end_vector.position != start_vector.position);\n let pct = (pos_changed) ? PosDelta.CHANGE : PosDelta.NOOP;\n\n // movement change\n let mct;\n if (was_moving && is_moving) {\n let vel_changed = (end_vector.velocity != start_vector.velocity);\n let acc_changed = (end_vector.acceleration != start_vector.acceleration);\n let move_changed = (vel_changed || acc_changed);\n if (move_changed) {\n mct = MoveDelta.CHANGE;\n } else {\n mct = MoveDelta.NOOP_MOVING;\n }\n } else if (!was_moving && is_moving) {\n mct = MoveDelta.START;\n } else if (was_moving && !is_moving) {\n mct = MoveDelta.STOP;\n } else if (!was_moving && !is_moving) {\n mct = MoveDelta.NOOP;\n }\n this._mc = [pct, mct];\n }\n }\n\n get posDelta () {\n return this._mc[0];\n }\n\n get moveDelta () {\n return this._mc[1]\n }\n\n toString() {\n const PosDelta = MotionDelta.PosDelta;\n const MoveDelta = MotionDelta.MoveDelta;\n let str = (this.posDelta == PosDelta.CHANGE) ? \"jump, \" : \"\";\n if (this.moveDelta == MoveDelta.START) {\n str += \"movement started\";\n } else if (this.moveDelta == MoveDelta.CHANGE) {\n str += \"movement changed\";\n } else if (this.moveDelta == MoveDelta.STOP) {\n str += \"movement stopped\";\n } else if (this.moveDelta == MoveDelta.NOOP_MOVING) {\n str += \"movement noop - moving\";\n } else if (this.moveDelta == MoveDelta.NOOP) {\n str += \"movement noop - not moving\";\n }\n return str;\n }\n}\n\n\nMotionDelta.PosDelta = PosDelta;\nMotionDelta.MoveDelta = MoveDelta;\n\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport Interval from './interval.js';\n\n// check if n is a number\nfunction is_number(n) {\n\tvar N = parseFloat(n);\n return (n==N && !isNaN(N));\n};\n\n\n/*\n utility function for protecting against duplicates\n*/\nfunction unique(A) {\n return [...new Set(A)];\n};\n\n\n\n/*\n batch inserts and removes have two strategies\n 1) change-sort\n 2) splice\n\n simple rule by measurement\n splice is better for batchlength <= 100 for both insert and remove\n*/\nfunction resolve_approach(arrayLength, batchLength) {\n if (arrayLength == 0) {\n return \"sort\";\n }\n return (batchLength <= 100) ? \"splice\" : \"sort\";\n};\n\n\nclass BinarySearchError extends Error {\n\n constructor(message) {\n super(message);\n this.name = \"BinarySearchError\";\n }\n\n}\n\n\n/*\n\nBINARY SEARCH\n\n- based on sorted list of unique elements\n- implements protection against duplicates\n\n\nPublic API\n- update (remove_elements, insert_elements)\n- lookup (interval) - returns list for all elements\n- remove (interval) - removes elements within interval\n- has (element) - returns true if element exists with value == element, else false\n- get (element) - returns element with value if exists, else undefined\n- values () - returns iterable for all elements\n- indexOf(element) - returns index of element\n- indexOfElements(elements)\n- getByIndex(index) - returns element at given index\n\n\n*/\n\nfunction cmp(a, b) {return a-b;};\n\n\nclass BinarySearch {\n\n constructor(options) {\n this.array = [];\n this.options = options || {};\n }\n\n\n /**\n * Binary search on sorted array\n * @param {*} searchElement The item to search for within the array.\n * @return {Number} The index of the element which defaults to -1 when not found.\n */\n binaryIndexOf(searchElement) {\n let minIndex = 0;\n let maxIndex = this.array.length - 1;\n let currentIndex;\n let currentElement;\n while (minIndex <= maxIndex) {\n \t\tcurrentIndex = (minIndex + maxIndex) / 2 | 0;\n \t\tcurrentElement = this.array[currentIndex];\n if (currentElement < searchElement) {\n minIndex = currentIndex + 1;\n } else if (currentElement > searchElement) {\n maxIndex = currentIndex - 1;\n } else {\n // found\n \t\t return currentIndex;\n \t\t}\n }\n // not found - indicate at what index the element should be inserted\n \treturn ~maxIndex;\n\n // NOTE : ambiguity\n\n /*\n search for an element that is less than array[0]\n should return a negative value indicating that the element\n was not found. Furthermore, as it escapes the while loop\n the returned value should indicate the index that this element\n would have had - had it been there - as is the idea of this bitwise\n operator trick\n\n so, it follows that search for value of minimum element returns 0 if it exists, and 0 if it does not exists\n this ambiguity is compensated for in relevant methods\n */\n };\n\n\n /*\n utility function for resolving ambiguity\n */\n isFound(index, x) {\n if (index > 0) {\n return true;\n }\n if (index == 0 && this.array.length > 0 && this.array[0] == x) {\n return true;\n }\n return false;\n };\n\n /*\n returns index of value or -1\n */\n indexOf(x) {\n var index = this.binaryIndexOf(x);\n return (this.isFound(index, x)) ? index : -1;\n };\n\n indexOfElements(elements) {\n let x, index;\n let indexes = [];\n for (let i=0; i -1) {\n indexes.push(index);\n }\n }\n return indexes;\n };\n\n /*\n element exists with value\n */\n has(x) {\n return (this.indexOf(x) > -1) ? true : false;\n };\n\n get(index) {\n return this.array[index];\n };\n\n\n\n /*\n REMOVE\n Removes all elements with given values\n search for each one and splice remove them individually\n (reverse order)\n\n INSERT\n binarysearch and splice\n insert - binarysearch and splice\n\n WARNING - there should be no need to insert elements that are already\n present in the array. This function drops such duplicates\n */\n _update_splice(to_remove, to_insert, options) {\n\n // REMOVE\n if (this.array.length > 0) {\n let indexes = this.indexOfElements(to_remove);\n /*\n sort indexes to make sure we are removing elements\n in backwards order\n optimization\n - if elements were sorted in the first place this should not be necessary\n */\n indexes.sort(function(a,b){return a-b;});\n for (let i=indexes.length-1; i > -1; i--) {\n this.array.splice(indexes[i], 1);\n }\n }\n\n // INSERT\n let x, index;\n let len = to_insert.length;\n for (let i=0; i 0 && to_remove.length > 0) {\n // visit all elements and set their value to undefined\n // undefined values will be sorted to the end of the array\n let indexes = this.indexOfElements(to_remove);\n for (let i=0; i 0) {\n let index = this.array.indexOf(undefined);\n if (index > -1) {\n this.array.splice(index, this.array.length-index);\n }\n }\n // remove duplicates\n this.array = unique(this.array);\n };\n\n\n /*\n Update - removing and inserting elements in one operation\n\n a single element should only be present once in the list, thus avoiding\n multiple operations to one element. This is presumed solved externally.\n - also objects must not be members of both lists.\n\n - internally selects the best method - searchsplice or concatsort\n - selection based on relative sizes of existing elements and new elements\n\n */\n update(to_remove, to_insert, options) {\n let size = to_remove.length + to_insert.length;\n if (size == 0) {\n return;\n }\n\n // regular case\n let approach = resolve_approach(this.array.length, size);\n if (approach == \"splice\") {\n this._update_splice(to_remove, to_insert, options);\n } else if (approach == \"sort\"){\n this._update_sort(to_remove, to_insert, options);\n }\n };\n\n\n /*\n Accessors\n */\n\n getMinimum() {\n return (this.array.length > 0) ? this.array[0] : undefined;\n };\n\n getMaximum = function () {\n return (this.array.length > 0) ? this.array[this.array.length - 1] : undefined;\n };\n\n\n /*\n Internal search functions\n */\n\n /*\n Find index of largest value less than x\n Returns -1 if noe values exist that are less than x\n */\n ltIndexOf(x) {\n var i = this.binaryIndexOf(x);\n if (this.isFound(i, x)) {\n /*\n found - x is found on index i\n consider element to the left\n if we are at the left end of the array nothing is found\n return -1\n */\n if (i > 0) {\n return i-1;\n } else {\n return -1;\n }\n } else {\n /*\n not found - Math.abs(i) is index where x should be inserted\n => Math.abs(i) - 1 is the largest value less than x\n */\n return Math.abs(i)-1;\n }\n };\n\n /*\n Find index of rightmost value less than x or equal to x\n Returns -1 if noe values exist that are less than x or equal to x\n */\n leIndexOf(x) {\n var i = this.binaryIndexOf(x);\n if (this.isFound(i, x)) {\n /*\n element found\n */\n return i;\n } else {\n // not found - consider element to the left\n i = Math.abs(i) - 1;\n return (i >= 0) ? i : -1;\n }\n };\n\n /*\n \tFind index of leftmost value greater than x\n \tReturns -1 if no values exist that are greater than x\n */\n\n gtIndexOf(x) {\n var i = this.binaryIndexOf(x);\n if (this.isFound(i, x)) {\n /*\n found - x is found on index i\n if there are no elements to the right return -1\n */\n if (i < this.array.length -1) {\n return i+1;\n } else {\n return -1;\n }\n } else {\n /*\n not found - Math.abs(i) is index where x should be inserted\n => Math.abs(i) is the smallest value greater than x\n unless we hit the end of the array, in which cas no smalles value\n exist which is greater than x\n */\n let idx = Math.abs(i);\n return (idx < this.array.length) ? idx : -1;\n }\n };\n\n\n /*\n Find index of leftmost value which is greater than x or equal to x\n Returns -1 if noe values exist that are greater than x or equal to x\n */\n\n geIndexOf(x) {\n var i = this.binaryIndexOf(x);\n if (this.isFound(i, x)) {\n /*\n found element\n */\n return i;\n } else {\n // not found - consider the element where x would be inserted\n i = Math.abs(i);\n return (i -1) {\n return [index, index + 1];\n } else {\n return [undefined, undefined];\n }\n }\n\n // regular non-singular interval\n var start_index = -1, end_index = -1;\n if (interval.lowInclude) {\n start_index = this.geIndexOf(interval.low);\n } else {\n start_index = this.gtIndexOf(interval.low);\n }\n if (start_index === -1) {\n return [undefined, undefined];\n }\n if (interval.highInclude) {\n end_index = this.leIndexOf(interval.high);\n } else {\n end_index = this.ltIndexOf(interval.high);\n }\n if (end_index === -1) { // not reachable - I think\n return [undefined, undefined];\n }\n return [start_index, end_index + 1];\n };\n\n\n /*\n lookup by interval\n */\n lookup(interval) {\n let [start, end] = this.lookupIndexes(interval);\n return (start != undefined) ? this.array.slice(start, end) : [];\n };\n\n /*\n remove by interval\n */\n remove(interval) {\n let [start, end] = this.lookupIndexes(interval);\n return (start != undefined) ? this.array.splice(start, end-start) : [];\n };\n\n\n slice(start, end) {\n return this.array.slice(start, end);\n };\n\n splice(start, length) {\n return this.array.splice(start, length);\n };\n\n\n\n /*\n method for removing multiple closely placed elements in place\n - removeList is sorted\n - changes only affect the part of the index between first and last element\n - move remaining elements to the left, remove elements with a single splice\n - efficent if removelist references elements that are close to eachother\n */\n\n removeInSlice(removeList) {\n if (removeList.length == 0){\n return;\n }\n const low = removeList[0];\n const high = removeList[removeList.length-1];\n let [start, end] = this.lookupIndexes(new Interval(low, high, true, true));\n\n let rd_ptr = start;\n let wr_ptr = start;\n let rm_ptr = 0;\n\n while (rd_ptr < end) {\n let rd_elem = this.array[rd_ptr];\n let rm_elem = removeList[rm_ptr];\n if (rd_elem < rm_elem) {\n this.array[wr_ptr] = this.array[rd_ptr];\n wr_ptr++;\n rd_ptr++;\n } else if (rd_elem == rm_elem) {\n rd_ptr++;\n rm_ptr++;\n } else {\n // rd_elem > rm_elem\n rm_ptr++;\n }\n if (rm_ptr == removeList.length) {\n break\n }\n }\n this.array.splice(wr_ptr, rd_ptr-wr_ptr);\n };\n\n\n values() {\n return this.array.values();\n };\n\n clear() {\n this.array = [];\n };\n\n get length () {\n return this.array.length;\n }\n\n}\n\nexport default BinarySearch;\n\n\n\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\n\n/*\n\tEvent\n\t- name: event name\n\t- publisher: the object which defined the event\n\t- init: true if the event suppports init events\n\t- subscriptions: subscriptins to this event\n\n*/\n\nclass Event {\n\n\tconstructor (publisher, name, options) {\n\t\toptions = options || {}\n\t\tthis.publisher = publisher;\n\t\tthis.name = name;\n\t\tthis.init = (options.init === undefined) ? false : options.init;\n\t\tthis.subscriptions = [];\n\t}\n\n\t/*\n\t\tsubscribe to event\n\t\t- subscriber: subscribing object\n\t\t- callback: callback function to invoke\n\t\t- options:\n\t\t\tinit: if true subscriber wants init events\n\t*/\n\tsubscribe (callback, options) {\n\t\tif (!callback || typeof callback !== \"function\") {\n\t\t\tthrow new Error(\"Callback not a function\", callback);\n\t\t}\n\t\tconst sub = new Subscription(this, callback, options);\n\t\tthis.subscriptions.push(sub);\n\t // Initiate init callback for this subscription\n\t if (this.init && sub.init) {\n\t \tsub.init_pending = true;\n\t \tlet self = this;\n\t \tPromise.resolve().then(function () {\n\t \t\tconst eArgs = self.publisher.eventifyInitEventArgs(self.name) || [];\n\t \t\tfor (let eArg of eArgs) {\n\t \t\t\tself.trigger(eArg, [sub], true);\n\t \t\t}\n\t \t\tsub.init_pending = false;\n\t \t});\n\t }\n\t\treturn sub\n\t}\n\n\t/*\n\t\ttrigger event\n\n\t\t- if sub is undefined - publish to all subscriptions\n\t\t- if sub is defined - publish only to given subscription\n\t*/\n\ttrigger (eArg, subs, init) {\n\t\tlet eInfo, ctx;\n\t\tfor (const sub of subs) {\n\t\t\t// ignore terminated subscriptions\n\t\t\tif (sub.terminated) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\teInfo = {\n\t\t\t\tsrc: this.publisher,\n\t\t\t\tname: this.name,\n\t\t\t\tsub: sub,\n\t\t\t\tinit: init\n\t\t\t}\n\t\t\tctx = sub.ctx || this.publisher;\n\t\t\ttry {\n\t\t\t\tsub.callback.call(ctx, eArg, eInfo);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.log(`Error in ${this.name}: ${sub.callback} ${err}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\tunsubscribe from event\n\t- use subscription returned by previous subscribe\n\t*/\n\tunsubscribe(sub) {\n\t\tlet idx = this.subscriptions.indexOf(sub);\n\t\tif (idx > -1) {\n\t\t\tthis.subscriptions.splice(idx, 1);\n\t\t\tsub.terminate();\n\t\t}\n\t}\n}\n\n\n/*\n\tSubscription class\n*/\n\nclass Subscription {\n\n\tconstructor(event, callback, options) {\n\t\toptions = options || {}\n\t\tthis.event = event;\n\t\tthis.name = event.name;\n\t\tthis.callback = callback\n\t\tthis.init = (options.init === undefined) ? this.event.init : options.init;\n\t\tthis.init_pending = false;\n\t\tthis.terminated = false;\n\t\tthis.ctx = options.ctx;\n\t}\n\n\tterminate() {\n\t\tthis.terminated = true;\n\t\tthis.callback = undefined;\n\t\tthis.event.unsubscribe(this);\n\t}\n}\n\n\n/*\n\n\tEVENTIFY INSTANCE\n\n\tEventify brings eventing capabilities to any object.\n\n\tIn particular, eventify supports the initial-event pattern.\n\tOpt-in for initial events per event type.\n\n\teventifyInitEventArgs(name) {\n\t\tif (name == \"change\") {\n\t\t\treturn [this._value];\n\t\t}\n\t}\n\n*/\n\nexport function eventifyInstance (object) {\n\tobject.__eventify_eventMap = new Map();\n\tobject.__eventify_buffer = [];\n\treturn object;\n};\n\n\n/*\n\tEVENTIFY PROTOTYPE\n\n\tAdd eventify functionality to prototype object\n*/\n\nexport function eventifyPrototype(_prototype) {\n\n\tfunction eventifyGetEvent(object, name) {\n\t\tconst event = object.__eventify_eventMap.get(name);\n\t\tif (event == undefined) {\n\t\t\tthrow new Error(\"Event undefined\", name);\n\t\t}\n\t\treturn event;\n\t}\n\n\t/*\n\t\tDEFINE EVENT\n\t\t- used only by event source\n\t\t- name: name of event\n\t\t- options: {init:true} specifies init-event semantics for event\n\t*/\n\tfunction eventifyDefine(name, options) {\n\t\t// check that event does not already exist\n\t\tif (this.__eventify_eventMap.has(name)) {\n\t\t\tthrow new Error(\"Event already defined\", name);\n\t\t}\n\t\tthis.__eventify_eventMap.set(name, new Event(this, name, options));\n\t};\n\n\t/*\n\t\tON\n\t\t- used by subscriber\n\t\tregister callback on event.\n\t*/\n\tfunction on(name, callback, options) {\n\t\treturn eventifyGetEvent(this, name).subscribe(callback, options);\n\t};\n\n\t/*\n\t\tOFF\n\t\t- used by subscriber\n\t\tUn-register a handler from a specfic event type\n\t*/\n\tfunction off(sub) {\n\t\treturn eventifyGetEvent(this, sub.name).unsubscribe(sub);\n\t};\n\n\n\tfunction eventifySubscriptions(name) {\n\t\treturn eventifyGetEvent(this, name).subscriptions;\n\t}\n\n\n\n\t/*\n\t\tTrigger list of eventItems on object\n\n\t\teventItem: {name:.., eArg:..}\n\n\t\tcopy all eventItems into buffer.\n\t\trequest emptying the buffer, i.e. actually triggering events,\n\t\tevery time the buffer goes from empty to non-empty\n\t*/\n\tfunction eventifyTriggerAll(eventItems) {\n\t\tif (eventItems.length == 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// make trigger items\n\t\t// resolve non-pending subscriptions now\n\t\t// else subscriptions may change from pending to non-pending\n\t\t// between here and actual triggering\n\t\t// make list of [ev, eArg, subs] tuples\n\t\tlet triggerItems = eventItems.map((item) => {\n\t\t\tlet {name, eArg} = item;\n\t\t\tlet ev = eventifyGetEvent(this, name);\n\t\t\tlet subs = ev.subscriptions.filter(sub => sub.init_pending == false);\n\t\t\treturn [ev, eArg, subs];\n\t\t}, this);\n\n\t\t// append trigger Items to buffer\n\t\tconst len = triggerItems.length;\n\t\tconst buf = this.__eventify_buffer;\n\t\tconst buf_len = this.__eventify_buffer.length;\n\t\t// reserve memory - set new length\n\t\tthis.__eventify_buffer.length = buf_len + len;\n\t\t// copy triggerItems to buffer\n\t\tfor (let i=0; i {\n\t\t\treturn {name, eArg};\n\t\t}));\n\t}\n\n\t/*\n\t\tTrigger single event\n\t*/\n\tfunction eventifyTrigger(name, eArg) {\n\t\treturn this.eventifyTriggerAll([{name, eArg}]);\n\t}\n\n\t_prototype.eventifyDefine = eventifyDefine;\n\t_prototype.eventifyTrigger = eventifyTrigger;\n\t_prototype.eventifyTriggerAlike = eventifyTriggerAlike;\n\t_prototype.eventifyTriggerAll = eventifyTriggerAll;\n\t_prototype.eventifySubscriptions = eventifySubscriptions;\n\t_prototype.on = on;\n\t_prototype.off = off;\n};\n\n\n/*\n\tEvent Variable\n\n\tObjects with a single \"change\" event\n*/\n\nexport class EventVariable {\n\n\tconstructor (value) {\n\t\teventifyInstance(this);\n\t\tthis._value = value;\n\t\tthis.eventifyDefine(\"change\", {init:true});\n\t}\n\n\teventifyInitEventArgs(name) {\n\t\tif (name == \"change\") {\n\t\t\treturn [this._value];\n\t\t}\n\t}\n\n\tget value () {return this._value};\n\tset value (value) {\n\t\tif (value != this._value) {\n\t\t\tthis._value = value;\n\t\t\tthis.eventifyTrigger(\"change\", value);\n\t\t}\n\t}\n}\neventifyPrototype(EventVariable.prototype);\n\n/*\n\tEvent Boolean\n\n\n\tNote : implementation uses falsiness of input parameter to constructor and set() operation,\n\tso eventBoolean(-1) will actually set it to true because\n\t(-1) ? true : false -> true !\n*/\n\nexport class EventBoolean extends EventVariable {\n\tconstructor(value) {\n\t\tsuper(Boolean(value));\n\t}\n\n\tset value (value) {\n\t\tsuper.value = Boolean(value);\n\t}\n\tget value () {return super.value};\n}\n\n\n/*\n\tmake a promise which is resolved when EventBoolean changes\n\tvalue.\n*/\nexport function makePromise(eventObject, conditionFunc) {\n\tconditionFunc = conditionFunc || function(val) {return val == true};\n\treturn new Promise (function (resolve, reject) {\n\t\tlet sub = eventObject.on(\"change\", function (value) {\n\t\t\tif (conditionFunc(value)) {\n\t\t\t\tresolve(value);\n\t\t\t\teventObject.off(sub);\n\t\t\t}\n\t\t});\n\t});\n};\n\n// module api\nexport default {\n\teventifyPrototype,\n\teventifyInstance,\n\tEventVariable,\n\tEventBoolean,\n\tmakePromise\n};\n\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport eventify from './eventify.js';\n\n/*******************************************************************\n BASE OBSERVABLE MAP\n*******************************************************************/\n\n/*\n This is a base class for observable map\n*/\n\nclass ObservableMap {\n\n constructor (options={}) {\n \n this.options = options;\n\n // Events\n eventify.eventifyInstance(this);\n this.eventifyDefine(\"batch\", {init:true});\n this.eventifyDefine(\"change\", {init:true});\n this.eventifyDefine(\"remove\", {init:false});\n }\n\n /**\n * Abstract accessor to datasource backing implementation\n * of observable map. Typically this is an instance of Map() class.\n * \n * Must be implemented by subclass. \n */\n\n get datasource () {\n throw new Error(\"not implemented\");\n }\n\n /***************************************************************\n ORDERING\n ***************************************************************/\n\n sortOrder(options={}) {\n // sort options override constructor options\n let {order=this.options.order} = options;\n if (typeof order == \"function\") {\n return order;\n } \n }\n\n /* \n Sort values of Observable map\n ordering can be overidden by specifying option \n fallback to order from constructor\n noop if no ordering is defined\n */\n sortValues(iter, options={}) {\n let order = this.sortOrder(options);\n if (typeof order == \"function\") {\n // sort\n // if iterable not array - convert into array ahead of sorting\n let arr = (Array.isArray(iter)) ? iter : [...iter];\n return arr.sort(order);\n } else {\n // noop\n return iter;\n }\n }\n\n /* \n Sort items (in-place) by value {new:value, old:value} using\n ordering function for values\n */\n sortItems(items) {\n let order = this.sortOrder(); \n if (typeof order == \"function\") {\n items.sort(function(item_a, item_b) {\n let cue_a = (item_a.new) ? item_a.new : item_a.old;\n let cue_b = (item_b.new) ? item_b.new : item_b.old;\n return order(cue_a, cue_b);\n });\n }\n }\n\n /***************************************************************\n EVENTS\n ***************************************************************/\n\n /*\n Eventify: immediate events\n */\n eventifyInitEventArgs(name) {\n if (name == \"batch\" || name == \"change\") {\n let items = [...this.datasource.entries()].map(([key, val]) => {\n return {key:key, new:val, old:undefined};\n });\n // sort init items (if order defined)\n this.sortItems(items);\n return (name == \"batch\") ? [items] : items;\n }\n }\n\n /*\n Event Notification\n */\n _notifyEvents(items) {\n // event notification\n if (items.length == 0) {\n return;\n }\n const has_update_subs = this.eventifySubscriptions(\"batch\").length > 0;\n const has_remove_subs = this.eventifySubscriptions(\"remove\").length > 0;\n const has_change_subs = this.eventifySubscriptions(\"change\").length > 0;\n // update\n if (has_update_subs) {\n this.eventifyTrigger(\"batch\", items);\n }\n // change, remove\n if (has_remove_subs || has_change_subs) {\n for (let item of items) {\n if (item.new == undefined && item.old != undefined) {\n if (has_remove_subs) {\n this.eventifyTrigger(\"remove\", item);\n }\n } else {\n if (has_change_subs) {\n this.eventifyTrigger(\"change\", item);\n }\n }\n }\n }\n }\n\n\n /***************************************************************\n ACCESSORS\n ***************************************************************/\n\n get size () {\n return this.datasource.size;\n }\n\n has(key) {\n return this.datasource.has(key);\n };\n\n get(key) {\n return this.datasource.get(key);\n };\n\n keys() {\n return this.datasource.keys();\n };\n\n values() {\n return this.datasource.values();\n };\n\n entries() {\n return this.datasource.entries();\n }\n\n\n /***************************************************************\n MODIFY\n ***************************************************************/\n\n set(key, value) {\n let old = undefined;\n if (this.datasource.has(key)) {\n old = this.datasource.get(key);\n }\n this.datasource.set(key, value);\n this._notifyEvents([{key: key, new:value, old: old}]);\n return this;\n }\n\n delete(key) {\n let result = false;\n let old = undefined;\n if (this.datasource.has(key)) {\n old = this.datasource.get(key);\n this.datasource.delete(key);\n result = true;\n }\n this._notifyEvents([{key: key, new:undefined, old: old}]);\n return result;\n }\n\n clear() {\n // create change events for all cues\n const items = [...this.datasource.entries()].map(([key, val]) => {\n return {key: key, new: undefined, old: val};\n })\n // clear _map\n this.datasource.clear();\n // event notification\n this._notifyEvents(items);\n }\n\n}\n\neventify.eventifyPrototype(ObservableMap.prototype);\n\nexport default ObservableMap;\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport ObservableMap from '../util/observablemap.js';\nimport Interval from '../util/interval.js';\n\n/**\n * Extends ObservableMap\n * \n * with logic specific to collections of cues.\n */\n\nclass CueCollection extends ObservableMap {\n\n static cmpLow(cue_a, cue_b) {\n return Interval.cmpLow(cue_a.interval, cue_b.interval);\n }\n\n static cmpHigh(cue_a, cue_b) {\n return Interval.cmpHigh(cue_a.interval, cue_b.interval);\n }\n\n // extend sortOrder to accept order as string\n sortOrder(options={}) {\n let order = options.order || super.sortOrder(options);\n if (order == \"low\") {\n return CueCollection.cmpLow;\n } else if (order == \"high\") {\n return CueCollection.cmpHigh;\n } else {\n if (typeof order != \"function\") {\n return;\n }\n }\n return order;\n }\n\n // add cues method\n cues (options = {}) {\n let cues = this.sortValues(this.values(), options);\n // ensure array\n return (Array.isArray(cues)) ? cues : [...cues];\n }\n}\n\n// module definition\nexport default CueCollection;","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n\n/*\n Wraps the built in setTimeout to provide a\n Timeout that does not fire too early.\n\n Importantly, the Timeout object manages at most\n one timeout.\n\n - Given clock.now() returns a value in seconds.\n - The timeout is set with and absolute timestamp,\n not a delay.\n*/\n\nclass Timeout {\n\n constructor (timingObject, callback) {\n this.tid = undefined;\n this.to = timingObject;\n this.callback = callback;\n }\n\n isSet() {\n return this.tid != undefined;\n }\n\n /*\n set timeout to point in time (seconds)\n */\n setTimeout(target_ts, arg) {\n if (this.tid != undefined) {\n throw new Error(\"at most on timeout\");\n }\n let now = this.to.clock.now();\n let delay = Math.max(target_ts - now, 0) * 1000;\n this.tid = setTimeout(this.onTimeout.bind(this), delay, target_ts, arg);\n }\n\n /*\n handle timeout intended for point in time (seconds)\n */\n onTimeout(target_ts, arg) {\n if (this.tid != undefined) {\n this.tid = undefined;\n // check if timeout was too early\n let now = this.to.clock.now()\n if (now < target_ts) {\n // schedule new timeout\n this.setTimeout(target_ts, arg);\n } else {\n // handle timeout\n this.callback(now, arg);\n }\n }\n }\n\n /*\n cancel and clear timeout if active\n */\n clear() {\n if (this.tid != undefined) {\n clearTimeout(this.tid);\n this.tid = undefined;\n }\n }\n}\n\nexport default Timeout;\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\n/*\n\tMASTER CLOCK\n\n\n\tMasterClock is the reference clock used by TimingObjects.\n\n\tIt is implemented using performance.now,\n\tbut is skewed and rate-adjusted relative to this local clock.\n\n\tThis allows it to be used as a master clock in a distributed system,\n\twhere synchronization is generally relative to some other clock than the local clock.\n\n\tThe master clock may need to be adjusted in time, for instance as a response to\n\tvarying estimation of clock skew or drift. The master clock supports an adjust primitive for this purpose.\n\n\tWhat policy is used for adjusting the master clock may depend on the circumstances\n\tand is out of scope for the implementation of the MasterClock.\n\tThis policy is implemented by the timing object. This policy may or may not\n\tprovide monotonicity.\n\n\tA change event is emitted every time the masterclock is adjusted.\n\n\tVector values define\n\t- position : absolute value of the clock in seconds\n\t- velocity : how many seconds added per second (1.0 exactly - or very close)\n\t- timestamp : timstamp from local system clock (performance) in seconds. Defines point in time where position and velocity are valid.\n\n\tIf initial vector is not provided, default value is\n\t{position: now, velocity: 1.0, timestamp: now};\n\timplying that master clock is equal to local clock.\n*/\n\nimport eventify from '../util/eventify.js';\n\n\n// Need a polyfill for performance,now as Safari on ios doesn't have it...\n(function(){\n if (\"performance\" in window === false) {\n window.performance = {};\n window.performance.offset = new Date().getTime();\n }\n if (\"now\" in window.performance === false){\n window.performance.now = function now(){\n return new Date().getTime() - window.performance.offset;\n };\n }\n\t})();\n\n// local clock in seconds\nconst local_clock = {\n\tnow : function () {return performance.now()/1000.0;}\n};\n\nfunction calculateVector(vector, tsSec) {\n\tif (tsSec === undefined) tsSec = local_clock.now();\n\tvar deltaSec = tsSec - vector.timestamp;\n\treturn {\n\t\tposition : vector.position + vector.velocity*deltaSec,\n\t\tvelocity : vector.velocity,\n\t\ttimestamp : tsSec\n\t};\n};\n\nclass MasterClock {\n\n\tconstructor (options) {\n\t\tvar now = local_clock.now();\n\t\toptions = options || {};\n\t\tthis._vector = {position: now, velocity: 1.0, timestamp: now};\n\t\t// event support\n\t\teventify.eventifyInstance(this);\n\t\tthis.eventifyDefine(\"change\", {init:false}); // define change event (no init-event)\n\t\t// adjust\n\t\tthis.adjust(options);\n\t};\n\n\t/*\n\t\tADJUST\n\t\t- could also accept timestamp for velocity if needed?\n\t\t- given skew is relative to local clock\n\t\t- given rate is relative to local clock\n\t*/\n\tadjust(options) {\n\t\toptions = options || {};\n\t\tvar now = local_clock.now();\n\t\tvar nowVector = this.query(now);\n\t\tif (options.skew === undefined && options.rate === undefined) {\n\t\t\treturn;\n\t\t}\n\t\tthis._vector = {\n\t\t\tposition : (options.skew !== undefined) ? now + options.skew : nowVector.position,\n\t\t\tvelocity : (options.rate !== undefined) ? options.rate : nowVector.velocity,\n\t\t\ttimestamp : nowVector.timestamp\n\t\t}\n\t\tthis.eventifyTrigger(\"change\");\n\t};\n\n\t/*\n\t\tNOW\n\t\t- calculates the value of the clock right now\n\t\t- shorthand for query\n\t*/\n\tnow() {\n\t\treturn calculateVector(this._vector, local_clock.now()).position;\n\t};\n\n\t/*\n\t\tQUERY\n\t\t- calculates the state of the clock right now\n\t\t- result vector includes position and velocity\n\t*/\n\tquery(now) {\n\t\treturn calculateVector(this._vector, now);\n\t};\n\n}\neventify.eventifyPrototype(MasterClock.prototype);\n\nexport default MasterClock;\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\nimport MasterClock from './masterclock.js';\nimport {calculateVector, checkRange} from '../util/motionutils.js';\n\n\n/*\n\tINTERNAL PROVIDER\n\n\tTiming provider internal to the browser context\n\n\tUsed by timing objects as timingsrc if no timingsrc is specified.\n*/\n\nclass InternalProvider {\n\n\tconstructor (callback, options) {\n\t\toptions = options || {};\n\t\t// initialise internal state\n\t\tthis._clock = new MasterClock({skew:0});\n\t\tthis._range = [-Infinity, Infinity];\n\t\tthis._vector;\n\t\tthis._callback = callback;\n\t\t// options\n\t\toptions.timestamp = options.timestamp || this._clock.now();\n\t\tthis._process_update(options);\n\t};\n\n\t// internal clock\n\tget clock() {return this._clock;};\n\tget range() {return this._range;};\n\tget vector() {return this._vector;};\n\n\tisReady() {return true;};\n\n\t// update\n\t_process_update(arg) {\n\t\t// process arg\n\t\tlet {\n\t\t\tposition: pos,\n\t\t\tvelocity: vel,\n\t\t\tacceleration: acc,\n\t\t\ttimestamp: ts,\n\t\t\trange: range,\n\t\t\t...rest\n\t\t} = arg;\n\n\t\t// record state from current motion\n\t\tlet p = 0, v = 0, a = 0;\n\t\tif (this._vector != undefined) {\n\t\t\tlet nowVector = calculateVector(this._vector, ts);\n\t\t\tnowVector = checkRange(nowVector, this._range);\n\t\t\tp = nowVector.position;\n\t\t\tv = nowVector.velocity;\n\t\t\ta = nowVector.acceleration;\n\t\t}\n\n\t\t// fill in from current motion, for missing properties\n\t\tlet vector = {\n\t\t\tposition : (pos != undefined) ? pos : p,\n\t\t\tvelocity : (vel != undefined) ? vel : v,\n\t\t\tacceleration : (acc != undefined) ? acc : a,\n\t\t\ttimestamp : ts\n\t\t};\n\n\t\t// update range\n\t\tif (range != undefined) {\n\t\t\tlet [low, high] = range;\n\t\t\tif (low < high) {\n\t\t\t\tif (low != this._range[0] || high != this._range[1]) {\n\t\t\t\t\tthis._range = [low, high];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// check vector with respect to range\n\t\tvector = checkRange(vector, this._range);\n\t\t// save old vector\n\t\tthis._old_vector = this._vector;\n\t\t// update vector\n\t\tthis._vector = vector;\n\t\treturn {range, ...vector, ...rest};\n\t};\n\n\t// update\n\tupdate(arg) {\n\t\targ = this._process_update(arg);\n\t\treturn this._callback(arg);\n\t}\n\n\tclose() {\n\t\tthis._callback = undefined;\n\t}\n}\n\nexport default InternalProvider;\n\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n\n*/\n\n\n\nimport MasterClock from './masterclock.js';\n\n\nfunction checkTimingProvider(obj){\n\tlet required = [\"on\", \"skew\", \"vector\", \"range\", \"update\"];\n\tfor (let prop of required) {\n\t\tif (!(prop in obj)) {\n\t\t\tthrow new Error(`TimingProvider ${obj} missing property ${prop}`);\n\t\t}\n\t}\n}\n\n\n/*\n\tEXTERNAL PROVIDER\n\n\tExternal Provider bridges the gap between the PROVIDER API (implemented by external timing providers)\n\tand the TIMINGSRC API\n\n\tObjects implementing the TIMINGSRC API may be used as timingsrc (parent) for another timing object.\n\n\t- wraps a timing provider external\n\t- handles some complexity that arises due to the very simple API of providers\n\t- implements a clock for the provider\n*/\n\nclass ExternalProvider {\n\n\tconstructor(provider, callback, options) {\n\t\tcheckTimingProvider(provider);\n\t\toptions = options || {};\n\n\t\tthis._provider = provider;\n\t\tthis._callback = callback;\n\t\tthis._range;\n\t\tthis._vector;\n\t\tthis._ready = false\n\n\t\t/*\n\t\t\tprovider clock (may fluctuate based on live skew estimates)\n\t\t*/\n\t\tthis._provider_clock;\n\t\t/*\n\t\t\tlocal clock\n\t\t\tprovider clock normalised to values of performance now\n\t\t\tnormalisation based on first skew measurement, so\n\t\t*/\n\t\tthis._clock;\n\n\t\t// register event handlers\n\t\tthis._provider.on(\"vectorchange\", this._onVectorChange.bind(this));\n\t\tthis._provider.on(\"skewchange\", this._onSkewChange.bind(this));\n\n\t\t// check if provider is ready\n\t\tif (this._provider.skew != undefined) {\n\t\t\t// initialise immediately - without a callback\n\t\t\tthis._onSkewChange(true);\n\t\t}\n\t};\n\n\tisReady() {return this._ready;};\n\n\t// internal clock\n\tget clock() {return this._clock;};\n\tget range() {return this._range;};\n\n\n\t/*\n\t\t- local timestamp of vector is set for each new vector, using the skew available at that time\n\t\t- the vector then remains unchanged\n\t\t- skew changes affect local clock, thereby affecting the result of query operations\n\n\t\t- one could imagine reevaluating the vector as well when the skew changes,\n\t\t\tbut then this should be done without triggering change events\n\n\t\t- ideally the vector timestamp should be a function of the provider clock\n\t*/\n\n\tget vector() {\n\t\t// local_ts = provider_ts - skew\n\t\tlet local_ts = this._vector.timestamp - this._provider.skew;\n\t\treturn {\n\t\t\tposition : this._vector.position,\n\t\t\tvelocity : this._vector.velocity,\n\t\t\tacceleration : this._vector.acceleration,\n\t\t\ttimestamp : local_ts\n\t\t}\n\t}\n\n\n\t// internal provider object\n\tget provider() {return this._provider;};\n\n\n\t_onSkewChange(init=false) {\n\t\tif (!this._clock) {\n\t\t\tthis._provider_clock = new MasterClock({skew: this._provider.skew});\n\t\t\tthis._clock = new MasterClock({skew:0});\n\t\t} else {\n\t\t\tthis._provider_clock.adjust({skew: this._provider.skew});\n\t\t\t// provider clock adjusted with new skew - correct local clock similarly\n\t\t\t// current_skew = clock_provider - clock_local\n\t\t\tlet current_skew = this._provider_clock.now() - this._clock.now();\n\t\t\t// skew delta = new_skew - current_skew\n\t\t\tlet skew_delta = this._provider.skew - current_skew;\n\t\t\tthis._clock.adjust({skew: skew_delta});\n\t\t}\n\t\t// no upcalls on skew change\n\t};\n\n\t_onVectorChange() {\n\t\tif (this._clock) {\t\t\t\n\t\t\t// is ready (onSkewChange has fired earlier)\n\t\t\tif (!this._ready && this._provider.vector != undefined) {\n\t\t\t\t// become ready\n\t\t\t\tthis._ready = true;\n\t\t\t}\n\t\t\tif (this._ready) {\n\t\t\t\tif (!this._range) {\n\t\t\t\t\tthis._range = this._provider.range;\n\t\t\t\t}\n\t\t\t\tthis._vector = this._provider.vector;\n\t\t\t\tlet eArg = {\n\t\t\t\t\trange: this.range,\n\t\t\t\t\t...this.vector\n\t\t\t\t}\n\t\t\t\tthis._callback(eArg);\n\t\t\t}\n\t\t}\n\t};\n\n\t// update\n\t/*\n\t\tTODO - support setting range on provider\n\t\tTODO - suppport tunnel\n\t\tTODO - support onRangeChange from provider\n\t*/\n\tupdate(arg) {\n\t\tlet vector = {\n\t\t\tposition: arg.position,\n\t\t\tvelocity: arg.velocity,\n\t\t\tacceleration: arg.acceleration,\n\t\t\ttimestamp: arg.timestamp\n\t\t};\n\t\t// calc back to provider ts\n\t\t// local_ts = provider_ts - skew\n\t\tvector.timestamp = vector.timestamp + this._provider.skew;\n\t\tlet res = this._provider.update(vector);\n\t\t// return success\n\t\treturn true;\n\t};\n}\n\nexport default ExternalProvider;\n\n\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\nimport eventify from '../util/eventify.js';\nimport Timeout from '../util/timeout.js';\nimport * as motionutils from '../util/motionutils.js';\nimport InternalProvider from './internalprovider.js';\nimport ExternalProvider from './externalprovider.js';\n\nconst MAX_NONCE = 10000;\n\nfunction getRandomInt() {\n \treturn Math.floor(Math.random() * MAX_NONCE);\n};\n\nfunction isTimingProvider(obj){\n\tlet required = [\"on\", \"skew\", \"vector\", \"range\", \"update\"];\n\tfor (let prop of required) {\n\t\tif (!(prop in obj)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\n\n/*\n\tTIMING BASE\n\n\tabstract base class for objects that may be used as timingsrc\n\n\tessential internal state\n\t- range, vector\n\n\texternal methods\n\tquery, update\n\n\tevents\n\ton/off \"change\", \"timeupdate\"\n\n\tinternal methods for range timeouts\n\n\tdefines internal processing steps\n\t- handleEvent(arg) <- from external timingobject\n\t\t- vector = onChange(vector)\n\t\t- process(vector) <- from timeout or preProcess\n\t- handleTimeout(arg) <- timeout on range restrictions\n\t- process (arg)\n\t\t- set internal vector, range\n\t\t- dispatchEvents(arg)\n\t\t- renew range timeout\n\t- dispatchEvent (arg)\n\t\t- emit change event and timeupdate event\n\t\t- turn periodic timeupdate on or off\n\n\tindividual steps in this structure may be specialized\n\tby subclasses (i.e. timing converters)\n*/\n\n\nclass TimingObject {\n\n\tconstructor (timingsrc, options) {\n\n\t\t// special support for options given as first and only argument\n\t\t// equivalent to new TimingObject(undefined, options)\n\t\t// in this case, timingsrc may be found in options\n\t\tif (timingsrc != undefined && options == undefined) {\n\t\t\tif (!(timingsrc instanceof TimingObject) && !isTimingProvider(timingsrc)) {\n\t\t\t\t// timingsrc is neither timing object nor timingprovider\n\t\t\t\t// assume timingsrc is options\n\t\t\t\toptions = timingsrc;\n\t\t\t\ttimingsrc = undefined;\n\t\t\t\tif (options.provider) {\n\t\t\t\t\ttimingsrc = options.provider;\n\t\t\t\t} else if (options.timingsrc) {\n\t\t\t\t\ttimingsrc = options.timingsrc;\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t// options\n\t\toptions = options || {};\n\t\tthis.__options = options;\n\n\n\t\t// default timeout option\n\t\tif (options.timeout == undefined) {\n\t\t\toptions.timeout = true;\n\t\t}\n\n\t\t// cached vectors and range\n\t\tthis.__old_vector;\n\t\tthis.__vector;\n\t\tthis.__range = [-Infinity, Infinity];\n\n\t\t// range restriction timeout\n\t\tthis.__timeout = new Timeout(this, this.__handleTimeout.bind(this));\n\n\t\t// timeoutid for timeupdate event\n\t\tthis.__tid = undefined;\n\n\t\t// timingsrc\n\t\tthis.__timingsrc;\n\t\tthis.__sub;\n\n\t\t// update promises\n\t\tthis.__update_events = new Map();\n\n\t\t// readiness\n\t\tthis.__ready = new eventify.EventBoolean();\n\n\t\t// exported events\n\t\teventify.eventifyInstance(this);\n\t\tthis.eventifyDefine(\"timingsrc\", {init:true});\n\t\tthis.eventifyDefine(\"change\", {init:true});\n\t\tthis.eventifyDefine(\"rangechange\", {init:true});\n\t\tthis.eventifyDefine(\"timeupdate\", {init:true});\n\n\t\t// initialise timingsrc\n\t\tthis.__set_timingsrc(timingsrc, options);\n\t};\n\n\n\t/***************************************************************\n\n\t\tEVENTS\n\n\t***************************************************************/\n\n\t/*\n\t \toverrides how immediate events are constructed\n\t \tspecific to eventutils\n\t \t- overrides to add support for timeupdate events\n\t*/\n\teventifyInitEventArgs(name) {\n\t\tif (this.__ready.value) {\n\t\t\tif (name == \"timingsrc\") {\n\t\t\t\tlet eArg = {\n\t\t\t\t\t...this.__vector,\n\t\t\t\t\trange: this.__range,\n\t\t\t\t\tlive:false\n\t\t\t\t}\n\t\t\t\treturn [eArg];\n\t\t\t} else if (name == \"timeupdate\") {\n\t\t\t\treturn [undefined];\n\t\t\t} else if (name == \"change\") {\n\t\t\t\treturn [this.__vector];\n\t\t\t} else if (name == \"rangechange\") {\n\t\t\t\treturn [this.__range];\n\t\t\t}\n\t\t}\n\t};\n\n\n\t/***************************************************************\n\n\t\tACCESSORS\n\n\t***************************************************************/\n\n\t// ready or not\n\tisReady() {return this.__ready.value;};\n\n\t// ready promise\n get ready() {return eventify.makePromise(this.__ready);};\n\n // range\n get range() {\n \t// copy\n \treturn [this.__range[0], this.__range[1]];\n };\n\n // vector\n get vector() {\n \t// copy\n\t\treturn {\n\t\t\tposition : this.__vector.position,\n\t\t\tvelocity : this.__vector.velocity,\n\t\t\tacceleration : this.__vector.acceleration,\n\t\t\ttimestamp : this.__vector.timestamp\n\t\t};\n };\n\n // old vector\n get old_vector() {return this.__old_vector;};\n\n // delta\n get delta() {\n \treturn new motionutils.MotionDelta(this.__old_vector, this.__vector);\n }\n\n\t// clock - from timingsrc or provider\n\tget clock() {return this.__timingsrc.clock};\n\n\tget version() {return 5;}\n\n\n\t/***************************************************************\n\n\t\tQUERY\n\n\t***************************************************************/\n\n\t// query\n\tquery() {\n\t\tif (this.__ready.value == false) {\n\t\t\tthrow new Error(\"query before timing object is ready\");\n\t\t}\n\t\t// reevaluate state to handle range violation\n\t\tlet vector = motionutils.calculateVector(this.__vector, this.clock.now());\n\t\t// detect range violation - only if timeout is set {\n\t\tif (this.__timeout.isSet()) {\n\t\t\tif (vector.position < this.__range[0] || this.__range[1] < vector.position) {\n\t\t\t\t// emulate update event to trigger range restriction\n\t\t\t\tthis.__process({...vector});\n\t\t\t}\n\t\t\t// re-evaluate query after state transition\n\t\t\treturn motionutils.calculateVector(this.__vector, this.clock.now());\n\t\t}\n\t\treturn vector;\n\t};\n\n\t// shorthand query\n\tget pos() {return this.query().position;};\n\tget vel() {return this.query().velocity;};\n\tget acc() {return this.query().acceleration;};\n\n\n\t/***************************************************************\n\n\t\tUPDATE\n\n\t***************************************************************/\n\n\t// internal update\n\t__update(arg) {\n\t\tif (this.__timingsrc instanceof TimingObject) {\n\t\t\treturn this.__timingsrc.__update(arg);\n\t\t} else {\n\t\t\t// provider\n\t\t\treturn this.__timingsrc.update(arg);\n\t\t}\n\t};\n\n\t// external update\n\tupdate(arg) {\n\t\t// check if noop\n\t\tlet ok = (arg.range != undefined);\n\t\tok = ok || (arg.position != undefined);\n\t\tok = ok || (arg.velocity != undefined);\n\t\tok = ok || (arg.acceleration != undefined);\n\t\tif (!ok) {\n\t\t\treturn Promise.resolve(arg);\n\t\t}\n\t\targ.tunnel = getRandomInt();\n\t\tif (arg.timestamp == undefined) {\n\t\t\targ.timestamp = this.clock.now();\n\t\t}\n\t\tlet event = new eventify.EventVariable();\n\t\tthis.__update_events.set(arg.tunnel, event);\n\t\tlet promise = eventify.makePromise(event, val => (val != undefined));\n\t\tthis.__update(arg);\n\t\treturn promise;\n\t}\n\n\n\t/***************************************************************\n\n\t\tCORE UPDATE PROCESSING\n\n\t***************************************************************/\n\n\t/*\n\t\tdo not override\n\t\thandle incoming change event\n\t\teArg = {vector:vector, range:range, live:true}\n\n\t\tsubclasses may specialise behaviour by overriding\n\t\tonVectorChange\n\n\t*/\n\t__handleEvent(arg) {\n\t\tlet {\n\t\t\trange,\n\t\t\tlive = true,\n\t\t\t...rest\n\t\t} = arg;\n\t\t// copy range object\n\t\tif (range != undefined) {\n\t\t\trange = [range[0], range[1]];\n\t\t}\n\t\t// new arg object\n\t\tlet _arg = {\n\t\t\trange,\n\t\t\tlive,\n\t\t\t...rest,\n\t\t};\n\t\t_arg = this.onUpdateStart(_arg);\n\t\tif (_arg != undefined) {\n\t\t\treturn this.__process(_arg);\n\t\t}\n\t};\n\n\t/*\n\t\tdo not override\n\t\thandle timeout\n\t*/\n\t__handleTimeout(now, timeout_vector) {\n\t\tthis.__process({...timeout_vector});\n\t}\n\n\t/*\n\t\tcore processing step after change event or timeout\n\t\tassignes the internal vector\n\t*/\n\t__process(arg) {\n\t\tlet {\n\t\t\trange,\n\t\t\tposition,\n\t\t\tvelocity,\n\t\t\tacceleration,\n\t\t\ttimestamp,\n\t\t\tlive=true,\n\t\t\t...rest\n\t\t} = arg;\n\n\n\t\t// update range\n\t\tlet range_change = false;\n\t\tif (range != undefined) {\n\t\t\tlet [low, high] = range;\n\t\t\tif (low < high) {\n\t\t\t\tif (low != this.__range[0] || high != this.__range[1]) {\n\t\t\t\t\tthis.__range = [low, high];\n\t\t\t\t\trange = [low, high];\n\t\t\t\t\trange_change = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t\t- vector change (all vector elements defined)\n\t\t\t- range change (no vector elements defined)\n\t\t\t- both (all vector elements and range defined)\n\t\t*/\n\t\tlet vector_change = (position != undefined);\n\t\tif (!vector_change && !range_change) {\n\t\t\tconsole.log(\"__process: WARNING - no vector change and no range change\")\n\t\t}\n\n\t\t/*\n\t\t\tcheck if vector is consistent with range\n\t\t\trange violation may occur if \n\t\t\t- vector change\n\t\t\t- range change\n\t\t\t- both\n\n\t\t\t- vector must be recalculated for present for detection\n\t\t\t of range violation\n\t\t*/\n\t\tlet vector;\n\t\tif (vector_change) {\n\t\t\t// vector change\n\t\t\tvector = {position, velocity, acceleration, timestamp};\n\t\t} else {\n\t\t\tvector = {...this.__vector};\n\t\t}\n\t\tlet now = this.clock.now();\n\t\tlet now_vector = motionutils.calculateVector(vector, now);\n\t\tlet violation = motionutils.detectRangeViolation(now_vector, this.__range);\n\t\tif (violation) {\n\t\t\tvector = this.onRangeViolation(now_vector);\n\t\t\tlive = true;\n\t\t}\n\n\t\t// reevaluate vector change and live\n\t\tvector_change = vector_change || !motionutils.equalVectors(vector, this.__vector);\n\n\t\t// update vector\t\t\n\t\tif (vector_change) {\n\t\t\t// save old vector\n\t\t\tthis.__old_vector = this.__vector;\n\t\t\t// update vector\n\t\t\tthis.__vector = vector;\n\t\t}\n\n\t\tlet _arg;\n\t\tif (range_change && vector_change) {\n\t\t\t_arg = {range, ...vector, live, ...rest};\n\t\t} else if (range_change) {\n\t\t\t_arg = {range, live, ...rest};\n\t\t} else if (vector_change) {\n\t\t\t_arg = {...vector, live, ...rest};\n\t\t} else {\n\t\t\t_arg = {live, ...rest};\n\t\t}\n\n\t\t// trigger events\n\t\tthis.__ready.value = true;\n\t\tthis.__dispatchEvents(_arg, range_change, vector_change);\n\t\t// renew timeout\n\t\tif (this.__options.timeout) {\n\t\t\tthis.__renewTimeout();\n\t\t}\n\t\t// release update promises\n\t\tif (_arg.tunnel != undefined) {\n\t\t\tlet event = this.__update_events.get(_arg.tunnel);\n\t\t\tif (event) {\n\t\t\t\tthis.__update_events.delete(_arg.tunnel);\n\t\t\t\tdelete _arg.tunnel;\n\t\t\t\tevent.value = _arg;\n\t\t\t}\n\t\t}\n\t\t// TODO\n\t\t// since externalprovider does not support tunnel yet\n\t\t// free all remaining promises\n\t\tfor (let event of this.__update_events.values()) {\n\t\t\tevent.value = {};\n\t\t}\n\t\tthis.onUpdateDone(_arg);\n\t\treturn _arg;\n\t};\n\n\t/*\n\t\tprocess a new vector applied in order to trigger events\n\t\toverriding this is only necessary if external change events\n\t\tneed to be suppressed,\n\t*/\n\t__dispatchEvents(arg, range_change, vector_change) {\n\t\tlet {\n\t\t\trange,\n\t\t\tposition,\n\t\t\tvelocity,\n\t\t\tacceleration,\n\t\t\ttimestamp\n\t\t} = arg;\n\t\t// trigger timingsrc events\n\t\tthis.eventifyTrigger(\"timingsrc\", arg);\n\t\t// trigger public change events\n\t\tif (vector_change) {\n\t\t\tlet vector = {position, velocity, acceleration, timestamp};\n\t\t\tthis.eventifyTrigger(\"change\", vector);\n\t\t}\n\t\tif (range_change) {\n\t\t\tthis.eventifyTrigger(\"rangechange\", range);\n\t\t}\n\t\t// trigger timeupdate events\n\t\tthis.eventifyTrigger(\"timeupdate\");\n\t\tlet moving = motionutils.isMoving(this.__vector);\n\t\tif (moving && this.__tid === undefined) {\n\t\t\tlet self = this;\n\t\t\tthis.__tid = setInterval(function () {\n\t\t\t\tself.eventifyTrigger(\"timeupdate\");\n\t\t\t}, 200);\n\t\t} else if (!moving && this.__tid !== undefined) {\n\t\t\tclearTimeout(this.__tid);\n\t\t\tthis.__tid = undefined;\n\t\t}\n\t};\n\n\n\t/***************************************************************\n\n\t\tSUBCLASS MAY OVERRIDE\n\n\t***************************************************************/\n\n\t/*\n\t\tmay be overridden\n\t*/\n\tonRangeViolation(now_vector) {\n\t\treturn motionutils.checkRange(now_vector, this.__range);\n\t};\n\n\t/*\n\t\tmay be overridden\n\t*/\n\tonUpdateStart(arg) {return arg;};\n\n\t/*\n\t\tmay be overridden\n\t*/\n\tonUpdateDone(arg) {};\n\n\n\t/***************************************************************\n\n\t\tTIMEOUTS\n\n\t***************************************************************/\n\n\t/*\n\t\trenew timeout is called during every processing step\n\t\tin order to recalculate timeouts.\n\n\t\t- optional vector - default is own vector\n\t\t- optional range - default is own range\n\t*/\n\t__renewTimeout(vector, range) {\n\t\tthis.__timeout.clear();\n\t\tlet timeout_vector = this.__calculateTimeoutVector(vector, range);\n\t\tif (timeout_vector == undefined) {\n\t\t\treturn;\n\t\t}\n\t\tthis.__timeout.setTimeout(timeout_vector.timestamp, timeout_vector);\n\t};\n\n\n\t/*\n\t\tcalculate a vector that will be delivered to _process().\n\t\tthe timestamp in the vector determines when it is delivered.\n\n\t\t- optional vector - default is own vector\n\t\t- optional range - default is own range\n\t*/\n\t__calculateTimeoutVector(vector, range) {\n\t\tvector = vector || this.__vector;\n\t\trange = range || this.__range;\n\t\tlet now = this.clock.now();\n\t\tlet now_vector = motionutils.calculateVector(vector, now);\n\t\tlet [delta, pos] = motionutils.calculateDelta(now_vector, range);\n\t\tif (delta == undefined) {\n\t\t\treturn;\n\t\t}\n\t\t// vector when range restriction will be reached\n\t\tlet timeout_vector = motionutils.calculateVector(vector, now + delta);\n\t\t// possibly avoid rounding errors\n\t\ttimeout_vector.position = pos;\n\t\treturn timeout_vector;\n\t};\n\n\n\t/***************************************************************\n\n\t\tTIMINGSRC\n\n\t***************************************************************/\n\n\t/*\n\n\t\ttimingsrc property and switching on assignment\n\n\t*/\n\t__clear_timingsrc() {\n\t\t// clear timingsrc\n\t\tif (this.__timingsrc != undefined) {\n\t\t\tif (this.__timingsrc instanceof TimingObject) {\n\t\t\t\tthis.__timingsrc.off(this.__sub);\n\t\t\t\tthis.__sub = undefined;\n\t\t\t\tthis.__timingsrc = undefined;\n\t\t\t} else {\n\t\t\t\t// provider\n\t\t\t\tthis.__timingsrc.close();\n\t\t\t\tthis.__timingsrc = undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\t__set_timingsrc(timingsrc, options) {\n\t\t// set timingsrc\n\t\tlet callback = this.__handleEvent.bind(this);\n\t\tif (timingsrc instanceof TimingObject) {\n\t\t\t// timingsrc\n\t\t\tthis.__timingsrc = timingsrc;\n\t\t\tthis.__sub = this.__timingsrc.on(\"timingsrc\", callback);\n\t\t} else {\n\t\t\t// provider\n\t\t\tif (timingsrc == undefined) {\n\t\t\t\t// Internal Provider\n\t\t\t\tthis.__timingsrc = new InternalProvider(callback, options);\n\t\t\t} else {\n\t\t\t\t// External Provider\n\t\t\t\tthis.__timingsrc = new ExternalProvider(timingsrc, callback, options);\n\t\t\t}\n\t\t\t// emulating initial event from provider, causing\n\t\t\t// this timingobject to initialise\n\t\t\tif (this.__timingsrc.isReady()) {\n\t\t\t\tlet arg = {\n\t\t\t\t\trange: this.__timingsrc.range,\n\t\t\t\t\t...this.__timingsrc.vector,\n\t\t\t\t\tlive: false\n\t\t\t\t}\n\t\t\t\t// generate initial event\n\t\t\t\tcallback(arg);\n\t\t\t}\n\t\t}\n\t}\n\n\t__get_timingsrc() {\n\t\t// returns InternalProvider, ExternalProvider or TimingObject\n\t\treturn this.__timingsrc;\n\t}\n\n\tget timingsrc () {\n\t\t// returns TimingObject, Provider or undefined\n\t\tlet timingsrc = this.__get_timingsrc();\n\t\tif (timingsrc instanceof TimingObject) {\n\t\t\treturn timingsrc;\n\t\t} else if (timingsrc instanceof InternalProvider) {\n\t\t\treturn undefined;\n\t\t} else if (timingsrc instanceof ExternalProvider) {\n\t\t\treturn timingsrc._provider;\n\t\t} else {\n\t\t\tthrow new Error(\"illegal timingsrc\")\n\t\t}\n\t}\n\t\n\tset timingsrc(timingsrc) {\n\t\tthis.__clear_timingsrc();\n\t\tthis.__set_timingsrc(timingsrc);\n\t}\n\n}\n\neventify.eventifyPrototype(TimingObject.prototype);\n\nexport default TimingObject;\n\n\n\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n\n/*\n\tSKEW CONVERTER\n\n\tSkewing the timeline by 2 means that the timeline position 0 of the timingsrc becomes position 2 of Converter.\n\n*/\n\n\nimport TimingObject from './timingobject.js';\n\n\nclass SkewConverter extends TimingObject {\n\n\tconstructor (timingsrc, skew, options) {\n\t\tsuper(timingsrc, options);\n\t\tthis._skew = skew;\n this.eventifyDefine(\"skewchange\", {init:true});\n\t}\n\n // extend\n eventifyInitEventArgs(name) {\n if (name == \"skewchange\") {\n return [this._skew];\n } else {\n return super.eventifyInitEventArgs(name)\n }\n }\n\n\t// overrides\n\tonUpdateStart(arg) {\n if (arg.range != undefined) {\n arg.range[0] += this._skew;\n arg.range[1] += this._skew;\n }\n if (arg.position != undefined) {\n\t\t\targ.position += this._skew;\n }\n return arg;\n\t};\n\n\t// overrides\n\tupdate(arg) {\n if (arg.position != undefined) {\n\t\t\targ.position -= this._skew;\n }\n if (arg.range != undefined) {\n let [low, high] = arg.range;\n arg.range = [low - this._skew, high - this._skew];\n }\n\t\treturn super.update(arg);\n\t};\n\n\tget skew() {return this._skew;};\n\n\tset skew(skew) {\n if (skew != this._skew) {\n // set skew and emulate new event from timingsrc\n\t\t\tthis._skew = skew;\n\t\t\tthis.__handleEvent({\n ...this.__get_timingsrc().vector,\n range: this.__get_timingsrc().range\n });\n this.eventifyTrigger(\"skewchange\", skew);\n }\n\t}\n};\n\nexport default SkewConverter;\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\n/*\n\tDELAY CONVERTER\n\n\tDelay Converter introduces a positive time delay on a source timing object.\n\n\tGenerally - if the source timing object has some value at time t,\n\tthen the delayConverter will provide the same value at time t + delay.\n\n\tSince the delay Converter is effectively replaying past events after the fact,\n\tit is not LIVE and not open to interactivity (i.e. update)\n\n*/\n\nimport TimingObject from './timingobject.js';\nimport Timeout from '../util/timeout.js';\n\n\nclass DelayConverter extends TimingObject {\n\tconstructor (timingObject, delay) {\n\t\tif (delay < 0) {throw new Error (\"negative delay not supported\");}\n\t\tif (delay === 0) {throw new Error (\"zero delay makes delayconverter pointless\");}\n\t\tsuper(timingObject);\n\t\t// fixed delay\n\t\tthis._delay = delay;\n\t\t// buffer\n\t\tthis._buffer = [];\n\t\t// timeoutid\n\t\tthis._timeout = new Timeout(this, this.__handleDelayed.bind(this));\n this.eventifyDefine(\"delaychange\", {init:true});\n\t};\n\n // extend\n eventifyInitEventArgs(name) {\n if (name == \"delaychange\") {\n return [this._delay];\n } else {\n return super.eventifyInitEventArgs(name)\n }\n }\n\n\t// overrides\n\tonUpdateStart(arg) {\n\t\t/*\n\t\t\tVector's timestamp always time-shifted (back-dated) by delay\n\n\t\t\tNormal operation is to delay every incoming vector update.\n\t\t\tThis implies returning null to abort further processing at this time,\n\t\t\tand instead trigger a later continuation.\n\n\t\t\tHowever, delay is calculated based on the timestamp of the vector (age), not when the vector is\n\t\t\tprocessed in this method. So, for small small delays the age of the vector could already be\n\t\t\tgreater than delay, indicating that the vector is immediately valid and do not require delayed processing.\n\n\t\t\tThis is particularly true for the first vector, which may be old.\n\n\t\t\tSo we generally check the age to figure out whether to apply the vector immediately or to delay it.\n\t\t*/\n\n\t\tthis._buffer.push(arg);\n\t\t// if timeout for next already defined, nothing to do\n\t\tif (!this._timeout.isSet()) {\n\t\t\tthis.__handleDelayed();\n\t\t}\n\t\treturn;\n\t};\n\n\t__handleDelayed() {\n\t\t// run through buffer and apply vectors that are due\n\t\tlet now = this.clock.now();\n\t\tlet arg, due;\n\t\twhile (this._buffer.length > 0) {\n\t\t\tdue = this._buffer[0].timestamp + this._delay;\n\t\t\tif (now < due) {\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\targ = this._buffer.shift();\n\t\t\t\t// apply\n\t\t\t\targ.timestamp = due;\n\t\t\t\tthis.__process(arg);\n\t\t\t}\n\t\t}\n\t\t// set new timeout\n\t\tif (this._buffer.length > 0) {\n\t\t\tdue = this._buffer[0].timestamp + this._delay;\n\t\t\tthis._timeout.setTimeout(due);\n\t\t}\n\t};\n\n\tupdate(arg) {\n\t\t// Updates are prohibited on delayed timingobjects\n\t\tthrow new Error (\"update is not legal on delayed (non-live) timingobject\");\n\t};\n\n get delay() {return this._delay;};\n\n\tset delay(delay) {\n if (delay != this._delay) {\n // set delay and emulate new event from timingsrc\n this._delay = delay;\n this._timeout.clear();\n this.__handleDelayed();\n this.eventifyTrigger(\"delaychange\", delay);\n }\n }\n}\n\nexport default DelayConverter;\n\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n/*\n\tSCALE CONVERTER\n\n\tScaling by a factor 2 means that values of the timing object (position, velocity and acceleration) are multiplied by two.\n\tFor example, if the timing object represents a media offset in seconds, scaling it to milliseconds implies a scaling factor of 1000.\n\n*/\n\nimport TimingObject from './timingobject.js';\n\n\nclass ScaleConverter extends TimingObject {\n constructor (timingsrc, factor) {\n\t\tsuper(timingsrc);\n\t\tthis._factor = factor;\n this.eventifyDefine(\"scalechange\", {init:true});\n\t};\n\n // extend\n eventifyInitEventArgs(name) {\n if (name == \"scalechange\") {\n return [this._factor];\n } else {\n return super.eventifyInitEventArgs(name)\n }\n }\n\n\t// overrides\n onUpdateStart(arg) {\n if (arg.range != undefined) {\n arg.range = [arg.range[0]*this._factor, arg.range[1]*this._factor];\n }\n if (arg.position != undefined) {\n arg.position *= this._factor;\n }\n if (arg.velocity != undefined) {\n arg.velocity *= this._factor;\n }\n if (arg.acceleration != undefined) {\n arg.acceleration *= this._factor;\n }\n return arg;\n }\n\n\tupdate(arg) {\n\t\tif (arg.position != undefined) {\n arg.position /= this._factor;\n }\n\t\tif (arg.velocity != undefined) {\n arg.velocity /= this._factor;\n }\n\t\tif (arg.acceleration != undefined) {\n arg.acceleration /= this._factor;\n }\n\t\treturn super.update(arg);\n\t};\n\n get scale() {return this._factor;};\n\n set scale(factor) {\n if (factor != this._factor) {\n // set scale and emulate new event from timingsrc\n this._factor = factor;\n this.__handleEvent({\n ...this.__get_timingsrc().vector,\n range: this.__get_timingsrc().range\n });\n this.eventifyTrigger(\"scalechange\", factor);\n }\n }\n}\nexport default ScaleConverter;\n\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\n/*\n\tLOOP CONVERTER\n\n\tThis is a modulo type transformation where the converter will be looping within\n\ta given range. Potentially one could create an associated timing object keeping track of the\n\tloop number.\n*/\n\n\nimport {calculateVector} from '../util/motionutils.js';\nimport TimingObject from './timingobject.js';\n\n\n// ovverride modulo to behave better for negative numbers\nfunction mod(n, m) {\n\treturn ((n % m) + m) % m;\n};\n\nfunction transform(x, range) {\n\tlet skew = range[0];\n\tlet length = range[1] - range[0];\n\treturn skew + mod(x-skew, length);\n}\n\n\n/*\n\tLOOP CONVERTER\n*/\n\nclass LoopConverter extends TimingObject {\n\n\tconstructor(timingsrc, range) {\n\t\tsuper(timingsrc, {timeout:true});\n\n\t\tif (!Array.isArray(range) || range.length != 2) {\n\t\t\tthrow new Error(`range must be array [low, high], ${range}`);\n\t\t}\n\t\tthis.__range = range;\n\t};\n\n\tupdate(arg) {\n\t\t// range change - only a local operation\n\t\tif (arg.range != undefined) {\n\t\t\t// implement local range update\n\t\t\tlet [low, high] = arg.range;\n\t\t\tif (low >= high) {\n\t\t\t\tthrow new Error(\"illegal range\", arg.range)\n\t\t\t}\n\t\t\tif (low != this.__range[0] || high != this.__range[1]) {\n\t\t\t\tthis.__range = [low, high];\n\t\t\t\tlet vector = this.__get_timingsrc().query();\n\t\t\t\tvector.position = transform(vector.position, this.__range);\n\t\t\t\tthis.__vector = vector;\n\t\t\t\t// trigger vector change\n\t\t\t\tlet _arg = {range: this.__range, ...this.__vector, live:true};\n\t\t\t\tthis.__dispatchEvents(_arg, true, true);\n\t\t\t}\n\t\t\tdelete arg.range;\n\t\t}\n\t\t// vector change\n\t\tif (arg.position != undefined) {\n\t\t\t// inverse transformation of position, from looper\n\t\t\t// coordinates to timingsrc coordinates\n\t\t\t// preserve relative position diff\n\t\t\tlet now = this.clock.now();\n\t\t\tlet now_vector = calculateVector(this.vector, now);\n\t\t\tlet diff = now_vector.position - arg.position;\n\t\t\tlet now_vector_src = calculateVector(this.__get_timingsrc().vector, now);\n\t\t\targ.position = now_vector_src.position - diff;\n\t\t}\n\t\treturn super.update(arg);\n\t};\n\n\t// overrides\n\tonRangeViolation(now_vector) {\n\t\tnow_vector.position = transform(now_vector.position, this.__range);\n\t\treturn now_vector;\n\t};\n\n\t// overrides\n\tonUpdateStart(arg) {\n if (arg.range != undefined) {\n // ignore range change from timingsrc\n // instead, insist that this._range is correct\n arg.range = this.__range;\n }\n if (arg.position != undefined) {\n \t// vector change\n \targ.position = transform(arg.position, this.__range);\n\t\t\t/* \n\t\t\tvector change must also apply to timestamp\n\t\t\tthis is handlet in onRangeViolation \n\t\t\t*/\n }\n\t\treturn arg;\n\t};\n\n}\nexport default LoopConverter;\n\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n/*\n\n\tRANGE CONVERTER\n\n\tThe converter enforce a range on position.\n\n\tIt only has effect if given range is a restriction on the range of the timingsrc.\n\tRange converter will pause on range endpoints if timingsrc leaves the range.\n\tRange converters will continue mirroring timingsrc once it comes into the range.\n*/\n\n\nimport {RangeState, correctRangeState, checkRange} from '../util/motionutils.js';\nimport TimingObject from './timingobject.js';\n\n\nfunction state() {\n\tvar _state = RangeState.INIT;\n\tvar _range = null;\n\tvar is_special_state_change = function (old_state, new_state) {\n\t\t// only state changes between INSIDE and OUTSIDE* are special state changes.\n\t\tif (old_state === RangeState.OUTSIDE_HIGH && new_state === RangeState.OUTSIDE_LOW) return false;\n\t\tif (old_state === RangeState.OUTSIDE_LOW && new_state === RangeState.OUTSIDE_HIGH) return false;\n\t\tif (old_state === RangeState.INIT) return false;\n\t\treturn true;\n\t}\n\tvar get = function () {return _state;};\n\tvar set = function (new_state, new_range) {\n\n\t\tvar absolute = false; // absolute change\n\t\tvar special = false; // special change\n\n\t\t// check absolute change\n\t\tif (new_state !== _state || new_range !== _range) {\n\t\t\tabsolute = true;\n\t\t}\n\t\t// check special change\n\t\tif (new_state !== _state) {\n\t\t\tspecial = is_special_state_change(_state, new_state);\n\t\t}\n\t\t// range change\n\t\tif (new_range !== _range) {\n\t\t\t_range = new_range;\n\t\t}\n\t\t// state change\n\t\tif (new_state !== _state) {\n\t\t\t_state = new_state;\n\t\t}\n\t\treturn {special:special, absolute:absolute};\n\n\t}\n\treturn {get: get, set:set};\n};\n\n\n/*\n\tRange converter allows a new (smaller) range to be specified.\n\n\t- ignores the range of its timingsrc\n\t- vector change from timingsrc\n\t - outside own range - drop - set timeout to inside\n\t - inside own range - normal processing\n\t- extra vector changes (compared to timingsrc)\n\t\t- enter inside\n\t\t- range violation own range\n\t- range updated locally\n\n*/\n\nclass RangeConverter extends TimingObject {\n\n\tconstructor (timingObject, range) {\n\t\tsuper(timingObject, {timeout:true});\n\t\tthis.__state = state();\n\t\tthis.__range = range;\n\t};\n\n\n\tupdate(arg) {\n\t\tthrow Error(\"Not Implemented!\");\n\t\t/*\n\t\t\trange change - only a local operation\n\n\t\t\t\t- need to trigger local processing of new range,\n\t\t\t\tso that range is changed and events triggered\n\t\t\t\t- also need to trigger a reevaluation of\n\t\t\t\tvector from timingsrc vector, for instance, if\n\t\t\t\trange grows while timingsrc is outside, the\n\t\t\t\tposition of the vector needs to change\n\t\t\t\t- cannot do both these things via emulation\n\t\t\t\tof timingsrc event - because rangeconverter\n\t\t\t\tis supposed to ignore range change from timingsrc\n\t\t\t\t- could do both locally, but this would effectively\n\t\t\t\trequire reimplementation of logic in __process\n\t\t\t\t- in addition, this could be a request to update\n\t\t\t\tboth range and vector at the same time, in which case\n\t\t\t\tit would be good to do them both at the same time\n\n\t\t\t- possible solution - somehow let range converter\n\t\t\t discriminate range changes based on origin?\n\n\t\t*/\n\t\tif (arg.range != undefined) {\n\n\t\t\t// local processing of range change\n\t\t\t// to trigger range change event\n\t\t\tlet _arg = {range: arg.range, ...this.__get_timingsrc().vector, live:true};\n\t\t\tthis.__process(_arg);\n\t\t\t// avoid that range change affects timingsrc\n\t\t\tdelete arg.range;\n\n\t\t}\n\t\treturn super.update(arg);\n\t};\n\n\n\n\t// overrides\n\tonUpdateStart(arg) {\n if (arg.range != undefined) {\n \t// ignore range change from timingsrc\n \t// delete causes update to be dropped\n delete arg.range;\n }\n if (arg.position != undefined) {\n \t// vector change from timingsrc\n \tlet {position, velocity, acceleration, timestamp} = arg;\n \tlet vector = {position, velocity, acceleration, timestamp};\n \tvector = this.onVectorChange(vector);\n \tif (vector == undefined) {\n \t\t// drop because motion is outside\n\t\t\t\t// create new timeout for entering inside\n\t\t\t\tthis.__renewTimeout(this.__get_timingsrc().vector, this.__range);\n\t\t\t\treturn;\n \t} else {\n \t\t// regular\n \t\targ.position = vector.position;\n \t\targ.velocity = vector.velocity;\n \t\targ.acceleration = vector.acceleration;\n \t\targ.timestamp = vector.timestamp;\n \t}\n }\n return arg;\n\t};\n\n\n\tonVectorChange(vector) {\n\t\tvar new_state = correctRangeState(vector, this.__range);\n\t\tvar state_changed = this.__state.set(new_state, this.__range);\n\t\tif (state_changed.special) {\n\t\t\t// state transition between INSIDE and OUTSIDE\n\t\t\tif (this.__state.get() === RangeState.INSIDE) {\n\t\t\t\t// OUTSIDE -> INSIDE, generate fake start event\n\t\t\t\t// vector delivered by timeout\n\t\t\t\t// forward event unchanged\n\t\t\t} else {\n\t\t\t\t// INSIDE -> OUTSIDE, generate fake stop event\n\t\t\t\tvector = checkRange(vector, this.__range);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t// no state transition between INSIDE and OUTSIDE\n\t\t\tif (this.__state.get() === RangeState.INSIDE) {\n\t\t\t\t// stay inside or first event inside\n\t\t\t\t// forward event unchanged\n\t\t\t} else {\n\t\t\t\t// stay outside or first event outside\n\t\t\t\t// forward if\n\t\t\t\t// - first event outside\n\t\t\t\t// - skip from outside-high to outside-low\n\t\t\t\t// - skip from outside-low to outside-high\n\t\t\t\t// - range change\n\t\t\t\t// else drop\n\t\t\t\t// - outside-high to outside-high (no range change)\n\t\t\t\t// - outside-low to outside-low (no range change)\n\t\t\t\tif (state_changed.absolute) {\n\t\t\t\t\tvector = checkRange(vector, this.__range);\n\t\t\t\t} else {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn vector;\n\t};\n}\n\nexport default RangeConverter;\n\n","/*\n\tCopyright 2015 Norut Northern Research Institute\n\tAuthor : Ingar Mæhlum Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n/*\n\tTIMESHIFT CONVERTER\n\n\tTimeshift Converter timeshifts a timing object by timeoffset.\n\tPositive timeoffset means that the converter will run ahead of the source timing object.\n\tNegative timeoffset means that the converter will run behind the source timing object.\n\n\tUpdates affect the converter immediately.\n This means that update vector must be re-calculated\n\tto the value it would have at time-shifted time.\n Timestamps are not time-shifted, since the motion is still live.\n\tFor instance, (0, 1, ts) becomes (0+(1*timeshift), 1, ts)\n\n\tHowever, this transformation may cause range violation\n\t\t- this happens only when timing object is moving.\n\t\t- implementation requires range converter logic\n\n\t- range is infinite\n*/\n\nimport TimingObject from './timingobject.js';\nimport {calculateVector} from '../util/motionutils.js';\n\n\nclass TimeshiftConverter extends TimingObject {\n\n constructor (timingsrc, offset) {\n\t\tsuper(timingsrc);\n\t\tthis._offset = offset;\n this.eventifyDefine(\"offsetchange\", {init:true});\n\t};\n\n // extend\n eventifyInitEventArgs(name) {\n if (name == \"offsetchange\") {\n return [this._offset];\n } else {\n return super.eventifyInitEventArgs(name)\n }\n }\n\n // overrides\n onUpdateStart(arg) {\n if (arg.range != undefined) {\n arg.range = [-Infinity, Infinity];\n }\n if (arg.position != undefined) {\n // calculate timeshifted vector\n let ts = arg.timestamp;\n let new_vector = calculateVector(arg, ts + this._offset);\n arg.position = new_vector.position;\n arg.velocity = new_vector.velocity;\n arg.acceleration = new_vector.acceleration;\n arg.timestamp = ts;\n }\n return arg;\n };\n\n get offset() {return this._offset;};\n\n set offset(offset) {\n if (offset != this._offset) {\n // set offset and emulate new event from timingsrc\n this._offset = offset;\n this.__handleEvent({\n ...this.__get_timingsrc().vector,\n range: this.__get_timingsrc().range\n });\n this.eventifyTrigger(\"offsetchange\", offset);\n }\n }\n\n}\n\nexport default TimeshiftConverter;\n","/*\n\tCopyright 2020\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\n\n/**\n * Sampler for Timing Object\n * \n * - samples timing object position and emits a change event at certain frequency\n * - does not emit any events when timing object is paused\n * - options\n * - period (between samples) in ms\n * - frequency (sample frequency) in hz\n * if both given - period takes precedence\n * if none given - default period = 200 ms \n * \n * TODO\n - set refresh frequency to be sensitive\n to velocity - adapted to a fixed rate\n change in percent\n calculate percent velocity\n rate change in percent per second\n\n * \n * \n */\n\nimport eventify from '../util/eventify.js';\n\nconst DEFAULT_PERIOD = 200;\n\nclass TimingSampler {\n\n constructor (timingObject, options = {}) {\n this._to = timingObject;\n // timeout id\n this._tid;\n // period\n let {period, frequency} = options;\n this._period = DEFAULT_PERIOD;\n if (period != undefined) {\n this._period = period;\n } else if (frequency != undefined) {\n this._period = 1.0/frequency;\n } \n // Events\n eventify.eventifyInstance(this);\n\n this.eventifyDefine(\"change\", {init:true});\n // Handle timing object change event\n this._sub = this._to.on(\"change\", this._onChange.bind(this));\n }\n\n /*\n Eventify: immediate events\n */\n eventifyInitEventArgs(name) {\n if (name == \"change\" && this._to.isReady()) {\n return [this._to.pos];\n }\n }\n\n /**\n * Start/stop sampling\n */\n _onChange() {\n let v = this._to.query();\n let moving = (v.velocity != 0.0 || v.acceleration != 0.0);\n // start or stop sampling\n if (moving && this._tid == undefined) {\n this._tid = setInterval(function(){\n this._onSample();\n }.bind(this), this._period);\n }\n if (!moving && this._tid != undefined) {\n clearTimeout(this._tid);\n this._tid = undefined;\n }\n this._onSample(v.position);\n }\n\n /**\n * Sample timing object\n */\n _onSample(position) {\n position = (position != undefined) ? position : this._to.pos;\n this.eventifyTrigger(\"change\", position);\n }\n \n /**\n * Terminate sampler\n */\n clear() {\n // stop sampling\n if (this._tid) {\n clearTimeout(this._tid);\n this._tid = undefined;\n }\n // disconnect handler\n this._to.off(this._sub);\n }\n}\n\neventify.eventifyPrototype(TimingSampler.prototype);\n\nexport default TimingSampler;","\n\n\nimport Timeout from '../util/timeout.js';\nimport * as motionutils from '../util/motionutils.js';\n\n/*\n modify modulo operation\n*/\nfunction mod(n,m) {\n return ((n % m) + m) % m; \n}\n\n/*\n divide n by m, \n find q (integer) and r such that \n n = q*m + r \n*/\nfunction divmod(n, m) {\n let q = Math.floor(n/m);\n let r = mod(n, m);\n return [q,r];\n}\n\n/**\n * point n == offset + q*stride + r\n - given stride, offset\n represent point as [q, r]\n */\n\nfunction float2point(n, stride, offset) {\n return divmod(n-offset, stride);\n}\n\nfunction point2float(p, stride, offset) {\n let [q, r] = p;\n return offset + q*stride + r;\n}\n\n\n/*\n Given stride and offset, calculate nearest\n waypoints before and after given position.\n If position is exact match with waypoint,\n return [true, before, after]\n*/\nfunction stride_points(position, stride, offset) {\n let [q, r] = float2point(position, stride, offset);\n let after = [q+1, 0];\n let before = (r == 0) ? [q-1, 0]: [q, 0];\n before = point2float(before, stride, offset);\n after = point2float(after, stride, offset);\n return [(r==0), before, after];\n};\n\n\n\n/*\n \n Position callback\n\n - callback whenever the timing object position is x, \n where (x - offset) % stride === 0\n\n - analogy to setInterval - except callbacks are in position space, not\n in time space\n\n options : {\n stride - default 1\n offset - default 0\n }\n\n NOTE: pausing on x and later resuming from x triggers callback in both cases \n\n*/\n\nclass PositionCallback {\n\n constructor (timingObject, callback, options={}) {\n this._to = timingObject;\n let {stride=1, offset=0} = options;\n this._offset = offset;\n this._stride = stride;\n this._callback = callback;\n this._timeout = new Timeout(this._to, this._handleTimeout.bind(this));\n\n // timing object timingsrc event\n this._to.on(\"timingsrc\", this._onChange.bind(this));\n }\n\n _onChange(eArg, eInfo) {\n let pos = (eArg.live) ? eArg.position : this._to.pos; \n this._renewTimeout(pos);\n }\n\n _calculateTimeout(before, after) {\n let vector = this._to.query();\n let [delta, pos] = motionutils.calculateDelta(vector, [before, after]);\n if (delta == undefined) { \n return;\n } \n // check range violation\n let [rLow, rHigh] = this._to.range;\n if (pos < rLow || rHigh < pos ) {\n return [undefined, undefined];\n }\n return [vector.timestamp + delta, pos]; \n }\n\n _renewTimeout(pos) {\n this._timeout.clear();\n // find candidate points - before and after\n let [match, before, after] = stride_points(pos,\n this._stride, \n this._offset);\n // callback\n if (match) {\n this._callback(pos);\n }\n // calculate timeout to next\n let res = this._calculateTimeout(before, after);\n if (res == undefined) {\n return;\n }\n // set timeout\n let ts = res[0];\n this._timeout.setTimeout(ts, res);\n }\n \n _handleTimeout(now, arg) {\n let pos = arg[1];\n this._renewTimeout(pos);\n }\n}\n\n\nexport default PositionCallback;","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport * as utils from '../util/utils.js';\nimport eventify from '../util/eventify.js';\nimport endpoint from '../util/endpoint.js';\nimport Interval from '../util/interval.js';\nimport BinarySearch from '../util/binarysearch.js';\nimport CueCollection from './cuecollection.js';\n\nconst Relation = Interval.Relation;\n\n/*\n UTILITY\n*/\n\nfunction epoch() {\n return Date.now();\n}\n\n\nfunction asInterval(input) {\n if (input instanceof Interval || input == undefined) {\n return input;\n }\n else if (Array.isArray(input) ) {\n // support intervals as arrays\n let [low, high, lowInclude, highInclude] = input;\n return new Interval(low, high, lowInclude, highInclude);\n } else {\n throw new Error (\"input not an Interval\", input);\n }\n}\n\n\nfunction cue_to_string(cue) {\n if (cue) {\n return `${cue.interval.toString()} ${cue.data}`;\n } else {\n return `${cue}`;\n } \n}\n\n/*\n Add cue to array\n - does not add if cue already exists\n - returns array length\n*/\nfunction addCueToArray(arr, cue) {\n // cue equality defined by key property\n if (arr.length == 0) {\n arr.push(cue);\n } else {\n let idx = arr.findIndex(function (_cue) {\n return _cue.key == cue.key;\n });\n if (idx == -1) {\n arr.push(cue);\n }\n }\n return arr.length;\n};\n\n/*\n Remove cue from array\n - noop if cue does not exist\n - returns array empty\n*/\nfunction removeCueFromArray(arr, cue) {\n // cue equality defined by key property\n if (arr.length == 1) {\n if (arr[0].key == cue.key) {\n arr.shift();\n }\n return arr.length == 0;\n }\n else if (arr.length == 0) {\n return true;\n } else {\n let idx = arr.findIndex(function (_cue) {\n return _cue.key == cue.key;\n });\n if (idx > -1) {\n arr.splice(idx, 1);\n }\n return arr.length == 0;\n }\n};\n\n/*\n Replace cue in array\n - noop if cue does not exist in array\n - returns sucess\n*/\n\nfunction replaceCueInArray (arr, cue) {\n if (arr.length == 0) {\n return false;\n } else if (arr.length == 1) {\n if (arr[0].key == cue.key) {\n arr[0] = cue;\n return true;\n }\n } else {\n let idx = arr.findIndex(function (_cue) {\n return _cue.key == cue.key;\n });\n if (idx > -1) {\n arr[idx] = cue;\n return true;\n }\n }\n return false;\n}\n\n\n/*\n Setup ID's for cue buckets.\n*/\nconst CueBucketIds = [0, 10, 100, 1000, 10000, 100000, Infinity];\nvar getCueBucketId = function (length) {\n for (let i=0; i {\n return this._submit.bind(this)();\n });\n }\n\n _push(cue_args) {\n // append cue args\n let m = this._cues.length;\n let was_empty = m == 0;\n let n = cue_args.length;\n this._cues.length += n;\n for (let i=0; i 0) {\n // batch done immediately \n // will be submitted by donePromise in next microtask\n this._done.value = true;\n }\n }\n\n _submit() {\n let result = [];\n // carry out update if necessary\n if (this._cues.length > 0) {\n result = this._ds.update(this._cues, this._options); \n }\n // reset cue arg builder\n this._reset();\n // update result\n return result;\n } \n \n /*\n add or change single cue\n \n if both interval and data are undefined\n this is not interpreted as remove,\n but as a cue with no interval and a data value set\n to undefined\n */\n addCue(key, interval, data) {\n let cue_arg = {key:key};\n cue_arg.interval = interval; \n if (arguments.length > 2) {\n cue_arg.data = data;\n }\n this._push([cue_arg]);\n return this;\n }\n\n /* remove single cue */\n removeCue(key) {\n this._push([{key:key}]);\n return this;\n }\n\n /* load array of cue args into argbuilder */\n update(cue_args) {\n this._push(cue_args);\n }\n\n /* clear args currently in argbuilder */\n clear() {\n this._cues = [];\n return this;\n }\n\n /* manually submit cue args from cue arg builder */\n submit() {\n if (this._options.autosubmit) {\n throw new Error(\"manual submit while options.autosubmit is true\");\n }\n // mark batch as done\n // will be submitted by donePromise in next microtask\n this._done.value = true;\n }\n}\n\n\n/*\n this implements Dataset, a data collection supporting\n efficient lookup of cues tied to intervals on the timeline\n\n - cues may be tied to one or two points on the timeline, this\n is expressed by an Interval.\n - cues are indexed both by key and by intervals\n - the interval index is divided into a set of CueBuckets,\n based on cue interval length, for efficient lookup\n*/\n\nclass Dataset extends CueCollection {\n\n constructor(options) {\n super(options);\n\n this._map = new Map();\n this._builder = new CueArgBuilder(this);\n\n /*\n Initialise set of CueBuckets\n Each CueBucket is responsible for cues of a certain length\n */\n this._cueBuckets = new Map(); // CueBucketId -> CueBucket\n for (let i=0; i -1) {\n this._update_callbacks.splice(index, 1);\n }\n };\n\n\n _notify_callbacks (batchMap, relevanceInterval) {\n this._update_callbacks.forEach(function(handle) {\n handle.handler(batchMap, relevanceInterval);\n });\n };\n\n /***************************************************************\n MAP METHODS\n */\n\n set (key, value) {\n throw new Error(\"not implemented\");\n }\n\n delete (key) {\n throw new Error(\"not implemented\");\n }\n\n\n /***************************************************************\n CUE ARG BUILDER\n */\n \n makeBuilder(options) {\n return new CueArgBuilder(this, options);\n }\n\n // not really useful (v2 complience)\n get builder () {return this._builder;};\n\n \n /***************************************************************\n ADD CUE, REMOVE CUE\n\n - COMPATIBILTY WITH V2\n - SAFE TO USE repeatedly (batched using promise)\n */\n\n addCue(key, interval, data) {\n if (arguments.length > 2) {\n this._builder.addCue(key, interval, data);\n } else {\n this._builder.addCue(key, interval);\n }\n return this;\n }\n\n removeCue(key) {\n this._builder.removeCue(key);\n return this;\n }\n\n get updateDone() {return this._builder.updateDone};\n\n /***************************************************************\n ADD CUE, REMOVE CUE - INTERACTIVE USE\n\n - CONVENIENCE for interactive use\n - COMPATIBILTY WITH V2\n - NOT RECOMMENDED TO USE repeatedly (batched using promise)\n */\n\n _addCue(key, interval, data, options) {\n return this.update({key:key, interval:interval, data:data}, options);\n }\n\n _removeCue(key, options) {\n return this.update({key:key}, options);\n }\n\n /***************************************************************\n UPDATE\n\n - insert, replace or delete cues\n\n update(cues, equals, check)\n\n ordered list of cues to be updated\n - equality function for data objects\n\n cue = {\n key:key,\n interval: Interval,\n data: data\n }\n\n required\n - cue.key property is defined and value is != undefined\n - if cue.interval != undefined, it must be instance of Interval\n\n EXAMPLES\n\n // INSERT (no pre-existing cue)\n\n cue = {key:1, interval: new Interval(3,4), data: {}}\n // insert cue with only interval\n cue = {key:1, interval: new Interval(3,4)}\n // insert cue with only data\n cue = {key:1, data: {}}\n\n\n // REPLACE (pre-existing cue)\n preexisting_cue = {key:1, interval: new Interval(3,4), data: {}}\n\n cue = {key:1, interval: new Interval(3,5), data: {foo:\"bar\"}}\n // replace interval, keep data\n cue = {key:1, interval: new Interval(3,5)}\n // replace interval, delete data\n cue = {key:1, interval: new Interval(3,5), data: undefined\n // replace data, keep interval\n cue = {key:1, data: {foo:\"bar\"}}\n // replace data, delete interval\n cue = {key:1, interval: undefined, data: {foo:\"bar\"}}\n\n // DELETE (pre-existing)\n cue = {key:1}\n // delete interval, keep data\n cue = {key:1, interval: undefined}\n // delete data, keep interval\n cue = {key:1, data: undefined}\n\n\n Update returns a list of event items - describes the effects of an update.\n {\n new: new_cue,\n old: old_cue,\n delta: {\n interval: Delta,\n data: Delta\n }\n }\n\n with independent delta values for interval and data:\n Delta.NOOP: 0\n Delta.INSERT: 1\n Delta.REPLACE: 2\n Delta.DELETE: 3\n\n Duplicates\n - if there are multiple cue operations for the same key,\n within the same batch of cues,\n these will be processed in order.\n\n - The old cue will always be the state of the cue,\n before the batch started.\n\n - The returned delta values will be calcultated relative to\n the cue before the batch started (old).\n\n This way, external mirroring observers may will be able to\n replicate the effects of the update operation.\n\n ***************************************************************/\n\n update(cues, options = {}) {\n const batchMap = new Map();\n let current_cue;\n let has_interval, has_data;\n\n // options\n let {debug=false, equals} = options;\n\n // support single cue arg for convenience\n if (!utils.isIterable(cues)) {\n cues = [cues];\n }\n\n /***********************************************************\n process all cues\n ***********************************************************/\n const epoch_ts = epoch();\n const info = {\n ts: epoch_ts,\n author: options.author\n };\n\n for (let cue of cues) {\n\n /*******************************************************\n check validity of cue argument\n *******************************************************/\n\n if (cue == undefined || !cue.hasOwnProperty(\"key\") || cue.key == undefined) {\n\n if (cue == undefined) {\n throw new Error(\"cue is undefined\");\n } else if (!cue.hasOwnProperty(\"key\")) {\n throw new Error(\"cue missing key property\", cue);\n } else if (cue.key == undefined) {\n throw new Error(\"cue.key is undefined\", cue); \n }\n }\n\n has_interval = cue.hasOwnProperty(\"interval\");\n has_data = cue.hasOwnProperty(\"data\");\n if (has_interval) {\n cue.interval = asInterval(cue.interval);\n }\n\n\n /*******************************************************\n adjust cue so that it correctly represents\n the new cue to replace the current cue\n - includes preservation of values from current cue\n *******************************************************/\n\n current_cue = this._map.get(cue.key);\n if (current_cue == undefined) {\n // make sure properties are defined\n if (!has_interval) {\n cue.interval = undefined;\n }\n if (!has_data) {\n cue.data = undefined;\n }\n } else if (current_cue != undefined) {\n if (!has_interval && !has_data) {\n // make sure properties are defined\n cue.interval = undefined;\n cue.data = undefined;\n } else if (!has_data) {\n // REPLACE_INTERVAL, preserve data\n cue.data = current_cue.data;\n } else if (!has_interval) {\n // REPLACE_DATA, preserve interval\n cue.interval = current_cue.interval;\n } else {\n // REPLACE CUE\n }\n }\n\n /*******************************************************\n update cue\n - update _map\n - update cueBuckets\n - create batchMap\n *******************************************************/\n this._update_cue(batchMap, current_cue, cue, info, options);\n }\n\n // flush all buckets so updates take effect\n this._call_buckets(\"flush\");\n\n if (batchMap.size > 0) {\n\n /*\n create events without delta property\n and accumulate relevance interval for batch\n */\n let relevance = {low: Infinity, high: -Infinity};\n\n // create list of events and remove delta property\n let items = [...batchMap.values()].map(item => {\n if (item.new && item.new.interval) {\n relevance.low = endpoint.min(relevance.low, item.new.interval.endpointLow);\n relevance.high = endpoint.max(relevance.high, item.new.interval.endpointHigh);\n }\n if (item.old && item.old.interval) {\n relevance.low = endpoint.min(relevance.low, item.old.interval.endpointLow);\n relevance.high = endpoint.max(relevance.high, item.old.interval.endpointHigh);\n }\n return {key:item.key, new:item.new, old:item.old, info: item.info};\n });\n\n // extra filter items to remove NOOP transitions\n let event_items = items.filter((item) => {\n let delta = cue_delta(item.new, item.old, equals);\n return (delta.interval != Delta.NOOP || delta.data != Delta.NOOP);\n });\n\n // event notification\n this._notifyEvents(event_items);\n\n // create relevance Interval\n let relevanceInterval = undefined;\n if (relevance.low != Infinity) {\n relevanceInterval = Interval.fromEndpoints(relevance.low, relevance.high);\n }\n\n /*\n notify sequencer last so that change event\n from the dataset will be applied before change\n events from sequencers.\n */\n this._notify_callbacks(batchMap, relevanceInterval);\n \n // debug\n if (debug) {this.integrity();}\n return items;\n }\n // debug\n if (debug) {this.integrity();}\n return [];\n };\n\n\n\n /***************************************************************\n UPDATE CUE\n\n update operation for a single cue\n\n - update _map\n - generate entry for batchMap\n - update CueBucket\n ***************************************************************/\n\n _update_cue(batchMap, current_cue, cue, info, options) {\n\n let old_cue, new_cue;\n let item, _item;\n let oldCueBucket, newCueBucket;\n let low_changed, high_changed;\n let remove_needed, add_needed;\n\n // options\n let {chaining=true, safe=false, equals} = options;\n \n if (current_cue === cue) {\n throw Error(\"illegal cue arg: same object as current cue\");\n }\n\n // check for equality\n let delta = cue_delta(current_cue, cue, equals);\n\n // (NOOP, NOOP)\n if (delta.interval == Delta.NOOP && delta.data == Delta.NOOP) {\n item = {\n key:cue.key, new:current_cue,\n old:current_cue, delta: delta\n }\n batchMap.set(cue.key, item);\n return;\n }\n\n\n /***********************************************************\n update _map and batchMap\n ***********************************************************/\n\n if (current_cue == undefined) {\n // INSERT - add cue object to _map\n\n // cue info: add if missing\n if (cue.info == undefined) {\n cue.info = {\n ts: info.ts,\n change_ts: info.ts,\n change_id: 0\n }\n }\n\n old_cue = undefined;\n new_cue = (safe)? Object.freeze(cue) : cue;\n this._map.set(cue.key, new_cue);\n\n\n } else if (cue.interval == undefined && cue.data == undefined) {\n // DELETE - remove cue object from _map\n old_cue = current_cue;\n new_cue = undefined;\n this._map.delete(cue.key);\n\n // cue info: noop\n\n } else {\n // REPLACE\n\n // cue info - update if missing\n // preserve ts from current cue, update update_ts\n if (cue.info == undefined) {\n cue.info = {\n ts: current_cue.info.ts,\n change_ts: info.ts,\n change_id: current_cue.info.change_id + 1\n };\n }\n\n /*\n Solution used to be in-place modification\n of current cue.\n Now we instead implement replace by inserting\n a new cue object as current cue.\n Since current cue is referenced both in\n _map and in pointMap - it must be replaced both\n places.\n\n Adjustments to pointMap as a result of interval\n changes are handled further down\n\n Another design option would be to let point map\n manage only keys of cues. This however would \n impose an extra map lookup per item in lookup - \n so better to pay this modest price in update\n */\n old_cue = current_cue;\n new_cue = {\n key: cue.key,\n interval: cue.interval,\n data: cue.data,\n info: cue.info\n }\n\n if (safe) {\n new_cue = Object.freeze(new_cue);\n }\n\n // replace in cue map\n this._map.set(cue.key, new_cue);\n\n // replace in point map\n // - only necessary if old cue is in pointMap\n // i.e. if old_cue has interval\n if (old_cue.interval) {\n let bid = getCueBucketId(old_cue.interval.length);\n let cueBucket = this._cueBuckets.get(bid);\n // replace for low\n cueBucket.replace_endpoint(old_cue.interval.low, new_cue);\n // replace for high\n if (!old_cue.singular) {\n cueBucket.replace_endpoint(old_cue.interval.high, new_cue);\n }\n }\n }\n item = {key:cue.key, new:new_cue, old:old_cue, delta:delta, info};\n\n /*\n if this item has been set earlier in batchMap\n restore the correct old_cue by getting it from\n the previous batchMap item\n\n recalculate delta relative to old_cue\n - continue processing with the original (delta, old_cue) defined\n above, as this is required to correctly change cueBuckets\n which have already been affected by previous item.\n */\n if (chaining) {\n _item = batchMap.get(cue.key);\n if (_item != undefined) {\n item.old = _item.old;\n item.delta = cue_delta(new_cue, item.old, equals);\n }\n }\n\n batchMap.set(cue.key, item)\n\n //console.log(\"OLD:\", cue_to_string(old_cue));\n //console.log(\"NEW:\", cue_to_string(new_cue));\n\n /***********************************************************\n update cueBuckets\n\n - use delta.interval to avoid unnessesary changes\n\n - interval may change in several ways:\n - low changed\n - high changed\n - low and high changed\n - changed intervals may stay in bucket or change bucket:\n - changing to/from singular may require special consideration\n with respect to how many endpoints are being updated\n - singular -> singular\n - singular -> regular\n - regular -> singular\n - regular -> regular\n - changes to interval.lowInclude and interval highInclude\n do not require any changes to CueBuckets, as long\n as interval.low and interval.high values stay unchanged.\n ***********************************************************/\n\n if (delta.interval == Delta.NOOP) {\n // no changes to interval - no change needed in pointMap \n return;\n } else if (delta.interval == Delta.INSERT) {\n remove_needed = false;\n add_needed = true;\n low_changed = true;\n high_changed = true;\n } else if (delta.interval == Delta.DELETE) {\n remove_needed = true;\n add_needed = false;\n low_changed = true;\n high_changed = true;\n } else if (delta.interval == Delta.REPLACE) {\n remove_needed = true;\n add_needed = true;\n low_changed = new_cue.interval.low != old_cue.interval.low;\n high_changed = new_cue.interval.high != old_cue.interval.high;\n }\n\n /*\n old cue and new cue might not belong to the same cue bucket\n */\n if (remove_needed){\n let old_bid = getCueBucketId(old_cue.interval.length);\n oldCueBucket = this._cueBuckets.get(old_bid);\n }\n if (add_needed) {\n let new_bid = getCueBucketId(new_cue.interval.length);\n newCueBucket = this._cueBuckets.get(new_bid);\n }\n\n /*\n if old CueBucket is different from the new cue Buckets\n both low and high must be moved, even it one was not\n changed\n */\n if (oldCueBucket && newCueBucket) {\n if (oldCueBucket != newCueBucket) {\n remove_needed = true;\n add_needed = true;\n low_changed = true;\n high_changed = true;\n }\n }\n\n /*\n dispatch add and remove operations for interval points\n\n cues in CueBucket may be removed using a copy of the cue,\n because remove is by key.\n\n cues added to CueBucket must be the correct object\n (current_cue), so that later in-place modifications become\n reflected in CueBucket.\n */\n\n // update low point - if changed\n if (low_changed) {\n if (remove_needed) {\n oldCueBucket.del_endpoint(old_cue.interval.low, old_cue);\n }\n if (add_needed) {\n newCueBucket.add_endpoint(new_cue.interval.low, new_cue);\n }\n }\n // update high point - if changed\n if (high_changed) {\n if (remove_needed && !old_cue.interval.singular) {\n oldCueBucket.del_endpoint(old_cue.interval.high, old_cue);\n }\n if (add_needed && !new_cue.interval.singular) {\n newCueBucket.add_endpoint(new_cue.interval.high, new_cue);\n }\n }\n }\n\n\n /*\n INTERNAL FUNCTION\n execute method across all cue buckets\n and aggregate results\n */\n _call_buckets(method, ...args) {\n const arrays = [];\n for (let cueBucket of this._cueBuckets.values()) {\n let cues = cueBucket[method](...args);\n if (cues != undefined && cues.length > 0) {\n arrays.push(cues);\n }\n }\n return utils.array_concat(arrays);\n };\n\n\n /*\n LOOKUP ENDPOINTS\n\n returns (endpoint, cue) for all endpoints covered by given interval\n\n returns:\n - [{endpoint: endpoint, cue:cue}]\n */\n\n lookup_endpoints(interval) {\n interval = asInterval(interval);\n return this._call_buckets(\"lookup_endpoints\", interval);\n };\n\n\n /*\n LOOKUP\n */\n\n lookup(interval, mask) {\n interval = asInterval(interval);\n return this._call_buckets(\"lookup\", interval, mask);\n };\n\n\n /*\n REMOVE CUES BY INTERVAL\n */\n lookup_delete(interval, mask, options={}) {\n interval = asInterval(interval);\n const cues = this._call_buckets(\"lookup_delete\", interval, mask);\n // remove from _map and make event items\n const items = [];\n const info = {\n ts: epoch(),\n author: options.author\n };\n let cue;\n for (let i=0; i cue.interval == undefined);\n\n let count_buckets = cues.length;\n let count_no_interval = no_interval_cues.length;\n let count_map = this._map.size;\n let diff = count_map - count_buckets - count_no_interval;\n if (diff != 0) {\n console.log(\"count buckets\", count_buckets);\n console.log(\"count no intervals\", count_no_interval);\n console.log(\"count map\", count_map);\n console.log(\"count diff\", diff);\n throw new Error(\"inconsistent cue count\");\n }\n\n // check that cue maps are non overlapping\n let bucket_map = new Map(cues.map(cue => [cue.key, cue]));\n let map_map = new Map([...this._map.entries()].filter(([key, cue]) => {\n return (cue.interval != undefined);\n }));\n\n let missing = utils.map_difference(bucket_map, map_map);\n if (missing.size > 0) {\n console.log(\"buckets missing cues:\")\n console.log([...missing.keys()])\n throw new Error(`buckets missing cues: ${[...missing.keys()]}`);\n }\n \n missing = utils.map_difference(map_map, bucket_map);\n if (missing.size > 0) {\n throw new Error(`buckets too many cues: ${[...missing.keys()]}`);\n }\n\n return {\n cues: cues.length,\n points: points.length\n };\n };\n\n}\n\n\nDataset.Delta = Delta;\nDataset.cue_delta = cue_delta;\nDataset.cue_equals = cue_equals;\n\n\n/*\n CueBucket is a bucket of cues limited to specific length\n*/\n\n\nclass CueBucket {\n\n\n constructor(maxLength) {\n\n // max length of cues in this bucket\n this._maxLength = maxLength;\n\n /*\n pointMap maintains the associations between values (points on\n the timeline) and cues that reference such points. A single point value may be\n referenced by multiple cues, so one point value maps to a list of cues.\n\n value -> [cue, ....]\n */\n this._pointMap = new Map();\n\n\n /*\n pointIndex maintains a sorted list of numbers for efficient lookup.\n A large volume of insert and remove operations may be problematic\n with respect to performance, so the implementation seeks to\n do a single bulk update on this structure, for each batch of cue\n operations (i.e. each invocations of addCues). In order to do this\n all cue operations are processed to calculate a single batch\n of deletes and a single batch of inserts which then will be applied to\n the pointIndex in one atomic operation.\n\n [1.2, 3, 4, 8.1, ....]\n */\n this._pointIndex = new BinarySearch();\n\n // bookeeping during batch processing\n this._created = new Set(); // point\n this._dirty = new Set(); // point\n\n };\n\n\n /*\n\n ENDPOINT BATCH PROCESSING\n\n Needs to translate endpoint operations into a minimum set of\n operations on the pointIndex.\n\n To do this, we need to record points that are created and\n points that are removed.\n\n The total difference that the batch of cue operations\n amounts to is expressed as one list of values to be\n deleted, and and one list of values to be inserted.\n The update operation of the pointIndex will process both\n in one atomic operation.\n\n On flush both the pointMap and the pointIndex will be brought\n up to speed\n\n created and dirty are used for bookeeping during\n processing of a cue batch. They are needed to\n create the correct diff operation to be applied on pointIndex.\n\n created : includes values that were not in pointMap\n before current batch was processed\n\n dirty : includes values that were in pointMap\n before current batch was processed, and that\n have been become empty at least at one point during cue\n processing.\n\n created and dirty are used as temporary alternatives to pointMap.\n after the cue processing, pointmap will updated based on the\n contents of these two.\n\n process buffers operations for pointMap and index so that\n all operations may be applied in one batch. This happens in flush\n */\n\n add_endpoint(point, cue) {\n let init = (this._pointMap.size == 0);\n let cues = (init) ? undefined : this._pointMap.get(point);\n if (cues == undefined) {\n this._pointMap.set(point, [cue]);\n this._created.add(point);\n } else {\n cues.push(cue);\n //addCueToArray(cues, cue);\n }\n }\n\n del_endpoint(point, cue) {\n let init = (this._pointMap.size == 0);\n let cues = (init) ? undefined : this._pointMap.get(point);\n if (cues != undefined) {\n let empty = removeCueFromArray(cues, cue);\n if (empty) {\n this._dirty.add(point);\n }\n }\n };\n\n /* \n in case of data update without touching the interval\n the new cue needs to be insert in place of the old\n */\n replace_endpoint(point, cue) {\n let init = (this._pointMap.size == 0);\n let cues = (init) ? undefined : this._pointMap.get(point);\n if (cues != undefined) {\n let ok = replaceCueInArray (cues, cue);\n if (!ok) {\n console.log(\"WARNING: attempt to replace non-existent cue in pointMap\")\n }\n }\n }\n\n\n /*\n Batch processing is completed\n Commit changes to pointIndex and pointMap.\n\n pointMap\n - update with contents of created\n\n pointIndex\n - points to delete - dirty and empty\n - points to insert - created and non-empty\n\n it is possible that a cue ends up in both created and dirty\n\n */\n flush() {\n if (this._created.size == 0 && this._dirty.size == 0) {\n return;\n }\n\n // update pointIndex\n let to_remove = [];\n let to_insert = [];\n for (let point of this._created.values()) {\n let cues = this._pointMap.get(point);\n if (cues.length > 0) {\n to_insert.push(point);\n } else {\n this._pointMap.delete(point);\n }\n }\n for (let point of this._dirty.values()) {\n let cues = this._pointMap.get(point);\n if (cues == undefined) {\n // point already deleted from created set - ignore\n continue;\n }\n if (cues.length == 0) {\n to_remove.push(point);\n this._pointMap.delete(point);\n }\n }\n this._pointIndex.update(to_remove, to_insert);\n // cleanup\n this._created.clear();\n this._dirty.clear();\n };\n\n\n /*\n LOOKUP_ENDPOINTS\n\n returns all (endpoint, cue) pairs where\n - endpoint is a cue endpoint (cue.endpointLow or cue.endpointHigh)\n - endpoint is INSIDE search interval\n - [{endpoint:endpoint, cue: cue}]\n\n - a given endpoint may appear multiple times in the result,\n as multiple cues may be tied to the same endpoint\n - a given cue may appear two times in the result, if\n both cue.endpointLow and cue.endpointHigh are both INSIDE interval\n - a singular cue will appear only once\n - ordering: no specific order is guaranteed\n - results are concatenated from multiple CueBuckets\n - internally in a single CueBucket\n - no defined order for cues tied to the same endpoint\n - the natural order is endpoint order\n - but this can be added on the outside if needed\n - no order is defined if two cues have exactly the\n same endpoint\n\n */\n\n lookup_endpoints(interval) {\n if (this._pointMap.size == 0) {\n return [];\n }\n const broader_interval = new Interval(interval.low, interval.high, true, true);\n const points = this._pointIndex.lookup(broader_interval);\n const result = [];\n const len = points.length;\n let point, _endpoint;\n for (let i=0; i this._maxLength) {\n return cues;\n }\n\n /*\n handle match with COVERS separately\n\n search left of search interval for cues\n that covers the search interval\n search left is limited by CueBucket maxlength\n left_interval: [interval.high-maxLength, interval.low]\n\n it would be possible to search right too, but we\n have to choose one.\n */\n if (mask & Relation.COVERS) {\n\n\n let low = interval.high - this._maxLength;\n let high = interval.low;\n // protect against float rounding effects creating\n // high < low by a very small margin\n [low, high] = [Math.min(low, high), Math.max(low, high)];\n let left_interval = new Interval(low, high, true, true);\n this._lookup_cues(left_interval)\n .forEach(function(cue){\n if (cue.interval.match(interval, Relation.COVERS)) {\n cues.push(cue);\n }\n });\n }\n\n return cues;\n }\n\n\n /*\n REMOVE CUES\n */\n lookup_delete(interval, mask) {\n /*\n update pointMap\n - remove all cues from pointMap\n - remove empty entries in pointMap\n - record points that became empty, as these need to be deleted in pointIndex\n - separate into two bucketes, inside and outside\n */\n const cues = this.lookup(interval, mask);\n const to_remove = [];\n let cue, point, points;\n for (let i=0; i 0) {\n throw new Error(`pointMap missing points: ${[...missing]}`);\n }\n \n missing = utils.set_difference(map_point_set, index_point_set);\n if (missing.size > 0) {\n throw new Error(`pointIndex missing points: ${[...missing]}`);\n }\n }\n\n /*\n invariable - pointIndex shall always be sorted and not contain duplicates\n */\n let points = [...this._pointIndex.values()];\n if (points.length != index_point_set.size) {\n throw new Error(\"pointIndex include duplicate points\");\n }\n for (let i=1; i= points[i]) {\n throw new Error(\"pointIndex not ordered\");\n } \n }\n\n /**\n * invariable - pointMap point -> cues \n * cues shall only include cues which are relevant to given point\n */\n for (let point of points) {\n let cues = this._pointMap.get(point);\n for (let cue of cues) {\n // figure out if point is endpoint low or high\n if (point == cue.interval.low) {\n continue;\n } else if (point == cue.interval.high) {\n continue;\n } else {\n console.log(\"POINT:\", point); \n console.log(\"CUE:\", cue.interval.toString());\n throw new Error(\"pointMap: wrong cue\");\n }\n } \n }\n\n\n /**\n * invariable - all endpoints from all cues from pointMap are found as points in pointMap\n */\n\n for (let _cue_list of [...this._pointMap.values()]) {\n for (let cue of _cue_list) {\n for (let p of [cue.interval.low, cue.interval.high]) {\n if (!this._pointMap.has(p)) {\n throw new Error(`cue found with low or high point not in pointMap ${p} -> ${cue.interval.toString()} `);\n }\n }\n }\n }\n\n\n /*\n invariable - all cues in pointMap with same key are same object\n */\n\n // collect all cues from pointMap\n let _cues = [];\n for (let _cue_list of this._pointMap.values()) {\n for (let cue of _cue_list) {\n _cues.push(cue);\n }\n }\n\n // remove and check duplicates\n let cueMap = new Map();\n for (let cue of _cues) {\n let _cue = cueMap.get(cue.key);\n if (_cue == undefined) {\n cueMap.set(cue.key, cue);\n } else {\n // duplicate\n if (cue !== _cue) {\n throw new Error(\"pointMap: different cue objects for same key\");\n }\n }\n }\n let cues = [...cueMap.values()];\n\n /**\n * invariable - all cues belong to this bucket\n */\n\n for (let cue of cues.values()) {\n // check that cue belongs to this bucket\n if (cue.interval.length > this._maxLength) {\n throw new Error(`cue in wrong cue bucket ${this._maxLength}, ${cue.interval.toString()}`);\n }\n }\n\n return [{\n maxLength: this._maxLength,\n points: [...this._pointMap.keys()],\n cues: cues\n }];\n };\n}\n\n// module definition\nexport default Dataset;\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport CueCollection from './cuecollection.js';\nimport {array_concat, map_difference} from '../util/utils.js';\nimport Interval from '../util/interval.js';\n\n/*\n Subset provides read-only access to subset of a source Dataset\n\n - \n - : if defined only include cues that match the interval\n - : filter by cue key\n function keep(key) returns boolena\n - : filter by cue data\n function keep(data) returns boolean\n - : change cue data\n function convert(data) returns data\n NOTE: filtering occurs BEFORE convert\n and only impacts the presentation of cues\n WARNING: it is possible to change the value\n in such a way that filtering appears incorrect\n\n This subset implementation is STATELESS\n It does not manage its own state, only implements a\n stateless frontend over its source dataset.\n\n*/\n\nclass Subset extends CueCollection {\n\n constructor(dataset, options={}) {\n super(options);\n this._key_filter = options.key_filter;\n this._data_filter = options.data_filter;\n this._interval = options.interval;\n this._data_convert = options.data_convert;\n this._size = 0;\n\n // Callbacks\n this._callbacks = [];\n\n // Source Dataset\n this._src_ds = dataset;\n let cb = this._onDatasetCallback.bind(this)\n this._src_ds_cb = this._src_ds.add_callback(cb);\n }\n\n\n /***************************************************************\n ACCESSORS\n ***************************************************************/\n\n get datasource () {\n return this._src_ds;\n }\n\n get dataset () {\n return this._src_ds;\n }\n\n\n get interval () {\n return this._interval;\n }\n\n set interval (itv) {\n this._setInterval(itv);\n }\n\n\n /***************************************************************\n EVENT CALLBACKS - FOR SEQUENCERS\n ***************************************************************/\n\n add_callback (handler) {\n let handle = {\n handler: handler\n }\n this._callbacks.push(handle);\n return handle;\n };\n\n\n del_callback (handle) {\n let index = this._callbacks.indexof(handle);\n if (index > -1) {\n this._callbacks.splice(index, 1);\n }\n };\n\n\n _notify_callbacks (batchMap, relevanceInterval) {\n this._callbacks.forEach(function(handle) {\n handle.handler(batchMap, relevanceInterval);\n });\n };\n\n\n /***************************************************************\n FILTER & CONVER\n ***************************************************************/\n\n /* \n Keep cue \n */\n\n _cue_keep(cue) {\n if (cue == undefined) {\n return false;\n }\n // check if cue matches interval\n if (this._interval) {\n if (!this._interval.match(cue.interval)) {\n return false;\n }\n }\n // check key filter\n if (this._key_filter) {\n if (!this._key_filter(cue.key)) {\n return false;\n }\n }\n // check data filter\n if (this._data_filter) {\n if (!this._data_filter(cue.data)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Convert cue\n */\n _cue_convert(cue) {\n if (cue != undefined && this._data_convert) {\n // copy\n return {\n key: cue.key,\n interval: cue.interval,\n data: this._data_convert(cue.data)\n }\n }\n return cue;\n }\n\n /**\n * Filter (and modify) event items based on key_filter and data_filter\n */\n\n _items_filter_convert(items) {\n let _items = [];\n for (let item of items) {\n if (item.new == undefined && item.old == undefined) {\n continue;\n }\n /* \n use cue filter function to check relevance of both old and new\n consider change of unrelevant cue into relevant cue.\n old cue would be non-relevant, new cue would be relevant\n Since old cue was not part of the subset before, it needs\n to be removed from the item - effectively turning the change\n operation into an add operation. \n */\n let _old = (this._cue_keep(item.old)) ? item.old : undefined;\n let _new = (this._cue_keep(item.new)) ? item.new : undefined;\n if (_old == undefined && _new == undefined) {\n continue;\n }\n // convert\n _old = this._cue_convert(_old);\n _new = this._cue_convert(_new);\n // push\n _items.push({key:item.key, new: _new, old: _old});\n }\n return _items;\n }\n\n\n /***************************************************************\n LOOKUP\n ***************************************************************/\n\n _check_interval(interval) {\n if (this._interval) {\n // subset interval\n if (interval) {\n // lookup interval - find intersection\n let intersects = Interval.intersect(interval, this._interval);\n if (intersects.length == 0) {\n console.log(`warning - lookup interval ${interval.toString()} outside the subset interval ${this._interval.toString()}`);\n return [];\n } else {\n interval = intersects[0];\n }\n } else {\n // no lookup interval - use subset interval \n interval = this._interval;\n }\n }\n return interval;\n }\n\n /** \n * lookup cues\n */\n\n lookup(interval, mask) {\n let _interval = this._check_interval(interval);\n let cues;\n if (_interval) {\n cues = this.datasource.lookup(_interval, mask);\n } else {\n cues = [...this.datasource.values()];\n }\n // filter & convert cues\n return cues.filter(this._cue_keep, this)\n .map(this._cue_convert, this);\n }\n\n /* \n lookup endpoints\n used by sequencers\n */\n\n lookup_endpoints(interval) {\n let _interval = this._check_interval(interval);\n let items = this.datasource.lookup_endpoints(_interval);\n // filter and convert\n return items.filter((item) => {\n return this._cue_keep(item.cue);\n }, this).map((item) => {\n return {endpoint: item.endpoint, cue: this._cue_convert(item.cue)};\n }, this);\n }\n\n /***************************************************************\n INITIAL STATE\n ***************************************************************/\n\n eventifyInitEventArgs(name) {\n if (name == \"batch\" || name == \"change\") {\n // find cues\n let cues = this.lookup();\n // make event items\n let items = cues.map((cue) => {\n return {key:cue.key, new:cue, old:undefined};\n });\n // sort\n this.sortItems(items);\n return (name == \"batch\") ? [items] : items;\n }\n }\n\n /***************************************************************\n DATASET CALLBACK\n ***************************************************************/\n\n _onDatasetCallback(eventMap, relevanceInterval) {\n let items = [...eventMap.values()];\n items = this._items_filter_convert(items);\n // update size\n for (let item of items) {\n if (item.new != undefined && item.old == undefined) {\n // add\n this._size += 1;\n } else if (item.new == undefined && item.old != undefined) {\n // remove\n this._size -= 1;\n } \n } \n // forward as events\n super._notifyEvents(items);\n // forward as callbacks\n let batchMap = new Map(items.map((item) => {\n return [item.key, item];\n }));\n if (this._interval) {\n relevanceInterval = Interval.intersect(this._inverval, relevanceInterval);\n }\n this._notify_callbacks(batchMap, relevanceInterval);\n }\n\n\n /***************************************************************\n SET INTERVAL\n ***************************************************************/\n\n _setInterval (itv) {\n if (!itv instanceof Interval) {\n throw new Error(\"must be interval\", itv.toString());\n }\n if (!this._interval || !this._interval.equals(itv)) {\n // current cues (before interval update)\n let current_cues = this.lookup();\n // update interval\n this._interval = itv;\n // cues (after interval update)\n let new_cues = this.datasource.lookup(itv);\n // filter & convert cues\n new_cues = new_cues\n .filter(this._cue_keep, this)\n .map(this._cue_convert, this);\n // switch to map representation\n let currentCueMap = new Map([...current_cues].map((cue) => {\n return [cue.key, cue];\n }));\n let newCueMap = new Map([...new_cues].map((cue) => {\n return [cue.key, cue];\n }));\n // exit and enter cues\n let exitCueMap = map_difference(currentCueMap, newCueMap);\n let enterCueMap = map_difference(newCueMap, currentCueMap);\n // make list of event items\n let exitItems = [...exitCueMap.values()].map((cue) => {\n return {key: cue.key, new:undefined, old: cue}\n });\n let enterItems = [...enterCueMap.values()].map((cue) => {\n return {key: cue.key, new:cue, old: undefined}\n });\n // update size\n this._size -= exitItems.length;\n this._size += enterItems.length; \n // event notification\n const items = array_concat([exitItems, enterItems], {copy:false, order:true});\n this._notifyEvents(items);\n }\n }\n\n /***************************************************************\n MAP ACCESSORS\n ***************************************************************/\n\n get size () {\n return this._size;\n }\n\n has(key) {\n return (this.get(key) != undefined);\n };\n\n get(key) {\n let cue = super.get(key);\n if (cue != undefined && this._cue_keep(cue)) {\n return this._cue_convert(cue);\n }\n };\n\n keys() {\n return this.values().map((cue => {\n return cue.key;\n }));\n };\n\n values() {\n return [...super.values()]\n .filter((cue) => {\n return this._cue_keep(cue);\n }, this)\n .map((cue) => {\n return this._cue_convert(cue);\n }, this);\n };\n\n entries() {\n return this.values().map((cue) => {\n return [cue.key, cue];\n });\n };\n\n\n /***************************************************************\n MAP MODIFICATION METHODS\n ***************************************************************/\n\n update(cues, options) {\n throw new Error(\"not implemented\");\n }\n\n set (key, value) {\n throw new Error(\"not implemented\");\n }\n\n delete (key) {\n throw new Error(\"not implemented\");\n }\n\n clear (key) {\n throw new Error(\"not implemented\");\n }\n\n}\n\n// module definition\nexport default Subset;","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n\nimport endpoint from '../util/endpoint.js';\nimport Interval from '../util/interval.js';\nimport Timeout from '../util/timeout.js';\nimport * as motionutils from '../util/motionutils.js';\n\nconst pft = motionutils.posInterval_from_timeInterval;\n\nfunction queueCmp(a,b) {\n return endpoint.cmp(a.tsEndpoint, b.tsEndpoint);\n};\n\n// Default lookahead in seconds\nconst LOOKAHEAD = 5\n\nclass Schedule {\n\n constructor(dataset, to, options) {\n // timingobject\n this.to = to;\n // current timeout\n this.timeout = new Timeout(to, this.run.bind(this));\n // current vector\n this.vector;\n // current time interval\n this.timeInterval;\n // current position interval\n this.posInterval;\n // dataset\n this.dataset = dataset;\n // task queue\n this.queue = [];\n // callbacks\n this.callbacks = [];\n // options\n options = options || {};\n options.lookahead = options.lookahead || LOOKAHEAD;\n this.options = options;\n }\n\n\n /***************************************************************\n CALLBACKS\n ***************************************************************/\n\n add_callback (handler) {\n let handle = {\n handler: handler\n }\n this.callbacks.push(handle);\n return handle;\n };\n\n del_callback (handle) {\n let index = this.callbacks.indexof(handle);\n if (index > -1) {\n this.callbacks.splice(index, 1);\n }\n };\n\n _notify_callbacks (...args) {\n this.callbacks.forEach(function(handle) {\n handle.handler(...args);\n });\n };\n\n /***************************************************************\n MOTION CHANGE\n ***************************************************************/\n\n /*\n update schedule with new motion vector\n */\n setVector(vector) {\n let now = vector.timestamp;\n // clean up current motion\n let current_vector = this.vector;\n if (this.vector != undefined) {\n this.timeout.clear();\n this.timeInterval = undefined;\n this.posInterval = undefined;\n this.queue = [];\n }\n // update vector\n this.vector = vector;\n // start scheduler if moving\n if (motionutils.isMoving(this.vector)) {\n this.run(now);\n }\n }\n\n\n /***************************************************************\n TASK QUEUE\n ***************************************************************/\n\n /*\n push eventItem onto queue\n */\n push(eventItems) {\n eventItems.forEach(function(item) {\n if (this.timeInterval.covers_endpoint(item.tsEndpoint)) {\n this.queue.push(item);\n }\n }, this);\n // maintain ordering\n this.queue.sort(queueCmp);\n };\n\n /*\n pop due eventItems from queue\n */\n pop(now) {\n let eventItem, res = [];\n let len = this.queue.length;\n while (this.queue.length > 0 && this.queue[0].tsEndpoint[0] <= now) {\n res.push(this.queue.shift());\n }\n return res;\n };\n\n /*\n return timestamp of next eventItem\n */\n next() {\n return (this.queue.length > 0) ? this.queue[0].tsEndpoint[0]: undefined;\n }\n\n\n /***************************************************************\n ADVANCE TIMEINTERVAL/POSINTERVAL\n ***************************************************************/\n\n\n /*\n advance timeInterval and posInterval if needed\n */\n advance(now) {\n let start, delta = this.options.lookahead;\n let advance = false;\n if (this.timeInterval == undefined) {\n start = now;\n advance = true;\n } else if (endpoint.leftof(this.timeInterval.endpointHigh, now)) {\n start = this.timeInterval.high;\n advance = true\n }\n if (advance) {\n // advance intervals\n this.timeInterval = new Interval(start, start + delta, true, false);\n this.posInterval = pft(this.timeInterval, this.vector);\n // clear task queue\n this.queue = [];\n }\n return advance;\n }\n\n\n /***************************************************************\n LOAD\n ***************************************************************/\n\n /*\n load events\n */\n\n load(endpoints, minimum_tsEndpoint) {\n let endpointEvents = motionutils.endpointEvents(this.timeInterval,\n this.posInterval,\n this.vector,\n endpoints);\n\n /*\n ISSUE 1\n\n Range violation might occur within timeInterval.\n All endpointEvents with .tsEndpoint later or equal to range\n violation will be cancelled.\n */\n let range_ts = motionutils.rangeIntersect(this.vector, this.to.range)[0];\n\n /*\n ISSUE 2\n\n If load is used in response to dynamically added cues, the\n invocation of load might occor at any time during the timeInterval,\n as opposed to immediately after the start of timeInterval.\n This again implies that some of the endPointEvents we have found\n from the entire timeInterval might already be historic at time of\n invocation.\n\n Cancel endpointEvents with .tsEndpoint < minimum_ts.\n\n For regular loads this will have no effect since we\n do not specify a minimum_ts, but instead let it assume the\n default value of timeInterval.low.\n */\n if (minimum_tsEndpoint == undefined) {\n minimum_tsEndpoint = this.timeInterval.endpointLow;\n }\n\n /*\n ISSUE 3\n\n With acceleration the motion might change direction at\n some point, which might also be a cue endpoint. In this\n case, motion touches the cue endpoint but does not actually\n cross over it.\n\n For simplicity we say that this should not change the\n active state of that cue. The cue is either not activated\n or not inactivated by this occurrence. We might therefor\n simply drop such endpointEvents.\n\n To detect this, note that velocity will be exactly 0\n evaluated at the cue endpoint, but acceleration will be nonzero.\n\n Importantly, there is one exception. Dropping such events\n should only happen when 0 velocity is reached during motion,\n not at the start of a motion. For instance, in the case of\n starting with acceleration but no velocity, from a cue\n endpoint, this event should not be dropped.\n This is avoided by requiring that the tsEndpoint is not\n equal to timeInterval.endpointLow\n\n */\n\n return endpointEvents.filter(function(item) {\n // ISSUE 1\n if (range_ts <= item.tsEndpoint[0]) {\n // console.log(\"issue1\");\n return false;\n }\n\n // ISSUE 2\n if (endpoint.leftof(item.tsEndpoint, minimum_tsEndpoint)) {\n // console.log(\"issue2\");\n return false;\n }\n // ISSUE 3\n // checks every event. alternative approach would be\n // to calculate the ts of this event once, and compare\n // the result to the ts of all event\n if (this.vector.acceleration != 0.0) {\n let ts = item.tsEndpoint[0];\n if (ts > this.timeInterval.endpointLow[0]) {\n let v = motionutils.calculateVector(this.vector, ts);\n if (v.position == item.endpoint[0] && v.velocity == 0) {\n return false;\n }\n }\n }\n return true;\n }, this);\n }\n\n\n /***************************************************************\n RUN\n ***************************************************************/\n\n /*\n run schedule\n */\n run(now) {\n // process - due events\n let dueEvents = this.pop(now);\n // advance schedule and load events if needed\n if (this.advance(now)) {\n // fetch cue endpoints for posInterval\n let endpointItems = this.dataset.lookup_endpoints(this.posInterval);\n // load events and push on queue\n this.push(this.load(endpointItems));\n // process - possibly new due events\n dueEvents.push(...this.pop(now));\n }\n if (dueEvents.length > 0) {\n this._notify_callbacks(now, dueEvents, this);\n }\n // timeout - until next due event\n let ts = this.next() || this.timeInterval.high;\n this.timeout.setTimeout(Math.min(ts, this.timeInterval.high));\n }\n}\n\nexport default Schedule;\n\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport {map_intersect, map_difference} from '../util/utils.js';\nimport Interval from '../util/interval.js';\nimport CueCollection from '../dataset/cuecollection.js';\nimport Dataset from '../dataset/dataset.js';\n\n\nfunction isNoop(delta) {\n return (delta.interval == Dataset.Delta.NOOP && delta.data == Dataset.Delta.NOOP);\n}\n\n\n/*******************************************************************\n ACTIVE MAP\n*******************************************************************/\n/*\n\n This table describes cue changes to/from active state\n based on\n\n - to_role - the role of the timing object\n\n in the case of the double sequencer a timing object\n may be *LEFT* (L), *RIGHT* (R) or, in the corner case that\n the two timing objects are at the same position,\n *SINGULAR* (S)\n\n in the case of the single sequencer, the role is\n always *SINGULAR* (S)\n\n\n - to_direction - the direction of the movement of the\n timing object, either *RIGHT* (R) or *LEFT* (L)\n\n This map is only used when timing object is in a\n moving state, so *PAUSED* (P) is not needed.\n\n - endpoint_type - the type of endpoint which is\n passed by the timing object during motion, either\n *LEFT* (R) endpoint or *RIGHT* (R) endpoint, or\n *SINGULAR* (S) endpoint.\n\n - cue_change\n *ENTER* : cue changes from not active to active\n *EXIT*: cue changes from active to not active\n *STAY*: cue stays active\n *ENTER-EXIT*: cue changes from not active to active,\n and immediately back agoind to not active\n This only occurs when a *SINGULAR*\n timing object passed a *SINGULAR* cue.\n\n\n Table columns are:\n\n | to_role | to_direction | endpoint_type | cue change |\n\n left, right, left -> stay\n left, right, right -> exit\n left, right, singular -> exit\n\n left, left, left -> stay\n left, left, right -> enter\n left, left, singular -> enter\n\n right, right, left -> enter\n right, right, right -> stay\n right, right, singular -> enter\n\n right, left, left -> exit\n right, left, right -> stay\n right, left, singular -> exit\n\n // cornercase - timing objects are the same\n\n singular, right, left -> enter\n singular, right, right -> exit\n singular, right, singular -> enter, exit\n\n singular, left, left -> exit\n singular, left, right -> enter\n singular, left, singular -> enter, exit\n\n*/\n\nconst Active = Object.freeze({\n ENTER: 1,\n STAY: 0,\n EXIT: -1,\n ENTER_EXIT: 2\n});\n\nconst ActiveMap = new Map([\n [\"LRL\", Active.STAY],\n [\"LRR\", Active.EXIT],\n [\"LRS\", Active.EXIT],\n [\"LLL\", Active.STAY],\n [\"LLR\", Active.ENTER],\n [\"LLS\", Active.ENTER],\n [\"RRL\", Active.ENTER],\n [\"RRR\", Active.STAY],\n [\"RRS\", Active.ENTER],\n [\"RLL\", Active.EXIT],\n [\"RLR\", Active.STAY],\n [\"RLS\", Active.EXIT],\n [\"SRL\", Active.ENTER],\n [\"SRR\", Active.EXIT],\n [\"SRS\", Active.ENTER_EXIT],\n [\"SLL\", Active.EXIT],\n [\"SLR\", Active.ENTER],\n [\"SLS\", Active.ENTER_EXIT]\n]);\n\n\n\n/*******************************************************************\n DEFAULT EVENT ITEM ORDERING\n*******************************************************************/\n\nfunction cue_cmp_forwards (cue_a, cue_b) {\n return Interval.cmpLow(cue_a.interval, cue_b.interval);\n}\n\nfunction cue_cmp_backwards (cue_a, cue_b) {\n return -1 * Interval.cmpHigh(cue_a.interval, cue_b.interval);\n}\n\nfunction item_cmp_forwards (item_a, item_b) {\n let cue_a = (item_a.new) ? item_a.new : item_a.old;\n let cue_b = (item_b.new) ? item_b.new : item_b.old;\n return cue_cmp_forwards(cue_a, cue_b);\n}\n\nfunction item_cmp_backwards (item_a, item_b) {\n let cue_a = (item_a.new) ? item_a.new : item_a.old;\n let cue_b = (item_b.new) ? item_b.new : item_b.old;\n return cue_cmp_backwards(cue_a, cue_b);\n}\n\n/*******************************************************************\n BASE SEQUENCER\n*******************************************************************/\n\n/*\n This is an abstract base class for sequencers\n It implements common logic related to Dataset, events and activeCues.\n*/\n\nclass BaseSequencer extends CueCollection {\n\n\n constructor (dataset, options) {\n super(options);\n\n // Active cues\n this._map = new Map();\n\n // Dataset\n this._ds = dataset;\n let cb = this._onDatasetCallback.bind(this)\n this._ds_cb = this._ds.add_callback(cb);\n }\n\n /**\n * CueCollection (ObservableMap) needs access to map \n */\n get datasource () {\n return this._map;\n }\n\n /**\n * Access to dataset of sequencer\n */\n\n get dataset () { \n return this._ds;\n }\n\n /***************************************************************\n EVENTS\n ***************************************************************/\n\n /*\n Get the direction of movement\n To be implemented by subclass\n */\n _movementDirection() {\n throw new Error(\"not implemented\");\n }\n\n // override ObservableMap.sortValues to add special support for\n // direction sensitive ordering as default ordering\n sortValues(iter, options={}) {\n let order = this.sortOrder(options);\n if (typeof order == \"function\") {\n // use order specified by options\n return super.sortValues(iter, options)\n } else {\n // if iterable not array - convert into array ahead of sorting\n let cues = (Array.isArray(iter)) ? iter : [...iter];\n // default order is direction sensitive\n let direction = this._movementDirection();\n if (direction >= 0) {\n cues.sort(cue_cmp_forwards);\n } else {\n cues.sort(cue_cmp_backwards);\n }\n return cues\n } \n }\n\n\n // override ObservableMap.sortItems to add special support for\n // direction sensitive ordering as default ordering\n sortItems(items, direction) {\n let order = this.sortOrder(); \n if (typeof order == \"function\") {\n // use order specified by options\n return super.sortItems(items) \n } \n if (order == undefined) {\n // default order is direction sensitive\n if (direction == undefined) {\n direction = this._movementDirection();\n }\n if (direction >= 0) {\n items.sort(item_cmp_forwards);\n } else {\n items.sort(item_cmp_backwards);\n }\n }\n }\n\n /***************************************************************\n MAP METHODS\n ***************************************************************/\n\n set (key, value) {\n throw new Error(\"not implemented\");\n }\n\n delete (key) {\n throw new Error(\"not implemented\");\n }\n\n clear (key) {\n throw new Error(\"not implemented\");\n }\n\n /***************************************************************\n DATASET\n ***************************************************************/\n\n _onDatasetCallback(eventMap, relevanceInterval) {\n throw new Error(\"not implemented\");\n }\n\n /*\n make exit, change and enter events\n - based on eventMap\n */\n _items_from_dataset_events(eventMap, interval) {\n const enterEvents = [];\n const changeEvents = [];\n const exitEvents = [];\n const first = this._map.size == 0;\n let is_active, should_be_active, _item;\n for (let item of eventMap.values()) {\n if (isNoop(item.delta)) {\n continue;\n }\n // exit, change, enter events\n is_active = (first) ? false : this._map.has(item.key);\n should_be_active = false;\n if (item.new != undefined) {\n if (item.new.interval.match(interval)) {\n should_be_active = true;\n }\n }\n if (is_active && !should_be_active) {\n // exit\n _item = {key:item.key, new:undefined, old:item.old, info:item.info};\n exitEvents.push(_item);\n } else if (!is_active && should_be_active) {\n // enter\n _item = {key:item.key, new:item.new, old:undefined, info:item.info};\n enterEvents.push(_item);\n } else if (is_active && should_be_active) {\n // change\n _item = {key:item.key, new:item.new, old:item.old, info:item.info};\n changeEvents.push(_item);\n }\n };\n return [exitEvents, changeEvents, enterEvents];\n }\n\n /*\n make exit, change and enter events\n - based on dataset.lookup\n */\n _items_from_dataset_lookup(eventMap, interval) {\n\n /*\n Active cues\n\n find new set of active cues by querying the dataset\n */\n const _activeCues = new Map(this._ds.lookup(interval).map(function(cue) {\n return [cue.key, cue];\n }));\n\n let changeEvents = [];\n let exitEvents = [];\n let first = (this._map.size == 0);\n if (!first){\n\n /*\n Change Events\n\n change cues - cues which are modified, yet remain active cues\n */\n let remainCues = map_intersect(this._map, _activeCues);\n if (remainCues.size > 0) {\n /*\n Two approaches\n\n 1) large eventMap\n eventMap larger than remainCues\n - iterate remainCues\n - keep those that are found in eventMap\n\n 2) large remainCues\n remainCues larger than eventMap\n - iterate eventMap\n - keep those that are found in remainCues\n\n measurement shows that 2) is better\n */\n let cue, _item;\n for (let item of eventMap.values()) {\n cue = remainCues.get(item.key);\n if (cue != undefined && !isNoop(item.delta)) {\n _item = {key:item.key, new:item.new, old:item.old};\n changeEvents.push(_item);\n }\n }\n }\n\n /*\n Exit Events\n exit cues were in old active cues - but not in new\n */\n let exitCues = map_difference(this._map, _activeCues);\n exitEvents = [...exitCues.values()]\n .map(cue => {\n return {key:cue.key, new:undefined, old:cue};\n });\n }\n\n /*\n Enter Events\n enter cues were not in old active cues - but are in new\n */\n let enterCues;\n if (first) {\n enterCues = _activeCues\n } else {\n enterCues = map_difference(_activeCues, this._map);\n }\n let enterEvents = [...enterCues.values()]\n .map(cue => {\n return {key:cue.key, new:cue, old:undefined};\n });\n\n /*\n Preserve .info from eventMap\n */\n for (let eventList in [exitEvents, changeEvents, enterEvents]) {\n for (let item of eventList) {\n let _item = eventMap.get(item.key);\n if (_item != undefined) {\n item.info = _item.info;\n }\n } \n }\n\n return [exitEvents, changeEvents, enterEvents];\n }\n\n /***************************************************************\n V2 COMPATIBILTY\n\n Sequencers forward dataset operation to datase\n ***************************************************************/\n\n get builder() {\n return this.dataset.builder;\n }\n\n addCue(key, interval, data) {\n return this.dataset.addCue(key, interval, data);\n }\n\n removeCue(key) {\n return this.dataset.removeCue(key);\n }\n\n _addCue(key, interval, data) {\n return this.dataset._addCue(key, interval, data);\n }\n\n _removeCue(key) {\n return this.dataset._removeCue(key);\n }\n\n update(cues, options) {\n return this.dataset.update(cues, options);\n }\n\n clear() {\n return this.dataset.clear();\n }\n\n hasCue(key) {\n return this.dataset.has(key);\n }\n\n getCue(key) {\n return this.dataset.get(key);\n }\n\n getCues() {\n return this.dataset.cues();\n }\n\n getActiveKeys() {\n return [...this.keys()];\n }\n\n getActiveCues() {\n return this.cues();\n }\n\n isActive(key) {\n return this.has(key);\n }\n\n}\n\nBaseSequencer.Active = Active;\nBaseSequencer.ActiveMap = ActiveMap;\n\n\nexport default BaseSequencer;\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport {array_concat, map_difference} from '../util/utils.js';\nimport Interval from '../util/interval.js';\nimport * as motionutils from '../util/motionutils.js';\nimport Schedule from './schedule.js';\nimport BaseSequencer from './basesequencer.js';\n\nconst PosDelta = motionutils.MotionDelta.PosDelta;\nconst MoveDelta = motionutils.MotionDelta.MoveDelta;\nconst Active = BaseSequencer.Active;\nconst ActiveMap = BaseSequencer.ActiveMap;\n\nconst EVENTMAP_THRESHOLD = 5000;\nconst ACTIVECUES_THRESHOLD = 5000;\n\n\nclass PointModeSequencer extends BaseSequencer {\n\n constructor (dataset, to, options) {\n\n super(dataset, options);\n\n // Timing Object\n this._to = to;\n this._sub = this._to.on(\"timingsrc\", this._onTimingCallback.bind(this));\n\n // Schedule\n this._sched = new Schedule(this._ds, to);\n let cb = this._onScheduleCallback.bind(this);\n this._sched_cb = this._sched.add_callback(cb)\n }\n\n\n /*\n Implement movement direction from single timing object\n */\n _movementDirection() {\n const now = this._to.clock.now();\n return motionutils.calculateDirection(this._to.vector, now);\n }\n\n\n /***************************************************************\n DATASET CALLBACK\n ***************************************************************/\n\n /*\n Handling Dataset Update Callbacks\n */\n\n _onDatasetCallback(eventMap, relevanceInterval) {\n /*\n process dataset events which are relevant to the set\n of activeCues, or to the immediate future (schedule)\n\n enterCues - inactive -> active\n changeCues - active -> active, but changed\n exitCues - active -> inactive\n\n Two approaches\n - 1) EVENTS: filter list of events - compare to current active cues\n - 2) LOOKUP: regenerate new activeCues by looking up set of\n active cues from dataset, compare it to current active cues\n\n\n EventMap.size < about 1K-10K (5K)\n - EVENTS better or equal\n EventMap.size > about 5K\n - LOOKUP better\n - exception\n - If activeCues.size > 1K-10K (5K) - EVENTS BETTER\n\n If new cues are predominantly active cues, EVENTS are\n always better - and more so for larger sets of events.\n However, there is no information about this\n before making the choice, and also this is a somewhat\n unlikely scenario.\n\n So, the simple policy above works for typical workloads,\n where the majority of added cues are inactive.\n */\n\n if (!this._to.isReady()) {\n return;\n }\n\n if (relevanceInterval == undefined) {\n return;\n }\n\n const now = this._to.clock.now();\n const now_vector = motionutils.calculateVector(this._to.vector, now);\n\n // activeInterval\n const activeInterval = new Interval(now_vector.position);\n\n if (!activeInterval.match(relevanceInterval, Interval.Match.OUTSIDE)) {\n // relevanceInterval is NOT outside activeInterval\n // some events relevant for activeIntervale\n\n // choose approach to get events\n let get_items = this._items_from_dataset_events.bind(this);\n if (EVENTMAP_THRESHOLD < eventMap.size) {\n if (this._map.size < ACTIVECUES_THRESHOLD) {\n get_items = this._items_from_dataset_lookup.bind(this);\n }\n }\n\n // get items\n const [exit, change, enter] = get_items(eventMap, activeInterval);\n\n // update activeCues\n exit.forEach(item => {\n this._map.delete(item.key);\n });\n change.forEach(item => {\n this._map.set(item.key, item.new);\n });\n enter.forEach(item => {\n this._map.set(item.key, item.new);\n });\n\n // sort event items according to general movement direction\n let direction = motionutils.calculateDirection(now_vector);\n this.sortItems(exit, direction);\n this.sortItems(change, direction);\n this.sortItems(enter, direction);\n\n // notifications\n const items = array_concat([exit, change, enter], {copy:true, order:true});\n\n // event notification\n this._notifyEvents(items);\n }\n\n /*\n clear schedule\n\n This is only necessary if a cue interval is changed,\n and the change is relevant within the posInterval of\n of the schedule. RelevanceInterval to figure this out.\n */\n if (this._sched.posInterval) {\n if (!this._sched.posInterval.match(relevanceInterval, Interval.Match.OUTSIDE)) {\n // relevanceInterval is NOT outside schedule posInterval\n // refresh schedule\n this._sched.setVector(now_vector);\n }\n }\n }\n\n\n /***************************************************************\n TIMING OBJECT CALLBACK\n ***************************************************************/\n\n _onTimingCallback (eArg) {\n /*\n If update is the initial vector from the timing object,\n we set current time as the official time for the update.\n Else, the new vector is \"live\" and we use the timestamp\n when it was created as the official time for the update.\n This is represented by the new_vector.\n */\n let new_vector;\n\n if (eArg.live) {\n new_vector = this._to.vector;\n } else {\n // make a live vector from to vector\n new_vector = motionutils.calculateVector(this._to.vector, this._to.clock.now());\n }\n\n /*\n The nature of the vector change\n */\n let delta = new motionutils.MotionDelta(this._to.old_vector, new_vector);\n\n /*\n Reevaluate active state.\n This is required after any discontinuity of the position (jump),\n or if the motion stopped without jumping (pause or halt at range\n restriction)\n */\n if (delta.posDelta == PosDelta.CHANGE || delta.moveDelta == MoveDelta.STOP) {\n // make position interval\n let low = new_vector.position;\n let high = new_vector.position;\n let itv = new Interval(low, high, true, true);\n // new active cues\n let activeCues = new Map(this._ds.lookup(itv).map(cue => {\n return [cue.key, cue];\n }));\n // exit cues - in old activeCues but not in new activeCues\n let exitCues = map_difference(this._map, activeCues);\n // enter cues - not in old activeCues but in new activeCues\n let enterCues = map_difference(activeCues, this._map);\n // update active cues\n this._map = activeCues;\n\n // make event items\n let exitItems = [...exitCues.values()].map(cue => {\n return {key:cue.key, new:undefined, old:cue};\n });\n let enterItems = [...enterCues.values()].map(cue => {\n return {key:cue.key, new:cue, old:undefined};\n }); \n\n // sort event items according to general movement direction\n let direction = motionutils.calculateDirection(new_vector);\n this.sortItems(exitItems, direction);\n this.sortItems(enterItems, direction);\n\n // notifications\n const items = array_concat([exitItems, enterItems], {copy:true, order:true});\n\n // event notification\n this._notifyEvents(items);\n }\n\n /*\n Handle Timing Object Moving\n */\n this._sched.setVector(new_vector);\n };\n\n\n /***************************************************************\n SCHEDULE CALLBACK\n ***************************************************************/\n\n _onScheduleCallback = function(now, endpointItems, schedule) {\n if (!this._to.isReady()) {\n return;\n }\n\n const items = [];\n endpointItems.forEach(function (item) {\n let cue = item.cue;\n let has_cue = this._map.has(cue.key);\n let [value, right, closed, singular] = item.endpoint;\n\n /*\n Action Code - see sequenceutils\n */\n // to role\n let to_role = \"S\";\n // movement direction\n let to_dir = (item.direction > 0) ? \"R\" : \"L\";\n // endpoint type\n let ep_type = (singular) ? \"S\": (right) ? \"R\" : \"L\";\n // action code, enter, exit, stay, enter-exit\n let action_code = ActiveMap.get(`${to_role}${to_dir}${ep_type}`);\n\n if (action_code == Active.ENTER_EXIT) {\n if (has_cue) {\n // exit\n items.push({key:cue.key, new:undefined, old:cue});\n this._map.delete(cue.key);\n } else {\n // enter\n items.push({key:cue.key, new:cue, old:undefined});\n // exit\n items.push({key:cue.key, new:undefined, old:cue});\n // no need to both add and remove from activeCues\n }\n } else if (action_code == Active.ENTER) {\n if (!has_cue) {\n // enter\n items.push({key:cue.key, new:cue, old:undefined});\n this._map.set(cue.key, cue);\n }\n } else if (action_code == Active.EXIT) {\n if (has_cue) {\n // exit\n items.push({key:cue.key, new:undefined, old:cue});\n this._map.delete(cue.key);\n }\n }\n }, this);\n\n // Event items already sorted\n\n // event notification\n this._notifyEvents(items);\n };\n}\n\nexport default PointModeSequencer;\n\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport {array_concat, map_difference} from '../util/utils.js';\nimport Interval from '../util/interval.js';\nimport * as motionutils from '../util/motionutils.js';\nimport Schedule from './schedule.js';\nimport BaseSequencer from './basesequencer.js';\n\nconst PosDelta = motionutils.MotionDelta.PosDelta;\nconst MoveDelta = motionutils.MotionDelta.MoveDelta;\nconst Active = BaseSequencer.Active;\nconst ActiveMap = BaseSequencer.ActiveMap;\n\nconst EVENTMAP_THRESHOLD = 5000;\nconst ACTIVECUES_THRESHOLD = 5000;\n\n/*\n calculate general movement direction for double sequencer\n define movement direction as the aggregate movement direction\n for both timing objects\n*/\nfunction movement_direction (now_vector_A, now_vector_B) {\n let direction_A = motionutils.calculateDirection(now_vector_A);\n let direction_B = motionutils.calculateDirection(now_vector_B);\n let direction = direction_A + direction_B;\n return (direction > 0) ? 1 : (direction < 0) ? -1 : 0;\n}\n\n\nclass IntervalModeSequencer extends BaseSequencer {\n\n constructor (dataset, toA, toB, options) {\n\n super(dataset, options);\n\n // Timing objects\n this._toA = toA;\n this._toA_ready = false;\n this._toB = toB;\n this._toB_ready = false;\n let to_cb = this._onTimingCallback.bind(this);\n this._subA = this._toA.on(\"timingsrc\", to_cb);\n this._subB = this._toB.on(\"timingsrc\", to_cb);\n\n // Schedules\n let sched_cb = this._onScheduleCallback.bind(this);\n this._schedA = new Schedule(this._ds, toA);\n this._schedA_cb = this._schedA.add_callback(sched_cb);\n this._schedB = new Schedule(this._ds, toB);\n this._schedB_cb = this._schedB.add_callback(sched_cb);\n }\n\n\n _isReady() {\n return (this._toA_ready && this._toB_ready);\n }\n\n\n /*\n Implement movement direction from two timing objects\n */\n\n _movementDirection() {\n const now = this._toA.clock.now();\n const now_vector_A = motionutils.calculateVector(this._toA.vector, now);\n const now_vector_B = motionutils.calculateVector(this._toB.vector, now);\n return movement_direction(now_vector_A, now_vector_B);\n }\n\n /***************************************************************\n DATASET CALLBACK\n ***************************************************************/\n\n /*\n Handling Dataset Update Callbacks\n */\n _onDatasetCallback(eventMap, relevanceInterval) {\n if (!this._isReady()) {\n return;\n }\n\n if (relevanceInterval == undefined) {\n return;\n }\n\n // assuming both timing objects have the same clock\n const now = this._toA.clock.now();\n const now_vector_A = motionutils.calculateVector(this._toA.vector, now);\n const now_vector_B = motionutils.calculateVector(this._toB.vector, now);\n\n // active interval\n let [pos_A, pos_B] = [now_vector_A.position, now_vector_B.position];\n let [low, high] = (pos_A <= pos_B) ? [pos_A, pos_B] : [pos_B, pos_A];\n const activeInterval = new Interval(low, high, true, true);\n\n if (!activeInterval.match(relevanceInterval, Interval.Match.OUTSIDE)) {\n // relevanceInterval is NOT outside activeInterval\n // some events relevant for activeIntervale\n\n // choose approach to get events\n let get_items = this._items_from_dataset_events.bind(this);\n if (EVENTMAP_THRESHOLD < eventMap.size) {\n if (this._map.size < ACTIVECUES_THRESHOLD) {\n get_items = this._items_from_dataset_lookup.bind(this);\n }\n }\n\n // get items\n const [exit, change, enter] = get_items(eventMap, activeInterval);\n\n // update activeCues\n exit.forEach(item => {\n this._map.delete(item.key);\n });\n change.forEach(item => {\n this._map.set(item.key, item.new);\n });\n enter.forEach(item => {\n this._map.set(item.key, item.new);\n });\n\n // sort event items according to general movement direction\n let direction = movement_direction(now_vector_A, now_vector_B);\n this.sortItems(exit, direction);\n this.sortItems(change, direction);\n this.sortItems(enter, direction);\n\n // notifications\n const items = array_concat([exit, change, enter], {copy:true, order:true});\n \n // event notification\n this._notifyEvents(items, direction);\n }\n\n\n /*\n clear schedules\n\n This is only necessary if a cue interval is changed,\n and the change is relevant within the posInterval of\n one of the schedules. RelevanceInterval to figure this out.\n */\n\n if (this._schedA.posInterval) {\n if (!this._schedA.posInterval.match(relevanceInterval, Interval.Match.OUTSIDE)) {\n // relevanceInterval is NOT outside schedule posInterval\n // refresh schedule\n this._schedA.setVector(now_vector_A);\n }\n }\n\n if (this._schedB.posInterval) {\n if (!this._schedB.posInterval.match(relevanceInterval, Interval.Match.OUTSIDE)) {\n // relevanceInterval is NOT outside schedule posInterval\n // refresh schedule\n this._schedB.setVector(now_vector_B);\n }\n }\n }\n\n\n /***************************************************************\n TIMING OBJECT CALLBACK\n ***************************************************************/\n\n /*\n Handling Change Events from Timing Objects\n */\n _onTimingCallback (eArg, eInfo) {\n\n /*\n make sure both timingobjects are ready\n */\n let init = false;\n if (!this._isReady()) {\n if (eInfo.src == this._toA) {\n this._toA_ready = true;\n } else {\n this._toB_ready = true;\n }\n if (this._isReady()) {\n init = true;\n } else {\n return;\n }\n }\n\n /*\n figure out which timing object was firing\n */\n const to = eInfo.src;\n const other_to = (to == this._toA) ? this._toB : this._toA;\n\n /*\n If update is the initial vector from the timing object,\n we set current time as the official time for the update.\n Else, the new vector is \"live\" and we use the timestamp\n when it was created as the official time for the update.\n This is represented by the new_vector.\n */\n let new_vector;\n if (eArg.live) {\n new_vector = to.vector;\n } else {\n new_vector = motionutils.calculateVector(to.vector, to.clock.now());\n }\n\n /*\n The nature of the vector change\n */\n const delta = new motionutils.MotionDelta(to.old_vector, new_vector);\n\n /*\n Sample the state of the other timing object at same time.\n */\n let ts = new_vector.timestamp;\n let other_new_vector = motionutils.calculateVector(other_to.vector, ts);\n\n /*\n Reevaluate active state.\n This is required after any discontinuity of the position (jump),\n or if the motion stopped without jumping (pause or halt at range\n restriction)\n */\n if (delta.posDelta == PosDelta.CHANGE || delta.MoveDelta == MoveDelta.STOP) {\n\n // make position interval\n let low = Math.min(new_vector.position, other_new_vector.position);\n let high = Math.max(new_vector.position, other_new_vector.position);\n let itv = new Interval(low, high, true, true);\n\n // new active cues\n let activeCues = new Map(this._ds.lookup(itv).map(cue => {\n return [cue.key, cue];\n }));\n // exit cues - in old activeCues but not in new activeCues\n let exitCues = map_difference(this._map, activeCues);\n // enter cues - not in old activeCues but in new activeCues\n let enterCues = map_difference(activeCues, this._map);\n // update active cues\n this._map = activeCues;\n // make event items\n\n let exitItems = [...exitCues.values()].map(cue => {\n return {key:cue.key, new:undefined, old:cue};\n });\n let enterItems = [...enterCues.values()].map(cue => {\n return {key:cue.key, new:cue, old:undefined};\n }); \n // sort event items according to general movement direction\n let direction = movement_direction(new_vector, other_new_vector);\n this.sortItems(exitItems, direction);\n this.sortItems(enterItems, direction);\n\n // notifications\n const items = array_concat([exitItems, enterItems], {copy:true, order:true});\n\n // event notification\n this._notifyEvents(items);\n }\n\n /*\n Handle Timing Object Moving\n - on init both shedules must be updated\n */\n if (to == this._toA) {\n this._schedA.setVector(new_vector);\n } else if (to == this._toB) {\n this._schedB.setVector(new_vector);\n }\n if (init) {\n if (other_to == this._toA) {\n this._schedA.setVector(other_new_vector);\n } else if (other_to == this._toB) {\n this._schedB.setVector(other_new_vector);\n }\n }\n };\n\n\n /***************************************************************\n SCHEDULE CALLBACK\n ***************************************************************/\n\n /*\n Handling due Events from Schedules\n */\n _onScheduleCallback = function(now, endpointItems, schedule) {\n if (!this._isReady()) {\n return;\n }\n\n /*\n figure out which timing object was firing\n */\n const to = schedule.to;\n const other_to = (to == this._toA) ? this._toB : this._toA;\n\n const items = [];\n endpointItems.forEach(function (item) {\n\n /*\n figure out if to (event source) is lower than the other to\n at time of event\n */\n // endpoint\n let [pos, right, closed, singular] = item.endpoint;\n // position of other to at time of event\n let ts = item.tsEndpoint[0];\n let other_vector = motionutils.calculateVector(other_to.vector, ts);\n let pos_other = other_vector.position;\n\n /*\n Action Code - see sequenceutils\n */\n // to role\n let to_role = (pos < pos_other) ? \"L\" : (pos == pos_other) ? \"S\" : \"R\";\n // movement direction\n let to_dir = (item.direction > 0) ? \"R\" : \"L\";\n // endpoint type\n let ep_type = (singular) ? \"S\": (right) ? \"R\" : \"L\";\n // action code, enter, exit, stay, enter-exit\n let action_code = ActiveMap.get(`${to_role}${to_dir}${ep_type}`);\n\n /*\n state of cue\n */\n let cue = item.cue;\n let has_cue = this._map.has(cue.key);\n\n // filter action code\n if (action_code == Active.ENTER_EXIT) {\n /*\n both timing objects evaluated to same position\n either\n 1) to is moving and other_to is paused at this point,\n implying that the cue STAYS active\n or,\n 2) both are moving. if both are moving in the same\n direction - EXIT\n opposite direction - ENTER\n */\n let other_moving = motionutils.isMoving(other_vector);\n if (!other_moving) {\n // other not moving\n action_code = Active.ENTER;\n } else {\n // both moving\n let direction = motionutils.calculateDirection(other_vector); // movement direction\n action_code = (direction != item.direction) ? Active.ENTER : Active.EXIT;\n }\n }\n if (action_code == Active.STAY) {\n action_code = Active.ENTER;\n }\n if (action_code == Active.ENTER && has_cue) {\n return;\n }\n if (action_code == Active.EXIT && !has_cue) {\n return;\n }\n\n // enter or exit\n if (action_code == Active.ENTER) {\n // enter\n items.push({key:cue.key, new:cue, old:undefined});\n this._map.set(cue.key, cue);\n } else if (action_code == Active.EXIT) {\n // exit\n items.push({key:cue.key, new:undefined, old:cue});\n this._map.delete(cue.key);\n }\n }, this);\n\n // Event items already sorted\n\n // event notification\n this._notifyEvents(items);\n }\n}\n\nexport default IntervalModeSequencer;\n\n","/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\nimport {random_string} from '../util/utils.js';\n\nclass DatasetViewer {\n\n constructor(ds, elem) {\n this.ds = ds;\n this.elem = elem;\n this.nonce = random_string(4);\n this.ds.on(\"change\", this.onchange.bind(this));\n this.ds.on(\"remove\", this.onremove.bind(this));\n }\n\n cue2string(cue) {\n let itv = (cue.interval) ? cue.interval.toString() : \"undefined\";\n let data = JSON.stringify(cue.data); \n return `${cue.key}, ${itv}, ${data}`;\n }\n\n onchange(eItem) {\n let _id = `${this.nonce}-${eItem.key}`;\n let node = this.elem.querySelector(`#${_id}`);\n if (node) {\n // update existing node\n node.innerHTML = this.cue2string(eItem.new);\n } else {\n // create new node\n let node = document.createElement(\"div\");\n node.innerHTML = this.cue2string(eItem.new);\n node.setAttribute(\"id\", _id);\n this.elem.appendChild(node);\n }\n }\n\n onremove(eItem) {\n // remove node\n let _id = `${this.nonce}-${eItem.key}`;\n let node = document.getElementById(_id);\n if (node) {\n node.parentNode.removeChild(node);\n }\n }\n}\n\nexport default DatasetViewer;","/*\n\tCopyright 2020\n\tAuthor : Ingar Mæhlum Arntzen\n\n\tThis file is part of the Timingsrc module.\n\n\tTimingsrc is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tTimingsrc is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with Timingsrc. If not, see .\n*/\n\nimport TimingSampler from \"../timingobject/timingsampler.js\";\n\n/*\n TODO\n\n - treat progress change as a speculative\n change, (with a timeout)\n implementation - ideally as speculative converter\n easy solution - just lock\n*/\n\nclass TimingProgress {\n\n static position2percent(position, range) {\n let [low, high] = range;\n\n let offset = position - low;\n let length = high - low;\n return 100.0*offset/length;\n };\n\n static percent2position(percent, range) {\n let [low, high] = range;\n // make sure percent is [0,100]\n percent = Math.max(0, percent);\n percent = Math.min(100, percent);\n let length = high - low;\n let offset = length*percent/100.0;\n return low + offset;\n };\n\n constructor (timingObject, progress_elem, options={}) {\n this._to = timingObject;\n this._sampler = options.sampler;\n this._progress_elem = progress_elem;\n this._lock = false;\n this._options = options;\n this._range = options.range || this._to.range;\n let [low, high] = this._range;\n if (low == -Infinity || high == Infinity) {\n throw new Error(\"illegal range\", this._range);\n }\n\n // subscribe to input event from progress elem\n this._progress_elem.addEventListener(\"input\", function() {\n // set lock\n // no updates on progress elem from timing object until lock is released\n this._lock_value = true;\n }.bind(this));\n\n // subscribe to change event from progress elem\n this._progress_elem.addEventListener(\"change\", function () { \n // clear lock\n this._lock_value = false;\n // update the timing object\n let percent = parseInt(this._progress_elem.value); \n let position = TimingProgress.percent2position(percent, this._range);\n this._to.update({position: position});\n }.bind(this));\n \n // sampler\n if (this._sampler) {\n this._sampler.on(\"change\", this.refresh.bind(this));\n }\n }\n\n refresh() {\n let position = this._to.pos;\n // update progress elem if unlocked\n if (!this._lock_value) {\n let percent = TimingProgress.position2percent(position, this._range);\n if (this._options.thumb) {\n // check if percent is legal\n if (percent < 0.0 || 100.0 < percent) {\n // hide\n this._options.thumb.hide();\n return;\n }\n } else {\n percent = (percent < 0.0) ? 0.0 : percent;\n percent = (100.0 < percent) ? 100.0: percent;\n }\n this._progress_elem.value = `${percent}`;\n if (this._options.thumb) {\n this._options.thumb.show(); \n }\n }\n }\n}\n\nexport default TimingProgress;","\n/*\n Copyright 2020\n Author : Ingar Arntzen\n\n This file is part of the Timingsrc module.\n\n Timingsrc is free software: you can redistribute it and/or modify\n it under the terms of the GNU Lesser General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n Timingsrc is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Lesser General Public License for more details.\n\n You should have received a copy of the GNU Lesser General Public License\n along with Timingsrc. If not, see .\n*/\n\n// utils\nexport * as utils from './util/utils.js';\nexport * as motionutils from './util/motionutils.js';\nexport {default as BinarySearch} from './util/binarysearch.js';\nexport {default as endpoint} from './util/endpoint.js';\nexport {default as eventify} from './util/eventify.js';\nexport {default as Interval} from './util/interval.js';\nexport {default as CueCollection} from './dataset/cuecollection.js';\nexport {default as Timeout} from './util/timeout.js';\n\n// timing object\nimport {default as TimingObject} from './timingobject/timingobject.js';\nexport {TimingObject};\nexport {default as SkewConverter} from './timingobject/skewconverter.js';\nexport {default as DelayConverter} from './timingobject/delayconverter.js';\nexport {default as ScaleConverter} from './timingobject/scaleconverter.js';\nexport {default as LoopConverter} from './timingobject/loopconverter.js';\nexport {default as RangeConverter} from './timingobject/rangeconverter.js';\nexport {default as TimeshiftConverter} from './timingobject/timeshiftconverter.js';\nexport {default as TimingSampler} from './timingobject/timingsampler.js';\nexport {default as PositionCallback} from './timingobject/positioncallback.js';\n\n// timed data\nimport {default as Dataset} from './dataset/dataset.js';\nexport {Dataset};\nexport {default as Subset} from './dataset/subset.js';\nimport {default as PointModeSequencer} from './sequencing/pointsequencer.js';\nimport {default as IntervalModeSequencer} from './sequencing/intervalsequencer.js';\n\n// create single sequencer factory function\nexport function Sequencer() {\n // find datasets in arguments\n let ds_list = [...arguments].filter((e) => (e instanceof Dataset));\n let ds = (ds_list.length > 0) ? ds_list[0] : new Dataset();\n // find timing objects in arguments\n let to_list = [...arguments].filter((e) => (e instanceof TimingObject));\n // find options (plain objects) in arguments\n let obj_list = [...arguments].filter((e) => (Object.getPrototypeOf(e) === Object.prototype));\n let options = (obj_list.length > 0) ? obj_list[0] : {};\n if (to_list.length == 0) {\n throw new Error(\"no timingobject in arguments\");\n } else if (to_list.length == 1) {\n return new PointModeSequencer(ds, to_list[0], options);\n } else {\n return new IntervalModeSequencer(ds, to_list[0], to_list[1], options);\n }\n};\n\n// Add clone functions for backwards compatibility\nPointModeSequencer.prototype.clone = function () {\n let args = [this.dataset];\n args.push.apply(args, [...arguments]);\n return Sequencer(...args);\n};\n\n// Add clone functions for backwards compatibility\nIntervalModeSequencer.prototype.clone = function () {\n let args = [this.dataset];\n args.push.apply(args, [...arguments]);\n return Sequencer(...args);\n};\n\n// ui\nexport {default as DatasetViewer} from './ui/datasetviewer.js';\nexport {default as TimingProgress} from './ui/timingprogress.js';\n\nexport const version = \"v3.0\";\n"],"names":["isNumber","cmp","calculateVector","motionutils.MotionDelta","motionutils.calculateVector","motionutils.detectRangeViolation","motionutils.equalVectors","motionutils.isMoving","motionutils.checkRange","motionutils.calculateDelta","mod","divmod","Relation","utils.object_equals","utils.isIterable","utils.array_concat","utils.map_difference","utils.eqSet","utils.set_difference","motionutils.posInterval_from_timeInterval","endpointEvents","motionutils.endpointEvents","motionutils.rangeIntersect","PosDelta","MoveDelta","Active","ActiveMap","motionutils.calculateDirection","EVENTMAP_THRESHOLD","ACTIVECUES_THRESHOLD"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAC,MAAM,EAAE;AACtC,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC;AAClB,IAAI,IAAI,QAAQ,GAAG,sDAAsD,CAAC;AAC1E,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE;AACpC,QAAQ,IAAI,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7E,KAAK;AACL,IAAI,OAAO,IAAI,CAAC;AAChB,CAAC;AACD;AACA;AACA;AACO,SAAS,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE;AAC9B,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AACpD,CAAC;AACD;AACO,SAAS,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE;AAC9B,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,KAAK,CAAC;AACjD,IAAI,OAAO,IAAI,CAAC;AAChB,CAAC;AACD;AACO,SAAS,IAAI,CAAC,EAAE,EAAE;AACzB,IAAI,OAAO,UAAU,CAAC,EAAE;AACxB,QAAQ,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACzB,KAAK,CAAC;AACN,CAAC;AACD;AACO,SAAS,cAAc,CAAC,EAAE,EAAE,EAAE,EAAE;AACvC,IAAI,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,cAAc,GAAG,UAAU,CAAC,EAAE,CAAC,EAAE;AAC9C,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE;AACrB,QAAQ,OAAO,IAAI,GAAG,EAAE,CAAC;AACzB,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE;AAC5B,QAAQ,OAAO,CAAC,CAAC;AACjB,KAAK,MAAM;AACX,QAAQ,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE;AAC7D,YAAY,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;AAC9B,SAAS,CAAC,CAAC,CAAC;AACZ,KAAK;AACL,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACO,MAAM,aAAa,GAAG,UAAU,CAAC,EAAE,CAAC,EAAE;AAC7C,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE;AACrB;AACA,QAAQ,OAAO,IAAI,GAAG,EAAE,CAAC;AACzB,KAAK;AACL,IAAI,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE;AACzD,QAAQ,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;AACzB,KAAK,CAAC,CAAC,CAAC;AACR,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,SAAS,CAAC,aAAa,EAAE,OAAO,CAAC,EAAE,EAAE;AACrD,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;AAC5C;AACA,IAAI,IAAI,aAAa,YAAY,GAAG,EAAE;AACtC,QAAQ,OAAO,aAAa,CAAC;AAC7B,KAAK;AACL,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE;AACvC,QAAQ,MAAM,IAAI,KAAK,CAAC,6BAA6B,EAAE,aAAa,CAAC,CAAC;AACtE,KAAK;AACL,IAAI,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,EAAE;AACnC,QAAQ,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAC/C,KAAK;AACL,IAAI,IAAI,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK;AAC3C,QAAQ,QAAQ,CAAC,YAAY,GAAG,EAAE;AAClC,KAAK,CAAC,CAAC;AACP,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,EAAE;AAC1C,QAAQ,MAAM,IAAI,KAAK,CAAC,2CAA2C,EAAE,aAAa,CAAC,CAAC;AACpF,KAAK;AACL;AACA,IAAI,IAAI,CAAC,KAAK,EAAE;AAChB;AACA,QAAQ,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AACtD,KAAK;AACL;AACA,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC;AAC3D;AACA,IAAI,KAAK,IAAI,CAAC,IAAI,aAAa,EAAE;AACjC,QAAQ,KAAK,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;AAC5C,YAAY,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAChC,SAAS;AACT,KAAK;AACL,IAAI,OAAO,KAAK,CAAC;AACjB,CAAC;AACD;AACA;AACO,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE;AAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAClB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACpB,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAClB,CAAC;AACD;AACA;AACO,SAAS,UAAU,CAAC,GAAG,EAAE;AAChC;AACA,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE;AACrB,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK;AACL,IAAI,OAAO,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,UAAU,CAAC;AACtD,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,EAAE,EAAE;AACnD,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;AAC5C,IAAI,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE;AAC5B,QAAQ,OAAO,EAAE,CAAC;AAClB,KAAK;AACL,IAAI,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE;AAC5B,QAAQ,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACzB,KAAK;AACL,IAAI,IAAI,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACrE;AACA,IAAI,IAAI,CAAC,KAAK,EAAE;AAChB;AACA,QAAQ,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;AACnD,KAAK;AACL;AACA,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;AAC7C,IAAI,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;AAC7B;AACA,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;AAC7B;AACA,IAAI,IAAI,GAAG,EAAE,GAAG,CAAC;AACjB,IAAI,KAAK,IAAI,GAAG,IAAI,MAAM,EAAE;AAC5B,QAAQ,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC;AACzB,QAAQ,GAAG,GAAG,KAAK,GAAG,GAAG,CAAC;AAC1B,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;AAClC,YAAY,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,EAAC;AACrC,SAAS;AACT,QAAQ,KAAK,GAAG,GAAG,CAAC;AACpB,KAAK;AACL,IAAI,OAAO,KAAK,CAAC;AACjB,CACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE;AACpC;AACA,IAAI,IAAI,MAAM,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAC/C,IAAI,IAAI,MAAM,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAC/C,IAAI,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;AAC5B,IAAI,IAAI,QAAQ,CAAC;AACjB;AACA,IAAI,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE;AACxC,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK;AACL,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;AAC9B,QAAQ,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AAC7B;AACA,QAAQ,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE;AACzC,YAAY,OAAO,KAAK,CAAC;AACzB,SAAS;AACT,KAAK;AACL;AACA,IAAI,OAAO,IAAI,CAAC;AAChB,CAAC;AACD;AACA;AACA;AACO,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAC,SAAS,OAAO,EAAE;AACtD,IAAI,IAAI,QAAQ,CAAC,UAAU,KAAK,UAAU,EAAE;AAC5C,QAAQ,OAAO,EAAE,CAAC;AAClB,KAAK,MAAM;AACX,QAAQ,IAAI,OAAO,GAAG,YAAY;AAClC,YAAY,OAAO,EAAE,CAAC;AACtB,YAAY,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAC5E,YAAY,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAC9D,SAAS,CAAC;AACV,QAAQ,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AACrE,QAAQ,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AACvD,KAAK;AACL,CAAC,CAAC;;;;;;;;;;;;;;;;;;;AC1OF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,QAAQ,GAAG,SAAS,CAAC,EAAE;AAC7B,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;AACvB,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AAChC,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,eAAe,GAAG,CAAC,CAAC;AAC1B,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAC3B,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,MAAM,cAAc,GAAG,CAAC,CAAC;AACzB;AACA;AACA,SAAS,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE;AAC9C;AACA,CAAC,IAAI,GAAG,IAAI,QAAQ,EAAE;AACtB,EAAE,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,EAAE;AACzC,GAAG,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;AACzE,GAAG;AACH,EAAE;AACF,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE;AACvB,EAAE,IAAI,KAAK,IAAI,IAAI,IAAI,MAAM,IAAI,KAAK,EAAE;AACxC,GAAG,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC;AACxE,GAAG;AACH,EAAE;AACF,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AACvC,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,SAAS,QAAQ,CAAC,CAAC,EAAE;AACrB;AACA;AACA,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC;AACxC,CAAC,IAAI,KAAK,IAAI,SAAS,EAAE;AACzB,EAAE,OAAO,aAAa,CAAC;AACvB,EAAE,MAAM,IAAI,KAAK,EAAE;AACnB,EAAE,IAAI,MAAM,EAAE;AACd,GAAG,OAAO,iBAAiB,CAAC;AAC5B,GAAG,MAAM;AACT,GAAG,OAAO,eAAe,CAAC;AAC1B,GAAG;AACH,EAAE,MAAM;AACR,EAAE,IAAI,MAAM,EAAE;AACd,GAAG,OAAO,gBAAgB,CAAC;AAC3B,GAAG,MAAM;AACT,GAAG,OAAO,cAAc,CAAC;AACzB,GAAG;AACH,EAAE;AACF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE;AAC3B;AACA,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,SAAS,EAAE;AAC9B,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;AACrB,GAAG,MAAM,IAAI,KAAK,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;AAC1C,GAAG;AACH,EAAE,EAAE,GAAG,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AAC9C,EAAE;AACF,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,SAAS,EAAE;AAC9B,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;AACrB,GAAG,MAAM,IAAI,KAAK,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;AAC1C,GAAG;AACH,EAAE,EAAE,GAAG,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AAC9C,EAAE;AACF,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE;AACrB;AACA,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACxB,EAAE,MAAM;AACR;AACA,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;AACtC,EAAE;AACF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE;AACxB,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAC1C,CAAC,QAAQ,MAAM,GAAG,MAAM,EAAE;AAC1B,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE;AACzB,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAC1C,CAAC,QAAQ,MAAM,GAAG,MAAM,EAAE;AAC1B,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,SAAS,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE;AACxB,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAC1C,CAAC,QAAQ,MAAM,IAAI,MAAM,EAAE;AAC3B,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE;AACrB,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAC1C,CAAC,IAAI,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAC5B,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AACzB,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC5B,CAAC;AACD;AACA;AACA,SAAS,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE;AACrB,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC;AACxC,CAAC;AACD;AACA;AACA,SAAS,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE;AACrB,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC;AACxC,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,SAAS,QAAQ,CAAC,CAAC,EAAE;AACrB,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE;AAC7B,EAAE,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;AACtB,EAAE,MAAM;AACR,EAAE,IAAI,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AACzB,EAAE,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACjB,EAAE,IAAI,GAAG,IAAI,QAAQ,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE;AAC3C,GAAG,GAAG,GAAG,IAAI,CAAC;AACd,GAAG;AACH,EAAE,IAAI,IAAI,IAAI,eAAe,EAAE;AAC/B,GAAG,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AACnB,GAAG,MAAM,IAAI,IAAI,IAAI,gBAAgB,EAAE;AACvC,GAAG,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACnB,GAAG,MAAM,IAAI,IAAI,IAAI,aAAa,CAAC;AACnC,GAAG,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AACpB,GAAG,MAAM,IAAI,IAAI,IAAI,iBAAiB,EAAE;AACxC,GAAG,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AACnB,GAAG,MAAM,IAAI,IAAI,IAAI,cAAc,EAAE;AACrC,GAAG,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACnB,GAAG;AACH,EAAE;AACF,CAAC;AACD;AACA;AACA,eAAe;AACf,CAAC,GAAG;AACJ,CAAC,QAAQ;AACT,CAAC,MAAM;AACP,CAAC,OAAO;AACR,CAAC,MAAM;AACP,CAAC,MAAM;AACP,CAAC,GAAG;AACJ,CAAC,GAAG;AACJ,CAAC;;AC/ND;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA,MAAMA,UAAQ,GAAG,SAAS,CAAC,EAAE;AAC7B,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;AACvB,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AAChC,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,SAAS,KAAK,CAAC;AAClC,CAAC,WAAW,CAAC,OAAO,EAAE;AACtB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;AACjB,EAAE,IAAI,CAAC,IAAI,IAAI,eAAe,CAAC;AAC/B,EAAE;AACF,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;AAC/B,CAAC,YAAY,EAAE,EAAE;AACjB,CAAC,YAAY,EAAE,EAAE;AACjB,CAAC,OAAO,EAAE,EAAE;AACZ,CAAC,MAAM,EAAE,CAAC;AACV,CAAC,MAAM,EAAE,CAAC;AACV,CAAC,aAAa,EAAE,CAAC;AACjB,CAAC,aAAa,EAAE,CAAC;AACjB,CAAC,CAAC,CAAC;AACH;AACA;AACA;AACA;AACA,MAAM,aAAa,GAAG,QAAQ,CAAC,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC;AACrE,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC;AACxD,MAAM,aAAa,GAAG,YAAY;AAClC,CAAC,QAAQ,CAAC,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC;AAChD,MAAM,YAAY,GAAG,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC;AACrD,MAAM,SAAS,GAAG,YAAY,GAAG,aAAa,CAAC;AAC/C;AACA,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;AAC5B,CAAC,OAAO,EAAE,aAAa;AACvB,CAAC,MAAM,EAAE,YAAY;AACrB,CAAC,OAAO,EAAE,aAAa;AACvB,CAAC,MAAM,EAAE,YAAY;AACrB,CAAC,GAAG,EAAE,SAAS;AACf,CAAC,CAAC,CAAC;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE;AACvB,CAAC,IAAI,EAAE,CAAC,YAAY,QAAQ,EAAE;AAC9B;AACA,EAAE,IAAIA,UAAQ,CAAC,CAAC,CAAC,EAAE;AACnB,GAAG,CAAC,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,GAAG,MAAM;AACT,GAAG,MAAM,IAAI,aAAa,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;AAChD,GAAG;AACH,EAAE;AACF,CAAC,IAAI,EAAE,CAAC,YAAY,QAAQ,EAAE;AAC9B;AACA,EAAE,IAAIA,UAAQ,CAAC,CAAC,CAAC,EAAE;AACnB,GAAG,CAAC,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,GAAG,MAAM;AACT,GAAG,MAAM,IAAI,aAAa,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;AAChD,GAAG;AACH,EAAE;AACF;AACA,CAAC,IAAI,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;AACxD,CAAC,IAAI,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;AAC1D,CAAC,IAAI,GAAG,GAAG,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC;AAC5B;AACA,CAAC,IAAI,GAAG,IAAI,EAAE,EAAE;AAChB;AACA,EAAE,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE;AACtD,GAAG,OAAO,QAAQ,CAAC,aAAa,CAAC;AACjC,GAAG,MAAM;AACT,GAAG,OAAO,QAAQ,CAAC,aAAa,CAAC;AACjC,GAAG;AACH,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AACvC,EAAE,OAAO,QAAQ,CAAC,OAAO,CAAC;AAC1B,EAAE,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AACxC,EAAE,OAAO,QAAQ,CAAC,MAAM,CAAC;AACzB,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;AACtB,EAAE,OAAO,QAAQ,CAAC,MAAM,CAAC;AACzB,EAAE,MAAM;AACR;AACA;AACA,EAAE,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE;AACvD,GAAG,OAAO,QAAQ,CAAC,YAAY,CAAC;AAChC,GAAG,MAAM;AACT,GAAG,OAAO,QAAQ,CAAC,YAAY,CAAC;AAChC,GAAG;AACH,EAAE;AACF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,kBAAkB,CAAC,GAAG,EAAE;AACjC,CAAC,OAAO,SAAS,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE;AAC5B,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AACb,EAAE,IAAI,GAAG,EAAE;AACX,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;AACjD,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;AACjD,GAAG,MAAM;AACT,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;AAClD,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;AAClD,GAAG;AACH,EAAE,OAAO,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AAC9B,EAAE;AACF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,aAAa,CAAC,WAAW,EAAE,YAAY,EAAE;AAClD,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,CAAC,GAAG,WAAW,CAAC;AAC9D,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,CAAC,GAAG,YAAY,CAAC;AACnE,CAAC,IAAI,SAAS,EAAE;AAChB,EAAE,MAAM,IAAI,aAAa,CAAC,4CAA4C,CAAC,CAAC;AACxE,EAAE;AACF,CAAC,IAAI,CAAC,UAAU,EAAE;AAClB,EAAE,MAAM,IAAI,aAAa,CAAC,8CAA8C,CAAC,CAAC;AAC1E,EAAE;AACF,CAAC,OAAO,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AACzD,CACA;AACA;AACA;AACA,SAAS,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE;AACzB,CAAC,IAAI,GAAG,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACzB,CAAC,IAAI,GAAG,IAAI,QAAQ,CAAC,YAAY,EAAE;AACnC,EAAE,OAAO,EAAE,CAAC;AACZ,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,YAAY,EAAE;AAC1C,EAAE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;AACjE,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE;AACpC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AACb,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE;AACpC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AACb,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE;AACrC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AACb,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,aAAa,EAAE;AAC3C,EAAE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;AACjE,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,aAAa,EAAE;AAC3C,EAAE,OAAO,EAAE,CAAC;AACZ,EAAE;AACF,CAAC;AACD;AACA;AACA,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE;AACrB,CAAC,IAAI,GAAG,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACzB,CAAC,IAAI,GAAG,IAAI,QAAQ,CAAC,YAAY,EAAE;AACnC;AACA;AACA,EAAE,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;AAC5D;AACA,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACjB,GAAG,MAAM;AACT;AACA,GAAG,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;AAClE,GAAG;AACH,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,YAAY,EAAE;AAC1C,EAAE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;AACjE,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE;AACpC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AACb,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,EAAE;AACpC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AACb,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE;AACrC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AACb,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,aAAa,EAAE;AAC3C,EAAE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;AACjE,EAAE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,aAAa,EAAE;AAC3C;AACA;AACA,EAAE,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;AAC5D;AACA,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACjB,GAAG,MAAM;AACT;AACA,GAAG,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;AAClE,GAAG;AACH,EAAE;AACF,CAAC;AACD;AACA;AACA,SAAS,YAAY,CAAC,SAAS,EAAE;AACjC,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE;AAC5B,EAAE,OAAO,SAAS,CAAC;AACnB,EAAE;AACF,CAAC,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;AACpC,CAAC,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AAC9B,EAAE,IAAI,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC;AAC1B,EAAE,IAAI,IAAI,GAAG,SAAS,CAAC,KAAK,GAAE;AAC9B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACjD,EAAE;AACF,CAAC,OAAO,MAAM,CAAC;AACf,CAAC;AACD;AACA;AACA,SAAS,QAAQ,CAAC,SAAS,EAAE;AAC7B,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE;AAC5B,EAAE,OAAO,SAAS,CAAC;AACnB,EAAE;AACF,CAAC,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;AACpC,CAAC,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AAC9B,EAAE,IAAI,IAAI,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC;AAC1B,EAAE,IAAI,IAAI,GAAG,SAAS,CAAC,KAAK,GAAE;AAC9B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAC7C,EAAE;AACF,CAAC,OAAO,MAAM,CAAC;AACf,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,QAAQ,CAAC;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE;AAClD,EAAE,IAAI,WAAW,GAAGA,UAAQ,CAAC,GAAG,CAAC,CAAC;AAClC;AACA,EAAE,IAAI,WAAW,IAAI,IAAI,KAAK,SAAS,EAAE,IAAI,GAAG,GAAG,CAAC;AACpD,EAAE,IAAI,CAACA,UAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,aAAa,CAAC,kBAAkB,CAAC,CAAC;AAClE,EAAE,IAAI,CAACA,UAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,IAAI,aAAa,CAAC,mBAAmB,CAAC,CAAC;AACpE,EAAE,IAAI,GAAG,GAAG,IAAI,EAAE,MAAM,IAAI,aAAa,CAAC,YAAY,CAAC,CAAC;AACxD,EAAE,IAAI,GAAG,KAAK,IAAI,EAAE;AACpB,GAAG,UAAU,GAAG,IAAI,CAAC;AACrB,GAAG,WAAW,GAAG,IAAI,CAAC;AACtB,GAAG;AACH,EAAE,IAAI,GAAG,KAAK,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI,CAAC;AAC3C,EAAE,IAAI,IAAI,KAAK,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAC;AAC5C,EAAE,IAAI,UAAU,KAAK,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;AAClD,EAAE,IAAI,WAAW,KAAK,SAAS,EAAE,WAAW,GAAG,KAAK,CAAC;AACrD,EAAE,IAAI,OAAO,UAAU,KAAK,SAAS,EAAE,MAAM,IAAI,aAAa,CAAC,wBAAwB,CAAC,CAAC;AACzF,EAAE,IAAI,OAAO,WAAW,KAAK,SAAS,EAAE,MAAM,IAAI,aAAa,CAAC,yBAAyB,CAAC,CAAC;AAC3F,EAAE,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;AAClB,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;AACpB,EAAE,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;AAChC,EAAE,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;AAClC,EAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC;AACxC,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9C,EAAE,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAC/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;AAC1F,EAAE,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;AAC5F,EAAE;AACF;AACA;AACA,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC;AAC7C,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC;AAC/C,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC;AAC/C,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC;AACjD;AACA;AACA;AACA;AACA;AACA,CAAC,QAAQ,CAAC,GAAG;AAEb,EAAE,IAAI,IAAI,CAAC,SAAS,EAAE;AACtB,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAChC,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACnB,GAAG,MAAM;AACT,GAAG,IAAI,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;AAClD,GAAG,IAAI,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACpD,GAAG,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAC3B,GAAG;AACH,EAAE;AACF;AACA;AACA,CAAC,OAAO,GAAG;AACX,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;AACtE,EAAE;AACF;AACA,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE;AACrB,EAAE,IAAI,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;AACrD,EAAE,IAAI,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;AACxD,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC;AAC7B,EAAE;AACF;AACA,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE;AACjB,EAAE,OAAO,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC9B,EAAE;AACF;AACA,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE;AAChB,EAAE,OAAO,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC;AACjD,EAAE;AACF;AACA;AACA;AACA;AACA;AACA,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE;AAClC,EAAE,IAAI,QAAQ,GAAG,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACtC,EAAE,OAAO,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC;AAClC,EAAE;AACF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC;AAC7B,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;AACvB,QAAQ,CAAC,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;AAC3C,QAAQ,CAAC,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;AAC7C,QAAQ,CAAC,aAAa,GAAG,aAAa,CAAC;AACvC,QAAQ,CAAC,SAAS,GAAG,SAAS,CAAC;AAC/B,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;AACvB,QAAQ,CAAC,YAAY,GAAG,YAAY,CAAC;AACrC,QAAQ,CAAC,QAAQ,GAAG,QAAQ;;AC/Y5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA,MAAMC,KAAG,GAAG,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC5C;AACA;AACA;AACA;AACA;AACO,SAAS,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE;AACjD,IAAI,IAAI,GAAG,GAAG,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC;AACrD,IAAI,IAAI,GAAG,GAAG,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC;AACrD,IAAI,IAAI,GAAG,GAAG,QAAQ,CAAC,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAC;AAC7D,IAAI,IAAI,EAAE,GAAG,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,SAAS,CAAC;AACtD,IAAI,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;AACnC,CACA;AACA;AACO,SAAS,UAAU,CAAC,MAAM,EAAE;AACnC,IAAI,OAAO;AACX,QAAQ,QAAQ,EAAE,MAAM,CAAC,QAAQ;AACjC,QAAQ,QAAQ,EAAE,MAAM,CAAC,QAAQ;AACjC,QAAQ,YAAY,EAAE,MAAM,CAAC,YAAY;AACzC,QAAQ,SAAS,EAAE,MAAM,CAAC,SAAS;AACnC,KAAK;AACL,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,eAAe,CAAC,MAAM,EAAE,EAAE,EAAE;AAC5C,CAAC,IAAI,EAAE,KAAK,SAAS,EAAE;AACvB,KAAK,MAAM,IAAI,KAAK,EAAE,oCAAoC,CAAC,CAAC;AAC5D,EAAE;AACF,CAAC,MAAM,QAAQ,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;AACxC,CAAC,OAAO;AACR,EAAE,QAAQ,GAAG,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ;AACnG,EAAE,QAAQ,GAAG,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,QAAQ;AAC3D,EAAE,YAAY,GAAG,MAAM,CAAC,YAAY;AACpC,EAAE,SAAS,GAAG,EAAE;AAChB,EAAE,CAAC;AACH,CACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,kBAAkB,CAAC,MAAM,EAAE,EAAE,EAAE;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,WAAW,CAAC;AACpB,IAAI,IAAI,EAAE,IAAI,SAAS,EAAE;AACzB,QAAQ,WAAW,GAAG,MAAM,CAAC;AAC7B,KAAK,MAAM;AACX,QAAQ,WAAW,GAAG,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAClD,KAAK;AACL;AACA,IAAI,IAAI,SAAS,GAAGA,KAAG,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACnD,IAAI,IAAI,SAAS,KAAK,CAAC,EAAE;AACzB;AACA,QAAQ,SAAS,GAAGA,KAAG,CAAC,MAAM,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;AAClD,KAAK;AACL,IAAI,OAAO,SAAS,CAAC;AACrB,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,QAAQ,CAAC,MAAM,EAAE;AACjC,IAAI,QAAQ,MAAM,CAAC,QAAQ,KAAK,GAAG,IAAI,MAAM,CAAC,YAAY,KAAK,GAAG,EAAE;AACpE,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;AACxC,IAAI,IAAI,GAAG,MAAM;AACjB,IAAI,MAAM,EAAE,QAAQ;AACpB,IAAI,WAAW,EAAE,YAAY;AAC7B,IAAI,YAAY,EAAE,aAAa;AAC/B,CAAC,CAAC,CAAC;AACH;AACA;AACA;AACA;AACA;AACO,SAAS,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE;AACjD,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC;AAC/D,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,UAAU,CAAC,YAAY,CAAC;AAClD,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,UAAU,CAAC,WAAW,CAAC;AACjD;AACA,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE;AACrB,EAAE,IAAI,CAAC,GAAG,GAAG,EAAE,OAAO,UAAU,CAAC,YAAY,CAAC;AAC9C,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,GAAG,EAAE,OAAO,UAAU,CAAC,YAAY,CAAC;AAC3D,EAAE,MAAM,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE;AAC5B,KAAK,IAAI,CAAC,GAAG,GAAG,EAAE,OAAO,UAAU,CAAC,WAAW,CAAC;AAChD,KAAK,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,GAAG,EAAE,OAAO,UAAU,CAAC,YAAY,CAAC;AAC7D,EAAE;AACF,CAAC,OAAO,UAAU,CAAC,MAAM,CAAC;AAC1B,CACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,oBAAoB,CAAC,UAAU,EAAE,KAAK,EAAE;AACxD,IAAI,QAAQ,iBAAiB,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,EAAE;AACvE,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE;AAC1C,CAAC,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAChD,CAAC,IAAI,KAAK,KAAK,UAAU,CAAC,MAAM,EAAE;AAClC;AACA,EAAE,MAAM,CAAC,QAAQ,GAAG,GAAG,CAAC;AACxB,EAAE,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC;AAC5B,EAAE,IAAI,KAAK,KAAK,UAAU,CAAC,YAAY,EAAE;AACzC,GAAG,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9B,GAAG,MAAM,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AACpC,EAAE;AACF,CAAC,OAAO,MAAM,CAAC;AACf,CACA;AACA;AACA;AACA;AACA;AACO,SAAS,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE;AAC9C,IAAI,IAAI,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;AAC9B;AACA,IAAI,IAAI,SAAS,GAAG,gCAAgC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACvE;AACA,IAAI,IAAI,UAAU,GAAG,gCAAgC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACxE;AACA,IAAI,IAAI,SAAS,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,EAAE;AAC7D,QAAQ,IAAI,SAAS,GAAG,UAAU,EAAE;AACpC,YAAY,OAAO,CAAC,EAAE,GAAG,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,SAAS;AACT;AACA,YAAY,OAAO,CAAC,EAAE,GAAG,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,KAAK;AACL,SAAS,IAAI,SAAS,KAAK,SAAS;AACpC,QAAQ,OAAO,CAAC,EAAE,GAAG,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1C,SAAS,IAAI,UAAU,KAAK,SAAS;AACrC,QAAQ,OAAO,CAAC,EAAE,GAAG,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3C,SAAS,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACvC,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACnC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,OAAO,IAAI,CAAC;AACrD,MAAM,OAAO,KAAK,CAAC;AACnB,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACzC;AACA,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,EAAE;AAC7B,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;AAC3B,UAAU,OAAO,CAAC,GAAG,CAAC,CAAC;AACvB,EAAE;AACF;AACA,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACjC;AACA,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,OAAO,EAAE,CAAC;AACnD;AACA,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,CAAC,IAAI,YAAY,KAAK,GAAG,EAAE;AAC3B,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnB,EAAE;AACF,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;AAC1B,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;AAC1B,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1C,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,8BAA8B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACjD,CAAC,MAAM,GAAG,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;AACjC,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE;AAC3B,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE;AACvB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACnB,MAAM;AACN,UAAU,OAAO,EAAE,CAAC;AACpB,EAAE;AACF,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE;AAC3B,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,EAAE,CAAC;AACjC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,KAAK,OAAO,EAAE,CAAC;AACf,EAAE;AACF,MAAM,OAAO,EAAE,CAAC;AAChB,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,gCAAgC,CAAC,MAAM,EAAE,CAAC,EAAE;AACrD,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC;AAC/D,CAAC,MAAM,GAAG,GAAG,8BAA8B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE;AACvB,QAAQ,OAAO;AACf,KAAK;AACL,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;AACpB,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE;AAC9C;AACA,CAAC,IAAI,cAAc,GAAG,gCAAgC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzE;AACA,CAAC,IAAI,aAAa,GAAG,gCAAgC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACxE;AACA,IAAI,IAAI,cAAc,IAAI,QAAQ,EAAE;AACpC,QAAQ,cAAc,GAAG,SAAS,CAAC;AACnC,KAAK;AACL,IAAI,IAAI,aAAa,IAAI,QAAQ,EAAE;AACnC,QAAQ,aAAa,GAAG,SAAS,CAAC;AAClC,KAAK;AACL;AACA,CAAC,IAAI,cAAc,KAAK,SAAS,IAAI,aAAa,KAAK,SAAS,EAAE;AAClE,KAAK,IAAI,cAAc,GAAG,aAAa;AACvC,GAAG,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACrC;AACA,GAAG,OAAO,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,EAAE;AACF,MAAM,IAAI,cAAc,KAAK,SAAS;AACtC,KAAK,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,MAAM,IAAI,aAAa,KAAK,SAAS;AACrC,KAAK,OAAO,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,MAAM,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACpC,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,6BAA6B,EAAE,YAAY,EAAE,MAAM,EAAE;AACrE;AACA;AACA;AACA;AACA,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,QAAQ,EAAE;AACpD,QAAQ,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC7C,KAAK;AACL;AACA,IAAI,IAAI,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC;AAC9B,IAAI,IAAI,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC;AAC/B,IAAI,IAAI,SAAS,GAAG,YAAY,CAAC,UAAU,CAAC;AAC5C,IAAI,IAAI,SAAS,GAAG,YAAY,CAAC,WAAW,CAAC;AAC7C;AACA,IAAI,IAAI,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC9C,IAAI,IAAI,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;AAC9B,IAAI,IAAI,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC;AAC9B,IAAI,IAAI,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;AAClC,IAAI,IAAI,EAAE,GAAG,eAAe,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC;AAClD;AACA,IAAI,IAAI,EAAE,IAAI,CAAC,EAAE;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;AACnC,QAAQ,IAAI,YAAY,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE;AACpD,YAAY,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;AAChD;AACA,YAAY,IAAI,EAAE,GAAG,GAAG,EAAE;AAC1B;AACA;AACA,gBAAgB,IAAI,EAAE,GAAG,EAAE,EAAE;AAC7B,oBAAoB,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AACvE,iBAAiB,MAAM;AACvB,oBAAoB,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AACvE,iBAAiB;AACjB,aAAa,MAAM;AACnB;AACA;AACA,gBAAgB,IAAI,EAAE,GAAG,EAAE,EAAE;AAC7B,oBAAoB,OAAO,IAAI,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AACvE,iBAAiB,MAAM;AACvB,oBAAoB,OAAO,IAAI,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AACvE,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,EAAE,GAAG,EAAE,EAAE;AACjB;AACA,QAAQ,OAAO,IAAI,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAC1D,KAAK,MAAM;AACX;AACA,QAAQ,OAAO,IAAI,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAC1D,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,6BAA6B,CAAC,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE;AAC1E,IAAI,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,GAAG,WAAW,CAAC;AACpD;AACA,IAAI,IAAI,SAAS,GAAG,CAAC,IAAI,KAAK,KAAK,SAAS,EAAE;AAC9C,QAAQ,KAAK,GAAG,CAAC,MAAK;AACtB,KAAK;AACL,IAAI,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AACxC,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE;AAClF;AACA;AACA;AACA;AACA,IAAI,IAAI,YAAY,CAAC,QAAQ,EAAE;AAC/B,QAAQ,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;AACnE,KAAK;AACL,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AAC3B,QAAQ,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC;AACnD,KAAK;AACL;AACA,IAAI,IAAI,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC7B,IAAI,IAAI,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC7B,IAAI,IAAI,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC;AACjC,IAAI,IAAI,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;AAC9B;AACA,IAAI,IAAI,KAAK,EAAE,EAAE,EAAE,MAAM,CAAC;AAC1B,IAAI,IAAI,UAAU,EAAE,SAAS,CAAC;AAC9B,IAAI,IAAI,UAAU,GAAG,EAAE,CAAC;AACxB;AACA,IAAI,aAAa,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE;AACzC;AACA,QAAQ,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AACzD,YAAY,OAAO;AACnB,SAAS;AACT,QAAQ,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACjC;AACA,QAAQ,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE;AACjD,YAAY,OAAO;AACnB,SAAS;AACT;AACA;AACA;AACA,QAAQ,MAAM,GAAG,sBAAsB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;AACzD;AACA,QAAQ,MAAM,CAAC,OAAO,CAAC,SAAS,KAAK,EAAE;AACvC,YAAY,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;AAC5B,YAAY,SAAS,GAAG,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACvD,YAAY,UAAU,GAAG,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC;AACrF,YAAY,IAAI,YAAY,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;AACzD,gBAAgB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;AAC7C,gBAAgB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;AAC3C,gBAAgB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtC,aAAa;AACb,SAAS,CAAC,CAAC;AACX,KAAK,CAAC,CAAC;AACP;AACA;AACA,IAAI,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE;AAC/B,QAAQ,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;AACxD,KAAK,CAAC;AACN,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,IAAI,OAAO,UAAU,CAAC;AACtB,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;AAC/B,IAAI,IAAI,EAAE,CAAC;AACX,IAAI,MAAM,EAAE,CAAC;AACb,CAAC,CAAC,CAAC;AACH;AACA;AACA,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;AAChC,IAAI,IAAI,EAAE,CAAC;AACX,IAAI,WAAW,EAAE,CAAC;AAClB,IAAI,KAAK,EAAE,CAAC;AACZ,IAAI,MAAM,EAAE,CAAC;AACb,IAAI,IAAI,EAAE,CAAC;AACX,CAAC,CAAC,CAAC;AACH;AACA;AACO,MAAM,WAAW,CAAC;AACzB;AACA,IAAI,WAAW,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE;AACzC,QAAQ,IAAI,EAAE,GAAG,UAAU,CAAC,SAAS,CAAC;AACtC,QAAQ,IAAI,SAAS,GAAG,QAAQ,CAAC,UAAU,EAAC;AAC5C,QAAQ,IAAI,IAAI,IAAI,UAAU,IAAI,SAAS,IAAI,UAAU,CAAC,QAAQ,IAAI,SAAS,CAAC,CAAC;AACjF;AACA,QAAQ,IAAI,IAAI,EAAE;AAClB;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,SAAS,EAAE;AAC3B,gBAAgB,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;AAC9D,aAAa,MAAM;AACnB,gBAAgB,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;AAC7D,aAAa;AACb,SAAS,MAAM;AACf,YAAY,IAAI,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;AAClD,YAAY,IAAI,UAAU,GAAG,eAAe,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC7D,YAAY,IAAI,YAAY,GAAG,eAAe,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC/D;AACA;AACA,YAAY,IAAI,WAAW,IAAI,UAAU,CAAC,QAAQ,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;AAC7E,YAAY,IAAI,GAAG,GAAG,CAAC,WAAW,IAAI,QAAQ,CAAC,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC;AACtE;AACA;AACA,YAAY,IAAI,GAAG,CAAC;AACpB,YAAY,IAAI,UAAU,IAAI,SAAS,EAAE;AACzC,gBAAgB,IAAI,WAAW,IAAI,UAAU,CAAC,QAAQ,IAAI,YAAY,CAAC,QAAQ,CAAC,CAAC;AACjF,gBAAgB,IAAI,WAAW,IAAI,UAAU,CAAC,YAAY,IAAI,YAAY,CAAC,YAAY,CAAC,CAAC;AACzF,gBAAgB,IAAI,YAAY,IAAI,WAAW,IAAI,WAAW,CAAC,CAAC;AAChE,gBAAgB,IAAI,YAAY,EAAE;AAClC,oBAAoB,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC;AAC3C,iBAAiB,MAAM;AACvB,oBAAoB,GAAG,GAAG,SAAS,CAAC,WAAW,CAAC;AAChD,iBAAiB;AACjB,aAAa,MAAM,IAAI,CAAC,UAAU,IAAI,SAAS,EAAE;AACjD,gBAAgB,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC;AACtC,aAAa,MAAM,IAAI,UAAU,IAAI,CAAC,SAAS,EAAE;AACjD,gBAAgB,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC;AACrC,aAAa,MAAM,IAAI,CAAC,UAAU,IAAI,CAAC,SAAS,EAAE;AAClD,gBAAgB,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC;AACrC,aAAa;AACb,YAAY,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAClC,SAAS;AACT,KAAK;AACL;AACA,IAAI,IAAI,QAAQ,CAAC,GAAG;AACpB,QAAQ,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC3B,KAAK;AACL;AACA,IAAI,IAAI,SAAS,CAAC,GAAG;AACrB,QAAQ,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1B,KAAK;AACL;AACA,IAAI,QAAQ,GAAG;AACf,QAAQ,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC;AAC9C,QAAQ,MAAM,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC;AAChD,QAAQ,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,IAAI,QAAQ,GAAG,EAAE,CAAC;AACrE,QAAQ,IAAI,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,KAAK,EAAE;AAC/C,YAAY,GAAG,IAAI,kBAAkB,CAAC;AACtC,SAAS,MAAM,IAAI,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,EAAE;AACvD,YAAY,GAAG,IAAI,kBAAkB,CAAC;AACtC,SAAS,MAAM,IAAI,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,EAAE;AACrD,YAAY,GAAG,IAAI,kBAAkB,CAAC;AACtC,SAAS,MAAM,IAAI,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,WAAW,EAAE;AAC5D,YAAY,GAAG,IAAI,wBAAwB,CAAC;AAC5C,SAAS,MAAM,IAAI,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,EAAE;AACrD,YAAY,GAAG,IAAI,4BAA4B,CAAC;AAChD,SAAS;AACT,QAAQ,OAAO,GAAG,CAAC;AACnB,KAAK;AACL,CAAC;AACD;AACA;AACA,WAAW,CAAC,QAAQ,GAAG,QAAQ,CAAC;AAChC,WAAW,CAAC,SAAS,GAAG,SAAS;;;;;;;;;;;;;;;;;;;;;ACjrBjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AASA;AACA;AACA;AACA;AACA;AACA,SAAS,MAAM,CAAC,CAAC,EAAE;AACnB,IAAI,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3B,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE;AACpD,IAAI,IAAI,WAAW,IAAI,CAAC,EAAE;AAC1B,QAAQ,OAAO,MAAM,CAAC;AACtB,KAAK;AACL,IAAI,OAAO,CAAC,WAAW,IAAI,GAAG,IAAI,QAAQ,GAAG,MAAM,CAAC;AACpD,CACA;AACA;AACA,MAAM,iBAAiB,SAAS,KAAK,CAAC;AACtC;AACA,IAAI,WAAW,CAAC,OAAO,EAAE;AACzB,QAAQ,KAAK,CAAC,OAAO,CAAC,CAAC;AACvB,QAAQ,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;AACxC,KAAK;AACL;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,KAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAC/B;AACA;AACA,MAAM,YAAY,CAAC;AACnB;AACA,IAAI,WAAW,CAAC,OAAO,EAAE;AACzB,QAAQ,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;AACxB,QAAQ,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;AACrC,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,aAAa,CAAC,aAAa,EAAE;AACjC,QAAQ,IAAI,QAAQ,GAAG,CAAC,CAAC;AACzB,QAAQ,IAAI,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AAC7C,QAAQ,IAAI,YAAY,CAAC;AACzB,QAAQ,IAAI,cAAc,CAAC;AAC3B,QAAQ,OAAO,QAAQ,IAAI,QAAQ,EAAE;AACrC,MAAM,YAAY,GAAG,CAAC,QAAQ,GAAG,QAAQ,IAAI,CAAC,GAAG,CAAC,CAAC;AACnD,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AAChD,YAAY,IAAI,cAAc,GAAG,aAAa,EAAE;AAChD,gBAAgB,QAAQ,GAAG,YAAY,GAAG,CAAC,CAAC;AAC5C,aAAa,MAAM,IAAI,cAAc,GAAG,aAAa,EAAE;AACvD,gBAAgB,QAAQ,GAAG,YAAY,GAAG,CAAC,CAAC;AAC5C,aAAa,MAAM;AACnB;AACA,UAAU,OAAO,YAAY,CAAC;AAC9B,OAAO;AACP,SAAS;AACT;AACA,KAAK,OAAO,CAAC,QAAQ,CAAC;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE;AACtB,QAAQ,IAAI,KAAK,GAAG,CAAC,EAAE;AACvB,YAAY,OAAO,IAAI,CAAC;AACxB,SAAS;AACT,QAAQ,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;AACvE,YAAY,OAAO,IAAI,CAAC;AACxB,SAAS;AACT,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,OAAO,CAAC,CAAC,EAAE;AACf,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AAC1C,QAAQ,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;AACrD,KAAK;AACL;AACA,IAAI,eAAe,CAAC,QAAQ,EAAE;AAC9B,QAAQ,IAAI,CAAC,EAAE,KAAK,CAAC;AACrB,QAAQ,IAAI,OAAO,GAAG,EAAE,CAAC;AACzB,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC9C,YAAY,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC5B,YAAY,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACpC,YAAY,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;AAC5B,gBAAgB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACpC,aAAa;AACb,SAAS;AACT,QAAQ,OAAO,OAAO,CAAC;AACvB,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,GAAG,CAAC,CAAC,EAAE;AACX,QAAQ,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,KAAK,CAAC;AACrD,KAAK;AACL;AACA,IAAI,GAAG,CAAC,KAAK,EAAE;AACf,QAAQ,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACjC,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE;AAClD;AACA;AACA,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;AACnC,YAAY,IAAI,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;AAC1D;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,YAAY,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;AACtD,gBAAgB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACjD,aAAa;AACb,SAAS;AACT;AACA;AACA,QAAQ,IAAI,CAAC,EAAE,KAAK,CAAC;AACrB,QAAQ,IAAI,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC;AACnC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;AAClC,YAAY,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;AAC7B,YAAY,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AAC1C,YAAY,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE;AACzC;AACA,gBAAgB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACzD,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE;AAChD;AACA,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AAC3D;AACA;AACA,YAAY,IAAI,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;AAC1D,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE;AAChD,gBAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;AACnD,aAAa;AACb,SAAS;AACT;AACA;AACA,QAAQ,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAClD;AACA,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAACA,KAAG,CAAC,CAAC;AAC7B;AACA,QAAQ,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AAClC,YAAY,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AACtD,YAAY,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;AAC5B,gBAAgB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAClE,aAAa;AACb,SAAS;AACT;AACA,QAAQ,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACxC,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE;AAC1C,QAAQ,IAAI,IAAI,GAAG,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;AACvD,QAAQ,IAAI,IAAI,IAAI,CAAC,EAAE;AACvB,YAAY,OAAO;AACnB,SAAS;AACT;AACA;AACA,QAAQ,IAAI,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACjE,QAAQ,IAAI,QAAQ,IAAI,QAAQ,EAAE;AAClC,YAAY,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAC/D,SAAS,MAAM,IAAI,QAAQ,IAAI,MAAM,CAAC;AACtC,YAAY,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAC7D,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,GAAG;AACjB,QAAQ,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;AACnE,KAAK;AACL;AACA,IAAI,UAAU,GAAG,YAAY;AAC7B,QAAQ,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;AACvF,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,CAAC,CAAC,EAAE;AACjB,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AACtC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;AAChC;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,CAAC,GAAG,CAAC,EAAE;AACvB,gBAAgB,OAAO,CAAC,CAAC,CAAC,CAAC;AAC3B,aAAa,MAAM;AACnB,gBAAgB,OAAO,CAAC,CAAC,CAAC;AAC1B,aAAa;AACb,SAAS,MAAM;AACf;AACA;AACA;AACA;AACA,YAAY,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,CAAC,CAAC,EAAE;AACjB,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AACtC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;AAChC;AACA;AACA;AACA,YAAY,OAAO,CAAC,CAAC;AACrB,SAAS,MAAM;AACf;AACA,YAAY,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAChC,YAAY,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrC,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,CAAC,CAAC,EAAE;AACjB,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AACtC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;AAChC;AACA;AACA;AACA;AACA,YAAY,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;AAC1C,gBAAgB,OAAO,CAAC,CAAC,CAAC,CAAC;AAC3B,aAAa,MAAM;AACnB,gBAAgB,OAAO,CAAC,CAAC,CAAC;AAC1B,aAAa;AACb,SAAS,MAAM;AACf;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAClC,YAAY,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC;AACxD,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,CAAC,CAAC,EAAE;AACjB,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AACtC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;AAChC;AACA;AACA;AACA,YAAY,OAAO,CAAC,CAAC;AACrB,SAAS,MAAM;AACf;AACA,YAAY,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC5B,YAAY,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAClD,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,aAAa,CAAC,QAAQ,EAAE;AAC5B,QAAQ,IAAI,QAAQ,KAAK,SAAS;AAClC,YAAY,QAAQ,GAAG,IAAI,QAAQ,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACrE,QAAQ,IAAI,QAAQ,YAAY,QAAQ,KAAK,KAAK;AAClD,YAAY,MAAM,IAAI,iBAAiB,CAAC,mCAAmC,CAAC,CAAC;AAC7E;AACA;AACA,QAAQ,IAAI,QAAQ,CAAC,QAAQ,EAAE;AAC/B,YAAY,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACnD,YAAY,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;AAC5B,gBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;AAC1C,aAAa,MAAM;AACnB,gBAAgB,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AAC9C,aAAa;AACb,SAAS;AACT;AACA;AACA,QAAQ,IAAI,WAAW,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;AAC7C,QAAQ,IAAI,QAAQ,CAAC,UAAU,EAAE;AACjC,YAAY,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACvD,SAAS,MAAM;AACf,YAAY,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACvD,SAAS;AACT,QAAQ,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE;AAChC,YAAY,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AAC1C,SAAS;AACT,QAAQ,IAAI,QAAQ,CAAC,WAAW,EAAE;AAClC,YAAY,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACtD,SAAS,MAAM;AACf,YAAY,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACtD,SAAS;AACT,QAAQ,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE;AAC9B,YAAY,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AAC1C,SAAS;AACT,QAAQ,OAAO,CAAC,WAAW,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;AAC5C,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,QAAQ,EAAE;AACrB,QAAQ,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;AACxD,QAAQ,OAAO,CAAC,KAAK,IAAI,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;AACxE,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,QAAQ,EAAE;AACrB,QAAQ,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;AACxD,QAAQ,OAAO,CAAC,KAAK,IAAI,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;AAC/E,KAAK;AACL;AACA;AACA,IAAI,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE;AACtB,QAAQ,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC5C,KAAK;AACL;AACA,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE;AAC1B,QAAQ,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAChD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,aAAa,CAAC,UAAU,EAAE;AAC9B,QAAQ,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,CAAC;AACnC,YAAY,OAAO;AACnB,SAAS;AACT,QAAQ,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;AAClC,QAAQ,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACrD,QAAQ,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACnF;AACA,QAAQ,IAAI,MAAM,GAAG,KAAK,CAAC;AAC3B,QAAQ,IAAI,MAAM,GAAG,KAAK,CAAC;AAC3B,QAAQ,IAAI,MAAM,GAAG,CAAC,CAAC;AACvB;AACA,QAAQ,OAAO,MAAM,GAAG,GAAG,EAAE;AAC7B,YAAY,IAAI,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC7C,YAAY,IAAI,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;AAC7C,YAAY,IAAI,OAAO,GAAG,OAAO,EAAE;AACnC,gBAAgB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AACxD,gBAAgB,MAAM,EAAE,CAAC;AACzB,gBAAgB,MAAM,EAAE,CAAC;AACzB,aAAa,MAAM,IAAI,OAAO,IAAI,OAAO,EAAE;AAC3C,gBAAgB,MAAM,EAAE,CAAC;AACzB,gBAAgB,MAAM,EAAE,CAAC;AACzB,aAAa,MAAM;AACnB;AACA,gBAAgB,MAAM,EAAE,CAAC;AACzB,aAAa;AACb,YAAY,IAAI,MAAM,IAAI,UAAU,CAAC,MAAM,EAAE;AAC7C,gBAAgB,KAAK;AACrB,aAAa;AACb,SAAS;AACT,QAAQ,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;AACjD,KAAK;AACL;AACA;AACA,IAAI,MAAM,GAAG;AACb,QAAQ,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;AACnC,KAAK;AACL;AACA,IAAI,KAAK,GAAG;AACZ,QAAQ,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;AACxB,KAAK;AACL;AACA,IAAI,IAAI,MAAM,CAAC,GAAG;AAClB,QAAQ,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;AACjC,KAAK;AACL;AACA;;ACnhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,KAAK,CAAC;AACZ;AACA,CAAC,WAAW,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE;AACxC,EAAE,OAAO,GAAG,OAAO,IAAI,GAAE;AACzB,EAAE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;AAC7B,EAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;AACnB,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;AAClE,EAAE,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;AAC1B,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE;AAC/B,EAAE,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE;AACnD,GAAG,MAAM,IAAI,KAAK,CAAC,yBAAyB,EAAE,QAAQ,CAAC,CAAC;AACxD,GAAG;AACH,EAAE,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AACxD,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/B;AACA,KAAK,IAAI,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE;AAChC,MAAM,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC;AAC9B,MAAM,IAAI,IAAI,GAAG,IAAI,CAAC;AACtB,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,YAAY;AACzC,OAAO,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AAC3E,OAAO,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE;AAC/B,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;AACxC,QAAQ;AACR,OAAO,GAAG,CAAC,YAAY,GAAG,KAAK,CAAC;AAChC,OAAO,CAAC,CAAC;AACT,MAAM;AACN,EAAE,OAAO,GAAG;AACZ,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;AAC5B,EAAE,IAAI,KAAK,EAAE,GAAG,CAAC;AACjB,EAAE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;AAC1B;AACA,GAAG,IAAI,GAAG,CAAC,UAAU,EAAE;AACvB,IAAI,SAAS;AACb,IAAI;AACJ,GAAG,KAAK,GAAG;AACX,IAAI,GAAG,EAAE,IAAI,CAAC,SAAS;AACvB,IAAI,IAAI,EAAE,IAAI,CAAC,IAAI;AACnB,IAAI,GAAG,EAAE,GAAG;AACZ,IAAI,IAAI,EAAE,IAAI;AACd,KAAI;AACJ,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC;AACnC,GAAG,IAAI;AACP,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;AACxC,IAAI,CAAC,OAAO,GAAG,EAAE;AACjB,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;AACjE,IAAI;AACJ,GAAG;AACH,EAAE;AACF;AACA;AACA;AACA;AACA;AACA,CAAC,WAAW,CAAC,GAAG,EAAE;AAClB,EAAE,IAAI,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC5C,EAAE,IAAI,GAAG,GAAG,CAAC,CAAC,EAAE;AAChB,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACrC,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC;AACnB,GAAG;AACH,EAAE;AACF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,YAAY,CAAC;AACnB;AACA,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE;AACvC,EAAE,OAAO,GAAG,OAAO,IAAI,GAAE;AACzB,EAAE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;AACrB,EAAE,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;AACzB,EAAE,IAAI,CAAC,QAAQ,GAAG,SAAQ;AAC1B,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;AAC5E,EAAE,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;AAC5B,EAAE,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;AAC1B,EAAE,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;AACzB,EAAE;AACF;AACA,CAAC,SAAS,GAAG;AACb,EAAE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;AACzB,EAAE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;AAC5B,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AAC/B,EAAE;AACF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gBAAgB,EAAE,MAAM,EAAE;AAC1C,CAAC,MAAM,CAAC,mBAAmB,GAAG,IAAI,GAAG,EAAE,CAAC;AACxC,CAAC,MAAM,CAAC,iBAAiB,GAAG,EAAE,CAAC;AAC/B,CAAC,OAAO,MAAM,CAAC;AACf,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,iBAAiB,CAAC,UAAU,EAAE;AAC9C;AACA,CAAC,SAAS,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE;AACzC,EAAE,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrD,EAAE,IAAI,KAAK,IAAI,SAAS,EAAE;AAC1B,GAAG,MAAM,IAAI,KAAK,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;AAC5C,GAAG;AACH,EAAE,OAAO,KAAK,CAAC;AACf,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,SAAS,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE;AACxC;AACA,EAAE,IAAI,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAC1C,GAAG,MAAM,IAAI,KAAK,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAC;AAClD,GAAG;AACH,EAAE,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AACrE,EACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE;AACtC,EAAE,OAAO,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACnE,EACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE;AACnB,EAAE,OAAO,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;AAC3D,EACA;AACA;AACA,CAAC,SAAS,qBAAqB,CAAC,IAAI,EAAE;AACtC,EAAE,OAAO,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,aAAa,CAAC;AACpD,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,SAAS,kBAAkB,CAAC,UAAU,EAAE;AACzC,EAAE,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,EAAE;AAC9B,GAAG,OAAO;AACV,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,IAAI,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK;AAC9C,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC;AAC3B,GAAG,IAAI,EAAE,GAAG,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACzC,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,YAAY,IAAI,KAAK,CAAC,CAAC;AACxE,GAAG,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC3B,GAAG,EAAE,IAAI,CAAC,CAAC;AACX;AACA;AACA,EAAE,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC;AAClC,EAAE,MAAM,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC;AACrC,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC;AAChD;AACA,EAAE,IAAI,CAAC,iBAAiB,CAAC,MAAM,GAAG,OAAO,GAAG,GAAG,CAAC;AAChD;AACA,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;AAC5B,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AACpC,GAAG;AACH;AACA,EAAE,IAAI,OAAO,IAAI,CAAC,EAAE;AACpB,GAAG,IAAI,IAAI,GAAG,IAAI,CAAC;AACnB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,WAAW;AACrC,IAAI,KAAK,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,iBAAiB,EAAE;AACzD;AACA,KAAK,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;AACnC,KAAK;AACL,IAAI,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;AAChC,IAAI,CAAC,CAAC;AACN,GAAG;AACH,EAAE;AACF;AACA;AACA;AACA;AACA,CAAC,SAAS,oBAAoB,CAAC,IAAI,EAAE,KAAK,EAAE;AAC5C,EAAE,OAAO,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI;AACnD,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACvB,GAAG,CAAC,CAAC,CAAC;AACN,EAAE;AACF;AACA;AACA;AACA;AACA,CAAC,SAAS,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE;AACtC,EAAE,OAAO,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AACjD,EAAE;AACF;AACA,CAAC,UAAU,CAAC,cAAc,GAAG,cAAc,CAAC;AAC5C,CAAC,UAAU,CAAC,eAAe,GAAG,eAAe,CAAC;AAC9C,CAAC,UAAU,CAAC,oBAAoB,GAAG,oBAAoB,CAAC;AACxD,CAAC,UAAU,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;AACpD,CAAC,UAAU,CAAC,qBAAqB,GAAG,qBAAqB,CAAC;AAC1D,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;AACpB,CAAC,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC;AACtB,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,aAAa,CAAC;AAC3B;AACA,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE;AACrB,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;AACzB,EAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;AACtB,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7C,EAAE;AACF;AACA,CAAC,qBAAqB,CAAC,IAAI,EAAE;AAC7B,EAAE,IAAI,IAAI,IAAI,QAAQ,EAAE;AACxB,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACxB,GAAG;AACH,EAAE;AACF;AACA,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC;AAClC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE;AACnB,EAAE,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE;AAC5B,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;AACvB,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AACzC,GAAG;AACH,EAAE;AACF,CAAC;AACD,iBAAiB,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,YAAY,SAAS,aAAa,CAAC;AAChD,CAAC,WAAW,CAAC,KAAK,EAAE;AACpB,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AACxB,EAAE;AACF;AACA,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE;AACnB,EAAE,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;AAC/B,EAAE;AACF,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC;AAClC,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,WAAW,CAAC,WAAW,EAAE,aAAa,EAAE;AACxD,CAAC,aAAa,GAAG,aAAa,IAAI,SAAS,GAAG,EAAE,CAAC,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC;AACrE,CAAC,OAAO,IAAI,OAAO,EAAE,UAAU,OAAO,EAAE,MAAM,EAAE;AAChD,EAAE,IAAI,GAAG,GAAG,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,EAAE;AACtD,GAAG,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE;AAC7B,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;AACnB,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACzB,IAAI;AACJ,GAAG,CAAC,CAAC;AACL,EAAE,CAAC,CAAC;AACJ,CACA;AACA;AACA,eAAe;AACf,CAAC,iBAAiB;AAClB,CAAC,gBAAgB;AACjB,CAAC,aAAa;AACd,CAAC,YAAY;AACb,CAAC,WAAW;AACZ,CAAC;;AC5WD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC;AACpB;AACA,IAAI,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE;AAC7B;AACA,QAAQ,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;AAC/B;AACA;AACA,QAAQ,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;AACxC,QAAQ,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAClD,QAAQ,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACnD,QAAQ,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AACpD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,UAAU,CAAC,GAAG;AACtB,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE;AAC1B;AACA,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;AACjD,QAAQ,IAAI,OAAO,KAAK,IAAI,UAAU,EAAE;AACxC,YAAY,OAAO,KAAK,CAAC;AACzB,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE;AACjC,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AAC5C,QAAQ,IAAI,OAAO,KAAK,IAAI,UAAU,EAAE;AACxC;AACA;AACA,YAAY,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;AAC/D,YAAY,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACnC,SAAS,MAAM;AACf;AACA,YAAY,OAAO,IAAI,CAAC;AACxB,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,CAAC,KAAK,EAAE;AACrB,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;AACrC,QAAQ,IAAI,OAAO,KAAK,IAAI,UAAU,EAAE;AACxC,YAAY,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE;AAChD,gBAAgB,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;AACnE,gBAAgB,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;AACnE,gBAAgB,OAAO,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC3C,aAAa,CAAC,CAAC;AACf,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,qBAAqB,CAAC,IAAI,EAAE;AAChC,QAAQ,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI,IAAI,QAAQ,EAAE;AACjD,YAAY,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK;AAC3E,gBAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;AACzD,aAAa,CAAC,CAAC;AACf;AACA,YAAY,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAClC,YAAY,OAAO,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;AACvD,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,aAAa,CAAC,KAAK,EAAE;AACzB;AACA,QAAQ,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE;AAC/B,YAAY,OAAO;AACnB,SAAS;AACT,QAAQ,MAAM,eAAe,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AAC/E,QAAQ,MAAM,eAAe,GAAG,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AAChF,QAAQ,MAAM,eAAe,GAAG,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AAChF;AACA,QAAQ,IAAI,eAAe,EAAE;AAC7B,YAAY,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AACjD,SAAS;AACT;AACA,QAAQ,IAAI,eAAe,IAAI,eAAe,EAAE;AAChD,YAAY,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE;AACpC,gBAAgB,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,EAAE;AACpE,oBAAoB,IAAI,eAAe,EAAE;AACzC,wBAAwB,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC7D,qBAAqB;AACrB,iBAAiB,MAAM;AACvB,oBAAoB,IAAI,eAAe,EAAE;AACzC,wBAAwB,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC7D,qBAAqB;AACrB,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,IAAI,CAAC,GAAG;AAChB,QAAQ,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;AACpC,KAAK;AACL;AACA,IAAI,GAAG,CAAC,GAAG,EAAE;AACb,QAAQ,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACxC,KAAK;AACL;AACA,IAAI,GAAG,CAAC,GAAG,EAAE;AACb,QAAQ,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACxC,KAAK;AACL;AACA,IAAI,IAAI,GAAG;AACX,QAAQ,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;AACtC,KAAK;AACL;AACA,IAAI,MAAM,GAAG;AACb,QAAQ,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;AACxC,KAAK;AACL;AACA,IAAI,OAAO,GAAG;AACd,QAAQ,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;AACzC,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE;AACpB,QAAQ,IAAI,GAAG,GAAG,SAAS,CAAC;AAC5B,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;AACtC,YAAY,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC3C,SAAS;AACT,QAAQ,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACxC,QAAQ,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;AAC9D,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL;AACA,IAAI,MAAM,CAAC,GAAG,EAAE;AAChB,QAAQ,IAAI,MAAM,GAAG,KAAK,CAAC;AAC3B,QAAQ,IAAI,GAAG,GAAG,SAAS,CAAC;AAC5B,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;AACtC,YAAY,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC3C,YAAY,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACxC,YAAY,MAAM,GAAG,IAAI,CAAC;AAC1B,SAAS;AACT,QAAQ,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;AAClE,QAAQ,OAAO,MAAM,CAAC;AACtB,KAAK;AACL;AACA,IAAI,KAAK,GAAG;AACZ;AACA,QAAQ,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK;AACzE,YAAY,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACxD,SAAS,EAAC;AACV;AACA,QAAQ,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;AAChC;AACA,QAAQ,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAClC,KAAK;AACL;AACA,CAAC;AACD;AACA,QAAQ,CAAC,iBAAiB,CAAC,aAAa,CAAC,SAAS,CAAC;;AC1NnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,SAAS,aAAa,CAAC;AAC1C;AACA,IAAI,OAAO,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE;AAChC,QAAQ,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC/D,KAAK;AACL;AACA,IAAI,OAAO,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE;AACjC,QAAQ,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;AAChE,KAAK;AACL;AACA;AACA,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE;AAC1B,QAAQ,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AAC9D,QAAQ,IAAI,KAAK,IAAI,KAAK,EAAE;AAC5B,YAAY,OAAO,aAAa,CAAC,MAAM,CAAC;AACxC,SAAS,MAAM,IAAI,KAAK,IAAI,MAAM,EAAE;AACpC,YAAY,OAAO,aAAa,CAAC,OAAO,CAAC;AACzC,SAAS,MAAM;AACf,YAAY,IAAI,OAAO,KAAK,IAAI,UAAU,EAAE;AAC5C,gBAAgB,OAAO;AACvB,aAAa;AACb,SAAS;AACT,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK;AACL;AACA;AACA,IAAI,IAAI,CAAC,CAAC,OAAO,GAAG,EAAE,EAAE;AACxB,QAAQ,IAAI,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC;AAC3D;AACA,QAAQ,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;AACxD,KAAK;AACL;;AC5DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,OAAO,CAAC;AACd;AACA,IAAI,WAAW,CAAC,CAAC,YAAY,EAAE,QAAQ,EAAE;AACzC,QAAQ,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;AAC7B,QAAQ,IAAI,CAAC,EAAE,GAAG,YAAY,CAAC;AAC/B,QAAQ,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;AACjC,KAAK;AACL;AACA,IAAI,KAAK,GAAG;AACZ,QAAQ,OAAO,IAAI,CAAC,GAAG,IAAI,SAAS,CAAC;AACrC,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,UAAU,CAAC,SAAS,EAAE,GAAG,EAAE;AAC/B,QAAQ,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,EAAE;AACnC,YAAY,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;AAClD,SAAS;AACT,QAAQ,IAAI,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;AACtC,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;AACxD,QAAQ,IAAI,CAAC,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;AAChF,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,SAAS,CAAC,SAAS,EAAE,GAAG,EAAE;AAC9B,QAAQ,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,EAAE;AACnC,YAAY,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;AACjC;AACA,YAAY,IAAI,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,GAAE;AACzC,YAAY,IAAI,GAAG,GAAG,SAAS,EAAE;AACjC;AACA,gBAAgB,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;AAChD,aAAa,MAAM;AACnB;AACA,gBAAgB,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACxC,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,KAAK,GAAG;AACZ,QAAQ,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,EAAE;AACnC,YAAY,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnC,YAAY,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;AACjC,SAAS;AACT,KAAK;AACL;;ACpFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAoCA;AACA;AACA;AACA,CAAC,UAAU;AACX,IAAI,IAAI,aAAa,IAAI,MAAM,KAAK,KAAK,EAAE;AAC3C,QAAQ,MAAM,CAAC,WAAW,GAAG,EAAE,CAAC;AAChC,QAAQ,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;AACzD,KAAK;AACL,IAAI,IAAI,KAAK,IAAI,MAAM,CAAC,WAAW,KAAK,KAAK,CAAC;AAC9C,MAAM,MAAM,CAAC,WAAW,CAAC,GAAG,GAAG,SAAS,GAAG,EAAE;AAC7C,QAAQ,OAAO,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC;AAChE,OAAO,CAAC;AACR,KAAK;AACL,EAAE,GAAG,CAAC;AACN;AACA;AACA,MAAM,WAAW,GAAG;AACpB,CAAC,GAAG,GAAG,YAAY,CAAC,OAAO,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;AACrD,CAAC,CAAC;AACF;AACA,SAASC,iBAAe,CAAC,MAAM,EAAE,KAAK,EAAE;AACxC,CAAC,IAAI,KAAK,KAAK,SAAS,EAAE,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;AACpD,CAAC,IAAI,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC;AACzC,CAAC,OAAO;AACR,EAAE,QAAQ,GAAG,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ;AACvD,EAAE,QAAQ,GAAG,MAAM,CAAC,QAAQ;AAC5B,EAAE,SAAS,GAAG,KAAK;AACnB,EAAE,CAAC;AACH,CACA;AACA,MAAM,WAAW,CAAC;AAClB;AACA,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE;AACvB,EAAE,IAAI,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;AAC9B,EAAE,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;AAC1B,EAAE,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;AACjE;AACA,EAAE,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAClC,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9C;AACA,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACvB,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,MAAM,CAAC,OAAO,EAAE;AACjB,EAAE,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;AAC1B,EAAE,IAAI,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;AAC9B,EAAE,IAAI,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AAClC,EAAE,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE;AAChE,GAAG,OAAO;AACV,GAAG;AACH,EAAE,IAAI,CAAC,OAAO,GAAG;AACjB,GAAG,QAAQ,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,QAAQ;AACpF,GAAG,QAAQ,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,QAAQ;AAC9E,GAAG,SAAS,GAAG,SAAS,CAAC,SAAS;AAClC,IAAG;AACH,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;AACjC,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,GAAG,GAAG;AACP,EAAE,OAAOA,iBAAe,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC;AACnE,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,KAAK,CAAC,GAAG,EAAE;AACZ,EAAE,OAAOA,iBAAe,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC5C,EAAE;AACF;AACA,CAAC;AACD,QAAQ,CAAC,iBAAiB,CAAC,WAAW,CAAC,SAAS,CAAC;;ACzIjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,gBAAgB,CAAC;AACvB;AACA,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE;AACjC,EAAE,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;AAC1B;AACA,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1C,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACtC,EAAE,IAAI,CAAC,OAAO,CAAC;AACf,EAAE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;AAC5B;AACA,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;AAC7D,EAAE,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;AAChC,EAAE;AACF;AACA;AACA,CAAC,IAAI,KAAK,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC,IAAI,KAAK,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC,IAAI,MAAM,GAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC;AACpC;AACA,CAAC,OAAO,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;AACzB;AACA;AACA,CAAC,eAAe,CAAC,GAAG,EAAE;AACtB;AACA,EAAE,IAAI;AACN,GAAG,QAAQ,EAAE,GAAG;AAChB,GAAG,QAAQ,EAAE,GAAG;AAChB,GAAG,YAAY,EAAE,GAAG;AACpB,GAAG,SAAS,EAAE,EAAE;AAChB,GAAG,KAAK,EAAE,KAAK;AACf,GAAG,GAAG,IAAI;AACV,GAAG,GAAG,GAAG,CAAC;AACV;AACA;AACA,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;AAC1B,EAAE,IAAI,IAAI,CAAC,OAAO,IAAI,SAAS,EAAE;AACjC,GAAG,IAAI,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACrD,GAAG,SAAS,GAAG,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AAClD,GAAG,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC;AAC1B,GAAG,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC;AAC1B,GAAG,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC;AAC9B,GAAG;AACH;AACA;AACA,EAAE,IAAI,MAAM,GAAG;AACf,GAAG,QAAQ,GAAG,CAAC,GAAG,IAAI,SAAS,IAAI,GAAG,GAAG,CAAC;AAC1C,GAAG,QAAQ,GAAG,CAAC,GAAG,IAAI,SAAS,IAAI,GAAG,GAAG,CAAC;AAC1C,GAAG,YAAY,GAAG,CAAC,GAAG,IAAI,SAAS,IAAI,GAAG,GAAG,CAAC;AAC9C,GAAG,SAAS,GAAG,EAAE;AACjB,GAAG,CAAC;AACJ;AACA;AACA,EAAE,IAAI,KAAK,IAAI,SAAS,EAAE;AAC1B,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;AAC3B,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;AACnB,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;AACzD,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC/B,KAAK;AACL,IAAI;AACJ,GAAG;AACH;AACA;AACA,EAAE,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AAC3C;AACA,EAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC;AAClC;AACA,EAAE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;AACxB,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;AACrC,EAAE;AACF;AACA;AACA,CAAC,MAAM,CAAC,GAAG,EAAE;AACb,EAAE,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;AAClC,EAAE,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AAC7B,EAAE;AACF;AACA,CAAC,KAAK,GAAG;AACT,EAAE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;AAC7B,EAAE;AACF;;AChHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA,SAAS,mBAAmB,CAAC,GAAG,CAAC;AACjC,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC5D,CAAC,KAAK,IAAI,IAAI,IAAI,QAAQ,EAAE;AAC5B,EAAE,IAAI,EAAE,IAAI,IAAI,GAAG,CAAC,EAAE;AACtB,GAAG,MAAM,IAAI,KAAK,CAAC,CAAC,eAAe,EAAE,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AACrE,GAAG;AACH,EAAE;AACF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,gBAAgB,CAAC;AACvB;AACA,CAAC,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE;AAC1C,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AAEhC;AACA,EAAE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;AAC5B,EAAE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;AAC5B,EAAE,IAAI,CAAC,MAAM,CAAC;AACd,EAAE,IAAI,CAAC,OAAO,CAAC;AACf,EAAE,IAAI,CAAC,MAAM,GAAG,MAAK;AACrB;AACA;AACA;AACA;AACA,EAAE,IAAI,CAAC,eAAe,CAAC;AACvB;AACA;AACA;AACA;AACA;AACA,EAAE,IAAI,CAAC,MAAM,CAAC;AACd;AACA;AACA,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACrE,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACjE;AACA;AACA,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,SAAS,EAAE;AACxC;AACA,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AAC5B,GAAG;AACH,EAAE;AACF;AACA,CAAC,OAAO,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AAChC;AACA;AACA,CAAC,IAAI,KAAK,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC,IAAI,KAAK,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,IAAI,MAAM,GAAG;AACd;AACA,EAAE,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AAC9D,EAAE,OAAO;AACT,GAAG,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ;AACnC,GAAG,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ;AACnC,GAAG,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY;AAC3C,GAAG,SAAS,GAAG,QAAQ;AACvB,GAAG;AACH,EAAE;AACF;AACA;AACA;AACA,CAAC,IAAI,QAAQ,GAAG,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;AACxC;AACA;AACA,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE;AAC3B,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;AACpB,GAAG,IAAI,CAAC,eAAe,GAAG,IAAI,WAAW,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AACvE,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3C,GAAG,MAAM;AACT,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5D;AACA;AACA,GAAG,IAAI,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;AACrE;AACA,GAAG,IAAI,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,GAAG,YAAY,CAAC;AACvD,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC;AAC1C,GAAG;AACH;AACA,EAAE;AACF;AACA,CAAC,eAAe,GAAG;AACnB,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE;AACnB;AACA,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,SAAS,EAAE;AAC3D;AACA,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;AACvB,IAAI;AACJ,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE;AACpB,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;AACtB,KAAK,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;AACxC,KAAK;AACL,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;AACzC,IAAI,IAAI,IAAI,GAAG;AACf,KAAK,KAAK,EAAE,IAAI,CAAC,KAAK;AACtB,KAAK,GAAG,IAAI,CAAC,MAAM;AACnB,MAAK;AACL,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AACzB,IAAI;AACJ,GAAG;AACH,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,MAAM,CAAC,GAAG,EAAE;AACb,EAAE,IAAI,MAAM,GAAG;AACf,GAAG,QAAQ,EAAE,GAAG,CAAC,QAAQ;AACzB,GAAG,QAAQ,EAAE,GAAG,CAAC,QAAQ;AACzB,GAAG,YAAY,EAAE,GAAG,CAAC,YAAY;AACjC,GAAG,SAAS,EAAE,GAAG,CAAC,SAAS;AAC3B,GAAG,CAAC;AACJ;AACA;AACA,EAAE,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AAC5D,EAAE,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC1C;AACA,EAAE,OAAO,IAAI,CAAC;AACd,EAAE;AACF;;AC9KA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA,MAAM,SAAS,GAAG,KAAK,CAAC;AACxB;AACA,SAAS,YAAY,GAAG;AACxB,EAAE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;AAC/C,CACA;AACA,SAAS,gBAAgB,CAAC,GAAG,CAAC;AAC9B,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC5D,CAAC,KAAK,IAAI,IAAI,IAAI,QAAQ,EAAE;AAC5B,EAAE,IAAI,EAAE,IAAI,IAAI,GAAG,CAAC,EAAE;AACtB,GAAG,OAAO,KAAK,CAAC;AAChB,GAAG;AACH,EAAE;AACF,CAAC,OAAO,IAAI,CAAC;AACb,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,YAAY,CAAC;AACnB;AACA,CAAC,WAAW,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE;AAClC;AACA;AACA;AACA;AACA,EAAE,IAAI,SAAS,IAAI,SAAS,IAAI,OAAO,IAAI,SAAS,EAAE;AACtD,GAAG,IAAI,EAAE,SAAS,YAAY,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,EAAE;AAC7E;AACA;AACA,IAAI,OAAO,GAAG,SAAS,CAAC;AACxB,IAAI,SAAS,GAAG,SAAS,CAAC;AAC1B,IAAI,IAAI,OAAO,CAAC,QAAQ,EAAE;AAC1B,KAAK,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;AAClC,KAAK,MAAM,IAAI,OAAO,CAAC,SAAS,EAAE;AAClC,KAAK,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;AACnC,KAAK;AACL,IACA,GAAG;AACH;AACA;AACA,EAAE,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;AAC1B,EAAE,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC;AAC3B;AACA;AACA;AACA,EAAE,IAAI,OAAO,CAAC,OAAO,IAAI,SAAS,EAAE;AACpC,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;AAC1B,GAAG;AACH;AACA;AACA,EAAE,IAAI,CAAC,YAAY,CAAC;AACpB,EAAE,IAAI,CAAC,QAAQ,CAAC;AAChB,EAAE,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACvC;AACA;AACA,EAAE,IAAI,CAAC,SAAS,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACtE;AACA;AACA,EAAE,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;AACzB;AACA;AACA,EAAE,IAAI,CAAC,WAAW,CAAC;AACnB,EAAE,IAAI,CAAC,KAAK,CAAC;AACb;AACA;AACA,EAAE,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,EAAE,CAAC;AACnC;AACA;AACA,EAAE,IAAI,CAAC,OAAO,GAAG,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;AAC7C;AACA;AACA,EAAE,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAClC,EAAE,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAChD,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7C,EAAE,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAClD,EAAE,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACjD;AACA;AACA,EAAE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC3C,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,qBAAqB,CAAC,IAAI,EAAE;AAC7B,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;AAC1B,GAAG,IAAI,IAAI,IAAI,WAAW,EAAE;AAC5B,IAAI,IAAI,IAAI,GAAG;AACf,KAAK,GAAG,IAAI,CAAC,QAAQ;AACrB,KAAK,KAAK,EAAE,IAAI,CAAC,OAAO;AACxB,KAAK,IAAI,CAAC,KAAK;AACf,MAAK;AACL,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;AAClB,IAAI,MAAM,IAAI,IAAI,IAAI,YAAY,EAAE;AACpC,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;AACvB,IAAI,MAAM,IAAI,IAAI,IAAI,QAAQ,EAAE;AAChC,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC3B,IAAI,MAAM,IAAI,IAAI,IAAI,aAAa,EAAE;AACrC,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC1B,IAAI;AACJ,GAAG;AACH,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,OAAO,GAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AACvC;AACA;AACA,IAAI,IAAI,KAAK,GAAG,CAAC,OAAO,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAC5D;AACA;AACA,IAAI,IAAI,KAAK,GAAG;AAChB;AACA,KAAK,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,KAAK;AACL;AACA;AACA,IAAI,IAAI,MAAM,GAAG;AACjB;AACA,EAAE,OAAO;AACT,GAAG,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ;AACpC,GAAG,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ;AACpC,GAAG,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY;AAC5C,GAAG,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS;AACtC,GAAG,CAAC;AACJ,KAAK;AACL;AACA;AACA,IAAI,IAAI,UAAU,GAAG,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,CAAC;AAChD;AACA;AACA,IAAI,IAAI,KAAK,GAAG;AAChB,KAAK,OAAO,IAAIC,WAAuB,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC1E,KAAK;AACL;AACA;AACA,CAAC,IAAI,KAAK,GAAG,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;AAC5C;AACA,CAAC,IAAI,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,KAAK,GAAG;AACT,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,KAAK,GAAG;AACpC,GAAG,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;AAC1D,GAAG;AACH;AACA,EAAE,IAAI,MAAM,GAAGC,eAA2B,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;AAC5E;AACA,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE;AAC9B,GAAG,IAAI,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,EAAE;AAC/E;AACA,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;AAChC,IAAI;AACJ;AACA,GAAG,OAAOA,eAA2B,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;AACvE,GAAG;AACH,EAAE,OAAO,MAAM,CAAC;AAChB,EAAE;AACF;AACA;AACA,CAAC,IAAI,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC;AAC1C,CAAC,IAAI,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC;AAC1C,CAAC,IAAI,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,YAAY,CAAC,CAAC;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,QAAQ,CAAC,GAAG,EAAE;AACf,EAAE,IAAI,IAAI,CAAC,WAAW,YAAY,YAAY,EAAE;AAChD,GAAG,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACzC,GAAG,MAAM;AACT;AACA,GAAG,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACvC,GAAG;AACH,EAAE;AACF;AACA;AACA,CAAC,MAAM,CAAC,GAAG,EAAE;AACb;AACA,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC;AACpC,EAAE,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,QAAQ,IAAI,SAAS,CAAC,CAAC;AACzC,EAAE,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,QAAQ,IAAI,SAAS,CAAC,CAAC;AACzC,EAAE,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,YAAY,IAAI,SAAS,CAAC,CAAC;AAC7C,EAAE,IAAI,CAAC,EAAE,EAAE;AACX,GAAG,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC/B,GAAG;AACH,EAAE,GAAG,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;AAC9B,EAAE,IAAI,GAAG,CAAC,SAAS,IAAI,SAAS,EAAE;AAClC,GAAG,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;AACpC,GAAG;AACH,EAAE,IAAI,KAAK,GAAG,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;AAC3C,EAAE,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAC9C,EAAE,IAAI,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC;AACvE,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACrB,EAAE,OAAO,OAAO,CAAC;AACjB,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,aAAa,CAAC,GAAG,EAAE;AACpB,EAAE,IAAI;AACN,GAAG,KAAK;AACR,GAAG,IAAI,GAAG,IAAI;AACd,GAAG,GAAG,IAAI;AACV,GAAG,GAAG,GAAG,CAAC;AACV;AACA,EAAE,IAAI,KAAK,IAAI,SAAS,EAAE;AAC1B,GAAG,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAChC,GAAG;AACH;AACA,EAAE,IAAI,IAAI,GAAG;AACb,GAAG,KAAK;AACR,GAAG,IAAI;AACP,GAAG,GAAG,IAAI;AACV,GAAG,CAAC;AACJ,EAAE,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AAClC,EAAE,IAAI,IAAI,IAAI,SAAS,EAAE;AACzB,GAAG,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC/B,GAAG;AACH,EAAE;AACF;AACA;AACA;AACA;AACA;AACA,CAAC,eAAe,CAAC,GAAG,EAAE,cAAc,EAAE;AACtC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC;AACtC,EAAE;AACF;AACA;AACA;AACA;AACA;AACA,CAAC,SAAS,CAAC,GAAG,EAAE;AAChB,EAAE,IAAI;AACN,GAAG,KAAK;AACR,GAAG,QAAQ;AACX,GAAG,QAAQ;AACX,GAAG,YAAY;AACf,GAAG,SAAS;AACZ,GAAG,IAAI,CAAC,IAAI;AACZ,GAAG,GAAG,IAAI;AACV,GAAG,GAAG,GAAG,CAAC;AACV;AACA;AACA;AACA,EAAE,IAAI,YAAY,GAAG,KAAK,CAAC;AAC3B,EAAE,IAAI,KAAK,IAAI,SAAS,EAAE;AAC1B,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;AAC3B,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;AACnB,IAAI,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;AAC3D,KAAK,IAAI,CAAC,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAChC,KAAK,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACzB,KAAK,YAAY,GAAG,IAAI,CAAC;AACzB,KAAK;AACL,IAAI;AACJ,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,IAAI,aAAa,IAAI,QAAQ,IAAI,SAAS,CAAC,CAAC;AAC9C,EAAE,IAAI,CAAC,aAAa,IAAI,CAAC,YAAY,EAAE;AACvC,GAAG,OAAO,CAAC,GAAG,CAAC,2DAA2D,EAAC;AAC3E,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,IAAI,MAAM,CAAC;AACb,EAAE,IAAI,aAAa,EAAE;AACrB;AACA,GAAG,MAAM,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;AAC1D,GAAG,MAAM;AACT,GAAG,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC/B,GAAG;AACH,EAAE,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;AAC7B,EAAE,IAAI,UAAU,GAAGA,eAA2B,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC5D,EAAE,IAAI,SAAS,GAAGC,oBAAgC,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AAC7E,EAAE,IAAI,SAAS,EAAE;AACjB,GAAG,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;AAC9C,GAAG,IAAI,GAAG,IAAI,CAAC;AACf,GAAG;AACH;AACA;AACA,EAAE,aAAa,GAAG,aAAa,IAAI,CAACC,YAAwB,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AACpF;AACA;AACA,EAAE,IAAI,aAAa,EAAE;AACrB;AACA,GAAG,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC;AACrC;AACA,GAAG,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;AAC1B,GAAG;AACH;AACA,EAAE,IAAI,IAAI,CAAC;AACX,EAAE,IAAI,YAAY,IAAI,aAAa,EAAE;AACrC,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;AAC5C,GAAG,MAAM,IAAI,YAAY,EAAE;AAC3B,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;AACjC,GAAG,MAAM,IAAI,aAAa,EAAE;AAC5B,GAAG,IAAI,GAAG,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;AACrC,GAAG,MAAM;AACT,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;AAC1B,GAAG;AACH;AACA;AACA,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;AAC5B,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;AAC3D;AACA,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE;AAC9B,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;AACzB,GAAG;AACH;AACA,EAAE,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE;AAChC,GAAG,IAAI,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACrD,GAAG,IAAI,KAAK,EAAE;AACd,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC7C,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC;AACvB,IAAI,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;AACvB,IAAI;AACJ,GAAG;AACH;AACA;AACA;AACA,EAAE,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,EAAE;AACnD,GAAG,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;AACpB,GAAG;AACH,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AAC1B,EAAE,OAAO,IAAI,CAAC;AACd,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,gBAAgB,CAAC,GAAG,EAAE,YAAY,EAAE,aAAa,EAAE;AACpD,EAAE,IAAI;AACN,GAAG,KAAK;AACR,GAAG,QAAQ;AACX,GAAG,QAAQ;AACX,GAAG,YAAY;AACf,GAAG,SAAS;AACZ,GAAG,GAAG,GAAG,CAAC;AACV;AACA,EAAE,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;AACzC;AACA,EAAE,IAAI,aAAa,EAAE;AACrB,GAAG,IAAI,MAAM,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;AAC9D,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC1C,GAAG;AACH,EAAE,IAAI,YAAY,EAAE;AACpB,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;AAC9C,GAAG;AACH;AACA,EAAE,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;AACrC,EAAE,IAAI,MAAM,GAAGC,QAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACnD,EAAE,IAAI,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE;AAC1C,GAAG,IAAI,IAAI,GAAG,IAAI,CAAC;AACnB,GAAG,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,YAAY;AACxC,IAAI,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;AACvC,IAAI,EAAE,GAAG,CAAC,CAAC;AACX,GAAG,MAAM,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE;AAClD,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,GAAG,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;AAC1B,GAAG;AACH,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,gBAAgB,CAAC,UAAU,EAAE;AAC9B,EAAE,OAAOC,UAAsB,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AAC1D,EAAE;AACF;AACA;AACA;AACA;AACA,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC;AACjC;AACA;AACA;AACA;AACA,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE;AACrB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE;AAC/B,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;AACzB,EAAE,IAAI,cAAc,GAAG,IAAI,CAAC,wBAAwB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACpE,EAAE,IAAI,cAAc,IAAI,SAAS,EAAE;AACnC,GAAG,OAAO;AACV,GAAG;AACH,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,cAAc,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AACtE,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,wBAAwB,CAAC,MAAM,EAAE,KAAK,EAAE;AACzC,EAAE,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC;AACnC,EAAE,KAAK,GAAG,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC;AAChC,EAAE,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;AAC7B,EAAE,IAAI,UAAU,GAAGJ,eAA2B,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC5D,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,GAAGK,cAA0B,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;AACnE,EAAE,IAAI,KAAK,IAAI,SAAS,EAAE;AAC1B,GAAG,OAAO;AACV,GAAG;AACH;AACA,EAAE,IAAI,cAAc,GAAGL,eAA2B,CAAC,MAAM,EAAE,GAAG,GAAG,KAAK,CAAC,CAAC;AACxE;AACA,EAAE,cAAc,CAAC,QAAQ,GAAG,GAAG,CAAC;AAChC,EAAE,OAAO,cAAc,CAAC;AACxB,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,iBAAiB,GAAG;AACrB;AACA,EAAE,IAAI,IAAI,CAAC,WAAW,IAAI,SAAS,EAAE;AACrC,GAAG,IAAI,IAAI,CAAC,WAAW,YAAY,YAAY,EAAE;AACjD,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACrC,IAAI,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;AAC3B,IAAI,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;AACjC,IAAI,MAAM;AACV;AACA,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;AAC7B,IAAI,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;AACjC,IAAI;AACJ,GAAG;AACH,EAAE;AACF;AACA,CAAC,eAAe,CAAC,SAAS,EAAE,OAAO,EAAE;AACrC;AACA,EAAE,IAAI,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/C,EAAE,IAAI,SAAS,YAAY,YAAY,EAAE;AACzC;AACA,GAAG,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;AAChC,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;AAC3D,GAAG,MAAM;AACT;AACA,GAAG,IAAI,SAAS,IAAI,SAAS,EAAE;AAC/B;AACA,IAAI,IAAI,CAAC,WAAW,GAAG,IAAI,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC/D,IAAI,MAAM;AACV;AACA,IAAI,IAAI,CAAC,WAAW,GAAG,IAAI,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC1E,IAAI;AACJ;AACA;AACA,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE;AACnC,IAAI,IAAI,GAAG,GAAG;AACd,KAAK,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,KAAK;AAClC,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM;AAC/B,KAAK,IAAI,EAAE,KAAK;AAChB,MAAK;AACL;AACA,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC;AAClB,IAAI;AACJ,GAAG;AACH,EAAE;AACF;AACA,CAAC,eAAe,GAAG;AACnB;AACA,EAAE,OAAO,IAAI,CAAC,WAAW,CAAC;AAC1B,EAAE;AACF;AACA,CAAC,IAAI,SAAS,CAAC,GAAG;AAClB;AACA,EAAE,IAAI,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;AACzC,EAAE,IAAI,SAAS,YAAY,YAAY,EAAE;AACzC,GAAG,OAAO,SAAS,CAAC;AACpB,GAAG,MAAM,IAAI,SAAS,YAAY,gBAAgB,EAAE;AACpD,GAAG,OAAO,SAAS,CAAC;AACpB,GAAG,MAAM,IAAI,SAAS,YAAY,gBAAgB,EAAE;AACpD,GAAG,OAAO,SAAS,CAAC,SAAS,CAAC;AAC9B,GAAG,MAAM;AACT,GAAG,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC;AACvC,GAAG;AACH,EAAE;AACF;AACA,CAAC,IAAI,SAAS,CAAC,SAAS,EAAE;AAC1B,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC;AAC3B,EAAE,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;AAClC,EAAE;AACF;AACA,CAAC;AACD;AACA,QAAQ,CAAC,iBAAiB,CAAC,YAAY,CAAC,SAAS,CAAC;;ACznBlD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAYA;AACA;AACA,MAAM,aAAa,SAAS,YAAY,CAAC;AACzC;AACA,CAAC,WAAW,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE;AACxC,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC5B,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;AACpB,QAAQ,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACvD,EAAE;AACF;AACA;AACA,IAAI,qBAAqB,CAAC,IAAI,EAAE;AAChC,QAAQ,IAAI,IAAI,IAAI,YAAY,EAAE;AAClC,YAAY,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChC,SAAS,MAAM;AACf,YAAY,OAAO,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAAC;AACpD,SAAS;AACT,KAAK;AACL;AACA;AACA,CAAC,aAAa,CAAC,GAAG,EAAE;AACpB,QAAQ,IAAI,GAAG,CAAC,KAAK,IAAI,SAAS,EAAE;AACpC,YAAY,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC;AACvC,YAAY,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC;AACvC,SAAS;AACT,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,EAAE;AACvC,GAAG,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC;AAC9B,SAAS;AACT,QAAQ,OAAO,GAAG,CAAC;AACnB,EAAE;AACF;AACA;AACA,CAAC,MAAM,CAAC,GAAG,EAAE;AACb,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,EAAE;AACvC,GAAG,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC;AAC9B,SAAS;AACT,QAAQ,IAAI,GAAG,CAAC,KAAK,IAAI,SAAS,EAAE;AACpC,YAAY,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;AACxC,YAAY,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9D,SAAS;AACT,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC3B,EAAE;AACF;AACA,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;AAChC;AACA,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE;AAChB,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE;AAChC;AACA,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;AACrB,GAAG,IAAI,CAAC,aAAa,CAAC;AACtB,gBAAgB,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,MAAM;AAChD,gBAAgB,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,KAAK;AACnD,aAAa,CAAC,CAAC;AACf,YAAY,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;AACrD,SAAS;AACT,EAAE;AACF;;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAkBA;AACA;AACA,MAAM,cAAc,SAAS,YAAY,CAAC;AAC1C,CAAC,WAAW,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE;AACnC,EAAE,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC,MAAM,IAAI,KAAK,EAAE,8BAA8B,CAAC,CAAC,CAAC;AACpE,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,MAAM,IAAI,KAAK,EAAE,2CAA2C,CAAC,CAAC,CAAC;AACnF,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;AACtB;AACA,EAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;AACtB;AACA,EAAE,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;AACpB;AACA,EAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACrE,QAAQ,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACxD,EAAE;AACF;AACA;AACA,IAAI,qBAAqB,CAAC,IAAI,EAAE;AAChC,QAAQ,IAAI,IAAI,IAAI,aAAa,EAAE;AACnC,YAAY,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACjC,SAAS,MAAM;AACf,YAAY,OAAO,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAAC;AACpD,SAAS;AACT,KAAK;AACL;AACA;AACA,CAAC,aAAa,CAAC,GAAG,EAAE;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB;AACA,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE;AAC9B,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;AAC1B,GAAG;AACH,EAAE,OAAO;AACT,EAAE;AACF;AACA,CAAC,eAAe,GAAG;AACnB;AACA,EAAE,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;AAC7B,EAAE,IAAI,GAAG,EAAE,GAAG,CAAC;AACf,EAAE,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;AAClC,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC;AACjD,GAAG,IAAI,GAAG,GAAG,GAAG,EAAE;AAClB,IAAI,MAAM;AACV,IAAI,MAAM;AACV,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;AAC/B;AACA,IAAI,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC;AACxB,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AACxB,IAAI;AACJ,GAAG;AACH;AACA,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;AAC/B,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC;AACjD,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AACjC,GAAG;AACH,EAAE;AACF;AACA,CAAC,MAAM,CAAC,GAAG,EAAE;AACb;AACA,EAAE,MAAM,IAAI,KAAK,EAAE,wDAAwD,CAAC,CAAC;AAC7E,EAAE;AACF;AACA,IAAI,IAAI,KAAK,GAAG,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;AACrC;AACA,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE;AAClB,QAAQ,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE;AAClC;AACA,YAAY,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;AAChC,YAAY,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;AAClC,YAAY,IAAI,CAAC,eAAe,EAAE,CAAC;AACnC,YAAY,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;AACvD,SAAS;AACT,KAAK;AACL;;AC7HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAWA;AACA;AACA,MAAM,cAAc,SAAS,YAAY,CAAC;AAC1C,IAAI,WAAW,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE;AACpC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;AACnB,EAAE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;AACxB,QAAQ,IAAI,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACxD,EAAE;AACF;AACA;AACA,IAAI,qBAAqB,CAAC,IAAI,EAAE;AAChC,QAAQ,IAAI,IAAI,IAAI,aAAa,EAAE;AACnC,YAAY,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAClC,SAAS,MAAM;AACf,YAAY,OAAO,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAAC;AACpD,SAAS;AACT,KAAK;AACL;AACA;AACA,IAAI,aAAa,CAAC,GAAG,EAAE;AACvB,QAAQ,IAAI,GAAG,CAAC,KAAK,IAAI,SAAS,EAAE;AACpC,YAAY,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC/E,SAAS;AACT,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,EAAE;AACvC,YAAY,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC;AACzC,SAAS;AACT,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,EAAE;AACvC,YAAY,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC;AACzC,SAAS;AACT,QAAQ,IAAI,GAAG,CAAC,YAAY,IAAI,SAAS,EAAE;AAC3C,YAAY,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,CAAC;AAC7C,SAAS;AACT,QAAQ,OAAO,GAAG,CAAC;AACnB,KAAK;AACL;AACA,CAAC,MAAM,CAAC,GAAG,EAAE;AACb,EAAE,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,EAAE;AACjC,YAAY,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC;AACzC,SAAS;AACT,EAAE,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,EAAE;AACjC,YAAY,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC;AACzC,SAAS;AACT,EAAE,IAAI,GAAG,CAAC,YAAY,IAAI,SAAS,EAAE;AACrC,YAAY,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,CAAC;AAC7C,SAAS;AACT,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC3B,EAAE;AACF;AACA,IAAI,IAAI,KAAK,GAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC;AACtC;AACA,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE;AACtB,QAAQ,IAAI,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE;AACpC;AACA,YAAY,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;AAClC,YAAY,IAAI,CAAC,aAAa,CAAC;AAC/B,gBAAgB,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,MAAM;AAChD,gBAAgB,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,KAAK;AACnD,aAAa,CAAC,CAAC;AACf,YAAY,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AACxD,SAAS;AACT,KAAK;AACL;;AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAcA;AACA;AACA;AACA,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE;AACnB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CACA;AACA,SAAS,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE;AAC7B,CAAC,IAAI,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AACrB,CAAC,IAAI,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AAClC,CAAC,OAAO,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACnC,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,SAAS,YAAY,CAAC;AACzC;AACA,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,EAAE;AAC/B,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACnC;AACA,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE;AAClD,GAAG,MAAM,IAAI,KAAK,CAAC,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AAChE,GAAG;AACH,EAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;AACvB,EAAE;AACF;AACA,CAAC,MAAM,CAAC,GAAG,EAAE;AACb;AACA,EAAE,IAAI,GAAG,CAAC,KAAK,IAAI,SAAS,EAAE;AAC9B;AACA,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;AAC/B,GAAG,IAAI,GAAG,IAAI,IAAI,EAAE;AACpB,IAAI,MAAM,IAAI,KAAK,CAAC,eAAe,EAAE,GAAG,CAAC,KAAK,CAAC;AAC/C,IAAI;AACJ,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;AAC1D,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC/B,IAAI,IAAI,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,CAAC;AAChD,IAAI,MAAM,CAAC,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AAC/D,IAAI,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;AAC3B;AACA,IAAI,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AAClE,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC5C,IAAI;AACJ,GAAG,OAAO,GAAG,CAAC,KAAK,CAAC;AACpB,GAAG;AACH;AACA,EAAE,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,EAAE;AACjC;AACA;AACA;AACA,GAAG,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;AAC9B,GAAG,IAAI,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACtD,GAAG,IAAI,IAAI,GAAG,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;AACjD,GAAG,IAAI,cAAc,GAAG,eAAe,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC5E,GAAG,GAAG,CAAC,QAAQ,GAAG,cAAc,CAAC,QAAQ,GAAG,IAAI,CAAC;AACjD,GAAG;AACH,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC3B,EAAE;AACF;AACA;AACA,CAAC,gBAAgB,CAAC,UAAU,EAAE;AAC9B,EAAE,UAAU,CAAC,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AACrE,EAAE,OAAO,UAAU,CAAC;AACpB,EAAE;AACF;AACA;AACA,CAAC,aAAa,CAAC,GAAG,EAAE;AACpB,QAAQ,IAAI,GAAG,CAAC,KAAK,IAAI,SAAS,EAAE;AACpC;AACA;AACA,YAAY,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;AACrC,SAAS;AACT,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,EAAE;AACvC;AACA,SAAS,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AAC9D;AACA;AACA;AACA;AACA,SAAS;AACT,EAAE,OAAO,GAAG,CAAC;AACb,EAAE;AACF;AACA;;ACtHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAgBA;AACA;AACA,SAAS,KAAK,GAAG;AACjB,CAAC,IAAI,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC;AAC9B,CAAC,IAAI,MAAM,GAAG,IAAI,CAAC;AACnB,CAAC,IAAI,uBAAuB,GAAG,UAAU,SAAS,EAAE,SAAS,EAAE;AAC/D;AACA,EAAE,IAAI,SAAS,KAAK,UAAU,CAAC,YAAY,IAAI,SAAS,KAAK,UAAU,CAAC,WAAW,EAAE,OAAO,KAAK,CAAC;AAClG,EAAE,IAAI,SAAS,KAAK,UAAU,CAAC,WAAW,IAAI,SAAS,KAAK,UAAU,CAAC,YAAY,EAAE,OAAO,KAAK,CAAC;AAClG,EAAE,IAAI,SAAS,KAAK,UAAU,CAAC,IAAI,EAAE,OAAO,KAAK,CAAC;AAClD,EAAE,OAAO,IAAI,CAAC;AACd,GAAE;AACF,CAAC,IAAI,GAAG,GAAG,YAAY,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC;AACxC,CAAC,IAAI,GAAG,GAAG,UAAU,SAAS,EAAE,SAAS,EAAE;AAC3C;AACA,EAAE,IAAI,QAAQ,GAAG,KAAK,CAAC;AACvB,EAAE,IAAI,OAAO,GAAG,KAAK,CAAC;AACtB;AACA;AACA,EAAE,IAAI,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,MAAM,EAAE;AACpD,GAAG,QAAQ,GAAG,IAAI,CAAC;AACnB,GAAG;AACH;AACA,EAAE,IAAI,SAAS,KAAK,MAAM,EAAE;AAC5B,GAAG,OAAO,GAAG,uBAAuB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AACxD,GAAG;AACH;AACA,EAAE,IAAI,SAAS,KAAK,MAAM,EAAE;AAC5B,GAAG,MAAM,GAAG,SAAS,CAAC;AACtB,GAAG;AACH;AACA,EAAE,IAAI,SAAS,KAAK,MAAM,EAAE;AAC5B,GAAG,MAAM,GAAG,SAAS,CAAC;AACtB,GAAG;AACH,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC9C;AACA,GAAE;AACF,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;AAC5B,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,cAAc,SAAS,YAAY,CAAC;AAC1C;AACA,CAAC,WAAW,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE;AACnC,EAAE,KAAK,CAAC,YAAY,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACtC,EAAE,IAAI,CAAC,OAAO,GAAG,KAAK,EAAE,CAAC;AACzB,EAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;AACvB,EAAE;AACF;AACA;AACA,CAAC,MAAM,CAAC,GAAG,EAAE;AACb,EAAE,MAAM,KAAK,CAAC,kBAAkB,CAAC,CAAC;AAkClC,EAAE;AACF;AACA;AACA;AACA;AACA,CAAC,aAAa,CAAC,GAAG,EAAE;AACpB,QAAQ,IAAI,GAAG,CAAC,KAAK,IAAI,SAAS,EAAE;AACpC;AACA;AACA,YAAY,OAAO,GAAG,CAAC,KAAK,CAAC;AAC7B,SAAS;AACT,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,EAAE;AACvC;AACA,SAAS,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAC,GAAG,GAAG,CAAC;AACjE,SAAS,IAAI,MAAM,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;AACpE,SAAS,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;AAC9C,SAAS,IAAI,MAAM,IAAI,SAAS,EAAE;AAClC;AACA;AACA,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AACrE,IAAI,OAAO;AACX,UAAU,MAAM;AAChB;AACA,UAAU,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AACzC,UAAU,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AACzC,UAAU,GAAG,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;AACjD,UAAU,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;AAC3C,UAAU;AACV,SAAS;AACT,QAAQ,OAAO,GAAG,CAAC;AACnB,EAAE;AACF;AACA;AACA,CAAC,cAAc,CAAC,MAAM,EAAE;AACxB,EAAE,IAAI,SAAS,GAAG,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AAC1D,EAAE,IAAI,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AAChE,EAAE,IAAI,aAAa,CAAC,OAAO,EAAE;AAC7B;AACA,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,UAAU,CAAC,MAAM,EAAE,CAI7C,MAAM;AACV;AACA,IAAI,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AAC9C,IAAI;AACJ,GAAG;AACH,OAAO;AACP;AACA,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,UAAU,CAAC,MAAM,EAAE,CAG7C,MAAM;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,aAAa,CAAC,QAAQ,EAAE;AAChC,KAAK,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AAC/C,KAAK,MAAM;AACX,KAAK,OAAO;AACZ,KAAK;AACL,IAAI;AACJ,GAAG;AACH,EAAE,OAAO,MAAM,CAAC;AAChB,EAAE;AACF;;AC5MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAwBA;AACA;AACA,MAAM,kBAAkB,SAAS,YAAY,CAAC;AAC9C;AACA,IAAI,WAAW,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE;AACpC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;AACnB,EAAE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;AACxB,QAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACzD,EAAE;AACF;AACA;AACA,IAAI,qBAAqB,CAAC,IAAI,EAAE;AAChC,QAAQ,IAAI,IAAI,IAAI,cAAc,EAAE;AACpC,YAAY,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAClC,SAAS,MAAM;AACf,YAAY,OAAO,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAAC;AACpD,SAAS;AACT,KAAK;AACL;AACA;AACA,IAAI,aAAa,CAAC,GAAG,EAAE;AACvB,QAAQ,IAAI,GAAG,CAAC,KAAK,IAAI,SAAS,EAAE;AACpC,YAAY,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAC9C,SAAS;AACT,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,EAAE;AACvC;AACA,YAAY,IAAI,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC;AACnC,YAAY,IAAI,UAAU,GAAG,eAAe,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;AACrE,YAAY,GAAG,CAAC,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;AAC/C,YAAY,GAAG,CAAC,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;AAC/C,YAAY,GAAG,CAAC,YAAY,GAAG,UAAU,CAAC,YAAY,CAAC;AACvD,YAAY,GAAG,CAAC,SAAS,GAAG,EAAE,CAAC;AAC/B,SAAS;AACT,QAAQ,OAAO,GAAG,CAAC;AACnB,KAAK;AACL;AACA,IAAI,IAAI,MAAM,GAAG,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC;AACvC;AACA,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE;AACvB,QAAQ,IAAI,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE;AACpC;AACA,YAAY,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;AAClC,YAAY,IAAI,CAAC,aAAa,CAAC;AAC/B,gBAAgB,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,MAAM;AAChD,gBAAgB,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,KAAK;AACnD,aAAa,CAAC,CAAC;AACf,YAAY,IAAI,CAAC,eAAe,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AACzD,SAAS;AACT,KAAK;AACL;AACA;;AC5FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AA0BA;AACA,MAAM,cAAc,GAAG,GAAG,CAAC;AAC3B;AACA,MAAM,aAAa,CAAC;AACpB;AACA,IAAI,WAAW,CAAC,CAAC,YAAY,EAAE,OAAO,GAAG,EAAE,EAAE;AAC7C,QAAQ,IAAI,CAAC,GAAG,GAAG,YAAY,CAAC;AAChC;AACA,QAAQ,IAAI,CAAC,IAAI,CAAC;AAClB;AACA,QAAQ,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,OAAO,CAAC;AAC1C,QAAQ,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC;AACtC,QAAQ,IAAI,MAAM,IAAI,SAAS,EAAE;AACjC,YAAY,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;AAClC,SAAS,MAAM,IAAI,SAAS,IAAI,SAAS,EAAE;AAC3C,YAAY,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC;AACzC,SAAS;AACT;AACA,QAAQ,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;AACxC;AACA,QAAQ,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACnD;AACA,QAAQ,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACrE,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,qBAAqB,CAAC,IAAI,EAAE;AAChC,QAAQ,IAAI,IAAI,IAAI,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE;AACpD,YAAY,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAClC,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,SAAS,GAAG;AAChB,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;AACjC,QAAQ,IAAI,MAAM,IAAI,CAAC,CAAC,QAAQ,IAAI,GAAG,IAAI,CAAC,CAAC,YAAY,IAAI,GAAG,CAAC,CAAC;AAClE;AACA,QAAQ,IAAI,MAAM,IAAI,IAAI,CAAC,IAAI,IAAI,SAAS,EAAE;AAC9C,YAAY,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC,UAAU;AAC9C,gBAAgB,IAAI,CAAC,SAAS,EAAE,CAAC;AACjC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;AACxC,SAAS;AACT,QAAQ,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,IAAI,SAAS,EAAE;AAC/C,YAAY,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACpC,YAAY,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;AAClC,SAAS;AACT,QAAQ,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AACnC,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,SAAS,CAAC,QAAQ,EAAE;AACxB,QAAQ,QAAQ,GAAG,CAAC,QAAQ,IAAI,SAAS,IAAI,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AACrE,QAAQ,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACjD,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,KAAK,GAAG;AACZ;AACA,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE;AACvB,YAAY,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACpC,YAAY,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;AAClC,SAAS;AACT;AACA,QAAQ,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChC,KAAK;AACL,CAAC;AACD;AACA,QAAQ,CAAC,iBAAiB,CAAC,aAAa,CAAC,SAAS,CAAC;;ACjHnD;AACA;AACA;AACA,SAASM,KAAG,CAAC,CAAC,CAAC,CAAC,EAAE;AAClB,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,QAAM,CAAC,CAAC,EAAE,CAAC,EAAE;AACtB,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5B,IAAI,IAAI,CAAC,GAAGD,KAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACtB,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;AACxC,IAAI,OAAOC,QAAM,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpC,CAAC;AACD;AACA,SAAS,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE;AACxC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;AACnB,IAAI,OAAO,MAAM,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AACjC,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE;AACjD,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AACvD,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACzB,IAAI,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC7C,IAAI,MAAM,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AACjD,IAAI,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAC/C,IAAI,OAAO,EAAE,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,CAAC;AACnC,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,gBAAgB,CAAC;AACvB;AACA,IAAI,WAAW,CAAC,CAAC,YAAY,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,EAAE;AACrD,QAAQ,IAAI,CAAC,GAAG,GAAG,YAAY,CAAC;AAChC,QAAQ,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;AAC3C,QAAQ,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;AAC9B,QAAQ,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;AAC9B,QAAQ,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;AAClC,QAAQ,IAAI,CAAC,QAAQ,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9E;AACA;AACA,QAAQ,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5D,KAAK;AACL;AACA,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE;AAC3B,QAAQ,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAC7D,QAAQ,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;AAChC,KAAK;AACL;AACA,IAAI,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE;AACrC,QAAQ,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;AACtC,QAAQ,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,GAAGF,cAA0B,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AAC/E,QAAQ,IAAI,KAAK,IAAI,SAAS,EAAE;AAChC,YAAY,OAAO;AACnB,SAAS;AACT;AACA,QAAQ,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AAC3C,QAAQ,IAAI,GAAG,GAAG,IAAI,IAAI,KAAK,GAAG,GAAG,GAAG;AACxC,YAAY,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AAC1C,SAAS;AACT,QAAQ,OAAO,CAAC,MAAM,CAAC,SAAS,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC;AAC/C,KAAK;AACL;AACA,IAAI,aAAa,CAAC,GAAG,EAAE;AACvB,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;AAC9B;AACA,QAAQ,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,aAAa,CAAC,GAAG;AACvD,oDAAoD,IAAI,CAAC,OAAO;AAChE,oDAAoD,IAAI,CAAC,OAAO,CAAC,CAAC;AAClE;AACA,QAAQ,IAAI,KAAK,EAAE;AACnB,YAAY,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AAChC,SAAS;AACT;AACA,QAAQ,IAAI,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACxD,QAAQ,IAAI,GAAG,IAAI,SAAS,EAAE;AAC9B,YAAY,OAAO;AACnB,SAAS;AACT;AACA,QAAQ,IAAI,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;AACxB,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AAC1C,KAAK;AACL;AACA,IAAI,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE;AAC7B,QAAQ,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;AACzB,QAAQ,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;AAChC,KAAK;AACL;;ACrIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAQA;AACA,MAAMG,UAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;AACnC;AACA;AACA;AACA;AACA;AACA,SAAS,KAAK,GAAG;AACjB,IAAI,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;AACtB,CAAC;AACD;AACA;AACA,SAAS,UAAU,CAAC,KAAK,EAAE;AAC3B,IAAI,IAAI,KAAK,YAAY,QAAQ,IAAI,KAAK,IAAI,SAAS,EAAE;AACzD,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK;AACL,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG;AACpC;AACA,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC;AACzD,QAAQ,OAAO,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAChE,KAAK,MAAM;AACX,QAAQ,MAAM,IAAI,KAAK,EAAE,uBAAuB,EAAE,KAAK,CAAC,CAAC;AACzD,KAAK;AACL,CAAC;AA8BD;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAAE;AACtC;AACA,IAAI,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE;AACzB,QAAQ,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE;AACnC,YAAY,GAAG,CAAC,KAAK,EAAE,CAAC;AACxB,SAAS;AACT,QAAQ,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AAC/B,KAAK;AACL,SAAS,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE;AAC9B,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK,MAAM;AACX,QAAQ,IAAI,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,UAAU,IAAI,EAAE;AAChD,YAAY,OAAO,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC;AACvC,SAAS,CAAC,CAAC;AACX,QAAQ,IAAI,GAAG,GAAG,CAAC,CAAC,EAAE;AACtB,YAAY,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAC/B,SAAS;AACT,QAAQ,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AAC/B,KAAK;AACL,CACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE;AACtC,IAAI,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE;AACzB,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE;AAChC,QAAQ,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE;AACnC,YAAY,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AACzB,YAAY,OAAO,IAAI,CAAC;AACxB,SAAS;AACT,KAAK,MAAM;AACX,QAAQ,IAAI,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC,UAAU,IAAI,EAAE;AAChD,YAAY,OAAO,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC;AACvC,SAAS,CAAC,CAAC;AACX,QAAQ,IAAI,GAAG,GAAG,CAAC,CAAC,EAAE;AACtB,YAAY,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AAC3B,YAAY,OAAO,IAAI,CAAC;AACxB,SAAS;AACT,KAAK;AACL,IAAI,OAAO,KAAK,CAAC;AACjB,CAAC;AACD;AACA;AACA;AACA;AACA;AACA,MAAM,YAAY,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AACjE,IAAI,cAAc,GAAG,UAAU,MAAM,EAAE;AACvC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC9C,QAAQ,IAAI,MAAM,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE;AACvC,YAAY,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;AACnC,SAAS;AACT,KAAK;AACL,CAAC,CAAC;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;AAC5B,IAAI,IAAI,EAAE,CAAC;AACX,IAAI,MAAM,EAAE,CAAC;AACb,IAAI,OAAO,EAAE,CAAC;AACd,IAAI,MAAM,EAAE,CAAC;AACb,CAAC,CAAC,CAAC;AAeH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE;AACzC,IAAI,IAAI,cAAc,EAAE,UAAU,EAAE,EAAE,CAAC;AACvC;AACA,IAAI,IAAI,kBAAkB,GAAG,KAAK,IAAI,SAAS,IAAI,KAAK,CAAC,QAAQ,IAAI,SAAS,CAAC;AAC/E,IAAI,IAAI,kBAAkB,GAAG,KAAK,IAAI,SAAS,IAAI,KAAK,CAAC,QAAQ,IAAI,SAAS,CAAC;AAC/E,IAAI,IAAI,CAAC,kBAAkB,IAAI,CAAC,kBAAkB,EAAE;AACpD,QAAQ,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC;AACpC,KAAK,MAAM,IAAI,CAAC,kBAAkB,EAAE;AACpC,QAAQ,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC;AACtC,KAAK,MAAM,IAAI,CAAC,kBAAkB,EAAE;AACpC,QAAQ,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC;AACtC,KAAK,MAAM;AACX;AACA,QAAQ,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACnD,QAAQ,cAAc,GAAG,CAAC,EAAE,IAAI,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC;AAC3D,KAAK;AACL;AACA,IAAI,IAAI,cAAc,GAAG,KAAK,IAAI,SAAS,IAAI,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC;AACvE,IAAI,IAAI,cAAc,GAAG,KAAK,IAAI,SAAS,IAAI,KAAK,CAAC,IAAI,IAAI,SAAS,CAAC;AACvE,IAAI,IAAI,CAAC,cAAc,IAAI,CAAC,cAAc,EAAE;AAC5C,QAAQ,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC;AAChC,KAAK,MAAM,IAAI,CAAC,cAAc,EAAE;AAChC,QAAQ,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;AAClC,KAAK,MAAM,IAAI,CAAC,cAAc,EAAE;AAChC,QAAQ,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;AAClC,KAAK,MAAM;AACX;AACA,QAAQ,IAAI,MAAM,EAAE;AACpB,YAAY,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;AAChD,SAAS,MAAM;AACf,YAAY,EAAE,GAAGC,aAAmB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;AAC7D,SAAS;AACT,QAAQ,UAAU,GAAG,CAAC,EAAE,IAAI,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC;AACvD,KAAK;AACL,IAAI,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AACxD,CAAC;AACD;AACA;AACA,SAAS,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE;AAClC,IAAI,IAAI,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACxC,IAAI,OAAO,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;AACpE,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,CAAC;AACpB;AACA,IAAI,WAAW,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE;AACtC;AACA;AACA;AACA,QAAQ,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC;AAC3B;AACA,QAAQ,IAAI,QAAQ,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACzC,QAAQ,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC7D;AACA,QAAQ,IAAI,CAAC,KAAK,CAAC;AACnB;AACA,QAAQ,IAAI,CAAC,KAAK,CAAC;AACnB;AACA,QAAQ,IAAI,CAAC,UAAU,CAAC;AACxB;AACA,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;AACtB,KAAK;AACL;AACA,IAAI,MAAM,GAAG;AACb,QAAQ,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;AACxB;AACA,QAAQ,IAAI,CAAC,KAAK,GAAG,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;AACjD,QAAQ,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM;AACtE,YAAY,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC7C,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA,IAAI,KAAK,CAAC,QAAQ,EAAE;AACpB;AACA,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;AAClC,QAAQ,IAAI,SAAS,GAAG,CAAC,IAAI,CAAC,CAAC;AAC/B,QAAQ,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;AAChC,QAAQ,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;AAC/B,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;AAChC,YAAY,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC1C,SAAS;AACT,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,SAAS,IAAI,CAAC,GAAG,CAAC,EAAE;AAC5D;AACA;AACA,YAAY,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;AACpC,SAAS;AACT,KAAK;AACL;AACA,IAAI,OAAO,GAAG;AACd,QAAQ,IAAI,MAAM,GAAG,EAAE,CAAC;AACxB;AACA,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;AACnC,YAAY,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AAChE,SAAS;AACT;AACA,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;AACtB;AACA,QAAQ,OAAO,MAAM,CAAC;AACtB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE;AAChC,QAAQ,IAAI,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAChC,QAAQ,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;AACpC,QAAQ,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AAClC,YAAY,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;AAChC,SAAS;AACT,QAAQ,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAC9B,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL;AACA;AACA,IAAI,SAAS,CAAC,GAAG,EAAE;AACnB,QAAQ,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAChC,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL;AACA;AACA,IAAI,MAAM,CAAC,QAAQ,EAAE;AACrB,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC7B,KAAK;AACL;AACA;AACA,IAAI,KAAK,GAAG;AACZ,QAAQ,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;AACxB,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL;AACA;AACA,IAAI,MAAM,GAAG;AACb,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE;AACtC,YAAY,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;AAC9E,SAAS;AACT;AACA;AACA,QAAQ,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;AAChC,KAAK;AACL,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,OAAO,SAAS,aAAa,CAAC;AACpC;AACA,IAAI,WAAW,CAAC,OAAO,EAAE;AACzB,QAAQ,KAAK,CAAC,OAAO,CAAC,CAAC;AACvB;AACA,QAAQ,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;AAC9B,QAAQ,IAAI,CAAC,QAAQ,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC;AAChD;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;AACrC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAClD,YAAY,IAAI,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;AAC9C,YAAY,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC;AAC1E,SAAS;AACT;AACA;AACA,QAAQ,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;AACpC,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,IAAI,UAAU,CAAC,GAAG;AACtB,QAAQ,OAAO,IAAI,CAAC,IAAI,CAAC;AACzB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,CAAC,OAAO,EAAE;AAC3B,QAAQ,IAAI,MAAM,GAAG;AACrB,YAAY,OAAO,EAAE,OAAO;AAC5B,UAAS;AACT,QAAQ,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC5C,QAAQ,OAAO,MAAM,CAAC;AACtB,KAAK;AACL;AACA;AACA,IAAI,YAAY,CAAC,CAAC,MAAM,EAAE;AAC1B,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AAC3D,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;AACxB,YAAY,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACpD,SAAS;AACT,KAAK;AACL;AACA;AACA,IAAI,iBAAiB,CAAC,CAAC,QAAQ,EAAE,iBAAiB,EAAE;AACpD,QAAQ,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,SAAS,MAAM,EAAE;AACxD,YAAY,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AACxD,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE;AACrB,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA,IAAI,MAAM,CAAC,CAAC,GAAG,EAAE;AACjB,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,OAAO,EAAE;AACzB,QAAQ,OAAO,IAAI,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAChD,KAAK;AACL;AACA;AACA,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE;AAChC,QAAQ,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AAClC,YAAY,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AACtD,SAAS,MAAM;AACf,YAAY,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAChD,SAAS;AACT,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL;AACA,IAAI,SAAS,CAAC,GAAG,EAAE;AACnB,QAAQ,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AACrC,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL;AACA,IAAI,IAAI,UAAU,GAAG,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;AACtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE;AAC1C,QAAQ,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AAC7E,KAAK;AACL;AACA,IAAI,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE;AAC7B,QAAQ,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;AAC/C,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,IAAI,EAAE,OAAO,GAAG,EAAE,EAAE;AAC/B,QAAQ,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;AACnC,QAAQ,IAAI,WAAW,CAAC;AACxB,QAAQ,IAAI,YAAY,EAAE,QAAQ,CAAC;AACnC;AACA;AACA,QAAQ,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;AAC5C;AACA;AACA,QAAQ,IAAI,CAACC,UAAgB,CAAC,IAAI,CAAC,EAAE;AACrC,YAAY,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;AAC1B,SAAS;AACT;AACA;AACA;AACA;AACA,QAAQ,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC;AACjC,QAAQ,MAAM,IAAI,GAAG;AACrB,YAAY,EAAE,EAAE,QAAQ;AACxB,YAAY,MAAM,EAAE,OAAO,CAAC,MAAM;AAClC,SAAS,CAAC;AACV;AACA,QAAQ,KAAK,IAAI,GAAG,IAAI,IAAI,EAAE;AAC9B;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,GAAG,IAAI,SAAS,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,SAAS,EAAE;AACxF;AACA,gBAAgB,IAAI,GAAG,IAAI,SAAS,EAAE;AACtC,oBAAoB,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;AACxD,iBAAiB,MAAM,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE;AACvD,oBAAoB,MAAM,IAAI,KAAK,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC;AACrE,iBAAiB,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,SAAS,EAAE;AACjD,oBAAoB,MAAM,IAAI,KAAK,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;AACjE,iBAAiB;AACjB,aAAa;AACb;AACA,YAAY,YAAY,GAAG,GAAG,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;AAC1D,YAAY,QAAQ,GAAG,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;AAClD,YAAY,IAAI,YAAY,EAAE;AAC9B,gBAAgB,GAAG,CAAC,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxD,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACjD,YAAY,IAAI,WAAW,IAAI,SAAS,EAAE;AAC1C;AACA,gBAAgB,IAAI,CAAC,YAAY,EAAE;AACnC,oBAAoB,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC;AAC7C,iBAAiB;AACjB,gBAAgB,IAAI,CAAC,QAAQ,EAAE;AAC/B,oBAAoB,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC;AACzC,iBAAiB;AACjB,aAAa,MAAM,IAAI,WAAW,IAAI,SAAS,EAAE;AACjD,gBAAgB,IAAI,CAAC,YAAY,IAAI,CAAC,QAAQ,EAAE;AAChD;AACA,oBAAoB,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC;AAC7C,oBAAoB,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC;AACzC,iBAAiB,MAAM,IAAI,CAAC,QAAQ,EAAE;AACtC;AACA,oBAAoB,GAAG,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC;AAChD,iBAAiB,MAAM,IAAI,CAAC,YAAY,EAAE;AAC1C;AACA,oBAAoB,GAAG,CAAC,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC;AACxD,iBAEiB;AACjB,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACxE,SAAS;AACT;AACA;AACA,QAAQ,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AACpC;AACA,QAAQ,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE;AAC/B;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,SAAS,GAAG,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC;AAC7D;AACA;AACA,YAAY,IAAI,KAAK,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI;AAC3D,gBAAgB,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE;AACnD,oBAAoB,SAAS,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC/F,oBAAoB,SAAS,CAAC,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;AAClG,iBAAiB;AACjB,gBAAgB,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE;AACnD,oBAAoB,SAAS,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC/F,oBAAoB,SAAS,CAAC,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;AAClG,iBAAiB;AACjB,gBAAgB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AACnF,aAAa,CAAC,CAAC;AACf;AACA;AACA,YAAY,IAAI,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK;AACrD,gBAAgB,IAAI,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAClE,gBAAgB,QAAQ,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE;AAClF,aAAa,CAAC,CAAC;AACf;AACA;AACA,YAAY,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;AAC5C;AACA;AACA,YAAY,IAAI,iBAAiB,GAAG,SAAS,CAAC;AAC9C,YAAY,IAAI,SAAS,CAAC,GAAG,IAAI,QAAQ,EAAE;AAC3C,gBAAgB,iBAAiB,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;AAC1F,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAChE;AACA;AACA,YAAY,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;AAC1C,YAAY,OAAO,KAAK,CAAC;AACzB,SAAS;AACT;AACA,QAAQ,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;AACtC,QAAQ,OAAO,EAAE,CAAC;AAClB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,WAAW,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE;AAC3D;AACA,QAAQ,IAAI,OAAO,EAAE,OAAO,CAAC;AAC7B,QAAQ,IAAI,IAAI,EAAE,KAAK,CAAC;AACxB,QAAQ,IAAI,YAAY,EAAE,YAAY,CAAC;AACvC,QAAQ,IAAI,WAAW,EAAE,YAAY,CAAC;AACtC,QAAQ,IAAI,aAAa,EAAE,UAAU,CAAC;AACtC;AACA;AACA,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;AAC1D;AACA,QAAQ,IAAI,WAAW,KAAK,GAAG,EAAE;AACjC,YAAY,MAAM,KAAK,CAAC,6CAA6C,CAAC,CAAC;AACvE,SAAS;AACT;AACA;AACA,QAAQ,IAAI,KAAK,GAAG,SAAS,CAAC,WAAW,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;AACxD;AACA;AACA,QAAQ,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE;AACtE,YAAY,IAAI,GAAG;AACnB,gBAAgB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,WAAW;AAC5C,gBAAgB,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK;AAC7C,cAAa;AACb,YAAY,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACxC,YAAY,OAAO;AACnB,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,WAAW,IAAI,SAAS,EAAE;AACtC;AACA;AACA;AACA,YAAY,IAAI,GAAG,CAAC,IAAI,IAAI,SAAS,EAAE;AACvC,gBAAgB,GAAG,CAAC,IAAI,GAAG;AAC3B,oBAAoB,EAAE,EAAE,IAAI,CAAC,EAAE;AAC/B,oBAAoB,SAAS,EAAE,IAAI,CAAC,EAAE;AACtC,oBAAoB,SAAS,EAAE,CAAC;AAChC,kBAAiB;AACjB,aAAa;AACb;AACA,YAAY,OAAO,GAAG,SAAS,CAAC;AAChC,YAAY,OAAO,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AACvD,YAAY,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC5C;AACA;AACA,SAAS,MAAM,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,IAAI,GAAG,CAAC,IAAI,IAAI,SAAS,EAAE;AACvE;AACA,YAAY,OAAO,GAAG,WAAW,CAAC;AAClC,YAAY,OAAO,GAAG,SAAS,CAAC;AAChC,YAAY,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACtC;AACA;AACA;AACA,SAAS,MAAM;AACf;AACA;AACA;AACA;AACA,YAAY,IAAI,GAAG,CAAC,IAAI,IAAI,SAAS,EAAE;AACvC,gBAAgB,GAAG,CAAC,IAAI,GAAG;AAC3B,oBAAoB,EAAE,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE;AAC3C,oBAAoB,SAAS,EAAE,IAAI,CAAC,EAAE;AACtC,oBAAoB,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC;AAC7D,iBAAiB,CAAC;AAClB,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,OAAO,GAAG,WAAW,CAAC;AAClC,YAAY,OAAO,GAAG;AACtB,gBAAgB,GAAG,EAAE,GAAG,CAAC,GAAG;AAC5B,gBAAgB,QAAQ,EAAE,GAAG,CAAC,QAAQ;AACtC,gBAAgB,IAAI,EAAE,GAAG,CAAC,IAAI;AAC9B,gBAAgB,IAAI,EAAE,GAAG,CAAC,IAAI;AAC9B,cAAa;AACb;AACA,YAAY,IAAI,IAAI,EAAE;AACtB,gBAAgB,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACjD,aAAa;AACb;AACA;AACA,YAAY,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC5C;AACA;AACA;AACA;AACA,YAAY,IAAI,OAAO,CAAC,QAAQ,EAAE;AAClC,gBAAgB,IAAI,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAClE,gBAAgB,IAAI,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC1D;AACA,gBAAgB,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC1E;AACA,gBAAgB,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;AACvC,oBAAoB,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC/E,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC1E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,QAAQ,EAAE;AACtB,YAAY,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC1C,YAAY,IAAI,KAAK,IAAI,SAAS,EAAE;AACpC,gBAAgB,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;AACrC,gBAAgB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAClE,aAAa;AACb,SAAS;AACT;AACA,QAAQ,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAC;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE;AAC1C;AACA,YAAY,OAAO;AACnB,SAAS,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,EAAE;AACnD,YAAY,aAAa,GAAG,KAAK,CAAC;AAClC,YAAY,UAAU,GAAG,IAAI,CAAC;AAC9B,YAAY,WAAW,GAAG,IAAI,CAAC;AAC/B,YAAY,YAAY,GAAG,IAAI,CAAC;AAChC,SAAS,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,EAAE;AACnD,YAAY,aAAa,GAAG,IAAI,CAAC;AACjC,YAAY,UAAU,GAAG,KAAK,CAAC;AAC/B,YAAY,WAAW,GAAG,IAAI,CAAC;AAC/B,YAAY,YAAY,GAAG,IAAI,CAAC;AAChC,SAAS,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,EAAE;AACpD,YAAY,aAAa,GAAG,IAAI,CAAC;AACjC,YAAY,UAAU,GAAG,IAAI,CAAC;AAC9B,YAAY,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;AACvE,YAAY,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC1E,SAAS;AACT;AACA;AACA;AACA;AACA,QAAQ,IAAI,aAAa,CAAC;AAC1B,YAAY,IAAI,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAClE,YAAY,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACzD,SAAS;AACT,QAAQ,IAAI,UAAU,EAAE;AACxB,YAAY,IAAI,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAClE,YAAY,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACzD,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,YAAY,IAAI,YAAY,EAAE;AAC1C,YAAY,IAAI,YAAY,IAAI,YAAY,EAAE;AAC9C,gBAAgB,aAAa,GAAG,IAAI,CAAC;AACrC,gBAAgB,UAAU,GAAG,IAAI,CAAC;AAClC,gBAAgB,WAAW,GAAG,IAAI,CAAC;AACnC,gBAAgB,YAAY,GAAG,IAAI,CAAC;AACpC,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,WAAW,EAAE;AACzB,YAAY,IAAI,aAAa,EAAE;AAC/B,gBAAgB,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACzE,aAAa;AACb,YAAY,IAAI,UAAU,EAAE;AAC5B,gBAAgB,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACzE,aAAa;AACb,SAAS;AACT;AACA,QAAQ,IAAI,YAAY,EAAE;AAC1B,YAAY,IAAI,aAAa,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE;AAC7D,gBAAgB,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC1E,aAAa;AACb,YAAY,IAAI,UAAU,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE;AAC1D,gBAAgB,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC1E,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,aAAa,CAAC,MAAM,EAAE,GAAG,IAAI,EAAE;AACnC,QAAQ,MAAM,MAAM,GAAG,EAAE,CAAC;AAC1B,QAAQ,KAAK,IAAI,SAAS,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE;AACzD,YAAY,IAAI,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAClD,YAAY,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;AACtD,gBAAgB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClC,aAAa;AACb,SAAS;AACT,QAAQ,OAAOC,YAAkB,CAAC,MAAM,CAAC,CAAC;AAC1C,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,gBAAgB,CAAC,QAAQ,EAAE;AAC/B,QAAQ,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;AACxC,QAAQ,OAAO,IAAI,CAAC,aAAa,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;AAChE,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE;AAC3B,QAAQ,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;AACxC,QAAQ,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC5D,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE;AAC9C,QAAQ,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;AACxC,QAAQ,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,eAAe,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AACzE;AACA,QAAQ,MAAM,KAAK,GAAG,EAAE,CAAC;AACzB,QAAQ,MAAM,IAAI,GAAG;AACrB,YAAY,EAAE,EAAE,KAAK,EAAE;AACvB,YAAY,MAAM,EAAE,OAAO,CAAC,MAAM;AAClC,SAAS,CAAC;AACV,QAAQ,IAAI,GAAG,CAAC;AAChB,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC1C,YAAY,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1B,YAAY,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACtC;AACA,YAAY,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;AACtE,SAAS;AACT;AACA,QAAQ,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAClC,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE;AACtB;AACA,QAAQ,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AACpC;AACA,QAAQ,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;AAC7B,QAAQ,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;AAC9B;AACA,QAAQ,MAAM,KAAK,GAAG,EAAE,CAAC;AACzB,QAAQ,MAAM,IAAI,GAAG;AACrB,YAAY,EAAE,EAAE,KAAK,EAAE;AACvB,YAAY,MAAM,EAAE,OAAO,CAAC,MAAM;AAClC,SAAS,CAAC;AACV,QAAQ,KAAK,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE;AACvC,YAAY,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;AACvE,SAAS;AACT;AACA,QAAQ,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAClC,QAAQ,OAAO,KAAK,CAAC;AACrB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,GAAG;AAChB;AACA,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;AACpD;AACA;AACA,QAAQ,IAAI,IAAI,GAAG,EAAE,CAAC;AACtB,QAAQ,IAAI,MAAM,GAAG,EAAE,CAAC;AACxB,QAAQ,KAAK,IAAI,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,EAAE;AAC7C,YAAY,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACvC,YAAY,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AAC3C,SAAS;AACT,QAAQ,IAAI,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;AAClC,QAAQ,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC;AACtC;AACA,QAAQ,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AACtC;AACA;AACA;AACA,QAAQ,IAAI,gBAAgB,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,IAAI,SAAS,CAAC,CAAC;AAChG;AACA,QAAQ,IAAI,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC;AACxC,QAAQ,IAAI,iBAAiB,GAAG,gBAAgB,CAAC,MAAM,CAAC;AACxD,QAAQ,IAAI,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACvC,QAAQ,IAAI,IAAI,GAAG,SAAS,GAAG,aAAa,GAAG,iBAAiB,CAAC;AACjE,QAAQ,IAAI,IAAI,IAAI,CAAC,EAAE;AACvB,YAAY,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;AACxD,YAAY,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,iBAAiB,CAAC,CAAC;AACjE,YAAY,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAChD,YAAY,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;AAC5C,YAAY,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;AACtD,SAAS;AACT;AACA;AACA,QAAQ,IAAI,UAAU,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;AAClE,QAAQ,IAAI,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK;AAC9E,YAAY,QAAQ,GAAG,CAAC,QAAQ,IAAI,SAAS,EAAE;AAC/C,SAAS,CAAC,CAAC,CAAC;AACZ;AACA,QAAQ,IAAI,OAAO,GAAGC,cAAoB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAChE,QAAQ,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE;AAC9B,YAAY,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAC;AAChD,YAAY,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,EAAC;AAC5C,YAAY,MAAM,IAAI,KAAK,CAAC,CAAC,sBAAsB,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5E,SAAS;AACT;AACA,QAAQ,OAAO,GAAGA,cAAoB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC5D,QAAQ,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE;AAC9B,YAAY,MAAM,IAAI,KAAK,CAAC,CAAC,uBAAuB,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7E,SAAS;AACT;AACA,QAAQ,OAAO;AACf,YAAY,IAAI,EAAE,IAAI,CAAC,MAAM;AAC7B,YAAY,MAAM,EAAE,MAAM,CAAC,MAAM;AACjC,SAAS,CAAC;AACV,KAAK;AACL;AACA,CAAC;AACD;AACA;AACA,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;AACtB,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;AAC9B,OAAO,CAAC,UAAU,GAAG,UAAU,CAAC;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,SAAS,CAAC;AAChB;AACA;AACA,IAAI,WAAW,CAAC,SAAS,EAAE;AAC3B;AACA;AACA,QAAQ,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,WAAW,GAAG,IAAI,YAAY,EAAE,CAAC;AAC9C;AACA;AACA,QAAQ,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;AAClC,QAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;AAChC;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE;AAC7B,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;AAC9C,QAAQ,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAClE,QAAQ,IAAI,IAAI,IAAI,SAAS,EAAE;AAC/B,YAAY,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7C,YAAY,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACrC,SAAS,MAAM;AACf,YAAY,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3B;AACA,SAAS;AACT,KAAK;AACL;AACA,IAAI,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE;AAC7B,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;AAC9C,QAAQ,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAClE,QAAQ,IAAI,IAAI,IAAI,SAAS,EAAE;AAC/B,YAAY,IAAI,KAAK,GAAG,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACtD,YAAY,IAAI,KAAK,EAAE;AACvB,gBAAgB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACvC,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,gBAAgB,CAAC,KAAK,EAAE,GAAG,EAAE;AACjC,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;AAC9C,QAAQ,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAClE,QAAQ,IAAI,IAAI,IAAI,SAAS,EAAE;AAC/B,YAAY,IAAI,EAAE,GAAG,iBAAiB,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;AACnD,YAAY,IAAI,CAAC,EAAE,EAAE;AACrB,gBAAgB,OAAO,CAAC,GAAG,CAAC,0DAA0D,EAAC;AACvF,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,KAAK,GAAG;AACZ,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,EAAE;AAC9D,YAAY,OAAO;AACnB,SAAS;AACT;AACA;AACA,QAAQ,IAAI,SAAS,GAAG,EAAE,CAAC;AAC3B,QAAQ,IAAI,SAAS,GAAG,EAAE,CAAC;AAC3B,QAAQ,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE;AAClD,YAAY,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACjD,YAAY,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;AACjC,gBAAgB,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtC,aAAa,MAAM;AACnB,gBAAgB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC7C,aAAa;AACb,SAAS;AACT,QAAQ,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE;AAChD,YAAY,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACjD,YAAY,IAAI,IAAI,IAAI,SAAS,EAAE;AACnC;AACA,gBAAgB,SAAS;AACzB,aAAa;AACb,YAAY,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE;AAClC,gBAAgB,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtC,gBAAgB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC7C,aAAa;AACb,SAAS;AACT,QAAQ,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACtD;AACA,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;AAC9B,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;AAC5B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,gBAAgB,CAAC,QAAQ,EAAE;AAC/B,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,EAAE;AACtC,YAAY,OAAO,EAAE,CAAC;AACtB,SAAS;AACT,QAAQ,MAAM,gBAAgB,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACvF,QAAQ,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;AACjE,QAAQ,MAAM,MAAM,GAAG,EAAE,CAAC;AAC1B,QAAQ,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;AAClC,QAAQ,IAAI,KAAK,EAAE,SAAS,CAAC;AAC7B,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;AAClC,YAAY,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AAC9B,YAAY,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACrC,iBAAiB,OAAO,CAAC,UAAU,GAAG,EAAE;AACxC;AACA;AACA;AACA;AACA,oBAAoB,IAAI,KAAK,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE;AACnD,wBAAwB,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC;AAC7D,qBAAqB,MAAM,IAAI,KAAK,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE;AAC3D,wBAAwB,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC;AAC9D,qBAAqB,MAAM;AAC3B,wBAAwB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACtD,wBAAwB,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;AACnE,wBAAwB,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAC;AACjG,wBAAwB,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AACrD,wBAAwB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAC;AACpE,wBAAwB,IAAI,CAAC,SAAS,EAAE,CAAC;AACzC,wBAAwB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;AACrE,qBAAqB;AACrB,oBAAoB,IAAI,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE;AAC7D,wBAAwB,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACnE,qBAAqB;AACrB,iBAAiB,EAAE,IAAI,CAAC,CAAC;AACzB,SAAS;AACT,QAAQ,OAAO,MAAM,CAAC;AACtB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,QAAQ,EAAE;AAC3B,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,EAAE;AACtC,YAAY,OAAO,EAAE,CAAC;AACtB,SAAS;AACT,QAAQ,MAAM,gBAAgB,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACvF,QAAQ,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;AACjE,QAAQ,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;AAClC,QAAQ,MAAM,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;AACjC,QAAQ,MAAM,MAAM,GAAG,EAAE,CAAC;AAE1B,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;AAClC,YAAY,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACzC,iBAAiB,OAAO,CAAC,SAAS,GAAG,EAAE;AACvC;AACA,oBAAoB,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;AAC7C,wBAAwB,OAAO;AAC/B,qBAAqB,MAAM;AAC3B,wBAAwB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC5C,qBAAqB;AACrB,oBAAoB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACrC,iBAAiB,CAAC,CAAC;AACnB,SAAS;AACT,QAAQ,OAAO,MAAM,CAAC;AACtB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE;AACjD;AACA,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,EAAE;AACtC,YAAY,OAAO,EAAE,CAAC;AACtB,SAAS;AACT;AACA,QAAQ,IAAI,IAAI,GAAG,EAAE,CAAC;AACtB;AACA;AACA,QAAQ,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;AACtC;AACA;AACA,QAAQ,IAAI,IAAI,IAAIJ,UAAQ,CAAC,MAAM,EAAE;AACrC,YAAY,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,EAAE;AACzE,gBAAgB,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAEA,UAAQ,CAAC,MAAM,CAAC,CAAC;AACrE,aAAa,CAAC,CAAC;AACf,SAAS;AACT;AACA;AACA;AACA,QAAQ,IAAI,KAAK,GAAG,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;AAClD,QAAQ,IAAI,KAAK,EAAE;AACnB;AACA,YAAY,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;AAC9C,iBAAiB,MAAM,CAAC,SAAS,GAAG,CAAC;AACrC,oBAAoB,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AAC/D,iBAAiB,CAAC,CAAC;AACnB,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE;AAC/C,YAAY,OAAO,IAAI,CAAC;AACxB,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,IAAI,GAAGA,UAAQ,CAAC,MAAM,EAAE;AACpC;AACA;AACA,YAAY,IAAI,GAAG,GAAG,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;AACtD,YAAY,IAAI,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC;AACpC;AACA;AACA,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;AACrE,YAAY,IAAI,aAAa,GAAG,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACpE,YAAY,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC;AAC5C,iBAAiB,OAAO,CAAC,SAAS,GAAG,CAAC;AACtC,oBAAoB,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAEA,UAAQ,CAAC,MAAM,CAAC,EAAE;AACvE,wBAAwB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvC,qBAAqB;AACrB,iBAAiB,CAAC,CAAC;AACnB,SAAS;AACT;AACA,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACjD,QAAQ,MAAM,SAAS,GAAG,EAAE,CAAC;AAC7B,QAAQ,IAAI,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC;AAC/B,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC1C,YAAY,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1B;AACA,YAAY,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE;AACvC,gBAAgB,MAAM,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAC5C,aAAa,MAAM;AACnB,gBAAgB,MAAM,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC/D,aAAa;AACb,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAChD,gBAAgB,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;AAClC;AACA;AACA,gBAAgB,IAAI,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/E,gBAAgB,IAAI,KAAK,EAAE;AAC3B,oBAAoB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACjD,oBAAoB,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC1C,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,QAAQ,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;AAClD;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,KAAK,GAAG;AACZ,QAAQ,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;AAC/B,QAAQ,IAAI,CAAC,WAAW,GAAG,IAAI,YAAY,EAAE,CAAC;AAC9C,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;AAC9B,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;AAC5B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,GAAG;AAChB;AACA;AACA;AACA;AACA,QAAQ,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AACxE,QAAQ,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAClE;AACA,QAAQ,IAAI,CAACK,KAAW,CAAC,eAAe,EAAE,aAAa,CAAC,EAAE;AAC1D,YAAY,IAAI,OAAO,GAAGC,cAAoB,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;AAC/E,YAAY,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE;AAClC,gBAAgB,MAAM,IAAI,KAAK,CAAC,CAAC,yBAAyB,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5E,aAAa;AACb;AACA,YAAY,OAAO,GAAGA,cAAoB,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;AAC3E,YAAY,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE;AAClC,gBAAgB,MAAM,IAAI,KAAK,CAAC,CAAC,2BAA2B,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9E,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA,QAAQ,IAAI,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;AACpD,QAAQ,IAAI,MAAM,CAAC,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE;AACnD,YAAY,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;AACnE,SAAS;AACT,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC5C,YAAY,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE;AAC1C,gBAAgB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;AAC1D,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA;AACA,QAAQ,KAAK,IAAI,KAAK,IAAI,MAAM,EAAE;AAClC,YAAY,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACjD,YAAY,KAAK,IAAI,GAAG,IAAI,IAAI,EAAE;AAClC;AACA,gBAAgB,IAAI,KAAK,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE;AAC/C,oBAAoB,SAAS;AAC7B,iBAAiB,MAAM,IAAI,KAAK,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE;AACvD,oBAAoB,SAAS;AAC7B,iBAAiB,MAAM;AACvB,oBAAoB,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AACjD,oBAAoB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;AACjE,oBAAoB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAC3D,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,KAAK,IAAI,SAAS,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE;AAC5D,YAAY,KAAK,IAAI,GAAG,IAAI,SAAS,EAAE;AACvC,gBAAgB,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;AACrE,oBAAoB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;AAChD,wBAAwB,MAAM,IAAI,KAAK,CAAC,CAAC,iDAAiD,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAChI,qBAAqB;AACrB,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,KAAK,GAAG,EAAE,CAAC;AACvB,QAAQ,KAAK,IAAI,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE;AACvD,YAAY,KAAK,IAAI,GAAG,IAAI,SAAS,EAAE;AACvC,gBAAgB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAChC,aAAa;AACb,SAAS;AACT;AACA;AACA,QAAQ,IAAI,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;AAC/B,QAAQ,KAAK,IAAI,GAAG,IAAI,KAAK,EAAE;AAC/B,YAAY,IAAI,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC3C,YAAY,IAAI,IAAI,IAAI,SAAS,EAAE;AACnC,gBAAgB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACzC,aAAa,MAAM;AACnB;AACA,gBAAgB,IAAI,GAAG,KAAK,IAAI,EAAE;AAClC,oBAAoB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;AACpF,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT,QAAQ,IAAI,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;AACxC;AACA;AACA;AACA;AACA;AACA,QAAQ,KAAK,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE;AACvC;AACA,YAAY,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE;AACvD,gBAAgB,MAAM,IAAI,KAAK,CAAC,CAAC,yBAAyB,EAAE,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3G,aAAa;AACb,SAAS;AACT;AACA,QAAQ,OAAO,CAAC;AAChB,YAAY,SAAS,EAAE,IAAI,CAAC,UAAU;AACtC,YAAY,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;AAC9C,YAAY,IAAI,EAAE,IAAI;AACtB,SAAS,CAAC,CAAC;AACX,KAAK;AACL;;ACxoDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,SAAS,aAAa,CAAC;AACnC;AACA,IAAI,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE;AACrC,QAAQ,KAAK,CAAC,OAAO,CAAC,CAAC;AACvB,QAAQ,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;AAC9C,QAAQ,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;AAChD,QAAQ,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;AAC1C,QAAQ,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;AAClD,QAAQ,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;AACvB;AACA;AACA,QAAQ,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;AAC7B;AACA;AACA,QAAQ,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;AAC/B,QAAQ,IAAI,EAAE,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAC;AACnD,QAAQ,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AACxD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,UAAU,CAAC,GAAG;AACtB,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC;AAC5B,KAAK;AACL;AACA,IAAI,IAAI,OAAO,CAAC,GAAG;AACnB,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC;AAC5B,KAAK;AACL;AACA;AACA,IAAI,IAAI,QAAQ,CAAC,GAAG;AACpB,QAAQ,OAAO,IAAI,CAAC,SAAS,CAAC;AAC9B,KAAK;AACL;AACA,IAAI,IAAI,QAAQ,CAAC,CAAC,GAAG,EAAE;AACvB,QAAQ,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;AAC/B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,CAAC,OAAO,EAAE;AAC3B,QAAQ,IAAI,MAAM,GAAG;AACrB,YAAY,OAAO,EAAE,OAAO;AAC5B,UAAS;AACT,QAAQ,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACrC,QAAQ,OAAO,MAAM,CAAC;AACtB,KAAK;AACL;AACA;AACA,IAAI,YAAY,CAAC,CAAC,MAAM,EAAE;AAC1B,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACpD,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;AACxB,YAAY,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC7C,SAAS;AACT,KAAK;AACL;AACA;AACA,IAAI,iBAAiB,CAAC,CAAC,QAAQ,EAAE,iBAAiB,EAAE;AACpD,QAAQ,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,MAAM,EAAE;AACjD,YAAY,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AACxD,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,CAAC,GAAG,EAAE;AACnB,QAAQ,IAAI,GAAG,IAAI,SAAS,EAAE;AAC9B,YAAY,OAAO,KAAK,CAAC;AACzB,SAAS;AACT;AACA,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE;AAC5B,YAAY,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;AACrD,gBAAgB,OAAO,KAAK,CAAC;AAC7B,aAAa;AACb,SAAS;AACT;AACA,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE;AAC9B,YAAY,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;AAC5C,gBAAgB,OAAO,KAAK,CAAC;AAC7B,aAAa;AACb,SAAS;AACT;AACA,QAAQ,IAAI,IAAI,CAAC,YAAY,EAAE;AAC/B,YAAY,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAC9C,gBAAgB,OAAO,KAAK,CAAC;AAC7B,aAAa;AACb,SAAS;AACT,QAAQ,OAAO,IAAI,CAAC;AACpB,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,GAAG,EAAE;AACtB,QAAQ,IAAI,GAAG,IAAI,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE;AACpD;AACA,YAAY,OAAO;AACnB,gBAAgB,GAAG,EAAE,GAAG,CAAC,GAAG;AAC5B,gBAAgB,QAAQ,EAAE,GAAG,CAAC,QAAQ;AACtC,gBAAgB,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;AAClD,aAAa;AACb,SAAS;AACT,QAAQ,OAAO,GAAG,CAAC;AACnB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,qBAAqB,CAAC,KAAK,EAAE;AACjC,QAAQ,IAAI,MAAM,GAAG,EAAE,CAAC;AACxB,QAAQ,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE;AAChC,YAAY,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,EAAE;AAChE,gBAAgB,SAAS;AACzB,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;AACzE,YAAY,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;AACzE,YAAY,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,SAAS,EAAE;AACxD,gBAAgB,SAAS;AACzB,aAAa;AACb;AACA,YAAY,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AAC3C,YAAY,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AAC3C;AACA,YAAY,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;AAC9D,SAAS;AACT,QAAQ,OAAO,MAAM,CAAC;AACtB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,eAAe,CAAC,QAAQ,EAAE;AAC9B,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE;AAC5B;AACA,WAAW,IAAI,QAAQ,EAAE;AACzB;AACA,eAAe,IAAI,UAAU,GAAG,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;AAC7E,eAAe,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,EAAE;AAC3C,mBAAmB,OAAO,CAAC,GAAG,CAAC,CAAC,0BAA0B,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,6BAA6B,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5I,mBAAmB,OAAO,EAAE,CAAC;AAC7B,iBAAiB,MAAM;AACvB,oBAAoB,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;AAC7C,iBAAiB;AACjB,aAAa,MAAM;AACnB;AACA,gBAAgB,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;AAC1C,aAAa;AACb,SAAS;AACT,QAAQ,OAAO,QAAQ,CAAC;AACxB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE;AAC3B,QAAQ,IAAI,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;AACvD,QAAQ,IAAI,IAAI,CAAC;AACjB,QAAQ,IAAI,SAAS,EAAE;AACvB,YAAY,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAC3D,SAAS,MAAM;AACf,YAAY,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;AACjD,SAAS;AACT;AACA,QAAQ,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;AAChD,aAAa,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;AAC1C,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,gBAAgB,CAAC,QAAQ,EAAE;AAC/B,QAAQ,IAAI,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;AACvD,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAChE;AACA,QAAQ,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK;AACtC,YAAY,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5C,SAAS,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK;AAC/B,YAAY,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/E,SAAS,EAAE,IAAI,CAAC,CAAC;AACjB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,qBAAqB,CAAC,IAAI,EAAE;AAChC,QAAQ,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI,IAAI,QAAQ,EAAE;AACjD;AACA,YAAY,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;AACrC;AACA,YAAY,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK;AAC1C,gBAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;AAC7D,aAAa,CAAC,CAAC;AACf;AACA,YAAY,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAClC,YAAY,OAAO,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;AACvD,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,EAAE;AACpD,QAAQ,IAAI,KAAK,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;AAC3C,QAAQ,KAAK,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;AAClD;AACA,QAAQ,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE;AAChC,YAAY,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,EAAE;AAChE;AACA,gBAAgB,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;AAChC,aAAa,MAAM,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,EAAE;AACvE;AACA,gBAAgB,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;AAChC,aAAa;AACb,SAAS;AACT;AACA,QAAQ,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACnC;AACA,QAAQ,IAAI,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK;AACnD,YAAY,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACpC,SAAS,CAAC,CAAC,CAAC;AACZ,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE;AAC5B,YAAY,iBAAiB,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;AACtF,SAAS;AACT,QAAQ,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;AAC5D,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,CAAC,GAAG,EAAE;AACvB,QAAQ,IAAI,CAAC,GAAG,YAAY,QAAQ,EAAE;AACtC,YAAY,MAAM,IAAI,KAAK,CAAC,kBAAkB,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;AAChE,SAAS;AACT,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;AAC5D;AACA,YAAY,IAAI,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;AAC7C;AACA,YAAY,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;AACjC;AACA,YAAY,IAAI,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AACvD;AACA,YAAY,QAAQ,GAAG,QAAQ;AAC/B,iBAAiB,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;AAC7C,iBAAiB,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;AAC9C;AACA,YAAY,IAAI,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK;AACvE,gBAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACtC,aAAa,CAAC,CAAC,CAAC;AAChB,YAAY,IAAI,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK;AAC/D,gBAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACtC,aAAa,CAAC,CAAC,CAAC;AAChB;AACA,YAAY,IAAI,UAAU,GAAG,cAAc,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;AACtE,YAAY,IAAI,WAAW,GAAG,cAAc,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AACvE;AACA,YAAY,IAAI,SAAS,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK;AAClE,gBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC;AAC9D,aAAa,CAAC,CAAC;AACf,YAAY,IAAI,UAAU,GAAG,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK;AACpE,gBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC;AAC9D,aAAa,CAAC,CAAC;AACf;AACA,YAAY,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,MAAM,CAAC;AAC3C,YAAY,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,MAAM,CAAC;AAC5C;AACA,YAAY,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1F,YAAY,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACtC,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,IAAI,CAAC,GAAG;AAChB,QAAQ,OAAO,IAAI,CAAC,KAAK,CAAC;AAC1B,KAAK;AACL;AACA,IAAI,GAAG,CAAC,GAAG,EAAE;AACb,QAAQ,QAAQ,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,SAAS,EAAE;AAC5C,KAAK;AACL;AACA,IAAI,GAAG,CAAC,GAAG,EAAE;AACb,QAAQ,IAAI,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACjC,QAAQ,IAAI,GAAG,IAAI,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE;AACrD,YAAY,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;AAC1C,SAAS;AACT,KAAK;AACL;AACA,IAAI,IAAI,GAAG;AACX,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;AACzC,YAAY,OAAO,GAAG,CAAC,GAAG,CAAC;AAC3B,SAAS,EAAE,CAAC;AACZ,KAAK;AACL;AACA,IAAI,MAAM,GAAG;AACb,QAAQ,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;AAClC,aAAa,MAAM,CAAC,CAAC,GAAG,KAAK;AAC7B,gBAAgB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AAC3C,aAAa,EAAE,IAAI,CAAC;AACpB,aAAa,GAAG,CAAC,CAAC,GAAG,KAAK;AAC1B,gBAAgB,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;AAC9C,aAAa,EAAE,IAAI,CAAC,CAAC;AACrB,KAAK;AACL;AACA,IAAI,OAAO,GAAG;AACd,QAAQ,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK;AAC1C,YAAY,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAClC,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE;AAC1B,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE;AACrB,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA,IAAI,MAAM,CAAC,CAAC,GAAG,EAAE;AACjB,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA,IAAI,KAAK,CAAC,CAAC,GAAG,EAAE;AAChB,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA;;ACzZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA,MAAM,GAAG,GAAGC,6BAAyC,CAAC;AACtD;AACA,SAAS,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;AACvB,IAAI,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;AACpD,CACA;AACA;AACA,MAAM,SAAS,GAAG,EAAC;AACnB;AACA,MAAM,QAAQ,CAAC;AACf;AACA,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE;AACtC;AACA,QAAQ,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;AACrB;AACA,QAAQ,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5D;AACA,QAAQ,IAAI,CAAC,MAAM,CAAC;AACpB;AACA,QAAQ,IAAI,CAAC,YAAY,CAAC;AAC1B;AACA,QAAQ,IAAI,CAAC,WAAW,CAAC;AACzB;AACA,QAAQ,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;AAC/B;AACA,QAAQ,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;AACxB;AACA,QAAQ,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;AAC5B;AACA,QAAQ,OAAO,GAAG,OAAO,IAAI,EAAE,CAAC;AAChC,QAAQ,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,SAAS,CAAC;AAC3D,QAAQ,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;AAC/B,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,YAAY,CAAC,CAAC,OAAO,EAAE;AAC3B,QAAQ,IAAI,MAAM,GAAG;AACrB,YAAY,OAAO,EAAE,OAAO;AAC5B,UAAS;AACT,QAAQ,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACpC,QAAQ,OAAO,MAAM,CAAC;AACtB,KAAK;AACL;AACA,IAAI,YAAY,CAAC,CAAC,MAAM,EAAE;AAC1B,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AACnD,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE;AACxB,YAAY,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AAC5C,SAAS;AACT,KAAK;AACL;AACA,IAAI,iBAAiB,CAAC,CAAC,GAAG,IAAI,EAAE;AAChC,QAAQ,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,MAAM,EAAE;AAChD,YAAY,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AACpC,SAAS,CAAC,CAAC;AACX,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,SAAS,CAAC,MAAM,EAAE;AACtB,QAAQ,IAAI,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC;AACnC;AACA,QAAQ,IAAI,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;AACzC,QAAQ,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE;AACtC,YAAY,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;AACjC,YAAY,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;AAC1C,YAAY,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;AACzC,YAAY,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;AAC5B,SAAS;AACT;AACA,QAAQ,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;AAC7B;AACA,QAAQ,IAAIZ,QAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;AAC/C,YAAY,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC1B,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,CAAC,UAAU,EAAE;AACrB,QAAQ,UAAU,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE;AAC1C,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;AACpE,gBAAgB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtC,aAAa;AACb,SAAS,EAAE,IAAI,CAAC,CAAC;AACjB;AACA,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAClC,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,GAAG,CAAC,GAAG,EAAE;AACb,QAAW,IAAY,GAAG,GAAG,GAAG;AAChC,QAAQ,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;AACpC,QAAQ,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE;AAC5E,YAAY,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;AACzC,SAAS;AACT,QAAQ,OAAO,GAAG,CAAC;AACnB,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,IAAI,GAAG;AACX,QAAQ,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;AAChF,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,OAAO,CAAC,GAAG,EAAE;AACjB,QAAQ,IAAI,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;AAClD,QAAQ,IAAI,OAAO,GAAG,KAAK,CAAC;AAC5B,QAAQ,IAAI,IAAI,CAAC,YAAY,IAAI,SAAS,EAAE;AAC5C,YAAY,KAAK,GAAG,GAAG,CAAC;AACxB,YAAY,OAAO,GAAG,IAAI,CAAC;AAC3B,SAAS,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE;AACzE,YAAY,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;AAC3C,YAAY,OAAO,GAAG,KAAI;AAC1B,SAAS;AACT,QAAQ,IAAI,OAAO,EAAE;AACrB;AACA,YAAY,IAAI,CAAC,YAAY,GAAG,IAAI,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;AAChF,YAAY,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AACnE;AACA,YAAY,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;AAC5B,SAAS;AACT,QAAQ,OAAO,OAAO,CAAC;AACvB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,CAAC,SAAS,EAAE,kBAAkB,EAAE;AACxC,QAAQ,IAAIa,gBAAc,GAAGC,cAA0B,CAAC,IAAI,CAAC,YAAY;AACzE,wDAAwD,IAAI,CAAC,WAAW;AACxE,wDAAwD,IAAI,CAAC,MAAM;AACnE,wDAAwD,SAAS,CAAC,CAAC;AACnE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,QAAQ,GAAGC,cAA0B,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACjF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,kBAAkB,IAAI,SAAS,EAAE;AAC7C,YAAY,kBAAkB,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC;AAC/D,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,OAAOF,gBAAc,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE;AACpD;AACA,YAAY,IAAI,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;AAChD;AACA,gBAAgB,OAAO,KAAK,CAAC;AAC7B,aAAa;AACb;AACA;AACA,YAAY,IAAI,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,EAAE;AACtE;AACA,gBAAgB,OAAO,KAAK,CAAC;AAC7B,aAAa;AACb;AACA;AACA;AACA;AACA,YAAY,IAAI,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,GAAG,EAAE;AACjD,gBAAgB,IAAI,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAC5C,gBAAgB,IAAI,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE;AAC3D,oBAAoB,IAAI,CAAC,GAAGhB,eAA2B,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACzE,oBAAoB,IAAI,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,EAAE;AAC3E,wBAAwB,OAAO,KAAK,CAAC;AACrC,qBAAqB;AACrB,iBAAiB;AACjB,aAAa;AACb,YAAY,OAAO,IAAI,CAAC;AACxB,SAAS,EAAE,IAAI,CAAC,CAAC;AACjB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,GAAG,CAAC,GAAG,EAAE;AACb;AACA,QAAQ,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACtC;AACA,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AAC/B;AACA,YAAY,IAAI,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAChF;AACA,YAAY,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;AAChD;AACA,YAAY,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7C,SAAS;AACT,QAAQ,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AAClC,YAAY,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;AACzD,SAAS;AACT;AACA,QAAQ,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;AACvD,QAAQ,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;AACtE,KAAK;AACL;;AC/SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA,SAAS,MAAM,CAAC,KAAK,EAAE;AACvB,IAAI,QAAQ,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE;AACtF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AAC7B,IAAI,KAAK,EAAE,CAAC;AACZ,IAAI,IAAI,EAAE,CAAC;AACX,IAAI,IAAI,EAAE,CAAC,CAAC;AACZ,IAAI,UAAU,EAAE,CAAC;AACjB,CAAC,CAAC,CAAC;AACH;AACA,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;AAC1B,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;AACxB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;AACxB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;AACxB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;AACxB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;AACzB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;AACzB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;AACzB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;AACxB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;AACzB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;AACxB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;AACxB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;AACxB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;AACzB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;AACxB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC;AAC9B,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC;AACxB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;AACzB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC;AAC9B,CAAC,CAAC,CAAC;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,gBAAgB,EAAE,KAAK,EAAE,KAAK,EAAE;AACzC,IAAI,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC3D,CAAC;AACD;AACA,SAAS,iBAAiB,EAAE,KAAK,EAAE,KAAK,EAAE;AAC1C,IAAI,OAAO,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;AACjE,CAAC;AACD;AACA,SAAS,iBAAiB,EAAE,MAAM,EAAE,MAAM,EAAE;AAC5C,IAAI,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;AACvD,IAAI,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;AACvD,IAAI,OAAO,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC1C,CAAC;AACD;AACA,SAAS,kBAAkB,EAAE,MAAM,EAAE,MAAM,EAAE;AAC7C,IAAI,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;AACvD,IAAI,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;AACvD,IAAI,OAAO,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC3C,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,aAAa,SAAS,aAAa,CAAC;AAC1C;AACA;AACA,IAAI,WAAW,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE;AACnC,QAAQ,KAAK,CAAC,OAAO,CAAC,CAAC;AACvB;AACA;AACA,QAAQ,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;AAC9B;AACA;AACA,QAAQ,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC;AAC3B,QAAQ,IAAI,EAAE,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAC;AACnD,QAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AAChD,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,IAAI,UAAU,CAAC,GAAG;AACtB,QAAQ,OAAO,IAAI,CAAC,IAAI,CAAC;AACzB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,OAAO,CAAC,GAAG;AACnB,QAAQ,OAAO,IAAI,CAAC,GAAG,CAAC;AACxB,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,kBAAkB,GAAG;AACzB,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA;AACA;AACA,IAAI,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE;AACjC,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AAC5C,QAAQ,IAAI,OAAO,KAAK,IAAI,UAAU,EAAE;AACxC;AACA,YAAY,OAAO,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC;AAClD,SAAS,MAAM;AACf;AACA,YAAY,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;AAChE;AACA,YAAY,IAAI,SAAS,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;AACtD,YAAY,IAAI,SAAS,IAAI,CAAC,EAAE;AAChC,gBAAgB,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;AAC5C,aAAa,MAAM;AACnB,gBAAgB,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AAC7C,aAAa;AACb,YAAY,OAAO,IAAI;AACvB,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA,IAAI,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE;AAChC,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;AACrC,QAAQ,IAAI,OAAO,KAAK,IAAI,UAAU,EAAE;AACxC;AACA,YAAY,OAAO,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC;AACzC,SAAS;AACT,QAAQ,IAAI,KAAK,IAAI,SAAS,EAAE;AAChC;AACA,YAAY,IAAI,SAAS,IAAI,SAAS,EAAE;AACxC,gBAAgB,SAAS,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;AACtD,aAAa;AACb,YAAY,IAAI,SAAS,IAAI,CAAC,EAAE;AAChC,gBAAgB,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AAC9C,aAAa,MAAM;AACnB,gBAAgB,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;AAC/C,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE;AACrB,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA,IAAI,MAAM,CAAC,CAAC,GAAG,EAAE;AACjB,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA,IAAI,KAAK,CAAC,CAAC,GAAG,EAAE;AAChB,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,EAAE;AACpD,QAAQ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAC3C,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,0BAA0B,CAAC,QAAQ,EAAE,QAAQ,EAAE;AACnD,QAAQ,MAAM,WAAW,GAAG,EAAE,CAAC;AAC/B,QAAQ,MAAM,YAAY,GAAG,EAAE,CAAC;AAChC,QAAQ,MAAM,UAAU,GAAG,EAAE,CAAC;AAC9B,QAAQ,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;AAC1C,QAAQ,IAAI,SAAS,EAAE,gBAAgB,EAAE,KAAK,CAAC;AAC/C,QAAQ,KAAK,IAAI,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE;AAC5C,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACpC,gBAAgB,SAAS;AACzB,aAAa;AACb;AACA,YAAY,SAAS,GAAG,CAAC,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClE,YAAY,gBAAgB,GAAG,KAAK,CAAC;AACrC,YAAY,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,EAAE;AACvC,gBAAgB,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE;AACvD,oBAAoB,gBAAgB,GAAG,IAAI,CAAC;AAC5C,iBAAiB;AACjB,aAAa;AACb,YAAY,IAAI,SAAS,IAAI,CAAC,gBAAgB,EAAE;AAChD;AACA,gBAAgB,KAAK,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACpF,gBAAgB,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACvC,aAAa,MAAM,IAAI,CAAC,SAAS,IAAI,gBAAgB,EAAE;AACvD;AACA,gBAAgB,KAAK,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACpF,gBAAgB,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACxC,aAAa,MAAM,IAAI,SAAS,IAAI,gBAAgB,EAAE;AACtD;AACA,gBAAgB,KAAK,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnF,gBAAgB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACzC,aAAa;AACb,SACA,QAAQ,OAAO,CAAC,UAAU,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;AACvD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,0BAA0B,CAAC,QAAQ,EAAE,QAAQ,EAAE;AACnD;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,SAAS,GAAG,EAAE;AAChF,YAAY,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAClC,SAAS,CAAC,CAAC,CAAC;AACZ;AACA,QAAQ,IAAI,YAAY,GAAG,EAAE,CAAC;AAC9B,QAAQ,IAAI,UAAU,GAAG,EAAE,CAAC;AAC5B,QAAQ,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;AAC1C,QAAQ,IAAI,CAAC,KAAK,CAAC;AACnB;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AACnE,YAAY,IAAI,UAAU,CAAC,IAAI,GAAG,CAAC,EAAE;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,IAAI,GAAG,EAAE,KAAK,CAAC;AAC/B,gBAAgB,KAAK,IAAI,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE;AACpD,oBAAoB,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnD,oBAAoB,IAAI,GAAG,IAAI,SAAS,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACjE,wBAAwB,KAAK,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3E,wBAAwB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACjD,qBAAqB;AACrB,iBAAiB;AACjB,aAAa;AACb;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AAClE,YAAY,UAAU,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;AAC/C,iBAAiB,GAAG,CAAC,GAAG,IAAI;AAC5B,oBAAoB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;AACjE,iBAAiB,CAAC,CAAC;AACnB,SAAS;AACT;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,SAAS,CAAC;AACtB,QAAQ,IAAI,KAAK,EAAE;AACnB,YAAY,SAAS,GAAG,YAAW;AACnC,SAAS,MAAM;AACf,YAAY,SAAS,GAAG,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/D,SAAS;AACT,QAAQ,IAAI,WAAW,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC;AACjD,aAAa,GAAG,CAAC,GAAG,IAAI;AACxB,gBAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;AAC7D,aAAa,CAAC,CAAC;AACf;AACA;AACA;AACA;AACA,QAAQ,KAAK,IAAI,SAAS,IAAI,CAAC,UAAU,EAAE,YAAY,EAAE,WAAW,CAAC,EAAE;AACvE,YAAY,KAAK,IAAI,IAAI,IAAI,SAAS,EAAE;AACxC,gBAAgB,IAAI,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnD,gBAAgB,IAAI,KAAK,IAAI,SAAS,EAAE;AACxC,oBAAoB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;AAC3C,iBAAiB;AACjB,aAAa;AACb,SAAS;AACT;AACA,QAAQ,OAAO,CAAC,UAAU,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;AACvD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,IAAI,OAAO,GAAG;AAClB,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;AACpC,KAAK;AACL;AACA,IAAI,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE;AAChC,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AACxD,KAAK;AACL;AACA,IAAI,SAAS,CAAC,GAAG,EAAE;AACnB,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AAC3C,KAAK;AACL;AACA,IAAI,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE;AACjC,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;AACzD,KAAK;AACL;AACA,IAAI,UAAU,CAAC,GAAG,EAAE;AACpB,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC5C,KAAK;AACL;AACA,IAAI,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE;AAC1B,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAClD,KAAK;AACL;AACA,IAAI,KAAK,GAAG;AACZ,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;AACpC,KAAK;AACL;AACA,IAAI,MAAM,CAAC,GAAG,EAAE;AAChB,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACrC,KAAK;AACL;AACA,IAAI,MAAM,CAAC,GAAG,EAAE;AAChB,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACrC,KAAK;AACL;AACA,IAAI,OAAO,GAAG;AACd,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;AACnC,KAAK;AACL;AACA,IAAI,aAAa,GAAG;AACpB,QAAQ,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AAChC,KAAK;AACL;AACA,IAAI,aAAa,GAAG;AACpB,QAAQ,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;AAC3B,KAAK;AACL;AACA,IAAI,QAAQ,CAAC,GAAG,EAAE;AAClB,QAAQ,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC7B,KAAK;AACL;AACA,CAAC;AACD;AACA,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC;AAC9B,aAAa,CAAC,SAAS,GAAG,SAAS;;ACpdnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA,MAAMmB,UAAQ,GAAGpB,WAAuB,CAAC,QAAQ,CAAC;AAClD,MAAMqB,WAAS,GAAGrB,WAAuB,CAAC,SAAS,CAAC;AACpD,MAAMsB,QAAM,GAAG,aAAa,CAAC,MAAM,CAAC;AACpC,MAAMC,WAAS,GAAG,aAAa,CAAC,SAAS,CAAC;AAC1C;AACA,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAClC;AACA;AACA,MAAM,kBAAkB,SAAS,aAAa,CAAC;AAC/C;AACA,IAAI,WAAW,CAAC,CAAC,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE;AACvC;AACA,QAAQ,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAChC;AACA;AACA,QAAQ,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;AACtB,QAAQ,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAChF;AACA;AACA,QAAQ,IAAI,CAAC,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACjD,QAAQ,IAAI,EAAE,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrD,QAAQ,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,EAAC;AACrD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA,IAAI,kBAAkB,GAAG;AACzB,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;AACzC,QAAQ,OAAOC,kBAA8B,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACpE,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,EAAE;AACpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE;AACjC,YAAY,OAAO;AACnB,SAAS;AACT;AACA,QAAQ,IAAI,iBAAiB,IAAI,SAAS,EAAE;AAC5C,YAAY,OAAO;AACnB,SAAS;AACT;AACA,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;AACzC,QAAQ,MAAM,UAAU,GAAGvB,eAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC7E;AACA;AACA,QAAQ,MAAM,cAAc,GAAG,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AACjE;AACA,QAAQ,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,iBAAiB,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;AAC9E;AACA;AACA;AACA;AACA,YAAY,IAAI,SAAS,GAAG,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvE,YAAY,IAAI,kBAAkB,GAAG,QAAQ,CAAC,IAAI,EAAE;AACpD,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,oBAAoB,EAAE;AAC3D,oBAAoB,SAAS,GAAG,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3E,iBAAiB;AACjB,aAAa;AACb;AACA;AACA,YAAY,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,SAAS,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AAC9E;AACA;AACA,YAAY,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI;AACjC,gBAAgB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3C,aAAa,CAAC,CAAC;AACf,YAAY,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;AACnC,gBAAgB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,aAAa,CAAC,CAAC;AACf,YAAY,KAAK,CAAC,OAAO,CAAC,IAAI,IAAI;AAClC,gBAAgB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,aAAa,CAAC,CAAC;AACf;AACA;AACA,YAAY,IAAI,SAAS,GAAGuB,kBAA8B,CAAC,UAAU,CAAC,CAAC;AACvE,YAAY,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AAC5C,YAAY,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAC9C,YAAY,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAC7C;AACA;AACA,YAAY,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACvF;AACA;AACA,YAAY,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACtC,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;AACrC,YAAY,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,iBAAiB,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;AAC3F;AACA;AACA,gBAAgB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAClD,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,iBAAiB,CAAC,CAAC,IAAI,EAAE;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,UAAU,CAAC;AACvB;AACA,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE;AACvB,YAAY,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;AACzC,SAAS,MAAM;AACf;AACA,YAAY,UAAU,GAAGvB,eAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;AAC5F,SAAS;AACT;AACA;AACA;AACA;AACA,QAAQ,IAAI,KAAK,GAAG,IAAID,WAAuB,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AACjF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,KAAK,CAAC,QAAQ,IAAIoB,UAAQ,CAAC,MAAM,IAAI,KAAK,CAAC,SAAS,IAAIC,WAAS,CAAC,IAAI,EAAE;AACpF;AACA,YAAY,IAAI,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC;AAC1C,YAAY,IAAI,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC;AAC3C,YAAY,IAAI,GAAG,GAAG,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1D;AACA,YAAY,IAAI,UAAU,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI;AACrE,gBAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACtC,aAAa,CAAC,CAAC,CAAC;AAChB;AACA,YAAY,IAAI,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AACjE;AACA,YAAY,IAAI,SAAS,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AAClE;AACA,YAAY,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;AACnC;AACA;AACA,YAAY,IAAI,SAAS,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI;AAC9D,gBAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;AAC7D,aAAa,CAAC,CAAC;AACf,YAAY,IAAI,UAAU,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI;AAChE,gBAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;AAC7D,aAAa,CAAC,CAAC;AACf;AACA;AACA,YAAY,IAAI,SAAS,GAAGG,kBAA8B,CAAC,UAAU,CAAC,CAAC;AACvE,YAAY,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACjD,YAAY,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AAClD;AACA;AACA,YAAY,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACzF;AACA;AACA,YAAY,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACtC,SAAS;AACT;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAC1C,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,mBAAmB,GAAG,SAAS,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE;AACjE,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE;AACjC,YAAY,OAAO;AACnB,SAAS;AACT;AACA,QAAQ,MAAM,KAAK,GAAG,EAAE,CAAC;AACzB,QAAQ,aAAa,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE;AAC9C,YAAY,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;AAC/B,YAAY,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACjD,YAAY,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;AACjE;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,OAAO,GAAG,GAAG,CAAC;AAC9B;AACA,YAAY,IAAI,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,CAAC;AAC1D;AACA,YAAY,IAAI,OAAO,GAAG,CAAC,QAAQ,IAAI,GAAG,EAAE,CAAC,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;AAChE;AACA,YAAY,IAAI,WAAW,GAAGD,WAAS,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAC7E;AACA,YAAY,IAAI,WAAW,IAAID,QAAM,CAAC,UAAU,EAAE;AAClD,gBAAgB,IAAI,OAAO,EAAE;AAC7B;AACA,oBAAoB,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACtE,oBAAoB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC9C,iBAAiB,MAAM;AACvB;AACA,oBAAoB,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;AACtE;AACA,oBAAoB,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACtE;AACA,iBAAiB;AACjB,aAAa,MAAM,IAAI,WAAW,IAAIA,QAAM,CAAC,KAAK,EAAE;AACpD,gBAAgB,IAAI,CAAC,OAAO,EAAE;AAC9B;AACA,oBAAoB,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;AACtE,oBAAoB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAChD,iBAAiB;AACjB,aAAa,MAAM,IAAI,WAAW,IAAIA,QAAM,CAAC,IAAI,EAAE;AACnD,gBAAgB,IAAI,OAAO,EAAE;AAC7B;AACA,oBAAoB,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACtE,oBAAoB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC9C,iBAAiB;AACjB,aAAa;AACb,SAAS,EAAE,IAAI,CAAC,CAAC;AACjB;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAClC,KAAK;AACL;;ACjTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA,MAAMF,UAAQ,GAAGpB,WAAuB,CAAC,QAAQ,CAAC;AAClD,MAAMqB,WAAS,GAAGrB,WAAuB,CAAC,SAAS,CAAC;AACpD,MAAMsB,QAAM,GAAG,aAAa,CAAC,MAAM,CAAC;AACpC,MAAMC,WAAS,GAAG,aAAa,CAAC,SAAS,CAAC;AAC1C;AACA,MAAME,oBAAkB,GAAG,IAAI,CAAC;AAChC,MAAMC,sBAAoB,GAAG,IAAI,CAAC;AAClC;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,kBAAkB,EAAE,YAAY,EAAE,YAAY,EAAE;AACzD,IAAI,IAAI,WAAW,GAAGF,kBAA8B,CAAC,YAAY,CAAC,CAAC;AACnE,IAAI,IAAI,WAAW,GAAGA,kBAA8B,CAAC,YAAY,CAAC,CAAC;AACnE,IAAI,IAAI,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;AAC9C,IAAI,OAAO,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AACD;AACA;AACA,MAAM,qBAAqB,SAAS,aAAa,CAAC;AAClD;AACA,IAAI,WAAW,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE;AAC7C;AACA,QAAQ,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAChC;AACA;AACA,QAAQ,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;AACxB,QAAQ,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;AAChC,QAAQ,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;AACxB,QAAQ,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;AAChC,QAAQ,IAAI,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtD,QAAQ,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;AACtD,QAAQ,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;AACtD;AACA;AACA,QAAQ,IAAI,QAAQ,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3D,QAAQ,IAAI,CAAC,OAAO,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACnD,QAAQ,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;AAC9D,QAAQ,IAAI,CAAC,OAAO,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACnD,QAAQ,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;AAC9D,KAAK;AACL;AACA;AACA,IAAI,QAAQ,GAAG;AACf,QAAQ,QAAQ,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,UAAU,EAAE;AACpD,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,kBAAkB,GAAG;AACzB,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;AAC1C,QAAQ,MAAM,YAAY,GAAGvB,eAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAChF,QAAQ,MAAM,YAAY,GAAGA,eAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAChF,QAAQ,OAAO,kBAAkB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;AAC9D,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,EAAE;AACpD,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;AAC9B,YAAY,OAAO;AACnB,SAAS;AACT;AACA,QAAQ,IAAI,iBAAiB,IAAI,SAAS,EAAE;AAC5C,YAAY,OAAO;AACnB,SAAS;AACT;AACA;AACA,QAAQ,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;AAC1C,QAAQ,MAAM,YAAY,GAAGA,eAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAChF,QAAQ,MAAM,YAAY,GAAGA,eAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAChF;AACA;AACA,QAAQ,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;AAC5E,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC7E,QAAQ,MAAM,cAAc,GAAG,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACnE;AACA,QAAQ,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,iBAAiB,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;AAC9E;AACA;AACA;AACA;AACA,YAAY,IAAI,SAAS,GAAG,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvE,YAAY,IAAIwB,oBAAkB,GAAG,QAAQ,CAAC,IAAI,EAAE;AACpD,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,GAAGC,sBAAoB,EAAE;AAC3D,oBAAoB,SAAS,GAAG,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3E,iBAAiB;AACjB,aAAa;AACb;AACA;AACA,YAAY,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,SAAS,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AAC9E;AACA;AACA,YAAY,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI;AACjC,gBAAgB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC3C,aAAa,CAAC,CAAC;AACf,YAAY,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;AACnC,gBAAgB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,aAAa,CAAC,CAAC;AACf,YAAY,KAAK,CAAC,OAAO,CAAC,IAAI,IAAI;AAClC,gBAAgB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,aAAa,CAAC,CAAC;AACf;AACA;AACA,YAAY,IAAI,SAAS,GAAG,kBAAkB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;AAC3E,YAAY,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AAC5C,YAAY,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAC9C,YAAY,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAC7C;AACA;AACA,YAAY,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACvF;AACA;AACA,YAAY,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AACjD,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;AACtC,YAAY,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,iBAAiB,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;AAC5F;AACA;AACA,gBAAgB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;AACrD,aAAa;AACb,SAAS;AACT;AACA,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;AACtC,YAAY,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,iBAAiB,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;AAC5F;AACA;AACA,gBAAgB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;AACrD,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,iBAAiB,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;AACpC;AACA;AACA;AACA;AACA,QAAQ,IAAI,IAAI,GAAG,KAAK,CAAC;AACzB,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;AAC9B,YAAY,IAAI,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE;AACxC,gBAAgB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;AACvC,aAAa,MAAM;AACnB,gBAAgB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;AACvC,aAAa;AACb,YAAY,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;AACjC,gBAAgB,IAAI,GAAG,IAAI,CAAC;AAC5B,aAAa,MAAM;AACnB,gBAAgB,OAAO;AACvB,aAAa;AACb,SAAS;AACT;AACA;AACA;AACA;AACA,QAAQ,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC;AAC7B,QAAQ,MAAM,QAAQ,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;AACnE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,UAAU,CAAC;AACvB,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE;AACvB,YAAY,UAAU,GAAG,EAAE,CAAC,MAAM,CAAC;AACnC,SAAS,MAAM;AACf,YAAY,UAAU,GAAGzB,eAA2B,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;AAChF,SAAS;AACT;AACA;AACA;AACA;AACA,QAAQ,MAAM,KAAK,GAAG,IAAID,WAAuB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AAC7E;AACA;AACA;AACA;AACA,QAAQ,IAAI,EAAE,GAAG,UAAU,CAAC,SAAS,CAAC;AACtC,QAAQ,IAAI,gBAAgB,GAAGC,eAA2B,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAChF;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,KAAK,CAAC,QAAQ,IAAImB,UAAQ,CAAC,MAAM,IAAI,KAAK,CAAC,SAAS,IAAIC,WAAS,CAAC,IAAI,EAAE;AACpF;AACA;AACA,YAAY,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AAC/E,YAAY,IAAI,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AAChF,YAAY,IAAI,GAAG,GAAG,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1D;AACA;AACA,YAAY,IAAI,UAAU,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI;AACrE,gBAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACtC,aAAa,CAAC,CAAC,CAAC;AAChB;AACA,YAAY,IAAI,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AACjE;AACA,YAAY,IAAI,SAAS,GAAG,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AAClE;AACA,YAAY,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;AACnC;AACA;AACA,YAAY,IAAI,SAAS,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI;AAC9D,gBAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;AAC7D,aAAa,CAAC,CAAC;AACf,YAAY,IAAI,UAAU,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI;AAChE,gBAAgB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;AAC7D,aAAa,CAAC,CAAC;AACf;AACA,YAAY,IAAI,SAAS,GAAG,kBAAkB,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;AAC7E,YAAY,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AACjD,YAAY,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AAClD;AACA;AACA,YAAY,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACzF;AACA;AACA,YAAY,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACtC,SAAS;AACT;AACA;AACA;AACA;AACA;AACA,QAAQ,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE;AAC7B,YAAY,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAC/C,SAAS,MAAM,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE;AACpC,YAAY,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAC/C,SAAS;AACT,QAAQ,IAAI,IAAI,EAAE;AAClB,YAAY,IAAI,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE;AACvC,gBAAgB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;AACzD,aAAa,MAAM,IAAI,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE;AAC9C,gBAAgB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;AACzD,aAAa;AACb,SAAS;AACT,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAI,mBAAmB,GAAG,SAAS,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE;AACjE,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;AAC9B,YAAY,OAAO;AACnB,SAAS;AACT;AACA;AACA;AACA;AACA,QAAQ,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE,CAAC;AAC/B,QAAQ,MAAM,QAAQ,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;AACnE;AACA,QAAQ,MAAM,KAAK,GAAG,EAAE,CAAC;AACzB,QAAQ,aAAa,CAAC,OAAO,CAAC,UAAU,IAAI,EAAE;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;AAC/D;AACA,YAAY,IAAI,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACxC,YAAY,IAAI,YAAY,GAAGpB,eAA2B,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAChF,YAAY,IAAI,SAAS,GAAG,YAAY,CAAC,QAAQ,CAAC;AAClD;AACA;AACA;AACA;AACA;AACA,YAAY,IAAI,OAAO,GAAG,CAAC,GAAG,GAAG,SAAS,IAAI,GAAG,GAAG,CAAC,GAAG,IAAI,SAAS,IAAI,GAAG,GAAG,GAAG,CAAC;AACnF;AACA,YAAY,IAAI,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,CAAC;AAC1D;AACA,YAAY,IAAI,OAAO,GAAG,CAAC,QAAQ,IAAI,GAAG,EAAE,CAAC,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;AAChE;AACA,YAAY,IAAI,WAAW,GAAGsB,WAAS,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAC7E;AACA;AACA;AACA;AACA,YAAY,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;AAC/B,YAAY,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACjD;AACA;AACA,YAAY,IAAI,WAAW,IAAID,QAAM,CAAC,UAAU,EAAE;AAClD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,IAAI,YAAY,GAAGlB,QAAoB,CAAC,YAAY,CAAC,CAAC;AACtE,gBAAgB,IAAI,CAAC,YAAY,EAAE;AACnC;AACA,oBAAoB,WAAW,GAAGkB,QAAM,CAAC,KAAK,CAAC;AAC/C,iBAAiB,MAAM;AACvB;AACA,oBAAoB,IAAI,SAAS,GAAGE,kBAA8B,CAAC,YAAY,CAAC,CAAC;AACjF,oBAAoB,WAAW,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,IAAIF,QAAM,CAAC,KAAK,GAAGA,QAAM,CAAC,IAAI,CAAC;AAC7F,iBAAiB;AACjB,aAAa;AACb,YAAY,IAAI,WAAW,IAAIA,QAAM,CAAC,IAAI,EAAE;AAC5C,gBAAgB,WAAW,GAAGA,QAAM,CAAC,KAAK,CAAC;AAC3C,aAAa;AACb,YAAY,IAAI,WAAW,IAAIA,QAAM,CAAC,KAAK,IAAI,OAAO,EAAE;AACxD,gBAAgB,OAAO;AACvB,aAAa;AACb,YAAY,IAAI,WAAW,IAAIA,QAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE;AACxD,gBAAgB,OAAO;AACvB,aAAa;AACb;AACA;AACA,YAAY,IAAI,WAAW,IAAIA,QAAM,CAAC,KAAK,EAAE;AAC7C;AACA,gBAAgB,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;AAClE,gBAAgB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC5C,aAAa,MAAM,IAAI,WAAW,IAAIA,QAAM,CAAC,IAAI,EAAE;AACnD;AACA,gBAAgB,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAClE,gBAAgB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC1C,aAAa;AACb,SAAS,EAAE,IAAI,CAAC,CAAC;AACjB;AACA;AACA;AACA;AACA,QAAQ,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAClC,KAAK;AACL;;AC7YA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA,MAAM,aAAa,CAAC;AACpB;AACA,IAAI,WAAW,CAAC,EAAE,EAAE,IAAI,EAAE;AAC1B,QAAQ,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;AACrB,QAAQ,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;AACzB,QAAQ,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;AACtC,QAAQ,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACvD,QAAQ,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACvD,KAAK;AACL;AACA,IAAI,UAAU,CAAC,GAAG,EAAE;AACpB,QAAQ,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,WAAW,CAAC;AACzE,QAAQ,IAAI,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC5C,QAAQ,OAAO,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;AAC7C,KAAK;AACL;AACA,IAAI,QAAQ,CAAC,KAAK,EAAE;AACpB,QAAQ,IAAI,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/C,QAAQ,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;AACtD,QAAQ,IAAI,IAAI,EAAE;AAClB;AACA,YAAY,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACxD,SAAS,MAAM;AACf;AACA,YAAY,IAAI,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AACrD,YAAY,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACxD,YAAY,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACzC,YAAY,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AACxC,SAAS;AACT,KAAK;AACL;AACA,IAAI,QAAQ,CAAC,KAAK,EAAE;AACpB;AACA,QAAQ,IAAI,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/C,QAAQ,IAAI,IAAI,GAAG,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;AAChD,QAAQ,IAAI,IAAI,EAAE;AAClB,YAAY,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AAC9C,SAAS;AACT,KAAK;AACL;;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAM,cAAc,CAAC;AACrB;AACA,IAAI,OAAO,gBAAgB,CAAC,QAAQ,EAAE,KAAK,EAAE;AAC7C,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;AAChC;AACA,QAAQ,IAAI,MAAM,GAAG,QAAQ,GAAG,GAAG,CAAC;AACpC,QAAQ,IAAI,MAAM,GAAG,IAAI,GAAG,GAAG,CAAC;AAChC,QAAQ,OAAO,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;AACnC,KAAK;AACL;AACA,IAAI,OAAO,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE;AAC5C,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;AAChC;AACA,QAAQ,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACvC,QAAQ,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACzC,QAAQ,IAAI,MAAM,GAAG,IAAI,GAAG,GAAG,CAAC;AAChC,QAAQ,IAAI,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;AAC1C,QAAQ,OAAO,GAAG,GAAG,MAAM,CAAC;AAC5B,KAAK;AACL;AACA,IAAI,WAAW,CAAC,CAAC,YAAY,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,EAAE;AAC1D,QAAQ,IAAI,CAAC,GAAG,GAAG,YAAY,CAAC;AAChC,QAAQ,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;AACxC,QAAQ,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;AAC5C,QAAQ,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;AAC3B,QAAQ,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;AAChC,QAAQ,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AACtD,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;AACtC,QAAQ,IAAI,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,IAAI,QAAQ,EAAE;AAClD,YAAY,MAAM,IAAI,KAAK,CAAC,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AAC1D,SAAS;AACT;AACA;AACA,QAAQ,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW;AACjE;AACA;AACA,YAAY,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;AACpC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACtB;AACA;AACA,QAAQ,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY;AACnE;AACA,YAAY,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;AACrC;AACA,YAAY,IAAI,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;AAC9D,YAAY,IAAI,QAAQ,GAAG,cAAc,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AACjF,YAAY,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;AAClD,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACtB;AACA;AACA,QAAQ,IAAI,IAAI,CAAC,QAAQ,EAAE;AAC3B,YAAY,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAChE,SAAS;AACT,KAAK;AACL;AACA,IAAI,OAAO,GAAG;AACd,QAAQ,IAAI,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AACpC;AACA,QAAQ,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;AAC/B,YAAY,IAAI,OAAO,GAAG,cAAc,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AACjF,YAAY,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE;AACrC;AACA,gBAAgB,IAAI,OAAO,GAAG,GAAG,IAAI,KAAK,GAAG,OAAO,EAAE;AACtD;AACA,oBAAoB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;AAC/C,oBAAoB,OAAO;AAC3B,iBAAiB;AACjB,aAAa,MAAM;AACnB,gBAAgB,OAAO,GAAG,CAAC,OAAO,GAAG,GAAG,IAAI,GAAG,GAAG,OAAO,CAAC;AAC1D,gBAAgB,OAAO,GAAG,CAAC,KAAK,GAAG,OAAO,IAAI,KAAK,EAAE,OAAO,CAAC;AAC7D,aAAa;AACb,YAAY,IAAI,CAAC,cAAc,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACrD,YAAY,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE;AACrC,gBAAgB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;AAC3C,aAAa;AACb,SAAS;AACT,KAAK;AACL;;AC1DA;AACO,SAAS,SAAS,GAAG;AAC5B;AACA,IAAI,IAAI,OAAO,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,OAAO,CAAC,CAAC,CAAC;AACvE,IAAI,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;AAC/D;AACA,IAAI,IAAI,OAAO,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,YAAY,CAAC,CAAC,CAAC;AAC5E;AACA,IAAI,IAAI,QAAQ,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;AACjG,IAAI,IAAI,OAAO,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AAC3D,IAAI,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE;AAC7B,QAAQ,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;AACxD,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE;AACpC,QAAQ,OAAO,IAAI,kBAAkB,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC/D,KAAK,MAAM;AACX,QAAQ,OAAO,IAAI,qBAAqB,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9E,KAAK;AACL,CACA;AACA;AACA,kBAAkB,CAAC,SAAS,CAAC,KAAK,GAAG,YAAY;AACjD,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC9B,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;AAC1C,IAAI,OAAO,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9B,CAAC,CAAC;AACF;AACA;AACA,qBAAqB,CAAC,SAAS,CAAC,KAAK,GAAG,YAAY;AACpD,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAC9B,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;AAC1C,IAAI,OAAO,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9B,CAAC,CAAC;AAKF;AACY,MAAC,OAAO,GAAG;;;;"}
\ No newline at end of file
diff --git a/docs/lib/timingsrc-require-min-v1.js b/docs/lib/timingsrc-require-min-v1.js
index a0ca686..d6e5fed 100644
--- a/docs/lib/timingsrc-require-min-v1.js
+++ b/docs/lib/timingsrc-require-min-v1.js
@@ -18,5017 +18,6 @@
along with Timingsrc. If not, see .
*/
-
-
-
-define('util/eventutils',[],function () {
-
- 'use strict';
-
- /*
- UTILITY
- */
-
- // unique ID generator
- var id = (function(length) {
- var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- return function (len) { // key length
- len = len || length;
- var text = "";
- for( var i=0; i < len; i++ )
- text += possible.charAt(Math.floor(Math.random() * possible.length));
- return text;
- };
- })(10); // default key length
-
-
- Array.prototype.concatAll = function() {
- var results = [];
- this.forEach(function(subArray) {
- results.push.apply(results, subArray);
- }, this);
- return results;
- };
- Array.prototype.concatMap = function(projectionFunctionThatReturnsArray, ctx) {
- return this.
- map(function(item) {
- return projectionFunctionThatReturnsArray.call(ctx, item);
- }).
- // apply the concatAll function to flatten the two-dimensional array
- concatAll();
- };
-
-
- /*
- HANDLER MAP
- */
-
-
- // handler bookkeeping for one event type
- var HandlerMap = function () {
- this._id = 0;
- this._map = {}; // ID -> {handler:, ctx:, pending:, count: }
- };
-
- HandlerMap.prototype._newID = function () {
- this._id += 1;
- return this._id;
- };
-
- HandlerMap.prototype._getID = function (handler) {
- var item;
- var res = Object.keys(this._map).filter(function (id) {
- item = this._map[id];
- return (item.handler === handler);
- }, this);
- return (res.length > 0) ? res[0] : -1;
- };
-
- HandlerMap.prototype.getItem = function (id) {
- return this._map[id];
- };
-
- HandlerMap.prototype.register = function (handler, ctx) {
- var ID = this._getID(handler);
- if (ID > -1) {
- throw new Error("handler already registered");
- }
- ID = this._newID();
- this._map[ID] = {
- ID : ID,
- handler: handler,
- ctx : ctx,
- count : 0,
- pending : false
- };
- return ID;
- };
-
- HandlerMap.prototype.unregister = function (handler) {
- var ID = this._getID(handler);
- if (ID !== -1) {
- delete this._map[ID];
- }
- };
-
- HandlerMap.prototype.getItems = function () {
- return Object.keys(this._map).map(function (id) {
- return this.getItem(id);
- }, this);
- };
-
-
-
-
-
- /*
-
- EVENTIFY
-
- Eventify brings eventing capabilities to any object.
-
- In particular, eventify supports the initial-event pattern.
- Opt-in for initial events per event type.
-
- A protected event type "events" provides a callback with a batch of events in a list,
- instead as individual callbacks.
-
- if initial-events are used
- eventified object must implement this._makeInitEvents(type)
- - expect [{type:type, e:eArg}]
-
- */
-
- var eventify = function (object, _prototype) {
-
- /*
- Default event name "events" will fire a list of events
- */
- object._ID = id(4);
- object._callbacks = {}; // type -> HandlerMap
- // special event "events"
- object._callbacks["events"] = new HandlerMap();
- object._callbacks["events"]._options = {init:true};
-
-
-
-
- /*
- DEFINE EVENT TYPE
- type is event type (string)
- {init:true} specifies init-event semantics for this event type
- */
- _prototype.eventifyDefineEvent = function (type, options) {
- if (type === "events") throw new Error("Illegal event type : 'events' is protected");
- options = options || {};
- options.init = (options.init === undefined) ? false : options.init;
- this._callbacks[type] = new HandlerMap();
- this._callbacks[type]._options = options;
- };
-
- /*
- MAKE INIT EVENTS
-
- Produce init events for a specific callback handler - right after on("type", callback)
- Return list consistent with input .eventifyTriggerEvents
- [{type: "type", e: e}]
- If [] list is returned there will be no init events.
-
- Protected event type 'events' is handled automatically
-
- Implement
- .eventifyMakeInitEvents(type)
-
- */
- _prototype._eventifyMakeInitEvents = function (type) {
- var makeInitEvents = this.eventifyMakeInitEvents || function (type) {return [];};
- var typeList;
- if (type !== "events") {
- typeList = [type];
- } else {
- // type === 'events'
- typeList = Object.keys(this._callbacks).filter(function (key) {
- return (key !== "events" && this._callbacks[key]._options.init === true);
- }, this);
- }
- return typeList.concatMap(function (type) {
- return makeInitEvents.call(this, type);
- }, this);
- };
-
- /*
- EVENT FORMATTER
-
- Format the structure of EventArgs.
- Parameter e is the object that was supplied to triggerEvent
- Parameter type is the event type that was supplied to triggerEvent
- Default is to use 'e' given in triggerEvent unchanged.
-
- Note, for protected event type 'events', eventFormatter is also applied recursively
- within the list of events
- ex: { type: "events", e: [{type:"change",e:e1},])
-
- Implement
- .eventifyEventFormatter(type, e) to override default
- */
- _prototype._eventifyEventFormatter = function (type, e) {
- var eventFormatter = this.eventifyEventFormatter || function (type, e) {return e;};
- if (type === "events") {
- // e is really eList - run eventformatter on every item in list
- e = e.map(function(item){
- return eventFormatter.call(this, item.type, item.e);
- });
- }
- return eventFormatter(type,e);
- };
-
- /*
- CALLBACK FORMATTER
-
- Format which parameters are included in event callback.
- Returns a list of parameters.
- Default is to exclude type and eInfo and just deliver the event supplied to triggerEvent
-
- Implement
- .eventifyCallbackForamtter(type, e, eInfo) to override default
- */
- _prototype._eventifyCallbackFormatter = function (type, e, eInfo) {
- var callbackFormatter = this.eventifyCallbackFormatter || function (type, e, eInfo) { return [e];};
- return callbackFormatter.call(this, type, e, eInfo);
- };
-
- /*
- TRIGGER EVENTS
-
- Parameter is a list of objects where 'type' specifies the event type and 'e' specifies the event object.
- 'e' may be undefined
- - [{type: "type", e: e}]
- */
- _prototype.eventifyTriggerEvents = function (eItemList) {
- // check list for illegal events
- eItemList.forEach(function (eItem) {
- if (eItem.type === undefined) throw new Error("Illegal event type; undefined");
- if (eItem.type === "events") throw new Error("Illegal event type; triggering of events on protocted event type 'events'" );
- }, this);
- if (eItemList.length === 0) return;
- this._eventifyTriggerProtectedEvents(eItemList);
- this._eventifyTriggerRegularEvents(eItemList);
- return this;
- };
-
- /*
- TRIGGER EVENT
- Shorthand for triggering a single event
- */
- _prototype.eventifyTriggerEvent = function (type, e) {
- return this.eventifyTriggerEvents([{type:type, e:e}]);
- };
-
- /*
- Internal method for triggering events
- - distinguish "events" from other event names
- */
- _prototype._eventifyTriggerProtectedEvents = function (eItemList, handlerID) {
- // trigger event list on protected event type "events"
- this._eventifyTriggerEvent("events", {type:"events", e:eItemList}, handlerID);
- };
-
- _prototype._eventifyTriggerRegularEvents = function (eItemList, handlerID) {
- // trigger events on individual event types
- eItemList.forEach(function (eItem) {
- this._eventifyTriggerEvent(eItem.type, eItem, handlerID);
- }, this);
- };
-
- /*
- Internal method for triggering a single event.
- - if handler specificed - trigger only on given handler (for internal use only)
- - awareness of init-events
- */
- _prototype._eventifyTriggerEvent = function (type, eItem, handlerID) {
- var argList, e, eInfo = {};
- if (!this._callbacks.hasOwnProperty(type)) throw new Error("Unsupported event type " + type);
- var handlerMap = this._callbacks[type];
- var init = handlerMap._options.init;
- handlerMap.getItems().forEach(function (handlerItem) {
- if (handlerID === undefined) {
- // all handlers to be invoked, except those with initial pending
- if (handlerItem.pending) {
- return false;
- }
- } else {
- // only given handler to be called - ensuring that it is not removed
- if (handlerItem.ID === handlerID) {
- eInfo.init = true;
- handlerItem.pending = false;
- } else {
- return false;
- }
- }
- // eInfo
- if (init) {
- eInfo.init = (handlerItem.ID === handlerID) ? true : false;
- }
- eInfo.count = handlerItem.count;
- eInfo.src = this;
- // formatters
- e = this._eventifyEventFormatter(eItem.type, eItem.e);
- argList = this._eventifyCallbackFormatter(type, e, eInfo);
- try {
- handlerItem.handler.apply(handlerItem.ctx, argList);
- handlerItem.count += 1;
- return true;
- } catch (err) {
- console.log("Error in " + type + ": " + handlerItem.handler + " " + handlerItem.ctx + ": ", err);
- }
- }, this);
- return false;
- };
-
- /*
- ON
-
- register callback on event type. Available directly on object
- optionally supply context object (this) used on callback invokation.
- */
- _prototype.on = function (type, handler, ctx) {
- if (!handler || typeof handler !== "function") throw new Error("Illegal handler");
- if (!this._callbacks.hasOwnProperty(type)) throw new Error("Unsupported event type " + type);
- var handlerMap = this._callbacks[type];
- // register handler
- ctx = ctx || this;
- var handlerID = handlerMap.register(handler, ctx);
- // do initial callback - if supported by source
- if (handlerMap._options.init) {
- // flag handler
- var handlerItem = handlerMap.getItem(handlerID);
- handlerItem.pending = true;
- var self = this;
- setTimeout(function () {
- var eItemList = self._eventifyMakeInitEvents(type);
- if (eItemList.length > 0) {
- if (type === "events") {
- self._eventifyTriggerProtectedEvents(eItemList, handlerID);
- } else {
- self._eventifyTriggerRegularEvents(eItemList, handlerID);
- }
- } else {
- // initial callback is noop
- handlerItem.pending = false;
- }
- }, 0);
- }
- return this;
- };
-
- /*
- OFF
- Available directly on object
- Un-register a handler from a specfic event type
- */
-
- _prototype.off = function (type, handler) {
- if (this._callbacks[type] !== undefined) {
- var handlerMap = this._callbacks[type];
- handlerMap.unregister(handler);
-
- }
- return this;
- };
-
- // Eventify returns eventified object
- return object;
- };
-
- // module api
- return {
- eventify:eventify
- };
-});
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-define('util/motionutils',[],function () {
-
- 'use strict';
-
- // Calculate a snapshot of the motion vector,
- // given initials conditions vector: [p0,v0,a0,t0] and t (absolute - not relative to t0)
- // if t is undefined - t is set to now
- var calculateVector = function(vector, tsSec) {
- if (tsSec === undefined) {
- throw new Error ("no ts provided for calculateVector");
- }
- var deltaSec = tsSec - vector.timestamp;
- return {
- position : vector.position + vector.velocity*deltaSec + 0.5*vector.acceleration*deltaSec*deltaSec,
- velocity : vector.velocity + vector.acceleration*deltaSec,
- acceleration : vector.acceleration,
- timestamp : tsSec
- };
- };
-
-
- // RANGE STATE is used for managing/detecting range violations.
- var RangeState = Object.freeze({
- INIT : "init",
- INSIDE: "inside",
- OUTSIDE_LOW: "outsidelow",
- OUTSIDE_HIGH: "outsidehigh"
- });
-
- /*
- A snapshot vector is checked with respect to range,
- calclulates correct RangeState (i.e. INSIDE|OUTSIDE)
- */
- var getCorrectRangeState = function (vector, range) {
- var p = vector.position,
- v = vector.velocity,
- a = vector.acceleration;
- if (p > range[1]) return RangeState.OUTSIDE_HIGH;
- if (p < range[0]) return RangeState.OUTSIDE_LOW;
- // corner cases
- if (p === range[1]) {
- if (v > 0.0) return RangeState.OUTSIDE_HIGH;
- if (v === 0.0 && a > 0.0) return RangeState.OUTSIDE_HIGH;
- } else if (p === range[0]) {
- if (v < 0.0) return RangeState.OUTSIDE_LOW;
- if (v == 0.0 && a < 0.0) return RangeState.OUTSIDE_HIGH;
- }
- return RangeState.INSIDE;
- };
-
- /*
-
- A snapshot vector is checked with respect to range.
- Returns vector corrected for range violations, or input vector unchanged.
- */
- var checkRange = function (vector, range) {
- var state = getCorrectRangeState(vector, range);
- if (state !== RangeState.INSIDE) {
- // protect from range violation
- vector.velocity = 0.0;
- vector.acceleration = 0.0;
- if (state === RangeState.OUTSIDE_HIGH) {
- vector.position = range[1];
- } else vector.position = range[0];
- }
- return vector;
- };
-
-
-
- // Compare values
- var cmp = function (a, b) {
- if (a > b) {return 1;}
- if (a === b) {return 0;}
- if (a < b) {return -1;}
- };
-
- // Calculate direction of movement at time t.
- // 1 : forwards, -1 : backwards: 0, no movement
- var calculateDirection = function (vector, tsSec) {
- /*
- Given initial vector calculate direction of motion at time t
- (Result is valid only if (t > vector[T]))
- Return Forwards:1, Backwards -1 or No-direction (i.e. no-motion) 0.
- If t is undefined - t is assumed to be now.
- */
- var freshVector = calculateVector(vector, tsSec);
- // check velocity
- var direction = cmp(freshVector.velocity, 0.0);
- if (direction === 0) {
- // check acceleration
- direction = cmp(vector.acceleration, 0.0);
- }
- return direction;
- };
-
- // Given motion determined from p,v,a,t.
- // Determine if equation p(t) = p + vt + 0.5at^2 = x
- // has solutions for some real number t.
- var hasRealSolution = function (p,v,a,x) {
- if ((Math.pow(v,2) - 2*a*(p-x)) >= 0.0) return true;
- else return false;
- };
-
- // Given motion determined from p,v,a,t.
- // Determine if equation p(t) = p + vt + 0.5at^2 = x
- // has solutions for some real number t.
- // Calculate and return real solutions, in ascending order.
- var calculateRealSolutions = function (p,v,a,x) {
- // Constant Position
- if (a === 0.0 && v === 0.0) {
- if (p != x) return [];
- else return [0.0];
- }
- // Constant non-zero Velocity
- if (a === 0.0) return [(x-p)/v];
- // Constant Acceleration
- if (hasRealSolution(p,v,a,x) === false) return [];
- // Exactly one solution
- var discriminant = v*v - 2*a*(p-x);
- if (discriminant === 0.0) {
- return [-v/a];
- }
- var sqrt = Math.sqrt(Math.pow(v,2) - 2*a*(p-x));
- var d1 = (-v + sqrt)/a;
- var d2 = (-v - sqrt)/a;
- return [Math.min(d1,d2),Math.max(d1,d2)];
- };
-
- // Given motion determined from p,v,a,t.
- // Determine if equation p(t) = p + vt + 0.5at^2 = x
- // has solutions for some real number t.
- // Calculate and return positive real solutions, in ascending order.
- var calculatePositiveRealSolutions = function (p,v,a,x) {
- var res = calculateRealSolutions(p,v,a,x);
- if (res.length === 0) return [];
- else if (res.length == 1) {
- if (res[0] > 0.0) {
- return [res[0]];
- }
- else return [];
- }
- else if (res.length == 2) {
- if (res[1] < 0.0) return [];
- if (res[0] > 0.0) return [res[0], res[1]];
- if (res[1] > 0.0) return [res[1]];
- return [];
- }
- else return [];
- };
-
- // Given motion determined from p,v,a,t.
- // Determine if equation p(t) = p + vt + 0.5at^2 = x
- // has solutions for some real number t.
- // Calculate and return the least positive real solution.
- var calculateMinPositiveRealSolution = function (vector,x) {
- var p = vector.position;
- var v = vector.velocity;
- var a = vector.acceleration;
- var res = calculatePositiveRealSolutions(p,v,a,x);
- if (res.length === 0) return null;
- else return res[0];
- };
-
- // Given motion determined from p0,v0,a0
- // (initial conditions or snapshot)
- // Supply two posisions, posBefore < p0 < posAfter.
- // Calculate which of these positions will be reached first,
- // if any, by the movement described by the vector.
- // In addition, calculate when this position will be reached.
- // Result will be expressed as time delta relative to t0,
- // if solution exists,
- // and a flag to indicate Before (false) or After (true)
- // Note t1 == (delta + t0) is only guaranteed to be in the
- // future as long as the function
- // is evaluated at time t0 or immediately after.
- var calculateDelta = function (vector, range) {
- // Time delta to hit posBefore
- var deltaBeforeSec = calculateMinPositiveRealSolution(vector, range[0]);
- // Time delta to hit posAfter
- var deltaAfterSec = calculateMinPositiveRealSolution(vector, range[1]);
- // Pick the appropriate solution
- if (deltaBeforeSec !== null && deltaAfterSec !== null) {
- if (deltaBeforeSec < deltaAfterSec)
- return [deltaBeforeSec, range[0]];
- else
- return [deltaAfterSec, range[1]];
- }
- else if (deltaBeforeSec !== null)
- return [deltaBeforeSec, range[0]];
- else if (deltaAfterSec !== null)
- return [deltaAfterSec, range[1]];
- else return [null,null];
- };
-
-
- /*
- calculate_solutions_in_interval (vector, d, plist)
-
- Find all intersects in time between a motion and a the
- positions given in plist, within a given time-interval d. A
- single position may be intersected at 0,1 or 2 two different
- times during the interval.
-
- - vector = (p0,v0,a0) describes the initial conditions of
- (an ongoing) motion
-
- - relative time interval d is used rather than a tuple of
- absolute values (t_start, t_stop). This essentially means
- that (t_start, t_stop) === (now, now + d). As a consequence,
- the result is independent of vector[T]. So, if the goal is
- to find the intersects of an ongoing motion during the next
- d seconds, be sure to give a fresh vector from msv.query()
- (so that vector[T] actually corresponds to now).
-
-
- - plist is an array of objects with .point property
- returning a floating point. plist represents the points
- where we investigate intersects in time.
-
- The following equation describes how position varies with time
- p(t) = 0.5*a0*t*t + v0*t + p0
-
- We solve this equation with respect to t, for all position
- values given in plist. Only real solutions within the
- considered interval 0<=t<=d are returned. Solutions are
- returned sorted by time, thus in the order intersects will
- occur.
-
- */
- var sortFunc = function (a,b){return a[0]-b[0];};
- var calculateSolutionsInInterval = function(vector, deltaSec, plist) {
- var solutions = [];
- var p0 = vector.position;
- var v0 = vector.velocity;
- var a0 = vector.acceleration;
- for (var i=0; i 0 => p_turning minimum
- // a0 < 0 => p_turning maximum
- if (a0 > 0.0) {
- return [p_turning, Math.max(p0, p1)];
- }
- else {
- return [Math.min(p0,p1), p_turning];
- }
- }
- }
- // no turning point or turning point was not reached
- return [Math.min(p0,p1), Math.max(p0,p1)];
- };
-
-
- // return module object
- return {
- calculateVector : calculateVector,
- calculateDirection : calculateDirection,
- calculateMinPositiveRealSolution : calculateMinPositiveRealSolution,
- calculateDelta : calculateDelta,
- calculateInterval : calculateInterval,
- calculateSolutionsInInterval : calculateSolutionsInInterval,
- getCorrectRangeState : getCorrectRangeState,
- checkRange : checkRange,
- RangeState : RangeState
- };
-});
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-/*
- TimingBase defines base classes for TimingObject and ConverterBase used to implement timing converters.
- It makes use of eventutils for event stuff, including immediate events.
- It makes use of motionutils for timing calculations.
-*/
-
-define('timingobject/timingbase',['util/eventutils', 'util/motionutils'], function (eventutils, motionutils) {
-
- 'use strict';
-
- // Utility inheritance function.
- var inherit = function (Child, Parent) {
- var F = function () {}; // empty object to break prototype chain - hinder child prototype changes to affect parent
- F.prototype = Parent.prototype;
- Child.prototype = new F(); // child gets parents prototypes via F
- Child.uber = Parent.prototype; // reference in parent to superclass
- Child.prototype.constructor = Child; // resetting constructor pointer
- };
-
-
- // TIMING BASE
- /*
- Base class for TimingObject and ConverterBase
-
- essential internal state
- - range, vector
-
- external methods
- query, update
-
- event stuff from eventutils
- on/off "change", "timeupdate"
-
- internal methods for range timeouts
-
- defines internal processing steps
- - preProcess(vector) <- from external timingobject
- - vector = onChange(vector)
- - process(vector) <- from timeout or preProcess
- - process (vector)
- - set internal vector
- - postProcess(vector)
- - renew range timeout
- - postprocess (vector)
- - emit change event and timeupdate event
- - turn periodic timeupdate on or off
-
- individual steps in this structure may be specialized
- by subclasses
- */
-
-
- var TimingBase = function (options) {
- this._version = 3;
- // options
- this._options = options || {};
- // range timeouts off by default
- if (!this._options.hasOwnProperty("timeout")) {
- this._options.timeout = false;
- }
- // cached vector
- this._vector = null;
- // cached range
- this._range = null;
- // timeout support
- this._timeout = null; // timeout for range violation etc.
- this._tid = null; // timeoutid for timeupdate
- // readiness
- this._ready = false;
- // event support
- eventutils.eventify(this, TimingBase.prototype);
- this.eventifyDefineEvent("ready", {init:true}) // define ready event
- this.eventifyDefineEvent("change", {init:true}); // define change event (supporting init-event)
- this.eventifyDefineEvent("timeupdate", {init:true}); // define timeupdate event (supporting init-event)
- };
-
-
- // Accessors
-
- Object.defineProperty(TimingBase.prototype, 'version', {
- get : function () {
- return this._version;
- }
- });
-
- Object.defineProperty(TimingBase.prototype, 'range', {
- get : function () {
- if (this._range === null) return null;
- // copy internal range
- return [this._range[0], this._range[1]];
- }
- });
-
- // Accessor internal vector
- Object.defineProperty(TimingBase.prototype, 'vector', {
- get : function () {
- if (this._vector === null) return null;
- // copy cached vector
- return {
- position : this._vector.position,
- velocity : this._vector.velocity,
- acceleration : this._vector.acceleration,
- timestamp : this._vector.timestamp
- };
- }
- });
-
-
- Object.defineProperty(TimingBase.prototype, 'ready', {
- get : function () {
- return this._ready;
- }
- });
-
- Object.defineProperty(TimingBase.prototype, 'readyPromise', {
- get : function () {
- var self = this;
- return new Promise (function (resolve, reject) {
- if (self._ready) {
- resolve();
- } else {
- var onReady = function () {
- self.off("ready", onReady);
- resolve()
- };
- self.on("ready", onReady);
- }
- });
- }
- });
-
-
- // Shorthand accessors
- Object.defineProperty(TimingBase.prototype, 'pos', {
- get : function () {
- return this.query().position;
- }
- });
-
- Object.defineProperty(TimingBase.prototype, 'vel', {
- get : function () {
- return this.query().velocity;
- }
- });
-
- Object.defineProperty(TimingBase.prototype, 'acc', {
- get : function () {
- return this.query().acceleration;
- }
- });
-
-
-
-
- /*
- overrides how immediate events are constructed
- specific to eventutils
- change event fires immediately if timing object is well
- defined, i.e. query() not null
- no event args are passed (undefined)
- */
- TimingBase.prototype.eventifyMakeInitEvents = function (type) {
- if (type === "change") {
- return (this._ready) ? [{type: type, e: undefined}] : [];
- } else if (type === "timeupdate") {
- return (this._ready) ? [{type:type, e: undefined}] : [];
- } else if (type === "ready") {
- return (this._ready) ? [{type:type, e: undefined}] : [];
- }
- return [];
- };
-
- /*
- Basic query. Insensitive to range violations.
- Must be overrided by subclasses with specified range.
- */
- TimingBase.prototype.query = function () {
- if (this.vector === null) return {position:undefined, velocity:undefined, acceleration:undefined};
- return motionutils.calculateVector(this.vector, this.clock.now());
- };
-
- // to be overridden
- TimingBase.prototype.update = function (vector) {};
-
- /*
- To be overridden
- get range is useful for setting the range internally,
- when the range depends on the range of an external (upstream)
- timing object. Get range is invoked when first change
- event is received from external object, thereby guaranteeing
- that range of external timing object is well defined.
- (see _preProcess)
- return correct range [start, end]
-
- Invoked every time the external object is switched,
- thus is may change.
- */
- TimingBase.prototype._getRange = function () {return null;};
-
-
-
- // CHANGE EVENTS
-
-
- /*
- do not override
- Handle incoming vector, from "change" from external object
- or from an internal timeout.
-
- _onChange is invoked allowing subclasses to specify transformation
- on the incoming vector before processing.
- */
- TimingBase.prototype._preProcess = function (vector) {
- if (this._range === null) {
- this._range = this._getRange();
- }
- var vector = this._onChange(vector);
- this._process(vector);
- };
-
- /*
- to be ovverridden
- specify transformation
- on the incoming vector before processing.
- useful for Converters that do mathematical transformations,
- or as a way to enforse range restrictions.
- invoming vectors from external change events or internal
- timeout events
-
- returning null stops further processing, exept renewtimeout
- */
- TimingBase.prototype._onChange = function (vector) {
- return vector;
- };
-
- // TIMEOUTS
- // Use range to implement timeouts on range violation
-
- /*
- do not override
- renew timeout is called during evenry processing step
- in order to recalculate timeouts.
- the calculation may be specialized in
- _calculateTimeoutVector
- */
- TimingBase.prototype._renewTimeout = function () {
- if (this._options.timeout === true) {
- this._clearTimeout();
- var vector = this._calculateTimeoutVector();
- if (vector === null) {return;}
- var now = this.clock.now();
- var secDelay = vector.timestamp - now;
- var self = this;
- this._timeout = this.clock.setTimeout(function () {
- self._process(self._onTimeout(vector));
- }, secDelay, {anchor: now, early: 0.005});
- }
- };
-
- /*
- to be overridden
- must be implemented by subclass if range timeouts are required
- calculate a vector that will be delivered to _process().
- the timestamp in the vector determines when it is delivered.
- */
- TimingBase.prototype._calculateTimeoutVector = function () {
- return null;
- };
-
- /*
- do not override
- internal utility function for clearing vector timeout
- */
- TimingBase.prototype._clearTimeout = function () {
- if (this._timeout !== null) {
- this._timeout.cancel();
- this._timeout = null;
- }
- };
-
- /*
- to be overridden
- subclass may implement transformation on timeout vector
- before it is given to process.
- returning null stops further processing, exept renewtimeout
- */
- TimingBase.prototype._onTimeout = function (vector) {
- return vector;
- };
-
- // PROCESS
- /*
- do not override
- Core processing step after change event or timeout
- assignes the internal vector
- */
- TimingBase.prototype._process = function (vector) {
- if (vector !== null) {
- var old_vector = this._vector;
- // update internal vector
- this._vector = vector;
- // trigger events
- if (old_vector === null) {
- this._ready = true;
- this.eventifyTriggerEvent("ready");
- }
- this._postProcess(this.vector);
- }
- // renew timeout
- this._renewTimeout();
- };
-
- /*
- may be overridden
- process a new vector applied in order to trigger events
- overriding this is only necessary if external change events
- need to be suppressed,
- */
- TimingBase.prototype._postProcess = function (vector) {
- // trigger change events
- this.eventifyTriggerEvent("change");
- // trigger timeupdate events
- this.eventifyTriggerEvent("timeupdate");
- var moving = vector.velocity !== 0.0 || vector.acceleration !== 0.0;
- if (moving && this._tid === null) {
- var self = this;
- this._tid = setInterval(function () {
- self.eventifyTriggerEvent("timeupdate");
- }, 200);
- } else if (!moving && this._tid !== null) {
- clearTimeout(this._tid);
- this._tid = null;
- }
- };
-
-
- // CONVERTER BASE
-
- /*
- ConverterBase extends TimingBase to provide a
- base class for chainable Converters/emulators of timing objects
- ConverterBase conceptually add the notion of a timing source,
- a pointer to a timing object up the chain. Change events
- may be received from the timing object, and update requests
- are forwarded in the opposite direction.
- */
-
-
- var ConverterBase = function (timingObject, options) {
- TimingBase.call(this, options);
- // timing source
- this._timingsrc = null;
-
- /*
- store a wrapper function on the instance used as a callback handler from timingsrc
- (if this was a prototype function - it would be shared by multiple objects thus
- prohibiting them from subscribing to the same timingsrc)
- */
- var self = this;
- this._internalOnChange = function () {
- var vector = self.timingsrc.vector;
- self._preProcess(vector);
- };
-
- // set timing source
- this.timingsrc = timingObject;
- };
- inherit(ConverterBase, TimingBase);
-
-
- // Accessor internal clock
- Object.defineProperty(ConverterBase.prototype, 'clock', {
- get : function () { return this.timingsrc.clock; }
- });
-
- /*
- Accessor for timingsrc.
- Supports dynamic switching of timing source by assignment.
- */
- Object.defineProperty(ConverterBase.prototype, 'timingsrc', {
- get : function () {return this._timingsrc;},
- set : function (timingObject) {
- if (this._timingsrc) {
- this._timingsrc.off("change", this._internalOnChange, this);
- }
- // reset internal state
- this._range = null;
- this._vector = null;
- this._clearTimeout();
- clearTimeout(this._tid);
- this._timingsrc = timingObject;
- this._timingsrc.on("change", this._internalOnChange, this);
- }
- });
-
- /*
- to be overridden
- default forwards update request to timingsrc unchanged.
- */
- ConverterBase.prototype.update = function (vector) {
- return this.timingsrc.update(vector);
- };
-
- /*
- to be overridden
- by default the Converter adopts the range of timingsrc
- */
- ConverterBase.prototype._getRange = function () {
- return this.timingsrc.range;
- };
-
- // module
- return {
- TimingBase : TimingBase,
- ConverterBase : ConverterBase,
- inherit: inherit,
- motionutils : motionutils
- };
-});
-
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-/*
- SKEW CONVERTER
-
- Skewing the timeline by 2 means that the timeline position 0 of the timingsrc becomes position 2 of Converter.
-
-*/
-
-define('timingobject/skewconverter',['./timingbase'], function (timingbase) {
-
- 'use strict';
-
- var ConverterBase = timingbase.ConverterBase;
- var inherit = timingbase.inherit;
-
- var SkewConverter = function (timingObject, skew) {
- this._skew = skew;
- ConverterBase.call(this, timingObject);
- };
- inherit(SkewConverter, ConverterBase);
-
- // overrides
- SkewConverter.prototype._getRange = function () {
- var range = this.timingsrc.range;
- range[0] = (range[0] === -Infinity) ? range[0] : range[0] + this._skew;
- range[1] = (range[1] === Infinity) ? range[1] : range[1] + this._skew;
- return range;
- };
-
- // overrides
- SkewConverter.prototype._onChange = function (vector) {
- vector.position += this._skew;
- return vector;
- };
-
- SkewConverter.prototype.update = function (vector) {
- if (vector.position !== undefined && vector.position !== null) {
- vector.position = vector.position - this._skew;
- }
- return this.timingsrc.update(vector);
- };
-
-
- Object.defineProperty(SkewConverter.prototype, 'skew', {
- get : function () {
- return this._skew;
- }
- });
-
- SkewConverter.prototype.setSkew = function (skew) {
- this._skew = skew;
- // pick up vector from timingsrc
- var src_vector = this.timingsrc.vector;
- // use this vector to emulate new event from timingsrc
- this._preProcess(src_vector);
- };
-
- return SkewConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-/*
- DELAY CONVERTER
-
- Delay Converter introduces a positive time delay on a source timing object.
-
- Generally - if the source timing object has some value at time t,
- then the delayConverter will provide the same value at time t + delay.
-
- Since the delay Converter is effectively replaying past events after the fact,
- it is not LIVE and not open to interactivity (i.e. update)
-
-*/
-
-
-define('timingobject/delayconverter',['./timingbase'], function (timingbase) {
-
- 'use strict';
-
- var ConverterBase = timingbase.ConverterBase;
- var inherit = timingbase.inherit;
-
- var DelayConverter = function (timingObject, delay) {
- if (delay < 0) {throw new Error ("negative delay not supported");}
- if (delay === 0) {throw new Error ("zero delay makes delayconverter pointless");}
- ConverterBase.call(this, timingObject);
- // fixed delay
- this._delay = delay;
- };
- inherit(DelayConverter, ConverterBase);
-
- // overrides
- DelayConverter.prototype._onChange = function (vector) {
- /*
- Vector's timestamp always time-shifted (back-dated) by delay
-
- Normal operation is to delay every incoming vector update.
- This implies returning null to abort further processing at this time,
- and instead trigger a later continuation.
-
- However, delay is calculated based on the timestamp of the vector (age), not when the vector is
- processed in this method. So, for small small delays the age of the vector could already be
- greater than delay, indicating that the vector is immediately valid and do not require delayed processing.
-
- This is particularly true for the first vector, which may be old.
-
- So we generally check the age to figure out whether to apply the vector immediately or to delay it.
- */
-
- // age of incoming vector
- var age = this.clock.now() - vector.timestamp;
-
- // time-shift vector timestamp
- vector.timestamp += this._delay;
-
- if (age < this._delay) {
- // apply vector later - abort processing now
- var self = this;
- var delayMillis = (this._delay - age) * 1000;
- setTimeout(function () {
- self._process(vector);
- }, delayMillis);
- return null;
- }
- // apply vector immediately - continue processing
- return vector;
- };
-
- DelayConverter.prototype.update = function (vector) {
- // Updates are prohibited on delayed timingobjects
- throw new Error ("update is not legal on delayed (non-live) timingobject");
- };
-
- return DelayConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-/*
- SCALE CONVERTER
-
- Scaling by a factor 2 means that values of the timing object (position, velocity and acceleration) are multiplied by two.
- For example, if the timing object represents a media offset in seconds, scaling it to milliseconds implies a scaling factor of 1000.
-
-*/
-
-
-define('timingobject/scaleconverter',['./timingbase'], function (timingbase) {
-
- 'use strict';
-
- var ConverterBase = timingbase.ConverterBase;
- var inherit = timingbase.inherit;
-
- var ScaleConverter = function (timingObject, factor) {
- this._factor = factor;
- ConverterBase.call(this, timingObject);
- };
- inherit(ScaleConverter, ConverterBase);
-
- // overrides
- ScaleConverter.prototype._getRange = function () {
- var range = this.timingsrc.range;
- return [range[0]*this._factor, range[1]*this._factor];
- };
-
- // overrides
- ScaleConverter.prototype._onChange = function (vector) {
- vector.position = vector.position * this._factor;
- vector.velocity = vector.velocity * this._factor;
- vector.acceleration = vector.acceleration * this._factor;
- return vector;
- };
-
- ScaleConverter.prototype.update = function (vector) {
- if (vector.position !== undefined && vector.position !== null) vector.position = vector.position / this._factor;
- if (vector.velocity !== undefined && vector.velocity !== null) vector.velocity = vector.velocity / this._factor;
- if (vector.acceleration !== undefined && vector.acceleration !== null) vector.acceleration = vector.acceleration / this._factor;
- return this.timingsrc.update(vector);
- };
-
- return ScaleConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-/*
- LOOP CONVERTER
-
- This is a modulo type transformation where the converter will be looping within
- a given range. Potentially one could create an associated timing object keeping track of the
- loop number.
-*/
-
-
-define('timingobject/loopconverter',['./timingbase'], function (timingbase) {
-
- 'use strict';
-
- var motionutils = timingbase.motionutils;
- var ConverterBase = timingbase.ConverterBase;
- var inherit = timingbase.inherit;
-
- /*
- Coordinate system based on counting segments
- skew + n*length + offset === x
- skew : coordinate system is shifted by skew, so that segment 0 starts at offset.
- n : segment counter
- length : segment length
- offset : offset of value x into the segment where it lies
- x: float point value
- */
- var SegmentCoords = function (skew, length) {
- this.skew = skew;
- this.length = length;
- };
-
- /*
- Static method
- ovverride modulo to behave better for negative numbers
- */
- SegmentCoords.mod = function (n, m) {
- return ((n % m) + m) % m;
- };
-
- // get point representation from float
- SegmentCoords.prototype.getPoint = function (x) {
- return {
- n : Math.floor((x-this.skew)/this.length),
- offset : SegmentCoords.mod(x-this.skew,this.length)
- };
- };
-
- // get float value from point representation
- SegmentCoords.prototype.getFloat = function (p) {
- return this.skew + (p.n * this.length) + p.offset;
- };
-
- // transform float x into segment defined by other float y
- // if y isnt specified - transform into segment [skew, skew + length]
- SegmentCoords.prototype.transformFloat = function (x, y) {
- y = (y === undefined) ? this.skew : y;
- var xPoint = this.getPoint(x);
- var yPoint = this.getPoint(y);
- return this.getFloat({n:yPoint.n, offset:xPoint.offset});
- };
-
-
- /*
- LOOP CONVERTER
- */
-
- var LoopConverter = function (timingObject, range) {
- ConverterBase.call(this, timingObject, {timeout:true});
- this._range = range;
- this._coords = new SegmentCoords(range[0], range[1]-range[0]);
- };
- inherit(LoopConverter, ConverterBase);
-
- // transform value from coordiantes X of timing source
- // to looper coordinates Y
- LoopConverter.prototype._transform = function (x) {
- return this._coords.transformFloat(x);
- };
-
- // transform value from looper coordinates Y into
- // coordinates X of timing object - maintain relative diff
- LoopConverter.prototype._inverse = function (y) {
- var current_y = this.query().position;
- var current_x = this.timingsrc.query().position;
- var diff = y - current_y;
- var x = diff + current_x;
- // verify that x is witin range
- return x;
- };
-
- // overrides
- LoopConverter.prototype.query = function () {
- if (this.vector === null) return {position:undefined, velocity:undefined, acceleration:undefined};
- var vector = motionutils.calculateVector(this.vector, this.clock.now());
- // trigger state transition if range violation is detected
- if (vector.position > this._range[1]) {
- this._process(this._calculateInitialVector());
- } else if (vector.position < this._range[0]) {
- this._process(this._calculateInitialVector());
- } else {
- // no range violation
- return vector;
- }
- // re-evaluate query after state transition
- return motionutils.calculateVector(this.vector, this.clock.now());
- };
-
- // overrides
- LoopConverter.prototype.update = function (vector) {
- if (vector.position !== undefined && vector.position !== null) {
- vector.position = this._inverse(vector.position);
- }
- return this.timingsrc.update(vector);
- };
-
- // overrides
- LoopConverter.prototype._calculateTimeoutVector = function () {
- var freshVector = this.query();
- var res = motionutils.calculateDelta(freshVector, this.range);
- var deltaSec = res[0];
- if (deltaSec === null) return null;
- var position = res[1];
- var vector = motionutils.calculateVector(freshVector, freshVector.timestamp + deltaSec);
- vector.position = position; // avoid rounding errors
- return vector;
- };
-
- // overrides
- LoopConverter.prototype._onTimeout = function (vector) {
- return this._calculateInitialVector();
- };
-
- // overrides
- LoopConverter.prototype._onChange = function (vector) {
- return this._calculateInitialVector();
- };
-
- LoopConverter.prototype._calculateInitialVector = function () {
- // parent snapshot
- var parentVector = this.timingsrc.query();
- // find correct position for looper
- var position = this._transform(parentVector.position);
- // find looper vector
- return {
- position: position,
- velocity: parentVector.velocity,
- acceleration: parentVector.acceleration,
- timestamp: parentVector.timestamp
- };
- };
-
- return LoopConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-/*
-
- RANGE CONVERTER
-
- The converter enforce a range on position.
-
- It only has effect if given range is a restriction on the range of the timingsrc.
- Range converter will pause on range endpoints if timingsrc leaves the range.
- Range converters will continue mirroring timingsrc once it comes into the range.
-*/
-
-define('timingobject/rangeconverter',['./timingbase'], function (timingbase) {
-
- 'use strict';
-
- var motionutils = timingbase.motionutils;
- var ConverterBase = timingbase.ConverterBase;
- var RangeState = motionutils.RangeState;
- var inherit = timingbase.inherit;
-
- var state = function () {
- var _state = RangeState.INIT;
- var is_real_state_change = function (old_state, new_state) {
- // only state changes between INSIDE and OUTSIDE* are real state changes.
- if (old_state === RangeState.OUTSIDE_HIGH && new_state === RangeState.OUTSIDE_LOW) return false;
- if (old_state === RangeState.OUTSIDE_LOW && new_state === RangeState.OUTSIDE_HIGH) return false;
- if (old_state === RangeState.INIT) return false;
- return true;
- }
- var get = function () {return _state;};
- var set = function (new_state) {
- if (new_state === RangeState.INSIDE || new_state === RangeState.OUTSIDE_LOW || new_state === RangeState.OUTSIDE_HIGH) {
- if (new_state !== _state) {
- var old_state = _state;
- _state = new_state;
- return {real: is_real_state_change(old_state, new_state), abs: true};
- }
- };
- return {real:false, abs:false};
- }
- return {get: get, set:set};
- };
-
-
- /*
- Range converter allows a new (smaller) range to be specified.
- */
-
- var RangeConverter = function (timingObject, range) {
- ConverterBase.call(this, timingObject, {timeout:true});
- this._state = state();
- // todo - check range
- this._range = range;
- };
- inherit(RangeConverter, ConverterBase);
-
- // overrides
- RangeConverter.prototype.query = function () {
- if (this.vector === null) return {position:undefined, velocity:undefined, acceleration:undefined};
- // reevaluate state to handle range violation
- var vector = motionutils.calculateVector(this.timingsrc.vector, this.clock.now());
- var state = motionutils.getCorrectRangeState(vector, this._range);
- if (state !== RangeState.INSIDE) {
- this._preProcess(vector);
- }
- // re-evaluate query after state transition
- return motionutils.calculateVector(this.vector, this.clock.now());
- };
-
- // overridden
- RangeConverter.prototype._calculateTimeoutVector = function () {
- var freshVector = this.timingsrc.query();
- var res = motionutils.calculateDelta(freshVector, this.range);
- var deltaSec = res[0];
- if (deltaSec === null) return null;
- var position = res[1];
- var vector = motionutils.calculateVector(freshVector, freshVector.timestamp + deltaSec);
- vector.position = position; // avoid rounding errors
- return vector;
- };
-
- // overrides
- RangeConverter.prototype._onTimeout = function (vector) {
- return this._onChange(vector);
- };
-
- // overrides
- RangeConverter.prototype._onChange = function (vector) {
- var new_state = motionutils.getCorrectRangeState(vector, this._range);
- var state_changed = this._state.set(new_state);
- if (state_changed.real) {
- // state transition between INSIDE and OUTSIDE
- if (this._state.get() === RangeState.INSIDE) {
- // OUTSIDE -> INSIDE, generate fake start event
- // vector delivered by timeout
- // forward event unchanged
- } else {
- // INSIDE -> OUTSIDE, generate fake stop event
- vector = motionutils.checkRange(vector, this._range);
- }
- }
- else {
- // no state transition between INSIDE and OUTSIDE
- if (this._state.get() === RangeState.INSIDE) {
- // stay inside or first event inside
- // forward event unchanged
- } else {
- // stay outside or first event inside
- // drop unless
- // - first event outside
- // - skip from outside-high to outside-low
- // - skip from outside-low to outside-high
- if (state_changed.abs) {
- vector = motionutils.checkRange(vector, this._range);
- } else {
- // drop event
-
- return null;
- }
- }
- }
- return vector;
- };
-
- return RangeConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-/*
- TIMESHIFT CONVERTER
-
- Timeshift Converter timeshifts a timing object by timeoffset.
- Positive timeoffset means that the timeshift Converter will run ahead of the source timing object.
- Negative timeoffset means that the timeshift Converter will run behind the source timing object.
-
- Updates affect the converter immediately. This means that update vector must be re-calculated
- to the value it would have at time-shifted time. Timestamps are not time-shifted, since the motion is still live.
- For instance, (0, 1, ts) becomes (0+(1*timeshift), 1, ts)
-
- However, this transformation may cause range violation
- - this happens only when timing object is moving.
- - implementation requires range converter logic
-
- To fix this, the timeshift converter is always wrapped in a range converter. Range is inherited from timingsrc, if not specified.
-*/
-
-
-define('timingobject/timeshiftconverter',['./timingbase', './rangeconverter'], function (timingbase, RangeConverter) {
-
- 'use strict';
-
- var motionutils = timingbase.motionutils;
- var ConverterBase = timingbase.ConverterBase;
- var inherit = timingbase.inherit;
-
-
-
- var TimeShiftConverter = function (timingObject, timeOffset) {
- ConverterBase.call(this, timingObject);
- this._timeOffset = timeOffset;
- };
- inherit(TimeShiftConverter, ConverterBase);
-
- // overrides
- TimeShiftConverter.prototype._onChange = function (vector) {
- // calculate timeshifted vector
- var newVector = motionutils.calculateVector(vector, vector.timestamp + this._timeOffset);
- newVector.timestamp = vector.timestamp;
- return newVector;
- };
-
- /*
- Hides wrapping of range converter to specify new ranges.
- If range is not specified, default is to use range of timingObject
- */
- var RangeTimeShiftConverter = function (timingObject, timeOffset, range) {
- range = range || timingObject.range;
- return new RangeConverter(new TimeShiftConverter(timingObject, timeOffset), range);
- };
-
- return RangeTimeShiftConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-/*
- DERIVATIVE CONVERTER
-
- this Converter implements the derivative of it source timing object.
-
- The velocity of timingsrc becomes the position of the Converter.
-
- This means that the derivative Converter allows sequencing on velocity of a timing object,
- by attatching a sequencer on the derivative Converter.
-*/
-
-define('timingobject/derivativeconverter',['./timingbase'], function (timingbase) {
-
- 'use strict';
-
- var ConverterBase = timingbase.ConverterBase;
- var inherit = timingbase.inherit;
-
- var DerivativeConverter = function (timingObject, factor) {
- ConverterBase.call(this, timingObject);
- };
- inherit(DerivativeConverter, ConverterBase);
-
- // overrides
- DerivativeConverter.prototype._getRange = function () { return [-Infinity, Infinity];};
-
- // overrides
- DerivativeConverter.prototype._onChange = function (vector) {
- var newVector = {
- position : vector.velocity,
- velocity : vector.acceleration,
- acceleration : 0,
- timestamp : vector.timestamp
- };
- return newVector;
- };
-
- DerivativeConverter.prototype.update = function (vector) {
- throw new Error("updates illegal on derivative of timingobject");
- };
-
- return DerivativeConverter;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-define('timingobject/timingprovider',['util/motionutils', 'util/eventutils'], function (motionutils, eventutils) {
-
- // Polyfill for performance.now as Safari on ios doesn't have it...
- (function(){
- if ("performance" in window === false) {
- window.performance = {};
- window.performance.offset = new Date().getTime();
- }
- if ("now" in window.performance === false){
- window.performance.now = function now(){
- return new Date().getTime() - window.performance.offset;
- };
- }
- })();
-
- // local clock in seconds
- var clock = { now : function () {
- return performance.now()/1000.0;}
- };
-
- // readystates
- var TimingProviderState = Object.freeze({
- CONNECTING :"connecting",
- OPEN : "open",
- CLOSING : "closing",
- CLOSED : "closed"
- });
-
-
- /*
- LOCAL TIMING Provider
-
- Used by timing object if no timing provider is specified.
- */
-
- var LocalTimingProvider = function (options) {
- options = options || {};
- // initialise internal state
- this._range = options.range || [-Infinity, Infinity];
- this._vector = {
- position : 0.0,
- velocity : 0.0,
- acceleration : 0.0,
- timestamp : clock.now() // skew 0
- };
- this._skew = 0;
- this._readyState = TimingProviderState.OPEN;
- // events
- eventutils.eventify(this, LocalTimingProvider.prototype);
- this.eventifyDefineEvent("vectorchange", {init:false}); // define vector change event (not supporting init-event)
- this.eventifyDefineEvent("skewchange", {init:false}); // define skew change event (not supporting init-event)
- this.eventifyDefineEvent("readystatechange", {init:false}) // define readystatechange event (not supporting init-event)
-
- // set initial vector if provided
- if (options.vector) {
- this.update(options.vector);
- }
- };
-
- LocalTimingProvider.prototype._setSkew = function (skew) {
- this._skew = skew;
- this.eventifyTriggerEvent("skewchange");
- //this._doCallbacks("skewchange");
- };
-
- LocalTimingProvider.prototype._setVector = function (vector) {
- this._vector = vector;
- this.eventifyTriggerEvent("vectorchange");
- //this._doCallbacks("vectorchange");
- };
-
- LocalTimingProvider.prototype.update = function (vector) {
- if (!this._clock === null) throw new Error ("timing provider not ready to accept update");
- if (vector === undefined || vector === null) {throw new Error ("drop update, illegal updatevector");}
-
- var pos = (vector.position === undefined || vector.position === null) ? undefined : vector.position;
- var vel = (vector.velocity === undefined || vector.velocity === null) ? undefined : vector.velocity;
- var acc = (vector.acceleration === undefined || vector.acceleration === null) ? undefined : vector.acceleration;
-
- if (pos === undefined && vel === undefined && acc === undefined) {
- throw new Error ("drop update, noop");
- }
-
- var now = vector.timestamp || clock.now();
- var nowVector = motionutils.calculateVector(this._vector, now);
- nowVector = motionutils.checkRange(nowVector, this._range);
- var p = nowVector.position;
- var v = nowVector.velocity;
- var a = nowVector.acceleration;
- pos = (pos !== undefined) ? pos : p;
- vel = (vel !== undefined) ? vel : v;
- acc = (acc !== undefined) ? acc : a;
- var newVector = {
- position : pos,
- velocity : vel,
- acceleration : acc,
- timestamp : now
- };
- // break control flow
- var self = this;
- setTimeout(function () {
- self._setVector(newVector);
- });
- return newVector;
- };
-
-
- Object.defineProperty(LocalTimingProvider.prototype, 'range', {
- get : function () {
- // copy internal range
- return [this._range[0], this._range[1]];
- }
- });
-
- Object.defineProperty(LocalTimingProvider.prototype, 'skew', {
- get : function () { return this._skew;}
- });
-
- Object.defineProperty(LocalTimingProvider.prototype, 'vector', {
- get : function () { return this._vector; }
- });
-
- Object.defineProperty(LocalTimingProvider.prototype, 'readyState', {
- get : function () { return this._readyState; }
- });
-
- return {
- LocalTimingProvider: LocalTimingProvider,
- TimingProviderState : TimingProviderState
- };
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-define('util/timeoututils',[],function () {
-
- 'use strict';
-
- /*
- TIMEOUT
-
- Wraps setTimeout() to implement improved version
- - guarantee that timeout does not wake up too early
- - offers precise timeout by "busy"-looping just before timeout
- - wraps a single timeout
- - clock operates in seconds
- - parameters expected in seconds - breaking conformance with setTimeout
- - wakes up 3 seconds before on long timeouts to readjust
- */
-
- var Timeout = function (clock, callback, delay, options) {
- // clock
- this._clock = clock; // seconds
- var now = this._clock.now(); // seconds
- // timeout
- this._tid = null;
- this._callback = callback;
- this._delay_counter = 0;
- this._options = options || {};
-
- // options
- this._options.anchor = this._options.anchor || now; // seconds
- this._options.early = Math.abs(this._options.early) || 0; // seconds
- this._target = this._options.anchor + delay; // seconds
-
- // Initialise
- var self = this;
- window.addEventListener("message", this, true); // this.handleEvent
- var time_left = this._target - this._clock.now(); // seconds
- if (time_left > 10) {
- // long timeout > 10s - wakeup 3 seconds earlier to readdjust
- this._tid = setTimeout(function () {self._ontimeout();}, time_left - 3000);
- } else {
- // wake up just before
- this._tid = setTimeout(function () {self._ontimeout();}, (time_left - self._options.early)*1000);
- }
- };
-
- Object.defineProperty(Timeout.prototype, 'target', {
- get : function () {
- return this._target;
- }
- });
-
- // Internal function
- Timeout.prototype._ontimeout = function () {
- if (this._tid !== null) {
- var time_left = this._target - this._clock.now(); // seconds
- if (time_left <= 0) {
- // callback due
- this.cancel();
- this._callback();
- } else if (time_left > this._options.early) {
- // wakeup before target - options early sleep more
- var self = this;
- this._tid = setTimeout(function () {self._ontimeout();}, (time_left - this._options.early)*1000);
- } else {
- // wake up just before (options early) - event loop
- this._smalldelay();
- }
- }
- };
-
- // Internal function - handler for small delays
- Timeout.prototype.handleEvent = function (event) {
- if (event.source === window && event.data.indexOf("smalldelaymsg_") === 0) {
- event.stopPropagation();
- // ignore if timeout has been canceled
- var the_tid = parseInt(event.data.split("_")[1]);
- if (this._tid !== null && this._tid === the_tid) {
- this._ontimeout();
- }
- }
- };
-
- Timeout.prototype._smalldelay = function () {
- this._delay_counter ++;
- var self = this;
- window.postMessage("smalldelaymsg_" + self._tid, "*");
- };
-
- Timeout.prototype.cancel = function () {
- if (this._tid !== null) {
- clearTimeout(this._tid);
- this._tid = null;
- var self = this;
- window.removeEventListener("message", this, true);
- }
- };
-
- // return module object
- return {
- setTimeout: function (clock, callback, delay, options) {
- return new Timeout(clock, callback, delay, options);
- }
- };
-});
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-/*
- MASTER CLOCK
-
-
- MasterClock is the reference clock used by TimingObjects.
-
- It is implemented using performance.now,
- but is skewed and rate-adjusted relative to this local clock.
-
- This allows it to be used as a master clock in a distributed system,
- where synchronization is generally relative to some other clock than the local clock.
-
- The master clock may need to be adjusted in time, for instance as a response to
- varying estimation of clock skew or drift. The master clock supports an adjust primitive for this purpose.
-
- What policy is used for adjusting the master clock may depend on the circumstances
- and is out of scope for the implementation of the MasterClock.
- This policy is implemented by the timing object. This policy may or may not
- provide monotonicity.
-
- A change event is emitted every time the masterclock is adjusted.
-
- Vector values define
- - position : absolute value of the clock in seconds
- - velocity : how many seconds added per second (1.0 exactly - or very close)
- - timestamp : timstamp from local system clock (performance) in seconds. Defines point in time where position and velocity are valid.
-
- If initial vector is not provided, default value is
- {position: now, velocity: 1.0, timestamp: now};
- implying that master clock is equal to local clock.
-*/
-
-define('util/masterclock',['./eventutils', './timeoututils'], function (eventutils, timeoututils) {
-
- 'use strict';
-
- // Need a polyfill for performance,now as Safari on ios doesn't have it...
- (function(){
- if ("performance" in window === false) {
- window.performance = {};
- window.performance.offset = new Date().getTime();
- }
- if ("now" in window.performance === false){
- window.performance.now = function now(){
- return new Date().getTime() - window.performance.offset;
- };
- }
- })();
-
- // local clock in seconds
- var localClock = {
- now : function () {return performance.now()/1000.0;}
- };
-
- var calculateVector = function (vector, tsSec) {
- if (tsSec === undefined) tsSec = localClock.now();
- var deltaSec = tsSec - vector.timestamp;
- return {
- position : vector.position + vector.velocity*deltaSec,
- velocity : vector.velocity,
- timestamp : tsSec
- };
- };
-
- var MasterClock = function (options) {
- var now = localClock.now();
- options = options || {};
- this._vector = {position: now, velocity: 1.0, timestamp: now};
- // event support
- eventutils.eventify(this, MasterClock.prototype);
- this.eventifyDefineEvent("change"); // define change event (no init-event)
- // adjust
- this.adjust(options);
- };
-
- /*
- ADJUST
- - could also accept timestamp for velocity if needed?
- - given skew is relative to local clock
- - given rate is relative to local clock
- */
- MasterClock.prototype.adjust = function (options) {
- options = options || {};
- var now = localClock.now();
- var nowVector = this.query(now);
- if (options.skew === undefined && options.rate === undefined) {
- return;
- }
- this._vector = {
- position : (options.skew !== undefined) ? now + options.skew : nowVector.position,
- velocity : (options.rate !== undefined) ? options.rate : nowVector.velocity,
- timestamp : nowVector.timestamp
- }
- this.eventifyTriggerEvent("change");
- };
-
- /*
- NOW
- - calculates the value of the clock right now
- - shorthand for query
- */
- MasterClock.prototype.now = function () {
- return calculateVector(this._vector, localClock.now()).position;
- };
-
- /*
- QUERY
- - calculates the state of the clock right now
- - result vector includes position and velocity
- */
- MasterClock.prototype.query = function (now) {
- return calculateVector(this._vector, now);
- };
-
- /*
- Timeout support
- */
- MasterClock.prototype.setTimeout = function (callback, delay, options) {
- return timeoututils.setTimeout(this, callback, delay, options);
- };
-
- return MasterClock;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-/*
- TIMING OBJECT
-
- range and initial vector may be specified.
-
- master clock is the clock used by the timing object.
- timestamps in vectors refer to this clock.
-
- for local timing objects master clock is equal to performance.now
- for timing objects with a timing provider, the master clock will be
- maintained as a representation of the clock used by the timing provider.
-
-*/
-
-define('timingobject/timingobject',['./timingbase', './timingprovider', 'util/masterclock'], function (timingbase, timingprovider, MasterClock) {
-
- 'use strict';
-
- var motionutils = timingbase.motionutils;
- var TimingBase = timingbase.TimingBase;
- var inherit = timingbase.inherit;
- var LocalTimingProvider = timingprovider.LocalTimingProvider;
- var TimingProviderState = timingprovider.TimingProviderState;
-
- var TimingObject = function (options) {
- options = options || {};
- TimingBase.call(this, {timeout:true});
- this._clock = null;
- this._range = null;
- this._vector = null;
-
- // timing provider
- var self = this;
- this._provider = options.provider || new LocalTimingProvider(options);
- this._onSkewChangeWrapper = function () {self._onSkewChange();};
- this._onVectorChangeWrapper = function () {self._onVectorChange();};
- this._onReadystateChangeWrapper = function () {self._onReadystateChange();};
- this._provider.on("readystatechange", this._onReadystateChangeWrapper, this);
-
- // initialise
- this._initialise();
- };
- inherit(TimingObject, TimingBase);
-
- TimingObject.prototype._initialise = function () {
- if (this._provider.readyState !== TimingProviderState.OPEN) return;
- if (this._clock === null) {
- this._range = this._provider.range;
- this._clock = new MasterClock({skew: this._provider.skew});
- this._preProcess(this._provider.vector);
- this._provider.on("vectorchange", this._onVectorChangeWrapper, this);
- this._provider.on("skewchange", this._onSkewChangeWrapper, this);
- }
- };
-
- TimingObject.prototype._onReadystateChange = function () {
- this._initialise();
- };
-
- TimingObject.prototype._onSkewChange = function () {
- this._clock.adjust({skew: this._provider.skew});
- };
-
- TimingObject.prototype._onVectorChange = function () {
- this._preProcess(this._provider.vector);
- };
-
- // Accessors for timing object
- Object.defineProperty(TimingObject.prototype, 'clock', {
- get : function () { return this._clock; }
- });
- Object.defineProperty(TimingObject.prototype, 'provider', {
- get : function () {return this._provider; }
- });
-
- // overrides
- TimingObject.prototype.query = function () {
- if (this.vector === null) return {position:undefined, velocity:undefined, acceleration:undefined};
- // reevaluate state to handle range violation
- var vector = motionutils.calculateVector(this.vector, this.clock.now());
- var state = motionutils.getCorrectRangeState(vector, this._range);
- if (state !== motionutils.RangeState.INSIDE) {
- this._preProcess(vector);
- }
- // re-evaluate query after state transition
- return motionutils.calculateVector(this.vector, this.clock.now());
- };
-
- TimingObject.prototype.update = function (vector) {
- return this._provider.update(vector);
- };
-
- TimingObject.prototype._onChange = function (vector) {
- return motionutils.checkRange(vector, this._range);
- };
-
- // overrides
- TimingObject.prototype._calculateTimeoutVector = function () {
- var freshVector = this.query();
- var res = motionutils.calculateDelta(freshVector, this.range);
- var deltaSec = res[0];
- if (deltaSec === null) return null;
- if (deltaSec === Infinity) return null;
- var position = res[1];
- var vector = motionutils.calculateVector(freshVector, freshVector.timestamp + deltaSec);
- vector.position = position; // avoid rounding errors
- return vector;
- };
-
- // overrides
- TimingObject.prototype._onTimeout = function (vector) {
- return motionutils.checkRange(vector, this._range);
- };
-
- return TimingObject;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-define('timingobject/main',[
- './timingbase',
- './skewconverter',
- './delayconverter',
- './scaleconverter',
- './loopconverter',
- './rangeconverter',
- './timeshiftconverter',
- './derivativeconverter',
- './timingobject',
- './timingprovider'],
- function (timingbase, SkewConverter, DelayConverter, ScaleConverter, LoopConverter, RangeConverter, TimeShiftConverter, DerivativeConverter, TimingObject, timingprovider) {
- 'use strict';
- return {
- inherit : timingbase.inherit,
- ConverterBase : timingbase.ConverterBase,
- SkewConverter : SkewConverter,
- DelayConverter : DelayConverter,
- ScaleConverter : ScaleConverter,
- LoopConverter : LoopConverter,
- RangeConverter : RangeConverter,
- TimeShiftConverter : TimeShiftConverter,
- DerivativeConverter : DerivativeConverter,
- TimingObject : TimingObject,
- TimingProviderState: timingprovider.TimingProviderState
- };
- }
-);
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-define('util/interval',[],function () {
-
- 'use strict';
-
- /*
- INTERVAL
- */
-
- var isNumber = function(n) {
- var N = parseFloat(n);
- return (n===N && !isNaN(N));
- };
-
- var IntervalError = function (message) {
- this.name = "IntervalError";
- this.message = (message||"");
- };
- IntervalError.prototype = Error.prototype;
-
-
- var Interval = function (low, high, lowInclude, highInclude) {
- var lowIsNumber = isNumber(low);
- var highIsNumber = isNumber(high);
- // new Interval(3.0) defines singular - low === high
- if (lowIsNumber && high === undefined) high = low;
- if (!isNumber(low)) throw new IntervalError("low not a number");
- if (!isNumber(high)) throw new IntervalError("high not a number");
- if (low > high) throw new IntervalError("low > high");
- if (low === high) {
- lowInclude = true;
- highInclude = true;
- }
- if (low === -Infinity) lowInclude = true;
- if (high === Infinity) highInclude = true;
- if (lowInclude === undefined) lowInclude = true;
- if (highInclude === undefined) highInclude = false;
- if (typeof lowInclude !== "boolean") throw new IntervalError("lowInclude not boolean");
- if (typeof highInclude !== "boolean") throw new IntervalError("highInclude not boolean");
- this.__defineGetter__("length", function () {return high - low;});
- this.__defineGetter__("low", function () {return low;});
- this.__defineGetter__("high", function () {return high;});
- this.__defineGetter__("lowInclude", function () {return lowInclude;});
- this.__defineGetter__("highInclude", function () {return highInclude;});
- };
-
-
- Interval.prototype.toString = function () {
- var lowBracket = (this.lowInclude) ? "[" : "<";
- var highBracket = (this.highInclude) ? "]" : ">";
- var low = (this.low === -Infinity) ? "<--" : this.low.toFixed(2);
- var high = (this.high === Infinity) ? "-->" : this.high.toFixed(2);
- if (this.isSingular())
- return lowBracket + low + highBracket;
- return lowBracket + low + ',' + high + highBracket;
- };
- Interval.prototype.isFinite = function () {
- return (isFinite(this.low) && isFinite(this.high));
- };
- Interval.prototype.isSingular = function () {
- return (this.low === this.high);
- };
- Interval.prototype.coversPoint = function (x) {
- if (this.low < x && x < this.high) return true;
- if (this.lowInclude && x === this.low) return true;
- if (this.highInclude && x === this.high) return true;
- return false;
- };
-
- // overlap : it exists at least one point x covered by both interval
- Interval.prototype.overlapsInterval = function (other) {
- if (other instanceof Interval === false) throw new IntervalError("paramenter not instance of Interval");
- // singularities
- if (this.isSingular() && other.isSingular())
- return (this.low === other.low);
- if (this.isSingular())
- return other.coversPoint(this.low);
- if (other.isSingular())
- return this.coversPoint(other.low);
- // not overlap right
- if (this.high < other.low) return false;
- if (this.high === other.low) {
- return this.coversPoint(other.low) && other.coversPoint(this.high);
- }
- // not overlap left
- if (this.low > other.high) return false;
- if (this.low === other.high) {
- return (this.coversPoint(other.high) && other.coversPoint(this.low));
- }
- return true;
- };
- Interval.prototype.coversInterval = function (other) {
- if (other instanceof Interval === false) throw new IntervalError("paramenter not instance of Interval");
- if (other.low < this.low || this.high < other.high) return false;
- if (this.low < other.low && other.high < this.high) return true;
- // corner case - one or both endpoints are the same (the other endpoint is covered)
- if (this.low === other.low && this.lowInclude === false && other.lowInclude === true)
- return false;
- if (this.high === other.high && this.highInclude === false && other.highInclude === true)
- return false;
- return true;
- };
- Interval.prototype.equals = function (other) {
- if (this.low !== other.low) return false;
- if (this.high !== other.high) return false;
- if (this.lowInclude !== other.lowInclude) return false;
- if (this.highInclude !== other.highInclude) return false;
- return true;
- };
-
- /*
- Possibility for more interval methods such as union, intersection,
- */
-
- return Interval;
-});
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-define ('sequencing/sortedarraybinary',['util/interval'], function (Interval) {
-
- 'use strict';
-
- // check if n is a number
- var is_number = function(n) {
- var N = parseFloat(n);
- return (n==N && !isNaN(N));
- };
-
-
- var SortedArrayError = function (message) {
- this.name = "SortedArrayError";
- this.message = (message||"");
- };
- SortedArrayError.prototype = Error.prototype;
-
- /*
-
- SORTED ARRAY BINARY
-
- */
-
- var SortedArrayBinary = function () {
- /*
- use binary search to implement sorted insert
- guard against duplicates
- */
- this.array = [];
- };
-
- /**
- * Binary search on sorted array
- * @param {*} searchElement The item to search for within the array.
- * @return {Number} The index of the element which defaults to -1 when not found.
- */
- SortedArrayBinary.prototype.binaryIndexOf = function (searchElement) {
- var minIndex = 0;
- var maxIndex = this.array.length - 1;
- var currentIndex;
- var currentElement;
- while (minIndex <= maxIndex) {
- currentIndex = (minIndex + maxIndex) / 2 | 0;
- currentElement = this.array[currentIndex];
- if (currentElement < searchElement) {
- minIndex = currentIndex + 1;
- }
- else if (currentElement > searchElement) {
- maxIndex = currentIndex - 1;
- }
- else {
- return currentIndex;
- }
- }
- return ~maxIndex;
-
- // NOTE : ambiguity?
- // search for minimum element returns 0 if it exists, and 0 if it does not exists
- };
-
- SortedArrayBinary.prototype.insert = function (element) {
- var index = this.binaryIndexOf(element);
- if (index < 0 || (index === 0 && this.array[0] !== element)) {
- this.array.splice(Math.abs(index), 0, element);
- }
- };
-
- SortedArrayBinary.prototype.indexOf = function (element) {
- var index = this.binaryIndexOf(element);
- if (index < 0 || (index === 0 && this.array[0] !== element)) {
- return -1;
- } else {
- return index;
- }
- };
-
- SortedArrayBinary.prototype.hasElement = function (element) {
- var index = this.binaryIndexOf(element);
- if (index < 0 || (index === 0 && this.array[0] !== element)) {
- return false;
- } else {
- return true;
- }
- };
-
- SortedArrayBinary.prototype.remove = function (element) {
- var index = this.binaryIndexOf(element);
- if (index < 0 || (index === 0 && this.array[0] !== element)) {
- return;
- } else {
- this.array.splice(index, 1);
- }
- };
-
- SortedArrayBinary.prototype.getMinimum = function () {
- return (this.array.length > 0) ? this.array[0] : null;
- };
-
- SortedArrayBinary.prototype.getMaximum = function () {
- return (this.array.length > 0) ? this.array[this.array.length - 1] : null;
- };
-
- /*
- Find index of largest value less than x
- Returns -1 if noe values exist that are less than x
- */
- SortedArrayBinary.prototype.ltIndexOf = function(x) {
- var i = this.binaryIndexOf(x);
- // consider element to the left
- i = (i < 0) ? Math.abs(i) - 1 : i - 1;
- return (i >= 0) ? i : -1;
- };
-
- /*
- Find index of largest value less than x or equal to x
- Returns -1 if noe values exist that are less than x or equal to x
- */
- SortedArrayBinary.prototype.leIndexOf = function(x) {
- var i = this.binaryIndexOf(x);
- // equal
- if (i > 0 || (i === 0 && this.array[0] === x)) {
- return i;
- }
- // consider element to the left
- i = Math.abs(i) - 1;
- return (i >= 0) ? i : -1;
- };
-
- /*
- Find index of smallest value greater than x
- Returns -1 if noe values exist that are greater than x
-
- note ambiguity :
-
- search for for an element that is less than array[0]
- should return a negative value indicating that the element
- was not found. Furthermore, as it escapes the while loop
- the returned value should indicate the index that this element
- would have had - had it been there - as is the idea of this bitwise
- or trick
-
- it should return a negative value x so that
- Math.abs(x) - 1 gives the correct index which is 0
- thus, x needs to be -1
-
- instead it returns 0 - indicating that the non-existing value
- was found!
-
- I think this bug is specific to breaking out on (minIndex,maxIndex) === (0,-1)
-
-
-
- */
-
- SortedArrayBinary.prototype.gtIndexOf = function (x) {
- var i = this.binaryIndexOf(x);
-
- // ambiguity if i === 0
- if (i === 0) {
- if (this.array[0] === x) {
- // found element - need to exclude it
- // since this is gt it is element to the right
- i = 1;
- } else {
- // did not find element
- // - the first element is the correct
- // i === 0
- }
- }
- else {
- i = (i < 0) ? Math.abs(i): i + 1;
- }
- return (i < this.array.length) ? i : -1;
- };
-
-
- /*
- Find index of smallest value greater than x or equal to x
- Returns -1 if noe values exist that are greater than x or equal to x
- */
-
- SortedArrayBinary.prototype.geIndexOf = function(x) {
- var i = this.binaryIndexOf(x);
- // equal
- if (i > 0 || (i === 0 && this.array[0] === x)) {
- return i;
- }
- /*
- if (i === 0) {
- // ambiguity - either there is no element > x or array[0] is the smallest value > x
- if (array.length >= 0 && array[0] > x) {
- return 0;
- } else return -1;
- } else {
- // consider element to the right
- i = Math.abs(i);
- }
- */
- i = Math.abs(i);
- return (i < this.array.length) ? i : -1;
- };
-
- SortedArrayBinary.prototype.indexOf = function (element) {
- var index = this.binaryIndexOf(element);
- if (index < 0 || (index === 0 && this.array[0] !== element)) {
- return -1;
- } else {
- return index;
- }
- };
-
- SortedArrayBinary.prototype.lookup = function (interval) {
- if (interval === undefined)
- interval = new Interval(-Infinity, Infinity, true, true);
- if (interval instanceof Interval === false)
- throw new SortedArrayError("lookup requires Interval argument");
- var start_index = -1, end_index = -1;
- if (interval.lowInclude) {
- start_index = this.geIndexOf(interval.low);
- } else {
- start_index = this.gtIndexOf(interval.low);
- }
- if (start_index === -1) {
- return [];
- }
- if (interval.highInclude) {
- end_index = this.leIndexOf(interval.high);
- } else {
- end_index = this.ltIndexOf(interval.high);
- }
- if (end_index === -1) { // not reachable - I think
- return [];
- }
- return this.array.slice(start_index, end_index + 1);
- };
-
- SortedArrayBinary.prototype.get = function (i) {return this.array[i];};
- SortedArrayBinary.prototype.list = function () {return this.array;};
-
- return SortedArrayBinary;
-});
-
-
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-define ('sequencing/multimap',[],function () {
-
- 'use strict';
-
- /*
- MULTI MAP
-
- MultiMap stores (key,value) tuples
- - one key may be bound to multiple values
- - protection from duplicate (key, value) bindings.
- - values are not assumed to be unique, i.e., the same value may be
- associated with multiple points.
-
- MultiMap supports addition and removal of (key,value) bindings.
- - insert (key, value)
- - remove (key, value)
- */
-
- var MultiMap = function () {
- this._map = {}; // key -> [value,]
- };
-
- MultiMap.prototype.insert = function (key, value) {
- return this.insertAll([{key:key, value:value}]);
- };
-
- MultiMap.prototype.insertAll = function (tuples) {
- var values, added = [];
- tuples.forEach(function (tuple){
- if (!this._map.hasOwnProperty(tuple.key)) {
- this._map[tuple.key] = [];
- }
- // protect against duplicate (key,value) bindings
- values = this._map[tuple.key];
- if (values.indexOf(tuple.value) === -1) {
- values.push(tuple.value);
- added.push(tuple);
- }
- }, this);
- return added;
- };
-
- MultiMap.prototype.remove = function (key, value) {
- return this.removeAll([{key:key, value:value}]);
- };
-
- MultiMap.prototype.removeAll = function (tuples) {
- var index, values, removed = [];
- tuples.forEach(function (tuple) {
- if (this._map.hasOwnProperty(tuple.key)) {
- values = this._map[tuple.key];
- index = values.indexOf(tuple.value);
- if (index > -1) {
- values.splice(index, 1);
- removed.push(tuple);
- // clean up if empty
- if (values.length === 0) {
- delete this._map[tuple.key];
- }
- }
- }
- }, this);
- return removed;
- };
-
- MultiMap.prototype.hasKey = function (key) {
- return this._map.hasOwnProperty(key);
- };
-
- MultiMap.prototype.keys = function () {
- return Object.keys(this._map);
- };
-
- MultiMap.prototype.getItemsByKey = function (key) {
- var res = [];
- if (this.hasKey(key)) {
- this._map[key].forEach(function (value) {
- res.push({key: key, value: value});
- });
- }
- return res;
- };
-
- MultiMap.prototype.getItemsByKeys = function (_keys) {
- if (_keys === undefined) _keys = this.keys();
- var res = [];
- _keys.forEach(function (key) {
- res = res.concat(this.getItemsByKey(key));
- }, this);
- return res;
- };
- MultiMap.prototype.list = MultiMap.prototype.getItemsByKeys;
-
- return MultiMap;
-});
-
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-define ('sequencing/axis',['util/interval', './sortedarraybinary', './multimap'],
- function (Interval, SortedArrayBinary, MultiMap) {
-
- 'use strict';
-
- var AxisError = function (message) {
- this.name = "AxisError";
- this.message = (message || "");
- };
- AxisError.prototype = Error.prototype;
-
-
- // Operation Types
- var OpType = Object.freeze({
- NOOP : "noop",
- CREATE: "create",
- UPDATE: "update",
- REMOVE: "remove"
- });
-
- // POINT TYPES
- var PointType = Object.freeze({
- LOW: "low",
- SINGULAR: "singular",
- HIGH: "high",
- INSIDE: "inside",
- OUTSIDE: "outside",
- toInteger: function (s) {
- if (s === PointType.LOW) return -1;
- if (s === PointType.HIGH) return 1;
- if (s === PointType.INSIDE) return 2;
- if (s === PointType.OUTSIDE) return 3;
- if (s === PointType.SINGULAR) return 0;
- throw new AxisError("illegal string value for point type");
- },
- fromInteger: function (i) {
- if (i === -1) return PointType.LOW;
- else if (i === 0) return PointType.SINGULAR;
- else if (i === 1) return PointType.HIGH;
- else if (i === 2) return PointType.INSIDE;
- else if (i === 3) return PointType.OUTSIDE;
- throw new AxisError("illegal integer value for point type");
- }
- });
-
-
- /*
- AXIS
-
- Manages a collection of Intervals.
- Each interval is identified by a key, and may be inserted or removed using the key, just like a map/dictionary.
- Interval objects represents an interval on the Axis or real floating point numbers.
-
- In addition to key access, the Axis provides efficient access to Intervals by search.
- - lookupByInterval (searchInterval) returns all Intervals whose endpoints are covered by given search Interval
- - lookupByPoint (x) returns all Intervals in the collection that covers given point.
- */
-
- var Axis = function () {
- // Mapping key to Intervals
- this._map = {}; // key -> Interval(point,point)
- // Revers-mapping Interval points to Interval keys
- this._reverse = new MultiMap(); // point -> [key, ...]
- // Index for searching Intervals effectively by endpoints - used by lookupByInterval
- this._index = new SortedArrayBinary(); // [point, point, ...]
- // No index provided for lookupByPoint
-
- // Callbacks - change event - list of axis operations
- this._callbacks = {'change': []};
- };
-
- // internal helper function to insert (key, interval) into map, reverse and index
- Axis.prototype._insert = function (key, interval) {
- // map
- this._map[key] = interval;
- // index add to index if reverse is empty before insert
- if (!this._reverse.hasKey(interval.low)) {
- this._index.insert(interval.low);
- }
- if (!this._reverse.hasKey(interval.high)) {
- this._index.insert(interval.high);
- }
- // reverse index
- this._reverse.insert(interval.low, key);
- this._reverse.insert(interval.high, key);
- };
-
-
-
- // internal helper function to clean up map, reverse and index during (key,interval) removal
- Axis.prototype._remove = function (key) {
- if (!this._map.hasOwnProperty(key))
- throw new AxisError("attempt to remove non-existing key");
- var interval = this._map[key];
- // map
- delete this._map[key];
- // reverse
- this._reverse.remove(interval.low, key);
- this._reverse.remove(interval.high, key);
- // index remove from index if reverse is empty after remove
- if (!this._reverse.hasKey(interval.low)) {
- this._index.remove(interval.low);
- }
- if (!this._reverse.hasKey(interval.high)) {
- this._index.remove(interval.high);
- }
- // return old interval
- return interval;
- };
-
-
- /*
- UPDATEALL
- - process a batch of operations
- - creates, replaces or removes args [{key:key, interval:interval},]
- */
- Axis.prototype.updateAll = function (args) {
- var e, elist = [], oldInterval, key, interval;
- args.forEach(function(arg){
- key = arg.key;
- if (typeof key !== 'string') throw new AxisError("key is " + typeof key + " - must be string");
- interval = arg.interval;
- // INTERVAL is undefined
- if (interval === undefined) {
- if (this._map.hasOwnProperty(key)) {
- // REMOVE
- oldInterval = this._remove(key);
- e = {type: OpType.REMOVE, key: key, interval: oldInterval, data: arg.data};
- } else {
- // NOOP
- e = {type: OpType.NOOP, key: key, interval: undefined, data: undefined};
- }
- }
- // INTERVAL defined
- else {
- if (interval instanceof Interval === false) throw new AxisError("parameter must be instanceof Interval");
- if (this._map.hasOwnProperty(key)) {
- oldInterval = this._map[key];
-
- if (interval.equals(oldInterval)) {
- e = {type: OpType.NOOP, key: key, interval: oldInterval, data: arg.data};
- } else {
- this._remove(key);
- this._insert(key, interval);
- e = {type: OpType.UPDATE, key: key, interval: interval, data: arg.data};
- }
- } else {
- // CREATE
- this._insert(key, interval);
- e = {type: OpType.CREATE, key: key, interval: interval, data: arg.data};
- }
- }
- elist.push(e);
- }, this);
- // trigger events
- this._doCallbacks("change", elist);
- // return elist
- return elist;
- };
-
- // shorthand for update single (key, interval) pair
- Axis.prototype.update = function (key, interval) {
- return this.updateAll([{key:key, interval:interval}]);
- };
-
- /*
- AXIS EVENTS
- */
-
- // register callback
- Axis.prototype.on = function (what, handler, ctx) {
- if (!handler || typeof handler !== "function")
- throw new AxisError("Illegal handler");
- if (!this._callbacks.hasOwnProperty(what))
- throw new AxisError("Unsupported event " + what);
- var index = this._callbacks[what].indexOf(handler);
- if (index === -1) {
- // register handler
- handler["_ctx_"] = ctx || this;
- this._callbacks[what].push(handler);
- }
- return this;
- };
-
- // unregister callback
- Axis.prototype.off = function (what, handler) {
- if (this._callbacks[what] !== undefined) {
- var index = this._callbacks[what].indexOf(handler);
- if (index > -1) {
- this._callbacks[what].splice(index, 1);
- }
- }
- return this;
- };
-
- // perform callback
- Axis.prototype._doCallbacks = function(what, e) {
- var err;
- // invoke callback handlers
- this._callbacks[what].forEach(function(h) {
- try {
- h.call(h["_ctx_"], e);
- } catch (err) {
- console.log("Error in " + what + ": " + h + ": " + err);
- }
- }, this);
- };
-
-
- /*
- AXIS SEARCH
- */
-
- /*
- Find (key,interval) pairs for intervals that cover x.
- Simply scan all intervals in collection - no index provided.
- x undefined means all (key, interval)
- */
- Axis.prototype.lookupByPoint = function (x) {
- var interval, res = [];
- Object.keys(this._map).forEach(function(key){
- interval = this._map[key];
- if (x === undefined || interval.coversPoint(x)) {
- res.push({key:key, interval: interval});
- }
- }, this);
- return res;
- };
-
- /*
- Find all interval endpoints within given interval
- */
- Axis.prototype.lookupByInterval = function (interval) {
- // [point,]
- var points = this._index.lookup(interval);
- // [{key: key, point: point, interval:interval},]
- var res = [], items, point;
- this._index.lookup(interval).forEach(function (point) {
- this._reverse.getItemsByKey(point).forEach(function (item) {
- point = item.key;
- interval = this._map[item.value];
- res.push({
- key: item.value,
- interval: interval,
- point: point,
- pointType: this.getPointType(point, interval)
- });
- }, this);
- }, this);
- return res;
- };
-
- Axis.prototype.items = function () {return this.lookupByPoint();};
- Axis.prototype.keys = function () {return Object.keys(this._map);};
-
- Axis.prototype.getPointType = function (point, interval) {
- if (interval.isSingular() && point === interval.low) return PointType.SINGULAR;
- if (point === interval.low) return PointType.LOW;
- if (point === interval.high) return PointType.HIGH;
- if (interval.low < point && point < interval.high) return PointType.INSIDE;
- else return PointType.OUTSIDE;
- };
-
- Axis.prototype.getIntervalByKey = function (key) {
- return this._map[key];
- };
-
- Axis.prototype.hasKey = function (key) {
- return this._map.hasOwnProperty(key);
- };
-
- // module definition
- return {
- Axis: Axis,
- OpType : OpType,
- PointType: PointType
- };
-});
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-define('sequencing/sequencer',['util/motionutils', 'util/eventutils', 'util/interval', './axis'],
- function (motionutils, eventutils, Interval, axis) {
-
- 'use strict';
-
- // UTILITY
-
- var isMoving = function (vector) {
- return (vector.velocity !== 0.0 || vector.acceleration !== 0.0);
- };
-
- /*
- unique
- return list of elements that are unique to array 1
- */
- var unique = function (array1, array2) {
- var res = [];
- for (var i=0; i and timestamps defines the time
- interval covered by the schedule - the . The
- idea is to move this interval stepwise, to eventually cover the
- entire time-line. The length of this interval is defined by the
- option . The default value is 5 seconds.
-
- The operation moves the interval so that the next
- interval matches the previous interval . If
- lookahead is 5 seconds, the general idea is to advance the
- covering interval every 5 seconds. However, it is safe to
- advance it more often. It is also safe to advance it less
- often. In this case the covering interval will grow in length to
- cover otherwise lost parts of the timeline - but events will be
- delivered too late.
-
- The push(ts,task) operation allows tasks to be added to the
- schedule, provided their due-times fall within the covering
- interval. The push_immediate(task) will assign === now.
- Push maintains time ordering.
-
- The pop() operation is used to get all tasks that are due for
- execution. The schedule should be popped regularly/frequently to
- keep tasks from being delayed in execution. The delay_next()
- operation returns the time (milliseconds) until the next task is
- due. This can be used with setTimeout() to arrange timely
- popping. However, note that this timeout may have to be
- re-evealuated as new tasks are pushed onto the schedule.
-
- Associated with the (time), there is also a
- "covering interval" with respect to timing object(position). Eg. In real-time
- (epoch) interval [1434891233.407, 1434891235.407] movement of timing object covers
- positions [23.0, 25.0]. All tasks are associated with a position on a
- dimension. This is set by the advance() operation. The position
- interval is used (externally) to quickly evaluate relevance of tasks, essentially to
- avoid calculating the due-times of a task only to find that it falls
- outside the time convering interval. Position interval is only managed
- externally.
-
- */
-
- var Schedule = function (now, options) {
- this.queue = [];
- // options
- this.options = options || {};
- this.options.lookahead = this.options.lookahead || 5.0;
- // time-interval
- this.timeInterval = new Interval(now, now + this.options.lookahead, true, true);
- // position-interval
- this.posInterval = null;
- };
-
- Schedule.prototype.getTimeInterval = function (){return this.timeInterval;};
- Schedule.prototype.getPosInterval = function (){return this.posInterval;};
- Schedule.prototype.setPosInterval = function (interval) {this.posInterval = interval;};
- Schedule.prototype.sortFunc = function(a,b) {return a.ts - b.ts;};
-
- // push
- // task assumed to have a key -- se usage by Sequencer
- Schedule.prototype.push = function (now, ts, task) {
- if (this.timeInterval.coversPoint(ts)) {
- var entry = {
- ts: ts,
- task: task,
- push_ts: now
- };
- if (ts >= now) {
- this.queue.push(entry);
- this.queue.sort(this.sortFunc); // maintain ordering
- return true;
- } else {
- console.log("Schedule : task pushed a bit too late, ts < now ", (ts-now));
- }
- }
- return false;
- };
-
- // pop
- Schedule.prototype.pop = function (now) {
- var res = [];
- while (this.queue.length > 0 && this.queue[0].ts <= now) {
- var entry = this.queue.shift();
- var info = {
- task: entry.task,
- pop_ts: now, // fresh timestamp?
- push_ts: entry.push_ts,
- ts: entry.ts
- };
- res.push(info);
- }
- return res;
- };
-
-
- /* Invalidate task with given key */
- Schedule.prototype.invalidate = function (key) {
- var i, index, entry, remove = [];
- // Find
- for (i=0; i -1) {
- this.queue.splice(index, 1);
- }
- }
- };
-
-
- /*
-
- ADVANCE
-
- The covering time interval is defined by [start,end>
- The covering interval should be advanced so that it always
- contains real-time, e.g., now.
-
- Advancing the covering interval assumes task queues to be empty.
- Therefore, make sure to pop all task before calling advance.
-
- Also, the time-sequence of covering intervals should ideally
- lay back-to-back on the time-line. To achive this the end of
- one interval becomes the start of the next. The end of the interval is
- now + lookahead.
-
- If advance is called before the current interval is expired,
- the current interval is cut short.
-
- If advance is not called for an extended time, the next
- invocation will cause the covering interval to stretch long
- into the past.
-
- If parameter start is supplied, this is used as starting point
- for covering interval.
-
- */
-
- Schedule.prototype.advance = function(now) {
- if (now < this.timeInterval.low) {
- console.log("Schedule : Advancing backwards " + (now - this.timeInterval.low));
- }
- this.queue = []; // drop tasks (time interval cut off)
- this.timeInterval = new Interval(now, now + this.options.lookahead, false, true);
- this.posInterval = null; // reset
- };
-
- /*
- Current schedule is expired (at given time)
- */
- Schedule.prototype.isExpired = function(now) {
- return (now > this.timeInterval.high);
- };
-
- /*
- delay until the next due task in schedule, or until the
- current time_interval expires
- */
- Schedule.prototype.getDelayNextTs = function (ts) {
- // ts should be fresh timestamp in seconds
- if (this.queue.length > 0) {
- return Math.max(0.0, this.queue[0].ts - ts);
- }
- return Math.max(0.0, this.timeInterval.high - ts);
- };
-
- Schedule.prototype.getNextTaskPoint = function () {
- return (this.queue.length > 0) ? this.queue[0].task.point : null;
- };
-
- /*
- BUILDER
-
- Build arguments for updateAll function of Sequencer
- */
-
- var Builder = function (sequencer) {
- this._argOrder = [];
- this._argMap = {};
- this._sequencer = sequencer;
- };
-
- Builder.prototype.addCue = function (key, interval, data) {
- this._argOrder.push(key);
- this._argMap[key] = {key:key, interval:interval, data: data};
- return this;
- };
-
- Builder.prototype.removeCue = function (key, removedData) {
- return this.addCue(key, undefined, removedData);
- };
-
- Builder.prototype.submit = function () {
- var argList = [];
- this._argOrder.forEach(function (key) {
- argList.push(this._argMap[key]);
- }, this);
- // reset
- this._argMap = {};
- this._argOrder = [];
- if (argList.length > 0) {
- return this._sequencer.updateAll(argList);
- }
- return [];
- };
-
-
- /*
- Sequencer Error
- */
- var SequencerError = function (message) {
- this.name = "SequencerError";
- this.message = (message || "");
- };
- SequencerError.prototype = Error.prototype;
-
-
- /*
- Sequencer EArgs
- */
- var SequencerEArgs = function (sequencer, key, interval, data, point, pointType, ts, dueTs, directionType, verbType) {
- this.src = sequencer;
- this.key = key;
- this.interval = interval;
- this.point = point;
- this.pointType = pointType;
- this.dueTs = dueTs;
- this.delay = ts - dueTs;
- this.directionType = directionType;
- this.type = verbType;
- this.data = data;
- };
-
- SequencerEArgs.prototype.toString = function () {
- var s = "[" + this.point.toFixed(2) + "]";
- s += " " + this.key;
- s += " " + this.interval.toString();
- s += " " + this.type;
- s += " " + this.directionType;
- s += " " + this.pointType;
- s += " delay:" + this.delay.toFixed(4);
- if (this.data) s += " " + JSON.stringify(this.data);
- return s;
- };
-
-
- /*
- SequencerCue
- */
- var SequencerCue = function (key, interval, data) {
- this.key = key;
- this.interval = interval;
- this.data = data;
- };
-
- SequencerCue.prototype.toString = function () {
- var s = this.key + " " + this.interval.toString();
- if (this.data) s += " " + JSON.stringify(this.data);
- return s;
- };
-
-
- /*
-
- SEQUENCER
-
- */
- var Sequencer = function (timingObject, _axis) {
- this._to = timingObject;
- this._clock = timingObject.clock;
- this._axis = _axis || new axis.Axis();
- this._schedule = null;
- this._timeout = null; // timeout
- this._currentTimeoutPoint = null; // point associated with current timeout
- this._activeKeys = []; // active intervals
-
- // set up eventing stuff
- eventutils.eventify(this, Sequencer.prototype);
- this.eventifyDefineEvent("enter", {init:true}); // define enter event (supporting init-event)
- this.eventifyDefineEvent("exit");
- this.eventifyDefineEvent("change");
-
- // wrap prototype handlers and store ref on instance
- this._wrappedOnTimingChange = function () {this._onTimingChange();};
- this._wrappedOnAxisChange = function (e) {this._onAxisChange(e);};
-
- // initialise
- this._to.on("change", this._wrappedOnTimingChange, this);
- // Allow subclass to load data into the sequencer
- this.loadData();
- };
-
- // making Interval constructor available on all sequencer instances
- Object.defineProperty(Sequencer.prototype, "Interval", {
- get : function () {return Interval;}
- });
-
- /*
- overrides how immediate events are constructed
- */
- Sequencer.prototype.eventifyMakeInitEvents = function (type) {
- if (type === "enter") {
- return this._processInitialEvents();
- }
- return [];
- };
-
- // To be overridden by subclass specializations
- Sequencer.prototype.loadData = function () {};
- Sequencer.prototype.getData = function (key) {};
-
- /*
-
- ON TIMING OBJECT CHANGE
-
- Whenever the timingobject position changes abruptly we need to
- re-evaluate intervals.
-
- A) Abrupt changes in position occur
- 1) after certain timing object changes or
- 2) when the timing object is initially loaded.
-
- B) Non-abrupts changes occur when velocity or acceleration is
- changed without immediately affecting the position
-
- In all cases - the schedule and timeout need to be re-evaluated.
-
- In case A. 1) the timing object change is possibly late due to network
- latency. To include effects of singulars/intervals from the small "lost"
- time interval, make sure to advance according to the timestamp of the
- timing object vector. 2) is not delayed.
-
-
- Furthermore in a small time-interval just before timing object updates
- the previous vector incorrectly drove the sequencer instead of the new
- updated vector. This may have caused the sequencer to falsely
- report some events, and to not report other events. This time
- interval is (initVector[T], now). For non-singular Intervals this will be
- corrected by the general re-evalution of Intervals. For singular Intervals
- explicit action is required to signal incorrect events. This implementation
- does not support this.
-
- */
-
- Sequencer.prototype._isReady = function () {
- return (this._schedule !== null);
- };
-
- Sequencer.prototype._onTimingChange = function (event) {
- // Set the time for this processing step
- var now = this._clock.now();
- var initVector = this._to.vector;
-
- if (this._isReady() === false) {
- // Initial update from timing object starts the sequencer
- this._schedule = new Schedule(now);
- // Register handler on axis
- this._axis.on("change", this._wrappedOnAxisChange, this);
- } else {
- // Deliberately set time (a little) back for delayed updates
- now = initVector.timestamp;
- // Empty schedule
- this._schedule.advance(now);
- }
-
- /*
- Re-evaluate non-singularities
- This is strictly not necessary after vector changes that
- preserve position. However, for simplicity we
- re-evaluate intervals whenever vector changes.
- */
- var nowVector = motionutils.calculateVector(initVector, now);
- var oldKeys = this._activeKeys;
- var newKeys = this._axis.lookupByPoint(nowVector.position).map(function (item) {
- return item.key;
- });
- var exitKeys = unique(oldKeys, newKeys);
- var enterKeys = unique(newKeys, oldKeys);
-
-
-
- /*
- Corner Case: Exiting Singularities
- and
- Exiting closed intervals ]
- and
- Entering open intervals <
- */
- var _isMoving = isMoving(initVector);
- if (_isMoving) {
- var nowPos = nowVector.position;
- var points = this._axis.lookupByInterval(new Interval(nowPos, nowPos, true, true));
- points.forEach(function (pointInfo) {
- // singularities
- if (pointInfo.pointType === axis.PointType.SINGULAR) {
- exitKeys.push(pointInfo.key);
- } else {
- // closed interval?
- var interval = pointInfo.interval;
- var closed = false;
- if (pointInfo.pointType === axis.PointType.LOW && interval.lowInclude) {
- closed = true;
- } else if (pointInfo.pointType === axis.PointType.HIGH && interval.highInclude) {
- closed = true;
- }
- // exiting or entering interval?
- var direction = DirectionType.fromInteger(motionutils.calculateDirection(initVector, now));
- var entering = true;
- if (pointInfo.pointType === axis.PointType.LOW && direction === DirectionType.BACKWARDS)
- entering = false;
- if (pointInfo.pointType === axis.PointType.HIGH && direction === DirectionType.FORWARDS)
- entering = false;
- // exiting closed interval
- if (!entering && closed) {
- exitKeys.push(pointInfo.key);
- }
- // entering open interval
- if (entering && !closed) {
- enterKeys.push(pointInfo.key);
- }
- }
- }, this);
- }
-
-
- /*
- Note : is it possible that a key for singularity
- may be in both enterKeys and exitKeys?
- - only in the corner case of movement and evaluation at eaxctly the point
- where the singularity lies - have duplicate protection elsewhere - ignore
- */
-
- var exitItems = exitKeys.map(function (key) {
- return {key:key, interval: this._axis.getIntervalByKey(key), data: this.getData(key)};
- }, this);
- var enterItems = enterKeys.map(function (key) {
- return {key:key, interval: this._axis.getIntervalByKey(key), data: this.getData(key)};
- }, this);
- // Trigger interval events
- this._processIntervalEvents(now, exitItems, enterItems, []);
-
-
- /*
- Rollback falsely reported events
- Non-singular Intervals entered/left wrongly before update was sorted out above.
- - So far we do not roll back events.
- */
-
- /*
- Re-creating events lost due to network latency in timing object changes.
- This is achieved by advancing and loading from which is derived
- from update vector rather than an actual timestamp.
- */
-
- // Kick off main loop
- this._load(now);
- this._main(now);
- };
-
-
-
- /*
- UPDATE
-
- Updates the axis. Updates have further effect
- if they relate to intervals within the immediate future.
- This roughly corresponds to the covering
- time-interval and covering position-interval.
-
- - EVENTS (i.e. singular intervals)
-
- Relevant events for the sequencer are those that apply to the immediate future
- i.e. the Schedule.
-
- - removed events may have to be invalidated if they were due in immediate future
- - new events may be added to the schedule if due in immedate future
-
- - INTERVALS
- Relevant interval changes trigger exit or enter events,
- and since their relevance is continuous they will be delayed
- no matter how late they are, as long as the interval update is
- relevant for the current position of the timing object.
- */
-
- Sequencer.prototype.updateAll = function(argList) {
- this._axis.updateAll(argList);
- };
-
-
- Sequencer.prototype._onAxisChange = function (origOpList) {
- var self = this;
- var i, e, key, interval, data;
-
- // filter out NOOPs
- var opList = origOpList.filter(function (op) {
- return (op.type !== axis.OpType.NOOP);
- });
-
- var now = this._clock.now();
- var nowVector = motionutils.calculateVector(this._to.vector, now);
- var nowPos = nowVector.position;
-
- // EXIT and ENTER Intervals
- var enterItems = []; // {key:key, interval:interval}
- var exitItems = []; // {key:key, interval:interval}
- var isActive, shouldBeActive;
-
- opList.forEach(function (op) {
- interval = op.interval;
- key = op.key;
- /*
- Re-evaluate active intervals. Immediate action is required only if
- a interval was active, but no longer is -- or the opposite.
-
- Singularity intervals may not be ignored here - as a singluarity
- might have been an active interval and just now collapsed
- into a singularity
- */
- isActive = this.isActive(key);
- shouldBeActive = false;
- if (op.type === axis.OpType.CREATE || op.type === axis.OpType.UPDATE) {
- if (interval.coversPoint(nowPos)) {
- shouldBeActive = true;
- }
- }
- // set data element
- if (op.type === axis.OpType.REMOVE) {
- data = op.data
- } else {
- data = op.data || this.getData(key)
- }
- if (isActive && !shouldBeActive) {
- exitItems.push({key:key, interval:interval, data: data});
- } else if (!isActive && shouldBeActive) {
- enterItems.push({key:key, interval:interval, data: data});
- }
- }, this);
-
-
- /*
- change events
- generate change events for currently active spans, which did change,
- but remained active - thus no enter/exit events will be emitted).
-
- these are items that are active, but not in enterItems list
- including NOOP operation (change in non-temporal sense)
- */
- var exitKeys = exitItems.map(function (item) {return item.key;});
- var changeItems = origOpList.
- filter (function (op) {
- return (this.isActive(op.key) && exitKeys.indexOf(op.key) === -1);
- }, this).
- map (function (op) {
- return {key: op.key, interval: op.interval, data: op.data};
- }, this);
-
- /*
- special case
- - no changes to axis - no need to touch the SCHEDULE
- */
- if (opList.length === 0) {
- if (changeItems.length > 0) {
- // break control flow so that events are emitted after addCue has completed
- setTimeout(function () {
- // enterItems and exitItems are empty
- self._processIntervalEvents(now, [], [], changeItems);
- // no need to call main - will be called by scheduled timeout
- }, 0);
- }
- return;
- }
-
- /*
- special case
- - not moving - no need to touch the SCHEDULE
- */
- var _isMoving = isMoving(nowVector);
- if (!_isMoving) {
- // break control flow so that events are emitted after addCue has completed
- setTimeout(function () {
- self._processIntervalEvents(now, exitItems, enterItems, changeItems);
- // not moving should imply that SCHEDULE be empty
- // no need to call main - will be called by scheduled timeout
- }, 0);
- return;
- }
-
-
- /*
- filter cue operation relevant to (remainder of) current scheduler window
- purpose - detect common condition that cue operation is irrelevant for SCHEDULE
- no need to touch SCHEDULE.
- - cue endpoint included in scheduler, but needs to be excluded due to cue operation
- - cue endpoitn not in scheduler, but needs to be included due to cue operation
- */
- // TODO
-
- /*
- special case
- - no cue operation relevant to (remainder of) current scheduler window - no need to touch SCHEDULE
- */
- // TODO
-
-
- // INVALIDATE events in the SCHEDULE
- /*
- Re-evaluate the near future. The SCHEDULE may include
- tasks that refer to these keys. These may have to
- change as a result of cue intervals changing.
-
- Basic solution (assumes that this cue operation is relevant for SCHEDULE)
- - invalidate all tasks in the schedule
- - invalidate even if the timing object is not moving
- if timing object is not moving, the schedule may not have been advanced in a while
- simply advance it - to empty it - as an effective way of invalidation
- */
-
- // TODO - simplify the following based on above filtering of relevant cue operatiosn
-
- if (!_isMoving) {
- // not moving - not sure this is necessary
- this._schedule.advance(now);
- } else {
- // moving - invalidate all events - possibly advance is just as good
- opList.forEach(function (op) {
- this._schedule.invalidate(op.key);
- }, this);
-
- // RELOAD events into the SCHEDULE
- var point, reloadPoints = [];
- opList.forEach(function (op) {
- interval = op.interval;
- key = op.key;
-
- // Nothing to reload for remove events
- if (op.type === axis.OpType.REMOVE) {
- return;
- }
-
- /*
- Corner Case: If the new interval is singularity, and if it
- happens to be exactly at , then it needs to be
- fired.
- */
-
- // Reload only required if the msv is moving
- if (_isMoving) {
- /*
- Load interval endpoints into schedule
- The interval has one or two endpoints that might or might not be
- relevant for the remainder of the current time-interval of the schedule.
- Check relevance, i.t. that points are within the
- position range of the schedule.
- */
- var item = {key: key, interval: interval};
- var rangeInterval = this._schedule.getPosInterval();
- if (rangeInterval !== null) {
- if (rangeInterval.coversPoint(interval.low)) {
- item.point = interval.low;
- }
- if (rangeInterval.coversPoint(interval.high)) {
- item.point = interval.high;
- }
- item.pointType = this._axis.getPointType(item.point, item.interval);
- reloadPoints.push(item);
- }
- }
- }, this);
-
- // reload relevant points
- if (reloadPoints.length > 0) {
- this._load(now, reloadPoints);
- }
- }
-
- // break control so that events are emitted after addCue has completed
- setTimeout(function () {
- // notify interval events and change events
- self._processIntervalEvents(now, exitItems, enterItems, changeItems);
- // kick off main loop (should only be required if moving?)
- // TODO - should only be necessary if the SCHEDULE is touched - to cause a new timeout to be set.
- self._main(now);
- }, 0);
-
- };
-
-
- /*
- Sequencer core loop, loops via the timeout mechanism as long
- as the timing object is moving.
- */
- Sequencer.prototype._main = function (now) {
- var eList;
- now = now || this._clock.now();
- // process tasks (empty due tasks from schedule)
- eList = this._processScheduleEvents(now, this._schedule.pop(now));
- this.eventifyTriggerEvents(eList);
- // advance schedule window
- var _isMoving = isMoving(this._to.vector);
- if (_isMoving && this._schedule.isExpired(now)) {
- now = this._schedule.getTimeInterval().high;
- this._schedule.advance(now);
- this._load(now);
- // process tasks again
- eList = this._processScheduleEvents(now, this._schedule.pop(now));
- this.eventifyTriggerEvents(eList);
- }
- // adjust timeout if moving
- if (_isMoving) {
- var newTimeoutRequired = false;
- if (this._timeout === null) newTimeoutRequired = true;
- else {
- // timeout exist - modify?
- // avoid modifying timeout if new timeout is equal to existing timeout
- // i.e. if task point is the same as last time
- var nextTimeoutPoint = this._schedule.getNextTaskPoint();
- if (nextTimeoutPoint === null) {
- // timeout is set for schedule window - no tasks in schedule
- // do not modify timeout
- } else {
- // nextTimeoutPoint defined - tasks in the schedule
- if (nextTimeoutPoint === this._currentTimeoutPoint) {
- // do not modify timeout
- } else {
- // modify timeout
- newTimeoutRequired = true
- }
- }
- }
-
- if (newTimeoutRequired) {
- // clear timeout
- this._clearTimeout();
- // update timeout
- var secAnchor = this._clock.now();
- var secDelay = this._schedule.getDelayNextTs(secAnchor); // seconds
- this._currentTimeoutPoint = nextTimeoutPoint;
- var self = this;
- this._timeout = this._clock.setTimeout(function () {
- self._clearTimeout();
- self._main();
- }, secDelay, {anchor: secAnchor, early: 0.005});
- }
- }
- };
-
-
- Sequencer.prototype._clearTimeout = function () {
- this._currentTimeoutPoint = null;
- if (this._timeout !== null) {
- this._timeout.cancel();
- this._timeout = null;
- }
- };
-
- /*
- LOAD
-
- Sequencer loads a new batch of points from axis into
- the schedule
-
- If given_points is specified, this implies that the
- points to load are known in advance. This is the case when
- axis is being updated dynamically during execution. If
- points are not known the load function fetches points from
- the axis by means of the time cover of the schedule.
-
- load only makes sense when timing object is moving
- */
-
- Sequencer.prototype._load = function (now, givenPoints) {
- var initVector = this._to.vector;
- if (!isMoving(initVector)) {
- return;
- }
-
-
- /*
- MOVING
- Load events from time interval
- */
- var timeInterval = this._schedule.getTimeInterval();
- var tStart = timeInterval.low;
- var tEnd = timeInterval.high;
- var tDelta = tEnd - tStart;
- // range
- var range = this._to.range;
- var vectorStart = motionutils.calculateVector(initVector, tStart);
- var points = givenPoints;
-
- // Calculate points if not provided
- if (!points) {
- // 1) find the interval covered by the movement of timing object during the time delta
- var posRange = motionutils.calculateInterval(vectorStart, tDelta);
- var pStart = Math.max(posRange[0], range[0]);
- var pEnd = Math.min(posRange[1], range[1]);
- var posInterval = new Interval(pStart, pEnd, true, true);
- this._schedule.setPosInterval(posInterval);
-
- // 2) find all points in this interval
- points = this._axis.lookupByInterval(posInterval);
- }
-
- /*
- Add data to points
- */
- points.forEach(function (pointInfo){
- pointInfo.data = this.getData(pointInfo.key);
- }, this);
-
- /*
- Note : 1) and 2) could be replaced by simply fetching
- all points of the axis. However, in order to avoid
- calculating time intercepts for a lot of irrelevant points, we
- use step 1) and 2) to reduce the point set.
- */
-
- // create ordered list of all events for time interval t_delta
- var eventList = motionutils.calculateSolutionsInInterval(vectorStart, tDelta, points);
-
- /*
- SUBTLE 1 : adjust for range restrictions within
- time-interval tasks with larger delta will not be
- pushed to schedule it is not necessary to truncate the
- time interval of schedule similarly - just drop all
- events after prospective range violations. is
- time to (first) range violation
- */
- var rDelta = motionutils.calculateDelta(vectorStart, range)[0];
-
- /*
- SUBTLE 2: avoid tasks exactly at start of time-interval
- assume that this point should already be processed by the
- previous covering interval.
- */
-
- // filter and push events on sched
- eventList.forEach(function (e) {
-
- var d = e[0];
- var task = e[1];
- var push = true;
-
- /*
- drop events exactly at the start of the time covering
- interval.
- */
- if (d === 0) {
- push = false;
- }
- /*
- drop all events scheduled after (in time) range
- violation should occur
- */
- if (d > rDelta) {
- push = false;
- }
- /*
- event scheduled exactly at range point.
- - interval :
- Exiting/entering a interval should not happen at range point - drop
- */
- if (d === rDelta) {
- push = false;
- }
-
- /*
- check if we are touching an interval without
- entering or exiting. Note that direction will
- not be zero at this point, because direction
- includes acceleration, which is not zero in
- this case.
- drop all interval events that have zero velocity
- at the time it is supposed to fire
- */
- if (task.pointType === axis.PointType.LOW || task.pointType === axis.PointType.HIGH) {
- var v = motionutils.calculateVector(initVector, tStart + d);
- if (v.velocity === 0){
- push = false;
- }
- }
- // push
- if (push) {
- this._schedule.push(now, tStart + d, task);
- }
- }, this);
- };
-
-
- /*
- Helper function to make event messages
- */
- Sequencer.prototype._makeEArgs = function(key, interval, data, directionInt, verbType, point, ts, dueTs) {
- var directionType = DirectionType.fromInteger(directionInt);
- var pointType = this._axis.getPointType(point, interval);
- if (verbType === undefined) {
- var pointInt = axis.PointType.toInteger(pointType);
- var verbInt = pointInt * directionInt * -1;
- verbType = VerbType.fromInteger(verbInt);
- }
- return new SequencerEArgs(this, key, interval, data, point, pointType, ts, dueTs, directionType, verbType);
- };
-
-
- // Process point events originating from the schedule
- Sequencer.prototype._processScheduleEvents = function (now, eventList) {
- var msg, msgList = [];
- var nowVector = motionutils.calculateVector(this._to.vector, now);
- var directionInt = motionutils.calculateDirection(nowVector, now);
- var ts = this._clock.now();
- eventList.forEach(function (e) {
- if (e.task.interval.isSingular()) {
- // make two event messages for singular
- msg = this._makeEArgs(e.task.key, e.task.interval, e.task.data, directionInt, VerbType.ENTER,e.task.point, ts, e.ts);
- msgList.push(msg);
- msg = this._makeEArgs(e.task.key, e.task.interval, e.task.data, directionInt, VerbType.EXIT,e.task.point, ts, e.ts);
- msgList.push(msg);
- } else {
- msg = this._makeEArgs(e.task.key, e.task.interval, e.task.data, directionInt, undefined, e.task.point, ts, e.ts);
- msgList.push(msg);
- }
- }, this);
- return this._makeEvents(now, msgList);
- };
-
- // Process interval events orignating from axis change, timing object change or active keys
- Sequencer.prototype._processIntervalEvents = function (now, exitItems, enterItems, changeItems) {
- if (exitItems.length + enterItems.length + changeItems.length === 0) {
- return;
- }
- var nowVector = motionutils.calculateVector(this._to.vector, now);
- var directionInt = motionutils.calculateDirection(nowVector, now);
- var ts = this._clock.now();
- var msgList = [];
- // trigger events
- exitItems.forEach(function (item){
- msgList.push(this._makeEArgs(item.key, item.interval, item.data, directionInt, VerbType.EXIT, nowVector.position, ts, now));
- }, this);
- enterItems.forEach(function (item){
- msgList.push(this._makeEArgs(item.key, item.interval, item.data, directionInt, VerbType.ENTER, nowVector.position, ts, now));
- }, this);
- changeItems.forEach(function (item) {
- msgList.push(this._makeEArgs(item.key, item.interval, item.data, directionInt, VerbType.CHANGE, nowVector.position, ts, now));
- }, this);
- this.eventifyTriggerEvents(this._makeEvents(now, msgList));
- };
-
-
- Sequencer.prototype._processInitialEvents = function () {
- // called by makeInitEvents - return event list based on activeKeys
- var interval, data, eArg;
- var now = this._clock.now();
- var nowVector = motionutils.calculateVector(this._to.vector, now);
- var directionInt = motionutils.calculateDirection(nowVector, now);
- var ts = this._clock.now();
- return this._activeKeys.map(function (key) {
- interval = this._axis.getIntervalByKey(key);
- data = this.getData(key);
- eArg = this._makeEArgs(key, interval, data, directionInt, VerbType.ENTER, nowVector.position, ts, now);
- return {type: VerbType.ENTER, e: eArg};
- }, this);
- };
-
-
- /*
- make events ensures consistency of active keys as changes
- to active keys are driven by actual notifications
- */
-
- Sequencer.prototype._makeEvents = function (now, msgList) {
- if (msgList.length === 0) {
- return [];
- }
- // manage active keys
- var index, eventList = [];
- msgList.forEach(function (msg) {
- // exit interval - remove keys
- if (msg.type === VerbType.EXIT) {
- index = this._activeKeys.indexOf(msg.key);
- if (index > -1) {
- this._activeKeys.splice(index, 1);
- }
- }
- // enter interval - add key
- if (msg.type === VerbType.ENTER) {
- index = this._activeKeys.indexOf(msg.key);
- if (index === -1) {
- this._activeKeys.push(msg.key);
- }
- }
- eventList.push(msg);
- }, this);
- // make sure events are correctly ordered
- eventList = this._reorderEventList(eventList);
- // finalise events
- return eventList.map(function (item) {
- return {type: item.type, e:item};
- });
- };
-
- /*
- Event list is sorted by time.
- There can be multiple events on the same time.
- Events with the same point (thus time) need to be sorted according to the following precedence
- a. exit interval > (interval does not include exit-point)
- x. enter interval [ (interval includes enter-point)
- b. enter singular
- c. exit singular
- y. exit intervals ] (interval includes exit-point)
- d. enter intervals < (interval does not include enter-point)
- */
- Sequencer.prototype._reorderEventList = function (msgList) {
- if (msgList.length < 2) return msgList;
- // stack events per point
- var point, dueTs, newList = [];
- var s = {"a": [], "x": [], "b": [], "c": [], "y": [], "d": []};
- msgList.forEach(function(msg) {
- // new point - pop from stack
- if (msg.point !== point || msg.dueTs !== dueTs) {
- newList = newList
- .concat(s["a"])
- .concat(s["x"])
- .concat(s["b"])
- .concat(s["c"])
- .concat(s["y"])
- .concat(s["d"]);
- s = {"a": [], "x": [], "b": [], "c": [], "y": [], "d": []};
- point = msg.point;
- dueTs = msg.dueTs;
- }
- // push on stack
- if (msg.pointType === axis.PointType.SINGULAR) {
- if (msg.type === VerbType.ENTER) {
- // enter singular
- s["b"].push(msg);
- } else {
- // exit singular
- s["c"].push(msg);
- }
- } else {
- /*
- Interval
- special ordering when we enter or exit interval
- through endpoint (low or high) and this endpoint is CLOSED ] as opposed to OPEN >
- */
- var closed = false;
- if ((msg.pointType === axis.PointType.LOW) && msg.interval.lowInclude) {
- closed = true;
- } else if ((msg.pointType === axis.PointType.HIGH) && msg.interval.highInclude) {
- closed = true;
- }
- if (msg.type === VerbType.ENTER) {
- // enter interval
- if (closed) s["x"].push(msg);
- else s["d"].push(msg);
- } else {
- // exit interval
- if (closed) s["y"].push(msg);
- else s["a"].push(msg);
- }
- }
- }, this);
-
- // pop last from stack
- return newList
- .concat(s["a"])
- .concat(s["x"])
- .concat(s["b"])
- .concat(s["c"])
- .concat(s["y"])
- .concat(s["d"]);
- };
-
-
- // get request builder object
- Sequencer.prototype.request = function () {
- return new Builder(this);
- };
-
- // TODO : force SequencerCue object on input?
- Sequencer.prototype.addCue = function (key, interval, data) {
- return this.updateAll([{key:key, interval:interval, data: data}]);
- };
-
- Sequencer.prototype.removeCue = function (key, removedData) {
- return this.updateAll([{key:key, interval:undefined, data:removedData}]);
- };
-
- // true if cues exists with given key
- Sequencer.prototype.hasCue = function (key) {
- return this._axis.hasKey(key);
- };
-
- // Get all keys
- Sequencer.prototype.keys = function () {
- return this._axis.keys();
- };
-
- // get specific cue {key: key, interval:interva} given key
- Sequencer.prototype.getCue = function (key) {
- if (this._axis.hasKey(key)) {
- return new SequencerCue (key, this._axis.getIntervalByKey(key), this.getData(key));
- }
- };
-
- // get all cues
- Sequencer.prototype.getCues = function () {
- return this.keys().map(function (key) {
- return this.getCue(key);
- }, this);
- };
-
- // return true if cue of given key is currently active
- Sequencer.prototype.isActive = function (key) {
- return (this._activeKeys.indexOf(key) > -1);
- };
-
- // Get keys of active cues
- Sequencer.prototype.getActiveKeys = function () {
- // copy keys
- var res = [];
- this._activeKeys.forEach(function (key) {
- res.push(key);
- }, this);
- return res;
- };
-
- Sequencer.prototype.getActiveCues = function () {
- var res = [];
- this._activeKeys.forEach(function (key) {
- res.push(this.getCue(key));
- }, this);
- return res;
- };
-
-
- // return all (key, inteval, data) tuples, where interval covers point
- Sequencer.prototype.getCuesByPoint = function (point) {
- return this._axis.lookupByPoint(point).map(function (item) {
- return this.getCue(item.key);
- }, this);
- };
-
- // return all cues with at least one endpoint within searchInterval
- Sequencer.prototype.getCuesByInterval = function (searchInterval) {
- // keys may be mentioned for 2 points in searchInterval - use dict to avoid duplicating intervals
- var _dict = {};
- this._axis.lookupByInterval(searchInterval).forEach(function (pointInfo) {
- _dict[pointInfo.key] = pointInfo.interval;
- });
- return Object.keys(_dict).
- map(function(key){
- return this.getCue(key);
- }, this).
- filter(function (cue) {
- return (searchInterval.overlapsInterval(cue.interval));
- }, this);
- };
-
- // return all cues covered by searchInterval
- Sequencer.prototype.getCuesCoveredByInterval = function (searchInterval) {
- return this.getCuesByInterval(searchInterval).filter(function (cue) {
- return (searchInterval.coversInterval(cue.interval)) ? true : false;
- }, this);
- };
-
- // shutdown
- Sequencer.prototype.close = function () {
- this._to.off("change", this._wrappedOnTimingChange, this);
- this._axis.off("change", this._wrappedOnAxisChange, this);
- if (this._timeout !== null) {
- this._timeout.cancel();
- this._timeout = null;
- }
- };
-
-
- // Inherit function used for specialized sequencers.
- var inherit = function (Child, Parent) {
- var F = function () {}; // empty object to break prototype chain - hinder child prototype changes to affect parent
- F.prototype = Parent.prototype;
- Child.prototype = new F(); // child gets parents prototypes via F
- Child.uber = Parent.prototype; // reference in parent to superclass
- Child.prototype.constructor = Child; // resetting constructor pointer
- };
-
- // Module Definition
- return {
- inherit : inherit,
- Interval : Interval,
- DefaultSequencer : Sequencer,
- Axis : axis.Axis,
- SequencerError : SequencerError,
- };
-
-});
-
-
-
-
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-
-/*
- WINDOW SEQUENCER
-
- - a collection of Intervals are defined on an axis
- - a searchInterval is defined by two endpoints.
- - we are interested in all Intervals on the axis that are partially/fully covered by searchInterval
- - we then want to move the searchInterval along the axis
- - trigger onenter/onexit events as Intervals go from being not covered to partialy/fully covered and vica versa
- - define searchInterval endpoints by two motions that may or may not be dependent
- - use pointsequencer on each motion to generate events.
-*/
-
-
-define('sequencing/windowsequencer',['util/eventutils', 'util/motionutils', './axis', './sequencer'],
- function (eventutils, motionutils, axis, seq) {
-
- 'use strict';
-
- /*
- unique
- return list of elements that are unique to array 1
- */
- var unique = function (array1, array2) {
- var res = [];
- for (var i=0; i -1 && newKeys.indexOf(op.key) > -1) {
- changeKeys.push(op.key);
- }
- });
- }
-
- // update active keys
- this._activeKeys = newKeys;
-
- // make event items from enter/exit keys
- var eList = [];
- var exitItems = exitKeys.forEach(function (key) {
- var op = this._getOpFromAxisOpList(axisOpList, key);
- var interval, data;
- if (op.type === axis.OpType.REMOVE) {
- interval = op.interval;
- data = op.data;
- } else {
- interval = this._axis.getIntervalByKey(key);
- data = this.getData(key);
- }
- eList.push({
- type: "exit",
- e: {
- key : key,
- interval : interval,
- type : "exit",
- data : data
- }
- });
- }, this);
- var enterItems = enterKeys.forEach(function (key) {
- eList.push({
- type: "enter",
- e: {
- key:key,
- interval: this._axis.getIntervalByKey(key),
- type: "enter",
- data: this.getData(key)
- }
- });
- }, this);
- var changeItems = changeKeys.forEach(function (key) {
- eList.push({
- type: "change",
- e: {
- key:key,
- interval: this._axis.getIntervalByKey(key),
- type: "change",
- data: this.getData(key)
- }
- });
- }, this);
- this.eventifyTriggerEvents(eList);
-
- // make event items from active keys
- return this._activeKeys.map(function (key) {
- return {
- type: "enter",
- e: {
- key:key,
- interval: this._axis.getIntervalByKey(key),
- type : "enter"
- }
- };
- }, this);
- };
-
- /*
- API
-
- Operations that affect the axis can safely be directed to
- one of the sequencers, since the two sequencers forward these operations to a shared axis.
- */
-
- WindowSequencer.prototype.request = function () {
- return this._seqA.request();
- };
-
- WindowSequencer.prototype.addCue = function (key, interval, data) {
- return this._seqA.addCue(key, interval, data);
- };
-
- WindowSequencer.prototype.removeCue = function (key, removedData) {
- return this._seqA.removeCue(key, removedData);
- };
-
- // true if cues exists with given key
- WindowSequencer.prototype.hasCue = function (key) {
- return this._seqA.hasCue(key);
- };
-
- // Get all keys
- WindowSequencer.prototype.keys = function () {
- return this._seqA.keys();
- };
-
- // get specific cue {key: key, interval:interva} given key
- WindowSequencer.prototype.getCue = function (key) {
- return this._seqA.getCue(key);
- };
-
- // get all cues
- WindowSequencer.prototype.getCues = function () {
- return this._seqA.getCues();
- };
-
- // return true if cue of given key is currently active
- WindowSequencer.prototype.isActive = function (key) {
- return (this._activeKeys.indexOf(key) > -1);
- };
-
- // Get keys of active cues
- WindowSequencer.prototype.getActiveKeys = function () {
- // copy keys
- var res = [];
- this._activeKeys.forEach(function (key) {
- res.push(key);
- }, this);
- return res;
- };
-
- WindowSequencer.prototype.getActiveCues = function () {
- var res = [];
- this._activeKeys.forEach(function (key) {
- res.push(this.getCue(key));
- }, this);
- return res;
-
- };
-
- // return all (key, inteval, data) tuples, where interval covers point
- WindowSequencer.prototype.getCuesByPoint = function (point) {
- return this._seqA.getCuesByPoint(point);
- };
-
- // return all cues with at least one endpoint within searchInterval
- WindowSequencer.prototype.getCuesByInterval = function (searchInterval) {
- return this._seqA.getCuesByInterval(searchInterval);
- };
-
- // return all cues covered by searchInterval
- WindowSequencer.prototype.getCuesCoveredByInterval = function (searchInterval) {
- return this._seqA.getCuesCoveredByInterval(searchInterval);
- };
-
- // shutdown
- WindowSequencer.prototype.close = function () {
- this._axis.off("change", this._wrappedOnAxisChange);
- this._toA.off("change", this._wrappedOnTimingChangeA);
- this._toB.off("change", this._wrappedOnTimingChangeB);
- this._seqA.off("events", this._wrappedOnSequencerChangeA);
- this._seqB.off("events", this._wrappedOnSequencerChangeB);
- this._seqA.close();
- this._seqB.close();
- };
-
- // inheritance
- // To be overridden by subclass specializations
- WindowSequencer.prototype.loadData = function () {};
- WindowSequencer.prototype.getData = function (key) {};
-
- return WindowSequencer;
-});
/*
Copyright 2015 Norut Northern Research Institute
Author : Ingar Mæhlum Arntzen
@@ -5049,473 +38,6 @@ define('sequencing/windowsequencer',['util/eventutils', 'util/motionutils', './a
along with Timingsrc. If not, see .
*/
-define ('sequencing/timingcallbacks',['util/motionutils'], function (motionutils) {
-
- 'use strict';
-
- // Utility inheritance function.
- var inherit = function (Child, Parent) {
- var F = function () {}; // empty object to break prototype chain - hinder child prototype changes to affect parent
- F.prototype = Parent.prototype;
- Child.prototype = new F(); // child gets parents prototypes via F
- Child.uber = Parent.prototype; // reference in parent to superclass
- Child.prototype.constructor = Child; // resetting constructor pointer
- };
-
- var TimingCallbackBase = function (timingObject, handler) {
- this._timingsrc = timingObject;
- this._handler = handler;
- this._timeout = null;
- this._wrappedOnChange = function () {this._onChange();};
- // initialise
- this.timingsrc = timingObject;
- };
-
- TimingCallbackBase.prototype._renewTimeout = function () {
- this._clearTimeout();
- var res = this._calculateTimeout();
- if (res.delay === null) return null;
- var self = this;
- this._timeout = this._timingsrc.clock.setTimeout(function () {
- self._onTimeout();
- }, res.delay, {anchor: res.anchor, early: 0.005});
- };
-
- // update event from timing object
- TimingCallbackBase.prototype._clearTimeout = function () {
- // cleanup
- if (this._timeout !== null) {
- this._timeout.cancel();
- this._timeout = null;
- }
- };
-
- // update event from timing object
- TimingCallbackBase.prototype.cancel = function () {
- // cleanup
- this._clearTimeout();
- this._timingsrc.off("change", this._wrappedOnChange, this);
- };
-
- /*
- Accessor for timingsrc.
- Supports dynamic switching of timing source by assignment.
- */
- Object.defineProperty(TimingCallbackBase.prototype, 'timingsrc', {
- get : function () {return this._timingsrc;},
- set : function (timingObject) {
- if (this._timingsrc) {
- this._timingsrc.off("change", this._wrappedOnChange, this);
- }
- clearTimeout(this._tid);
- this._timingsrc = timingObject;
- this._timingsrc.on("change", this._wrappedOnChange, this);
- }
- });
-
-
- /*
- SET POINT CALLBACK
- callback when timing object position is equal to point
- options {repeat:true} implies that callback will occur repeatedly
- every time timing object passes point.
- Default is to fire only once, similar to setTimeout
- */
-
- var SetPointCallback = function (timingObject, handler, point, options) {
- TimingCallbackBase.call(this, timingObject, handler);
- this._options = options || {};
- this._options.repeat = (this._options.repeat !== undefined) ? this._options.repeat : false;
- this._point = point;
- };
- inherit(SetPointCallback, TimingCallbackBase);
-
-
- // update event from timing object
- SetPointCallback.prototype._onChange = function () {
- if (this._timingsrc.query().position === this._point) {
- this._handler();
- }
- this._renewTimeout();
- };
-
- // update event from timing object
- SetPointCallback.prototype._onTimeout = function () {
- if (!this._options.repeat) {
- this.cancel();
- };
- this._handler();
- this._renewTimeout();
- };
-
- SetPointCallback.prototype._calculateTimeout = function () {
- var vector = this._timingsrc.query();
- var delay = motionutils.calculateMinPositiveRealSolution(vector, this._point);
- return {
- anchor: vector.timestamp,
- delay: delay
- };
- };
-
-
- /*
-
- SET INTERVAL CALLBACK
-
- callback callback for every point x, where (x - offset) % length === 0
- options : {offset:offset}
- Default is offset 0
- */
-
- var SetIntervalCallback = function (timingObject, handler, length, options) {
- TimingCallbackBase.call(this, timingObject, handler);
- this._options = options || {};
- this._options.offset = (this._options.offset !== undefined) ? this._options.offset : 0;
- this._length = length;
- };
- inherit(SetIntervalCallback, TimingCallbackBase);
-
- // ovverride modulo to behave better for negative numbers
- SetIntervalCallback.prototype._mod = function (n, m) {
- return ((n % m) + m) % m;
- };
-
- // get point representation from float
- SetIntervalCallback.prototype._getPoint = function (x) {
- var skew = this._options.offset;
- return {
- n : Math.floor((x-skew)/this._length),
- offset : this._mod(x-skew, this._length)
- };
- };
-
- // get float value from point representation
- SetIntervalCallback.prototype._getFloat = function (p) {
- var skew = this._options.offset;
- return skew + (p.n * this._length) + p.offset;
- };
-
- // update event from timing object
- SetIntervalCallback.prototype._onChange = function () {
- var points = this._calculatePoints(this._timingsrc.query().position);
- if (points.isTarget) {
- this._handler();
- }
- this._renewTimeout();
- };
-
- // update event from timing object
- SetIntervalCallback.prototype._onTimeout = function () {
- this._handler();
- this._renewTimeout();
- };
-
- /*
- Calculate target points before and after a given position.
- If the given position is itself a target point, this will
- be reported as isTarget===true.
- */
-
- SetIntervalCallback.prototype._calculatePoints = function (position) {
- var beforePoint = {}, afterPoint = {};
- var target;
- var point = this._getPoint(position);
- if (point.offset === 0) {
- target = true;
- beforePoint.n = point.n - 1;
- beforePoint.offset = point.offset;
- afterPoint.n = point.n + 1;
- afterPoint.offset = point.offset;
- } else {
- target = false;
- beforePoint.n = point.n;
- beforePoint.offset = 0;
- afterPoint.n = point.n + 1;
- afterPoint.offset = 0;
- }
- return {
- isTarget : target,
- before : this._getFloat(beforePoint),
- after : this._getFloat(afterPoint)
- }
- };
-
- SetIntervalCallback.prototype._calculateTimeout = function () {
- var vector = this._timingsrc.query();
- var points = this._calculatePoints(vector.position);
- var delay = motionutils.calculateDelta(vector, [points.before, points.after])[0];
- return {
- anchor: vector.timestamp,
- delay: delay
- };
- };
-
-
- // module definition
- return {
- setPointCallback: function (timingObject, handler, point, options) { return new SetPointCallback(timingObject, handler, point, options);},
- setIntervalCallback : function (timingObject, handler, length, options) { return new SetIntervalCallback(timingObject, handler, length, options);}
- };
-});
-define('sequencing/jerkyinterval',['util/eventutils', 'util/motionutils'],
- function (eventutils, motionutils) {
-
-
- /*
- JERKY INTERVAL
-
- This describes an interval that can be controlled using one or two timing objects.
-
- - advances in a step-wise manner (i.e. DISCRETE or JERKY) along the timeline, when needed
- - triggered by change events from timingobjects, or
- - timingobjects violate left or right restrictions
-
- - left : buffer to the left of the leftmost timing object - defaults to 5 units (i.e. 5 seconds at velocity 1 unit/second)
- - right : buffer to the rigth of the rightmost timing object - defaults to 5 units (i.e. 5 seconds at velocity 1 unit/second)
-
- - total length of interval fixed when reevaluated - as the union of three intervals
- - [left, toA.position] U [toA.position, toB.position] U [toB.position, right]
-
- - the second timing object toB is optional. If missing the interval is fixed as
- - [left, toA.position] U [toA.position, right]
- */
-
-
- var JerkyInterval = function (toA, toB, options) {
- // timingobjects
- this._toA = toA;
- this._toB = toB;
- this._toList = [this._toA];
- if (this._toB) this._toList.push(this._toB);
-
- // timeouts needed to detect left|right violations
- this._timeout = null;
-
- // options
- options = options || {};
- this._left = options.left || 5;
- this._right = options.right || 5;
-
- // internal state
- this._low;
- this._high;
- this._ready = false;
-
- // event support
- eventutils.eventify(this, JerkyInterval.prototype);
- this.eventifyDefineEvent("ready", {init:true}) // define ready event
- this.eventifyDefineEvent("change", {init:true}); // define change event (supporting init-event)
-
- // ready when all timingobjects are ready
- var self = this;
- var promises = this._toList.map(function(to) {
- return to.readyPromise;
- });
- Promise.all(promises).then(function (values) {
- self._initialise();
- });
-
- // subscribe to events from all timing objects
- this._toList.forEach(function (to) {
- to.on("change", this._onChange, this);
- }, this);
- };
-
- JerkyInterval.prototype._initialise = function () {
- this._ready = true;
- this.eventifyTriggerEvent("ready");
- };
-
- JerkyInterval.prototype.eventifyMakeInitEvents = function (type) {
- if (type === "change") {
- return [{type: type, e: undefined}];
- } else if (type === "ready") {
- return (this._ready) ? [{type:type, e: undefined}] : [];
- }
- return [];
- };
-
- Object.defineProperty(JerkyInterval.prototype, 'ready', {
- get : function () {
- return this._ready;
- }
- });
-
- Object.defineProperty(JerkyInterval.prototype, 'low', {
- get : function () {
- return this._low;
- }
- });
-
- Object.defineProperty(JerkyInterval.prototype, 'high', {
- get : function () {
- return this._high;
- }
- });
-
- Object.defineProperty(JerkyInterval.prototype, 'readyPromise', {
- get : function () {
- var self = this;
- return new Promise (function (resolve, reject) {
- if (self._ready) {
- resolve();
- } else {
- var onReady = function () {
- self.off("ready", onReady);
- resolve()
- };
- self.on("ready", onReady);
- }
- });
- }
- });
-
- Object.defineProperty(JerkyInterval.prototype, 'range', {
- get : function () {
- return [this._low, this._high];
- }
- });
-
- JerkyInterval.prototype._onChange = function () {
- this._refresh();
- };
-
- JerkyInterval.prototype._onTimeout = function () {
- this._refresh();
- }
-
-
- JerkyInterval.prototype._refresh = function () {
- var self = this;
- var snapshots = this._toList.map(function (to) {
- return to.query();
- });
- var ok = this._checkRange(snapshots);
- if (!ok) {
- // not ok - update low and high based on snapshot
- this._update(snapshots);
- }
- this._resetTimeout();
- };
-
- JerkyInterval.prototype._update = function (vectorList) {
- var low = vectorList.reduce(function (prevLow, vector) {
- return Math.min(prevLow, vector.position);
- }, Infinity) - this._left;
- var high = vectorList.reduce(function (prevHigh, vector) {
- return Math.max(prevHigh, vector.position);
- }, -Infinity) + this._right;
- var dirty = false;
- if (low !== this._low){
- this._low = low;
- dirty = true;
- }
- if (high !== this._high) {
- this._high = high;
- dirty = true;
- }
- if (dirty) {
- this.eventifyTriggerEvent("change");
- }
- };
-
- JerkyInterval.prototype._checkRange = function (vectorList) {
- return vectorList.map(function (vector) {
- var direction = motionutils.calculateDirection(vector, vector.timestamp);
- var ok = true;
- if (this._low === undefined || this._high === undefined) {
- ok = false;
- } else if (vector.position < this._low || this._high < vector.position) {
- ok = false;
- } else if (vector.position === this._low && direction === -1) {
- ok = false;
- } else if (vector.position === this._high && direction === 1) {
- ok = false;
- }
- return ok;
- }, this)
- .reduce(function (prevResult, bool) {
- return prevResult && bool;
- }, true);
- };
-
- JerkyInterval.prototype._calculateTimeout = function () {
- var self = this;
- return this._toList.map(function (to) {
- return motionutils.calculateDelta(to.query(), [self._low, self._high])[0];
- })
- .reduce(function (prevDelay, delay) {
- // delta positive value or null
- if (prevDelay !== null && delay !== null) return Math.min(prevDelay, delay);
- else if (delay !== null) return delay;
- else if (prevDelay !== null) return prevDelay;
- else return null;
- }, null);
- };
-
- JerkyInterval.prototype._clearTimeout = function () {
- if (this._timeout !== null) {
- this._timeout.cancel();
- this._timeout = null;
- }
- };
-
- JerkyInterval.prototype._resetTimeout = function () {
- this._clearTimeout();
- var delay = this._calculateTimeout();
- if (delay !== null) {
- var self = this;
- this._timeout = this._toA.clock.setTimeout(function () {
- self._onTimeout();
- }, delay, {early: 0.005});
- }
- };
-
- return JerkyInterval;
-});
-/*
- Copyright 2015 Norut Northern Research Institute
- Author : Ingar Mæhlum Arntzen
-
- This file is part of the Timingsrc module.
-
- Timingsrc is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Timingsrc is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with Timingsrc. If not, see .
-*/
-
-define('sequencing/main',['./sequencer', './windowsequencer', './timingcallbacks','./jerkyinterval'],
- function (seq, WindowSequencer, timingcallbacks, JerkyInterval) {
- 'use strict';
-
- // Common constructor for Sequencer and WindowConstructor
- var Sequencer = function (timingObjectA, timingObjectB, _axis) {
- if (timingObjectB === undefined) {
- return new seq.DefaultSequencer(timingObjectA, _axis);
- } else {
- return new WindowSequencer(timingObjectA, timingObjectB, _axis);
- }
- };
-
- return {
- Sequencer : Sequencer,
- Interval : seq.Interval,
- inherit : seq.inherit,
- setPointCallback : timingcallbacks.setPointCallback,
- setIntervalCallback : timingcallbacks.setIntervalCallback,
- JerkyInterval : JerkyInterval
- };
- }
-);
/*
Copyright 2015 Norut Northern Research Institute
Author : Njaal Trygve Borch njaal.borch@norut.no
@@ -5536,823 +58,4 @@ define('sequencing/main',['./sequencer', './windowsequencer', './timingcallbacks
along with Timingsrc. If not, see .
*/
-/*
- MEDIASYNC
-
- Time-aligning a HTMLMediaElement to a Timing Object
-
-*/
-
-define ('mediasync/mediasync',[],function () {
-
- 'use strict';
-
- /**
- * Detect if we need to kick the element
- * If it returns true, you can re-run this function on
- * a user interaction to actually perform the kick
- */
- var _need_kick;
- function needKick(elem) {
- if (_need_kick === false) {
- return false;
- }
- if (elem.canplay) {
- _need_kick = false;
- return false;
- }
- var m = elem.muted;
- elem.muted = true
- elem.play();
- _need_kick = elem.paused == true;
- elem.pause();
- elem.muted = m;
- return _need_kick;
- }
-
- /**
- * The mediaSync object will try to synchronize an HTML
- * media element to a Shared Motion. It exploits
- * playbackRate functionality if possible, but will fallback
- * to only currentTime manipulation (skipping) if neccesariy.
- *
- * Options:
- * * skew (default 0.0)
- * how many seconds (float) should be added to the
- * motion before synchronization. Calculate by
- * start point of element - start point of motion
- * * automute (default true)
- * Mute the media element when playing too fast (or too slow)
- * * mode (default "auto")
- * "skip": Force "skip" mode - i.e. don't try using playbackRate.
- * "vpbr": Force variable playback rate. Normally not a good idea
- * "auto" (default): try playbackRate. If it's not supported, it will
- * struggle for a while before reverting. If 'remember' is not set to
- * false, this will only happen once after each browser update.
- * * loop (default false)
- * Loop the media
- * * debug (default null)
- * If debug is true, log to console, if a function, the function
- * will be called with debug info
- * * target (default 0.025 - 25ms ~ lipsync)
- * What are we aiming for? Default is likely OK, if we can do
- * better, we will. If the target is too narrow, you'll end up
- * with a more skippy experience. When using variable playback
- * rates, this parameter is ignored (target is always 0)
- * * remember (default false)
- * Remember the last experience on this device - stores support
- * or lack of support for variable playback rate. Records in
- * localStorage under key "mediascape_vpbr", clear it to re-learn
- */
- function mediaSync(elem, motion, options) {
- var API;
- var _options = options || {};
- _options.skew = _options.skew || 0.0;
- _options.target = _options.target || 0.025;
- _options.original_target = _options.target;
- _options.loop = _options.loop || false;
- _options.target = _options.target * 2; // Start out coarse
- if (_options.remember === undefined){
- _options.remember = false;
- }
- if (_options.debug || _options.remember === false) {
- localStorage.removeItem("mediascape_vpbr")
- _options.remember = false;
- }
- if (_options.automute === undefined) {
- _options.automute = true;
- }
- var _auto_muted = false;
-
-
- var onchange = function(e) {
- _bad = 0;
- _samples = [];
- _last_skip = null;
-
- // If we're paused, ignore
- if (_stopped || _paused) {
- return;
- }
-
- if (_update_func != undefined) {
- _update_func(e);
- } else {
- console.log("WARNING: onchange but no update func yet");
- }
- }
-
- var setMotion = function(motion) {
- _bad = 0;
- if (_motion) {
- _motion.off("change", onchange);
- }
- _motion = motion;
-
- // if motion is a timing object, we add some shortcuts
- if (_motion.version == 3) {
- _motion.__defineGetter__("pos", function() {return _motion.query().position});
- _motion.__defineGetter__("vel", function() {return _motion.query().velocity});
- _motion.__defineGetter__("acc", function() {return _motion.query().acceleration});
- }
-
- _motion.on("change", onchange);
- };
-
- if (!motion) {
- console.log("WARNING: No motion has been set");
- } else {
- //setMotion(motion);
- }
-
-
- var _stopped = false;
- var _paused = false;
- var _motion;
-
- function onpaused() {
- if (_motion.vel == 1) {
- elem.play();
- }
- }
- function onplay() {
- console.log("onplay");
- if (_motion.vel == 0) {
- elem.pause();
- }
- }
- function onerror() {
- console.log(err); // TODO: REPORT ERRORS
- stop();
- }
-
- var pause = function(val) {
- if (val == undefined) val = true;
- _paused = val;
- if (!_paused) {
- onchange();
- }
- }
-
- var stop = function() {
- _stopped = true;
- elem.removeEventListener("paused", onpaused);
- elem.removeEventListener("play", onplay);
- elem.removeEventListener("error", onerror);
- }
-
-
- var _update_func;
- var _bad = 0;
- var _amazing = 0;
- var last_update;
- var _samples = [];
- var _vpbr; // Variable playback rate
- var _last_bad = 0;
- var _perfect = 5;
- var _is_in_sync = false;
-
-
- var _last_skip;
- var _thrashing = 0;
- var skip = function(pos) {
- if (elem.readyState == 0) {
- return;
- }
- if (_motion.vel != 1) {
- // Just skip, don't do estimation
- elem.currentTime = pos;
- _last_skip = undefined;
- _doCallbacks("skip", {event:"skip", pos:pos, target:_motion.pos, adjust:0})
- return;
- }
-
- var adjust = 0;
- var now = performance.now();
- if (_last_skip) {
- if (now - _last_skip.ts < 1500) {
- _thrashing += 1;
- if (_thrashing > 3) {
- // We skipped just a short time ago, we're thrashing
- _dbg("Lost all confidence (thrashing)");
- _options.target = Math.min(1, _options.target*2);
- _doCallbacks("target_change", {
- event: "target_change",
- target: _options.target,
- reason: "thrashing"
- });
- _thrashing = 0;
- }
- } else {
- _thrashing = 0;
- }
- var elapsed = (now - _last_skip.ts) / 1000;
- var cur_pos = elem.currentTime;
- var miss = (loop(_last_skip.pos + elapsed)) - cur_pos;
- adjust = _last_skip.adjust + miss;
- if (Math.abs(adjust) > 5) adjust = 0; // Too sluggish, likely unlucky
- }
- // Ensure that we're playing back at speed 1
- elem.playbackRate = 1.0;
- _dbg({type:"skip", pos:pos + adjust, target:loop(_motion.pos), adjust:adjust});
- _perfect = Math.min(5, _perfect + 5);
- if (_motion.vel != 1) {
- elem.currentTime = pos;
- } else {
- elem.currentTime = pos + adjust;
- _last_skip = {
- ts: now, //performance.now(),
- pos: pos,
- adjust: adjust
- }
- }
- if (_is_in_sync) {
- _is_in_sync = false;
- _doCallbacks("sync", {event:"sync", sync:false});
- }
- _doCallbacks("skip", {event:"skip", pos:pos + adjust, target:_motion.pos, adjust:adjust})
- };
-
-
- function loop(pos) {
- if (_options.loop) {
- if (_options.duration) {
- return pos % _options.duration;
- } else {
- return pos % elem.duration;
- }
- }
- return pos;
- }
-
- // onTimeChange handler for variable playback rate
- var update_func_playbackspeed = function(e) {
- if (_stopped || _paused) {
- return;
- }
- var snapshot = query();
- if (loop(snapshot.pos) == last_update) {
- return;
- }
- last_update = loop(snapshot.pos);
-
- // If we're outside of the media range, don't stress the system
- var p = loop(snapshot.pos + _options.skew);
- var duration = elem.duration;
- if (duration) {
- if (p < 0 || p > duration) {
- if (!elem.paused) {
- elem.pause();
- }
- return;
- }
- }
-
- // Force element to play/pause correctly
- if (snapshot.vel != 0) {
- if (elem.paused) {
- elem.play();
- }
- } else if (!elem.paused) {
- elem.pause();
- }
-
- try {
- if (!_vpbr && _bad > 40) {
- if (_auto_muted) {
- elem.muted = false;
- _auto_muted = false;
- }
- _doCallbacks("muted", {event:"muted", muted:false});
- throw new Error("Variable playback rate seems broken - " + _bad + " bad");
- }
- // If we're WAY OFF, jump
- var diff = p - elem.currentTime;
- if ((diff < -1) || (snapshot.vel == 0 || Math.abs(diff) > 1)) {
- _dbg({type:"jump", diff:diff});
- // Stationary, we need to just jump
- var new_pos = loop(snapshot.pos + _options.skew);
- if (performance.now() - _last_bad > 150) {
- //_bad += 10;
- _last_bad = performance.now();
- skip(new_pos);
- }
- return;
- }
-
- // Need to smooth diffs, many browsers are too inconsistent!
- _samples.push(diff);
- if (_samples.length >= 3) {
- var avg = 0;
- for (var i = 0; i < _samples.length; i++) {
- avg += _samples[i];
- }
- diff = avg / _samples.length;
- _samples = _samples.splice(0, 1);;
- } else {
- return;
- }
-
- // Actual sync
- _dbg({type:"dbg", diff:diff, bad:_bad, vpbr:_vpbr});
- var getRate = function(limit, suggested) {
- return Math.min(_motion.vel+limit, Math.max(_motion.vel-limit, _motion.vel + suggested));
- }
-
- if (Math.abs(diff) > 1) {
- _samples = [];
- elem.playbackRate = getRate(1, diff*1.3); //Math.max(0, _motion.vel + (diff * 1.30));
- _dbg({type:"vpbr", level:"coarse", rate:elem.playbackRate});
- _bad += 4;
- } else if (Math.abs(diff) > 0.5) {
- _samples = [];
- elem.playbackRate = getRate(0.5, diff*0.75);//Math.min(1.10, _motion.vel + (diff * 0.75));
- _dbg({type:"vpbr", level:"mid", rate:elem.playbackRate});
- _bad += 2;
- } else if (Math.abs(diff) > 0.1) {
- _samples = [];
- elem.playbackRate = getRate(0.4, diff*0.75);//Math.min(1.10, _motion.vel + (diff * 0.75));
- _dbg({type:"vpbr", level:"midfine", rate:elem.playbackRate});
- _bad += 1;
- } else if (Math.abs(diff) > 0.025) {
- _samples = [];
- elem.playbackRate = getRate(0.30, diff*0.60)//Math.min(1.015, _motion.vel + (diff * 0.30));
- _dbg({type:"vpbr", level:"fine", rate:elem.playbackRate});
- } else {
- if (!_vpbr) {
- _bad = Math.max(0, _bad-20);
- _amazing++;
- if (_amazing > 5) {
- _vpbr = true; // Very unlikely to get here if we don't support it!
- if (localStorage && _options.remember) {
- _dbg("Variable Playback Rate capability stored");
- localStorage["mediascape_vpbr"] = JSON.stringify({'appVersion':navigator.appVersion, "vpbr":true});
- }
- }
- }
- if (!_is_in_sync) {
- _is_in_sync = true;
- _doCallbacks("sync", {
- event: "sync",
- sync: true
- });
- }
- elem.playbackRate = getRate(0.02, diff * 0.07); //_motion.vel + (diff * 0.1);
- }
- if (_options.automute) {
- if (!elem.muted && (elem.playbackRate > 1.05 || elem.playbackRate < 0.95)) {
- _auto_muted = true;
- elem.muted = true;
- _doCallbacks("muted", {event:"muted", muted:true});
- _dbg({type:"mute", muted:true});
- } else if (elem.muted && _auto_muted) {
- _auto_muted = false;
- elem.muted = false;
- _dbg({type:"mute", muted:false});
- _doCallbacks("muted", {event:"muted", muted:false});
- }
- }
-
- } catch (err) {
- // Not supported after all!
- if (_options.automute) {
- elem.muted = false;
- }
- _last_skip = null; // Reset skip stuff
- if (localStorage && _options.remember) {
- _dbg("Variable Playback Rate NOT SUPPORTED, remembering this ");
- localStorage["mediascape_vpbr"] = JSON.stringify({'appVersion':navigator.appVersion, "vpbr":false});
- }
- console.log("Error setting variable playback speed - seems broken", err);
- _setUpdateFunc(update_func_skip);
- }
- };
-
- var last_pos;
- var last_diff;
- // timeUpdate handler for skip based sync
- var update_func_skip = function(ev) {
- if (_stopped || _paused) {
- return;
- }
-
- var snapshot = query();
- if (snapshot.vel > 0) {
- if (elem.paused) {
- elem.play();
- }
- } else if (!elem.paused) {
- elem.pause();
- }
-
- if (snapshot.vel != 1) {
- if (loop(snapshot.pos) == last_pos) {
- return;
- }
- last_pos = snapshot.pos;
- _dbg("Jump, playback speed is not :", snapshot.vel);
- // We need to just jump
- var new_pos = loop(snapshot.pos + _options.skew);
- if (elem.currentTime != new_pos) {
- skip(new_pos, "jump");
- }
- return;
- }
-
- var p = snapshot.pos + _options.skew;
- var diff = p - elem.currentTime;
-
- // If this was a Motion jump, skip immediately
- if (ev != undefined && ev.pos != undefined) {
- _dbg("MOTION JUMP");
- var new_pos = snapshot.pos + _options.skew;
- skip(new_pos);
- return;
- }
-
- // Smooth diffs as currentTime is often inconsistent
- _samples.push(diff);
- if (_samples.length >= 3) {
- var avg = 0;
- for (var i = 0; i < _samples.length; i++) {
- avg += _samples[i];
- }
- diff = avg / _samples.length;
- _samples.splice(0, 1);
- } else {
- return;
- }
-
- // We use the number of very good hits to build confidence
- if (Math.abs(diff) < 0.001) {
- _perfect = Math.max(5, _perfect); // Give us some breathing space!
- }
-
- if (_perfect <= -2) {
- // We are failing to meet the target, make target bigger
- _dbg("Lost all confidence");
- _options.target = Math.min(1, _options.target*1.4);
- _perfect = 0;
- _doCallbacks("target_change", {
- event: "target_change",
- target: _options.target,
- reason: "unknown"
- });
- } else if (_perfect > 15) {
- // We are hitting the target, make target smaller if we're beyond the users preference
- _dbg("Feels better");
- if (_options.target == _options.original_target) {
- // We're improving yet 'perfect', trigger "good" sync event
- if (!_is_in_sync) {
- _is_in_sync = true;
- _doCallbacks("sync", {event:"sync", sync:true});
- }
- }
- _options.target = Math.max(Math.abs(diff) * 0.7, _options.original_target);
- _perfect -= 8;
- _doCallbacks("target_change", {
- event: "target_change",
- target: _options.target,
- reason: "improving"
- });
- }
-
- _dbg({type:"dbg", diff:diff, target:_options.target, perfect:_perfect});
-
- if (Math.abs(diff) > _options.target) {
- // Target miss - if we're still confident, don't do anything about it
- _perfect -= 1;
- if (_perfect > 0) {
- return;
- }
- // We've had too many misses, skip
- new_pos = _motion.pos + _options.skew
- //_dbg("Adjusting time to " + new_pos);
- _perfect += 8; // Give some breathing space
- skip(new_pos);
- } else {
- // Target hit
- if (Math.abs(diff - last_diff) < _options.target / 2) {
- _perfect++;
- }
- last_diff = diff;
- }
- }
-
- var _initialized = false;
- var init = function() {
- if (_initialized) return;
- _initialized = true;
- if (_motion === undefined) {
- setMotion(motion);
- }
- if (localStorage && _options.remember) {
- if (localStorage["mediascape_vpbr"]) {
- var vpbr = JSON.parse(localStorage["mediascape_vpbr"]);
- if (vpbr.appVersion === navigator.appVersion) {
- _vpbr = vpbr.vpbr;
- }
- }
- }
-
- if (_options.mode === "vpbr") {
- _vpbr = true;
- }
- if (_options.mode === "skip" || _vpbr === false) {
- elem.playbackRate = 1.0;
- _update_func = update_func_skip;
- } else {
- if (_options.automute) {
- elem.muted = true;
- _auto_muted = true;
- _doCallbacks("muted", {event:"muted", muted:true});
- }
- _update_func = update_func_playbackspeed;
- }
- elem.removeEventListener("canplay", init);
- elem.removeEventListener("playing", init);
- _setUpdateFunc(_update_func);
- _motion.on("change", onchange);
- }
-
- elem.addEventListener("canplay", init);
- elem.addEventListener("playing", init);
-
- var _last_update_func;
- var _poller;
- var _setUpdateFunc = function(func) {
- if (_last_update_func) {
- clearInterval(_poller);
- elem.removeEventListener("timeupdate", _last_update_func);
- elem.removeEventListener("pause", _last_update_func);
- elem.removeEventListener("ended", _last_update_func);
- }
- _last_update_func = func;
- elem.playbackRate = 1.0;
- elem.addEventListener("timeupdate", func);
- elem.addEventListener("pause", func);
- elem.addEventListener("ended", func);
-
- if (func === update_func_playbackspeed) {
- _doCallbacks("mode_change", {event:"mode_change", mode:"vpbr"});
- } else {
- _doCallbacks("mode_change", {event:"mode_change", mode:"skip"});
- }
- }
-
- var query = function() {
- // Handle both msvs and timing objects
- if (_motion.version == 3) {
- var q = _motion.query();
- return {
- pos: q.position,
- vel: q.velocity,
- acc: q.acceleration
- }
- }
- return _motion.query();
- }
-
-
- var setSkew = function(skew) {
- _options.skew = skew;
- }
-
- var getSkew = function() {
- return _options.skew;
- }
-
- var setOption = function(option, value) {
- _options[option] = value;
- if (option === "target") {
- _options.original_target = value;
- }
- }
-
- /*
- * Return 'playbackRate' or 'skip' for play method
- */
- var getMethod = function() {
- if (_update_func === update_func_playbackspeed) {
- return "playbackRate";
- }
- return "skip";
- }
-
- // As we are likely asynchronous, we don't really know if elem is already
- // ready! If it has, it will not emit canplay. Also, canplay seems shady
- // regardless
- var beater = setInterval(function() {
- if (elem.readyState >= 2) {
- clearInterval(beater);
- try {
- var event = new Event("canplay");
- elem.dispatchEvent(event);
- } catch (e) {
- var event = document.createEvent("Event");
- event.initEvent("canplay", true, false)
- elem.dispatchEvent(event);
- }
- };
- }, 100);
-
-
- // callbacks
- var _callbacks = {
- skip: [],
- mode_change: [],
- target_change: [],
- muted: [],
- sync: []
- };
- var _doCallbacks = function(what, e) {
- if (!_callbacks.hasOwnProperty(what)) {
- throw "Unsupported event: " + what;
- }
- for (var i = 0; i < _callbacks[what].length; i++) {
- h = _callbacks[what][i];
- try {
- h.call(API, e);
- } catch (e) {
- console.log("Error in " + what + ": " + h + ": " + e);
- }
- }
- };
-
- // unregister callback
- var off = function(what, handler) {
- if (!_callbacks.hasOwnProperty(what)) throw "Unknown parameter " + what;
- var index = _callbacks[what].indexOf(handler);
- if (index > -1) {
- _callbacks[what].splice(index, 1);
- }
- return API;
- };
-
- var on = function(what, handler, agentid) {
- if (!_callbacks.hasOwnProperty(what)) {
- throw new Error("Unsupported event: " + what);
- }
- if (!handler || typeof handler !== "function") throw "Illegal handler";
- var index = _callbacks[what].indexOf(handler);
- if (index != -1) {
- throw new Error("Already registered");
- }
-
- // register handler
- _callbacks[what].push(handler);
-
- // do immediate callback?
- setTimeout(function() {
- if (what === "sync") {
- _doCallbacks(what, {
- event: what,
- sync: _is_in_sync
- }, handler);
- }
- if (what === "muted") {
- _doCallbacks(what, {
- event: what,
- muted: _auto_muted
- }, handler);
- }
- }, 0);
- return API;
- };
-
-
- function _dbg() {
- if (!_options.debug) {
- return;
- }
- if (typeof(_options.debug) === "function") {
- //_options.debug(arguments);
- var args = arguments;
- setTimeout(function() {
- _options.debug.apply(window, args);
- }, 0);
- } else {
- var args = [];
- for (var k in arguments) {
- args.push(arguments[k]);
- }
- console.log(JSON.stringify(args));
- }
- }
-
-
-
-
- // Export the API
- API = {
- setSkew: setSkew,
- getSkew: getSkew,
- setOption: setOption,
- getMethod: getMethod,
- setMotion: setMotion,
- stop: stop,
- pause: pause,
- on: on,
- off: off,
- init:init
- };
- return API;
- }
-
-
- var MediaSync = function (elem, timingObject, options) {
- this._sync = mediaSync(elem, timingObject, options);
- };
-
- MediaSync.prototype.setSkew = function (skew) {
- this._sync.setSkew(skew);
- };
-
- MediaSync.prototype.getSkew = function () {
- this._sync.getSkew();
- };
-
- MediaSync.prototype.setOption = function (option, value) {
- this._sync.setOption(option, value);
- };
-
- MediaSync.prototype.getMethod = function () {
- this._sync.getMethod();
- };
-
- /*
- Accessor for timingsrc.
- Supports dynamic switching of timing source by assignment.
- */
- Object.defineProperty(MediaSync.prototype, 'timingsrc', {
- get : function () {return this._sync._motion;},
- set : function (timingObject) {
- this._sync.setMotion(timingObject);
- }
- });
-
- MediaSync.prototype.stop = function () {
- this._sync.stop();
- };
-
- MediaSync.prototype.pause = function (val) {
- this._sync.pause(val);
- };
-
- MediaSync.prototype.on = function (what, handler, agentid) {
- this._sync.on(what, handler, agentid);
- };
-
- MediaSync.prototype.off = function (type, handler) {
- this._sync.off(type, handler);
- };
-
- // export module
- return {
- mediaSync : mediaSync,
- MediaSync: MediaSync,
- mediaNeedKick : needKick
- };
-});
-
-
-/*
- Written by Ingar Arntzen, Norut
-*/
-
-define ('timingsrc',['./timingobject/main', './sequencing/main', './mediasync/mediasync'],
- function (timingobject, sequencing, mediasync) {
- return {
- version : "v1",
-
- // Utils
- inherit : timingobject.inherit,
-
- // Timing Object
- TimingObject : timingobject.TimingObject,
- TimingProviderState : timingobject.TimingProviderState,
-
- // Timing Converters
- ConverterBase : timingobject.ConverterBase,
- SkewConverter : timingobject.SkewConverter,
- DelayConverter : timingobject.DelayConverter,
- ScaleConverter : timingobject.ScaleConverter,
- LoopConverter : timingobject.LoopConverter,
- RangeConverter : timingobject.RangeConverter,
- TimeShiftConverter : timingobject.TimeShiftConverter,
- LocalConverter : timingobject.LocalConverter,
- DerivativeConverter : timingobject.DerivativeConverter,
-
- // Sequencing
- Interval : sequencing.Interval,
- Sequencer : sequencing.Sequencer,
- setPointCallback : sequencing.setPointCallback,
- setIntervalCallback : sequencing.setIntervalCallback,
- JerkyInterval : sequencing.JerkyInterval,
-
- // MediaSync
- MediaSync: mediasync.MediaSync,
- mediaNeedKick : mediasync.needKick
- };
-});
-
+define("util/eventutils",[],function(){"use strict";var e=function(e){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";return function(n){n=n||e;var r="";for(var i=0;i0?n[0]:-1},t.prototype.getItem=function(e){return this._map[e]},t.prototype.register=function(e,t){var n=this._getID(e);if(n>-1)throw new Error("handler already registered");return n=this._newID(),this._map[n]={ID:n,handler:e,ctx:t,count:0,pending:!1},n},t.prototype.unregister=function(e){var t=this._getID(e);t!==-1&&delete this._map[t]},t.prototype.getItems=function(){return Object.keys(this._map).map(function(e){return this.getItem(e)},this)};var n=function(n,r){return n._ID=e(4),n._callbacks={},n._callbacks.events=new t,n._callbacks.events._options={init:!0},r.eventifyDefineEvent=function(e,n){if(e==="events")throw new Error("Illegal event type : 'events' is protected");n=n||{},n.init=n.init===undefined?!1:n.init,this._callbacks[e]=new t,this._callbacks[e]._options=n},r._eventifyMakeInitEvents=function(e){var t=this.eventifyMakeInitEvents||function(e){return[]},n;return e!=="events"?n=[e]:n=Object.keys(this._callbacks).filter(function(e){return e!=="events"&&this._callbacks[e]._options.init===!0},this),n.concatMap(function(e){return t.call(this,e)},this)},r._eventifyEventFormatter=function(e,t){var n=this.eventifyEventFormatter||function(e,t){return t};return e==="events"&&(t=t.map(function(e){return n.call(this,e.type,e.e)})),n(e,t)},r._eventifyCallbackFormatter=function(e,t,n){var r=this.eventifyCallbackFormatter||function(e,t,n){return[t]};return r.call(this,e,t,n)},r.eventifyTriggerEvents=function(e){e.forEach(function(e){if(e.type===undefined)throw new Error("Illegal event type; undefined");if(e.type==="events")throw new Error("Illegal event type; triggering of events on protocted event type 'events'")},this);if(e.length===0)return;return this._eventifyTriggerProtectedEvents(e),this._eventifyTriggerRegularEvents(e),this},r.eventifyTriggerEvent=function(e,t){return this.eventifyTriggerEvents([{type:e,e:t}])},r._eventifyTriggerProtectedEvents=function(e,t){this._eventifyTriggerEvent("events",{type:"events",e:e},t)},r._eventifyTriggerRegularEvents=function(e,t){e.forEach(function(e){this._eventifyTriggerEvent(e.type,e,t)},this)},r._eventifyTriggerEvent=function(e,t,n){var r,i,s={};if(!this._callbacks.hasOwnProperty(e))throw new Error("Unsupported event type "+e);var o=this._callbacks[e],u=o._options.init;return o.getItems().forEach(function(o){if(n===undefined){if(o.pending)return!1}else{if(o.ID!==n)return!1;s.init=!0,o.pending=!1}u&&(s.init=o.ID===n?!0:!1),s.count=o.count,s.src=this,i=this._eventifyEventFormatter(t.type,t.e),r=this._eventifyCallbackFormatter(e,i,s);try{return o.handler.apply(o.ctx,r),o.count+=1,!0}catch(a){console.log("Error in "+e+": "+o.handler+" "+o.ctx+": ",a)}},this),!1},r.on=function(e,t,n){if(!t||typeof t!="function")throw new Error("Illegal handler");if(!this._callbacks.hasOwnProperty(e))throw new Error("Unsupported event type "+e);var r=this._callbacks[e];n=n||this;var i=r.register(t,n);if(r._options.init){var s=r.getItem(i);s.pending=!0;var o=this;setTimeout(function(){var t=o._eventifyMakeInitEvents(e);t.length>0?e==="events"?o._eventifyTriggerProtectedEvents(t,i):o._eventifyTriggerRegularEvents(t,i):s.pending=!1},0)}return this},r.off=function(e,t){if(this._callbacks[e]!==undefined){var n=this._callbacks[e];n.unregister(t)}return this},n};return{eventify:n}}),define("util/motionutils",[],function(){"use strict";var e=function(e,t){if(t===undefined)throw new Error("no ts provided for calculateVector");var n=t-e.timestamp;return{position:e.position+e.velocity*n+.5*e.acceleration*n*n,velocity:e.velocity+e.acceleration*n,acceleration:e.acceleration,timestamp:t}},t=Object.freeze({INIT:"init",INSIDE:"inside",OUTSIDE_LOW:"outsidelow",OUTSIDE_HIGH:"outsidehigh"}),n=function(e,n){var r=e.position,i=e.velocity,s=e.acceleration;if(r>n[1])return t.OUTSIDE_HIGH;if(r