@tolokoban/tgd
Version:
ToloGameDev library for WebGL2
233 lines • 18.4 kB
JavaScript
import { TgdEventPriority } from "./../event/index.js";
import { TgdUtilCyclicBuffer } from "./../utils/index.js";
const MOUSE_BUTTON_RIGHT = 2;
export class TgdInputPointer {
constructor(canvas) {
this.canvas = canvas;
this.eventTap = new TgdEventPriority();
this.eventTapMultiple = new TgdEventPriority();
this.eventMoveStart = new TgdEventPriority();
this.eventMove = new TgdEventPriority();
this.eventHover = new TgdEventPriority();
this.eventMoveEnd = new TgdEventPriority();
this.eventZoom = new TgdEventPriority();
/**
* This is a tap only of the pointer touched for less that
* `tapDelay` milliseconds.
*/
this.tapDelay = 300;
this.moves = new TgdUtilCyclicBuffer(8);
this.controlKeys = {
altKey: false,
ctrlKey: false,
metaKey: false,
shiftKey: false,
};
this.start = {
x: 0,
y: 0,
t: 0,
fingersCount: 1,
};
this.current = {
x: 0,
y: 0,
t: 0,
fingersCount: 1,
};
this.previous = {
x: 0,
y: 0,
t: 0,
fingersCount: 1,
};
/**
* To manage multi taps.
*/
this.lastTap = null;
this.tapsCount = 0;
/**
* If not null, the pointer is touching.
*/
this.pointerEvent = null;
this.handleContextMenu = (event) => {
event.preventDefault();
};
this.handleCanvasWheel = (event) => {
const eventDelta = event.deltaX + event.deltaY + event.deltaZ;
const delta = eventDelta > 0 ? 1 : -1;
this.eventZoom.dispatch({
...resolvePointerButtons(event),
current: this.getPoint(event),
direction: delta,
preventDefault: () => event.preventDefault(),
...this.controlKeys,
});
};
this.handlePointerDown = (event) => {
if (!event.isPrimary)
return;
this.canvas?.setPointerCapture(event.pointerId);
event.preventDefault();
event.stopPropagation();
this.pointerEvent = event;
const point = this.getPoint(event);
this.start = this.current = this.previous = point;
this.eventMoveStart.dispatch({
...resolvePointerButtons(event),
start: point,
current: point,
previous: point,
...this.controlKeys,
});
};
this.handlePointerMove = (event) => {
const point = this.getPoint(event);
this.moves.push(point);
if (!event.isPrimary || !this.canvas)
return;
this.previous = this.current;
this.current = point;
const output = {
...resolvePointerButtons(event),
start: this.start,
current: this.current,
previous: this.previous,
...this.controlKeys,
};
this.eventHover.dispatch(output);
if (this.pointerEvent) {
this.eventMove.dispatch(output);
}
};
this.handlePointerUp = (event) => {
if (!event.isPrimary || !this.pointerEvent)
return;
event.preventDefault();
this.current = this.getPoint(event);
this.eventMoveEnd.dispatch({
...resolvePointerButtons(event),
start: this.start,
current: this.current,
previous: this.previous,
...this.controlKeys,
});
this.pointerEvent = null;
// Tap event.
const seconds = event.timeStamp * 1e-3;
if (seconds - this.start.t < this.tapDelay) {
let tapEventEnabled = true;
if (this.isMultiTap(this.start)) {
this.tapsCount++;
this.eventTapMultiple.dispatch({
...resolvePointerButtons(event),
tapsCount: this.tapsCount,
...this.current,
start: this.start,
...this.controlKeys,
preventTap: () => {
tapEventEnabled = false;
},
});
}
else {
this.tapsCount = 1;
}
if (tapEventEnabled) {
this.eventTap.dispatch({
...resolvePointerButtons(event),
...this.current,
start: this.start,
...this.controlKeys,
});
}
this.lastTap = structuredClone(this.start);
}
};
if (!canvas)
return;
canvas.addEventListener("pointerdown", this.handlePointerDown, true);
canvas.addEventListener("wheel", this.handleCanvasWheel);
canvas.addEventListener("contextmenu", this.handleContextMenu);
canvas.addEventListener("pointermove", this.handlePointerMove);
canvas.addEventListener("pointerup", this.handlePointerUp);
}
get x() {
return this.moves.newest?.x ?? 0;
}
get y() {
return this.moves.newest?.y ?? 0;
}
get speedX() {
const x1 = this.moves.newest?.x ?? 0;
const t1 = Date.now() * 1e-3;
const x0 = this.moves.oldest?.x ?? 0;
const t0 = this.moves.oldest?.t ?? 0;
return t0 < t1 ? (1e3 * (x1 - x0)) / (t1 - t0) : 0;
}
get speedY() {
const y1 = this.moves.newest?.y ?? 0;
const t1 = Date.now() * 1e-3;
const y0 = this.moves.oldest?.y ?? 0;
const t0 = this.moves.oldest?.t ?? 0;
return t0 < t1 ? (1e3 * (y1 - y0)) / (t1 - t0) : 0;
}
isTouching(hitTest) {
if (!this.pointerEvent)
return false;
if (!hitTest)
return true;
return hitTest(this.current);
}
detach() {
const { canvas } = this;
if (!canvas)
return;
canvas.removeEventListener("pointerdown", this.handlePointerDown);
canvas.removeEventListener("wheel", this.handleCanvasWheel);
canvas.removeEventListener("contextmenu", this.handleContextMenu);
canvas.removeEventListener("pointermove", this.handlePointerMove);
canvas.removeEventListener("pointerup", this.handlePointerUp);
}
isMultiTap(tap) {
const { lastTap } = this;
if (!lastTap)
return false;
if (tap.t - lastTap.t > this.tapDelay)
return false;
if (tap.fingersCount !== lastTap.fingersCount)
return false;
return true;
}
getPoint(event) {
this.controlKeys = {
altKey: event.altKey || event.buttons === MOUSE_BUTTON_RIGHT,
ctrlKey: event.ctrlKey,
metaKey: event.metaKey,
shiftKey: event.shiftKey,
};
const { left, top, width, height } = this.canvas
? this.canvas.getBoundingClientRect()
: {
left: 0,
top: 0,
width: 1,
height: 1,
};
const x = 2 * ((event.clientX - left) / width - 0.5);
const y = -2 * ((event.clientY - top) / height - 0.5);
return { x, y, t: event.timeStamp * 1e-3, fingersCount: 1 };
}
}
export function resolvePointerButtons({ buttons }) {
const b = (v) => Boolean(buttons & v);
return {
buttons,
buttonLeft: b(1),
buttonRight: b(2),
buttonMiddle: b(4),
buttonBack: b(8),
buttonForward: b(16),
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9pbnRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbnB1dC9wb2ludGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFlBQVksQ0FBQTtBQVE3QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFFaEQsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLENBQUE7QUFFNUIsTUFBTSxPQUFPLGVBQWU7SUFrRHhCLFlBQTZCLE1BQTBCO1FBQTFCLFdBQU0sR0FBTixNQUFNLENBQW9CO1FBakQ5QyxhQUFRLEdBQUcsSUFBSSxnQkFBZ0IsRUFBcUMsQ0FBQTtRQUNwRSxxQkFBZ0IsR0FBRyxJQUFJLGdCQUFnQixFQUE2QyxDQUFBO1FBQ3BGLG1CQUFjLEdBQUcsSUFBSSxnQkFBZ0IsRUFBc0MsQ0FBQTtRQUMzRSxjQUFTLEdBQUcsSUFBSSxnQkFBZ0IsRUFBc0MsQ0FBQTtRQUN0RSxlQUFVLEdBQUcsSUFBSSxnQkFBZ0IsRUFBc0MsQ0FBQTtRQUN2RSxpQkFBWSxHQUFHLElBQUksZ0JBQWdCLEVBQXNDLENBQUE7UUFDekUsY0FBUyxHQUFHLElBQUksZ0JBQWdCLEVBQXNDLENBQUE7UUFDL0U7OztXQUdHO1FBQ0ksYUFBUSxHQUFHLEdBQUcsQ0FBQTtRQUViLFVBQUssR0FBRyxJQUFJLG1CQUFtQixDQUE2QixDQUFDLENBQUMsQ0FBQTtRQUU5RCxnQkFBVyxHQUFHO1lBQ2xCLE1BQU0sRUFBRSxLQUFLO1lBQ2IsT0FBTyxFQUFFLEtBQUs7WUFDZCxPQUFPLEVBQUUsS0FBSztZQUNkLFFBQVEsRUFBRSxLQUFLO1NBQ2xCLENBQUE7UUFDTyxVQUFLLEdBQStCO1lBQ3hDLENBQUMsRUFBRSxDQUFDO1lBQ0osQ0FBQyxFQUFFLENBQUM7WUFDSixDQUFDLEVBQUUsQ0FBQztZQUNKLFlBQVksRUFBRSxDQUFDO1NBQ2xCLENBQUE7UUFDTyxZQUFPLEdBQStCO1lBQzFDLENBQUMsRUFBRSxDQUFDO1lBQ0osQ0FBQyxFQUFFLENBQUM7WUFDSixDQUFDLEVBQUUsQ0FBQztZQUNKLFlBQVksRUFBRSxDQUFDO1NBQ2xCLENBQUE7UUFDTyxhQUFRLEdBQStCO1lBQzNDLENBQUMsRUFBRSxDQUFDO1lBQ0osQ0FBQyxFQUFFLENBQUM7WUFDSixDQUFDLEVBQUUsQ0FBQztZQUNKLFlBQVksRUFBRSxDQUFDO1NBQ2xCLENBQUE7UUFDRDs7V0FFRztRQUNLLFlBQU8sR0FBc0MsSUFBSSxDQUFBO1FBQ2pELGNBQVMsR0FBRyxDQUFDLENBQUE7UUFDckI7O1dBRUc7UUFDSyxpQkFBWSxHQUF3QixJQUFJLENBQUE7UUFxRC9CLHNCQUFpQixHQUFHLENBQUMsS0FBcUMsRUFBRSxFQUFFO1lBQzNFLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQTtRQUMxQixDQUFDLENBQUE7UUFFZ0Isc0JBQWlCLEdBQUcsQ0FBQyxLQUFpQixFQUFFLEVBQUU7WUFDdkQsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUE7WUFDN0QsTUFBTSxLQUFLLEdBQUcsVUFBVSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtZQUNyQyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQztnQkFDcEIsR0FBRyxxQkFBcUIsQ0FBQyxLQUFLLENBQUM7Z0JBQy9CLE9BQU8sRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztnQkFDN0IsU0FBUyxFQUFFLEtBQUs7Z0JBQ2hCLGNBQWMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsY0FBYyxFQUFFO2dCQUM1QyxHQUFHLElBQUksQ0FBQyxXQUFXO2FBQ3RCLENBQUMsQ0FBQTtRQUNOLENBQUMsQ0FBQTtRQUVnQixzQkFBaUIsR0FBRyxDQUFDLEtBQW1CLEVBQUUsRUFBRTtZQUN6RCxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVM7Z0JBQUUsT0FBTTtZQUU1QixJQUFJLENBQUMsTUFBTSxFQUFFLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQTtZQUMvQyxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUE7WUFDdEIsS0FBSyxDQUFDLGVBQWUsRUFBRSxDQUFBO1lBQ3ZCLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFBO1lBQ3pCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDbEMsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFBO1lBQ2pELElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDO2dCQUN6QixHQUFHLHFCQUFxQixDQUFDLEtBQUssQ0FBQztnQkFDL0IsS0FBSyxFQUFFLEtBQUs7Z0JBQ1osT0FBTyxFQUFFLEtBQUs7Z0JBQ2QsUUFBUSxFQUFFLEtBQUs7Z0JBQ2YsR0FBRyxJQUFJLENBQUMsV0FBVzthQUN0QixDQUFDLENBQUE7UUFDTixDQUFDLENBQUE7UUFFZ0Isc0JBQWlCLEdBQUcsQ0FBQyxLQUFtQixFQUFFLEVBQUU7WUFDekQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUNsQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUN0QixJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNO2dCQUFFLE9BQU07WUFFNUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFBO1lBQzVCLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFBO1lBQ3BCLE1BQU0sTUFBTSxHQUE2QjtnQkFDckMsR0FBRyxxQkFBcUIsQ0FBQyxLQUFLLENBQUM7Z0JBQy9CLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztnQkFDakIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO2dCQUNyQixRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7Z0JBQ3ZCLEdBQUcsSUFBSSxDQUFDLFdBQVc7YUFDdEIsQ0FBQTtZQUNELElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBQ2hDLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUNwQixJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUNuQyxDQUFDO1FBQ0wsQ0FBQyxDQUFBO1FBRWdCLG9CQUFlLEdBQUcsQ0FBQyxLQUFtQixFQUFFLEVBQUU7WUFDdkQsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWTtnQkFBRSxPQUFNO1lBRWxELEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQTtZQUN0QixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDbkMsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUM7Z0JBQ3ZCLEdBQUcscUJBQXFCLENBQUMsS0FBSyxDQUFDO2dCQUMvQixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7Z0JBQ2pCLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztnQkFDckIsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRO2dCQUN2QixHQUFHLElBQUksQ0FBQyxXQUFXO2FBQ3RCLENBQUMsQ0FBQTtZQUNGLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFBO1lBQ3hCLGFBQWE7WUFDYixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQTtZQUN0QyxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ3pDLElBQUksZUFBZSxHQUFHLElBQUksQ0FBQTtnQkFDMUIsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO29CQUM5QixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUE7b0JBQ2hCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUM7d0JBQzNCLEdBQUcscUJBQXFCLENBQUMsS0FBSyxDQUFDO3dCQUMvQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7d0JBQ3pCLEdBQUcsSUFBSSxDQUFDLE9BQU87d0JBQ2YsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO3dCQUNqQixHQUFHLElBQUksQ0FBQyxXQUFXO3dCQUNuQixVQUFVLEVBQUUsR0FBRyxFQUFFOzRCQUNiLGVBQWUsR0FBRyxLQUFLLENBQUE7d0JBQzNCLENBQUM7cUJBQ0osQ0FBQyxDQUFBO2dCQUNOLENBQUM7cUJBQU0sQ0FBQztvQkFDSixJQUFJLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQTtnQkFDdEIsQ0FBQztnQkFDRCxJQUFJLGVBQWUsRUFBRSxDQUFDO29CQUNsQixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQzt3QkFDbkIsR0FBRyxxQkFBcUIsQ0FBQyxLQUFLLENBQUM7d0JBQy9CLEdBQUcsSUFBSSxDQUFDLE9BQU87d0JBQ2YsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO3dCQUNqQixHQUFHLElBQUksQ0FBQyxXQUFXO3FCQUN0QixDQUFDLENBQUE7Z0JBQ04sQ0FBQztnQkFDRCxJQUFJLENBQUMsT0FBTyxHQUFHLGVBQWUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7WUFDOUMsQ0FBQztRQUNMLENBQUMsQ0FBQTtRQWxKRyxJQUFJLENBQUMsTUFBTTtZQUFFLE9BQU07UUFFbkIsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFDcEUsTUFBTSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQTtRQUN4RCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1FBQzlELE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUE7UUFDOUQsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUE7SUFDOUQsQ0FBQztJQUVELElBQUksQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUNwQyxDQUFDO0lBQ0QsSUFBSSxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ3BDLENBQUM7SUFFRCxJQUFJLE1BQU07UUFDTixNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3BDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUE7UUFDNUIsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNwQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3BDLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ3RELENBQUM7SUFDRCxJQUFJLE1BQU07UUFDTixNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3BDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUE7UUFDNUIsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNwQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3BDLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ3RELENBQUM7SUFFRCxVQUFVLENBQUMsT0FBa0U7UUFDekUsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZO1lBQUUsT0FBTyxLQUFLLENBQUE7UUFFcEMsSUFBSSxDQUFDLE9BQU87WUFBRSxPQUFPLElBQUksQ0FBQTtRQUV6QixPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDaEMsQ0FBQztJQUVELE1BQU07UUFDRixNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFBO1FBQ3ZCLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTTtRQUVuQixNQUFNLENBQUMsbUJBQW1CLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1FBQ2pFLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLENBQUE7UUFDM0QsTUFBTSxDQUFDLG1CQUFtQixDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQTtRQUNqRSxNQUFNLENBQUMsbUJBQW1CLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1FBQ2pFLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFBO0lBQ2pFLENBQUM7SUFvR08sVUFBVSxDQUFDLEdBQStCO1FBQzlDLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUE7UUFDeEIsSUFBSSxDQUFDLE9BQU87WUFBRSxPQUFPLEtBQUssQ0FBQTtRQUUxQixJQUFJLEdBQUcsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsUUFBUTtZQUFFLE9BQU8sS0FBSyxDQUFBO1FBRW5ELElBQUksR0FBRyxDQUFDLFlBQVksS0FBSyxPQUFPLENBQUMsWUFBWTtZQUFFLE9BQU8sS0FBSyxDQUFBO1FBRTNELE9BQU8sSUFBSSxDQUFBO0lBQ2YsQ0FBQztJQUVPLFFBQVEsQ0FBQyxLQUFnQztRQUM3QyxJQUFJLENBQUMsV0FBVyxHQUFHO1lBQ2YsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sS0FBSyxrQkFBa0I7WUFDNUQsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ3RCLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztZQUN0QixRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVE7U0FDM0IsQ0FBQTtRQUNELE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTTtZQUM1QyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxxQkFBcUIsRUFBRTtZQUNyQyxDQUFDLENBQUM7Z0JBQ0ksSUFBSSxFQUFFLENBQUM7Z0JBQ1AsR0FBRyxFQUFFLENBQUM7Z0JBQ04sS0FBSyxFQUFFLENBQUM7Z0JBQ1IsTUFBTSxFQUFFLENBQUM7YUFDWixDQUFBO1FBQ1AsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQTtRQUNwRCxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUMsR0FBRyxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUE7UUFDckQsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssQ0FBQyxTQUFTLEdBQUcsSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDLEVBQUUsQ0FBQTtJQUMvRCxDQUFDO0NBQ0o7QUFFRCxNQUFNLFVBQVUscUJBQXFCLENBQUMsRUFBRSxPQUFPLEVBQXVCO0lBQ2xFLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFBO0lBRTdDLE9BQU87UUFDSCxPQUFPO1FBQ1AsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEIsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakIsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbEIsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEIsYUFBYSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUM7S0FDdkIsQ0FBQTtBQUNMLENBQUMifQ==