@c4h/chuci 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -32
- package/LICENSE +20 -20
- package/README.ja.md +143 -143
- package/README.md +224 -224
- package/dist/chuci.js +9067 -6595
- package/dist/chuci.umd.js +164 -165
- package/dist/index.d.ts +1 -0
- package/package.json +36 -33
- package/src/components/swiper/cc-swiper-slide.ts +49 -49
- package/src/components/swiper/cc-swiper-styles.ts +28 -28
- package/src/components/swiper/cc-swiper.ts +379 -361
- package/src/components/swiper/swiper-styles.css +4 -4
- package/src/components/viewer/cc-viewer-3dmodel.ts +491 -491
- package/src/components/viewer/cc-viewer-base.ts +278 -278
- package/src/components/viewer/cc-viewer-gaussian.ts +380 -380
- package/src/components/viewer/cc-viewer-image.ts +189 -189
- package/src/components/viewer/cc-viewer-panorama.ts +85 -85
- package/src/components/viewer/cc-viewer-styles.ts +55 -55
- package/src/components/viewer/cc-viewer-video.ts +109 -109
- package/src/components/viewer/cc-viewer-youtube.ts +75 -75
- package/src/components/viewer/cc-viewer.ts +290 -290
- package/src/index.ts +24 -24
- package/src/types/css-modules.d.ts +1 -1
- package/src/types/global.d.ts +10 -10
- package/src/utils/base-element.ts +76 -76
- package/dist/assets/azumaya_panorama1.png +0 -0
- package/dist/chuci.cjs +0 -4483
- package/dist/index-8VMexD2a.cjs +0 -255
- package/dist/index-kvsisbKS.js +0 -2125
- package/dist/index.html +0 -241
- package/dist/test-image.html +0 -63
package/dist/index-kvsisbKS.js
DELETED
|
@@ -1,2125 +0,0 @@
|
|
|
1
|
-
class I {
|
|
2
|
-
constructor(t = 0, F = 0, U = 0) {
|
|
3
|
-
this.x = t, this.y = F, this.z = U;
|
|
4
|
-
}
|
|
5
|
-
equals(t) {
|
|
6
|
-
return this.x === t.x && this.y === t.y && this.z === t.z;
|
|
7
|
-
}
|
|
8
|
-
add(t) {
|
|
9
|
-
return typeof t == "number" ? new I(this.x + t, this.y + t, this.z + t) : new I(this.x + t.x, this.y + t.y, this.z + t.z);
|
|
10
|
-
}
|
|
11
|
-
subtract(t) {
|
|
12
|
-
return typeof t == "number" ? new I(this.x - t, this.y - t, this.z - t) : new I(this.x - t.x, this.y - t.y, this.z - t.z);
|
|
13
|
-
}
|
|
14
|
-
multiply(t) {
|
|
15
|
-
return typeof t == "number" ? new I(this.x * t, this.y * t, this.z * t) : t instanceof I ? new I(this.x * t.x, this.y * t.y, this.z * t.z) : new I(this.x * t.buffer[0] + this.y * t.buffer[4] + this.z * t.buffer[8] + t.buffer[12], this.x * t.buffer[1] + this.y * t.buffer[5] + this.z * t.buffer[9] + t.buffer[13], this.x * t.buffer[2] + this.y * t.buffer[6] + this.z * t.buffer[10] + t.buffer[14]);
|
|
16
|
-
}
|
|
17
|
-
divide(t) {
|
|
18
|
-
return typeof t == "number" ? new I(this.x / t, this.y / t, this.z / t) : new I(this.x / t.x, this.y / t.y, this.z / t.z);
|
|
19
|
-
}
|
|
20
|
-
cross(t) {
|
|
21
|
-
const F = this.y * t.z - this.z * t.y, U = this.z * t.x - this.x * t.z, l = this.x * t.y - this.y * t.x;
|
|
22
|
-
return new I(F, U, l);
|
|
23
|
-
}
|
|
24
|
-
dot(t) {
|
|
25
|
-
return this.x * t.x + this.y * t.y + this.z * t.z;
|
|
26
|
-
}
|
|
27
|
-
lerp(t, F) {
|
|
28
|
-
return new I(this.x + (t.x - this.x) * F, this.y + (t.y - this.y) * F, this.z + (t.z - this.z) * F);
|
|
29
|
-
}
|
|
30
|
-
min(t) {
|
|
31
|
-
return new I(Math.min(this.x, t.x), Math.min(this.y, t.y), Math.min(this.z, t.z));
|
|
32
|
-
}
|
|
33
|
-
max(t) {
|
|
34
|
-
return new I(Math.max(this.x, t.x), Math.max(this.y, t.y), Math.max(this.z, t.z));
|
|
35
|
-
}
|
|
36
|
-
getComponent(t) {
|
|
37
|
-
switch (t) {
|
|
38
|
-
case 0:
|
|
39
|
-
return this.x;
|
|
40
|
-
case 1:
|
|
41
|
-
return this.y;
|
|
42
|
-
case 2:
|
|
43
|
-
return this.z;
|
|
44
|
-
default:
|
|
45
|
-
throw new Error(`Invalid component index: ${t}`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
minComponent() {
|
|
49
|
-
return this.x < this.y && this.x < this.z ? 0 : this.y < this.z ? 1 : 2;
|
|
50
|
-
}
|
|
51
|
-
maxComponent() {
|
|
52
|
-
return this.x > this.y && this.x > this.z ? 0 : this.y > this.z ? 1 : 2;
|
|
53
|
-
}
|
|
54
|
-
magnitude() {
|
|
55
|
-
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
|
|
56
|
-
}
|
|
57
|
-
distanceTo(t) {
|
|
58
|
-
return Math.sqrt((this.x - t.x) ** 2 + (this.y - t.y) ** 2 + (this.z - t.z) ** 2);
|
|
59
|
-
}
|
|
60
|
-
normalize() {
|
|
61
|
-
const t = this.magnitude();
|
|
62
|
-
return new I(this.x / t, this.y / t, this.z / t);
|
|
63
|
-
}
|
|
64
|
-
flat() {
|
|
65
|
-
return [this.x, this.y, this.z];
|
|
66
|
-
}
|
|
67
|
-
clone() {
|
|
68
|
-
return new I(this.x, this.y, this.z);
|
|
69
|
-
}
|
|
70
|
-
toString() {
|
|
71
|
-
return `[${this.flat().join(", ")}]`;
|
|
72
|
-
}
|
|
73
|
-
static One(t = 1) {
|
|
74
|
-
return new I(t, t, t);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
class z {
|
|
78
|
-
constructor(t = 0, F = 0, U = 0, l = 1) {
|
|
79
|
-
this.x = t, this.y = F, this.z = U, this.w = l;
|
|
80
|
-
}
|
|
81
|
-
equals(t) {
|
|
82
|
-
return this.x === t.x && this.y === t.y && this.z === t.z && this.w === t.w;
|
|
83
|
-
}
|
|
84
|
-
normalize() {
|
|
85
|
-
const t = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
|
|
86
|
-
return new z(this.x / t, this.y / t, this.z / t, this.w / t);
|
|
87
|
-
}
|
|
88
|
-
multiply(t) {
|
|
89
|
-
const F = this.w, U = this.x, l = this.y, a = this.z, n = t.w, e = t.x, Q = t.y, d = t.z;
|
|
90
|
-
return new z(F * e + U * n + l * d - a * Q, F * Q - U * d + l * n + a * e, F * d + U * Q - l * e + a * n, F * n - U * e - l * Q - a * d);
|
|
91
|
-
}
|
|
92
|
-
inverse() {
|
|
93
|
-
const t = this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
|
|
94
|
-
return new z(-this.x / t, -this.y / t, -this.z / t, this.w / t);
|
|
95
|
-
}
|
|
96
|
-
apply(t) {
|
|
97
|
-
const F = new z(t.x, t.y, t.z, 0), U = new z(-this.x, -this.y, -this.z, this.w), l = this.multiply(F).multiply(U);
|
|
98
|
-
return new I(l.x, l.y, l.z);
|
|
99
|
-
}
|
|
100
|
-
flat() {
|
|
101
|
-
return [this.x, this.y, this.z, this.w];
|
|
102
|
-
}
|
|
103
|
-
clone() {
|
|
104
|
-
return new z(this.x, this.y, this.z, this.w);
|
|
105
|
-
}
|
|
106
|
-
static FromEuler(t) {
|
|
107
|
-
const F = t.x / 2, U = t.y / 2, l = t.z / 2, a = Math.cos(U), n = Math.sin(U), e = Math.cos(F), Q = Math.sin(F), d = Math.cos(l), A = Math.sin(l);
|
|
108
|
-
return new z(a * Q * d + n * e * A, n * e * d - a * Q * A, a * e * A - n * Q * d, a * e * d + n * Q * A);
|
|
109
|
-
}
|
|
110
|
-
toEuler() {
|
|
111
|
-
const t = 2 * (this.w * this.x + this.y * this.z), F = 1 - 2 * (this.x * this.x + this.y * this.y), U = Math.atan2(t, F);
|
|
112
|
-
let l;
|
|
113
|
-
const a = 2 * (this.w * this.y - this.z * this.x);
|
|
114
|
-
l = Math.abs(a) >= 1 ? Math.sign(a) * Math.PI / 2 : Math.asin(a);
|
|
115
|
-
const n = 2 * (this.w * this.z + this.x * this.y), e = 1 - 2 * (this.y * this.y + this.z * this.z), Q = Math.atan2(n, e);
|
|
116
|
-
return new I(U, l, Q);
|
|
117
|
-
}
|
|
118
|
-
static FromMatrix3(t) {
|
|
119
|
-
const F = t.buffer, U = F[0] + F[4] + F[8];
|
|
120
|
-
let l, a, n, e;
|
|
121
|
-
if (U > 0) {
|
|
122
|
-
const Q = 0.5 / Math.sqrt(U + 1);
|
|
123
|
-
e = 0.25 / Q, l = (F[7] - F[5]) * Q, a = (F[2] - F[6]) * Q, n = (F[3] - F[1]) * Q;
|
|
124
|
-
} else if (F[0] > F[4] && F[0] > F[8]) {
|
|
125
|
-
const Q = 2 * Math.sqrt(1 + F[0] - F[4] - F[8]);
|
|
126
|
-
e = (F[7] - F[5]) / Q, l = 0.25 * Q, a = (F[1] + F[3]) / Q, n = (F[2] + F[6]) / Q;
|
|
127
|
-
} else if (F[4] > F[8]) {
|
|
128
|
-
const Q = 2 * Math.sqrt(1 + F[4] - F[0] - F[8]);
|
|
129
|
-
e = (F[2] - F[6]) / Q, l = (F[1] + F[3]) / Q, a = 0.25 * Q, n = (F[5] + F[7]) / Q;
|
|
130
|
-
} else {
|
|
131
|
-
const Q = 2 * Math.sqrt(1 + F[8] - F[0] - F[4]);
|
|
132
|
-
e = (F[3] - F[1]) / Q, l = (F[2] + F[6]) / Q, a = (F[5] + F[7]) / Q, n = 0.25 * Q;
|
|
133
|
-
}
|
|
134
|
-
return new z(l, a, n, e);
|
|
135
|
-
}
|
|
136
|
-
static FromAxisAngle(t, F) {
|
|
137
|
-
const U = F / 2, l = Math.sin(U), a = Math.cos(U);
|
|
138
|
-
return new z(t.x * l, t.y * l, t.z * l, a);
|
|
139
|
-
}
|
|
140
|
-
static LookRotation(t) {
|
|
141
|
-
const F = new I(0, 0, 1), U = F.dot(t);
|
|
142
|
-
if (Math.abs(U - -1) < 1e-6) return new z(0, 1, 0, Math.PI);
|
|
143
|
-
if (Math.abs(U - 1) < 1e-6) return new z();
|
|
144
|
-
const l = Math.acos(U), a = F.cross(t).normalize();
|
|
145
|
-
return z.FromAxisAngle(a, l);
|
|
146
|
-
}
|
|
147
|
-
toString() {
|
|
148
|
-
return `[${this.flat().join(", ")}]`;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
class Et {
|
|
152
|
-
constructor() {
|
|
153
|
-
const t = /* @__PURE__ */ new Map();
|
|
154
|
-
this.addEventListener = (F, U) => {
|
|
155
|
-
t.has(F) || t.set(F, /* @__PURE__ */ new Set()), t.get(F).add(U);
|
|
156
|
-
}, this.removeEventListener = (F, U) => {
|
|
157
|
-
t.has(F) && t.get(F).delete(U);
|
|
158
|
-
}, this.hasEventListener = (F, U) => !!t.has(F) && t.get(F).has(U), this.dispatchEvent = (F) => {
|
|
159
|
-
if (t.has(F.type)) for (const U of t.get(F.type)) U(F);
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
class Ut {
|
|
164
|
-
constructor(t = 1, F = 0, U = 0, l = 0, a = 0, n = 1, e = 0, Q = 0, d = 0, A = 0, i = 1, r = 0, c = 0, B = 0, W = 0, J = 1) {
|
|
165
|
-
this.buffer = [t, F, U, l, a, n, e, Q, d, A, i, r, c, B, W, J];
|
|
166
|
-
}
|
|
167
|
-
equals(t) {
|
|
168
|
-
if (this.buffer.length !== t.buffer.length) return !1;
|
|
169
|
-
if (this.buffer === t.buffer) return !0;
|
|
170
|
-
for (let F = 0; F < this.buffer.length; F++) if (this.buffer[F] !== t.buffer[F]) return !1;
|
|
171
|
-
return !0;
|
|
172
|
-
}
|
|
173
|
-
multiply(t) {
|
|
174
|
-
const F = this.buffer, U = t.buffer;
|
|
175
|
-
return new Ut(U[0] * F[0] + U[1] * F[4] + U[2] * F[8] + U[3] * F[12], U[0] * F[1] + U[1] * F[5] + U[2] * F[9] + U[3] * F[13], U[0] * F[2] + U[1] * F[6] + U[2] * F[10] + U[3] * F[14], U[0] * F[3] + U[1] * F[7] + U[2] * F[11] + U[3] * F[15], U[4] * F[0] + U[5] * F[4] + U[6] * F[8] + U[7] * F[12], U[4] * F[1] + U[5] * F[5] + U[6] * F[9] + U[7] * F[13], U[4] * F[2] + U[5] * F[6] + U[6] * F[10] + U[7] * F[14], U[4] * F[3] + U[5] * F[7] + U[6] * F[11] + U[7] * F[15], U[8] * F[0] + U[9] * F[4] + U[10] * F[8] + U[11] * F[12], U[8] * F[1] + U[9] * F[5] + U[10] * F[9] + U[11] * F[13], U[8] * F[2] + U[9] * F[6] + U[10] * F[10] + U[11] * F[14], U[8] * F[3] + U[9] * F[7] + U[10] * F[11] + U[11] * F[15], U[12] * F[0] + U[13] * F[4] + U[14] * F[8] + U[15] * F[12], U[12] * F[1] + U[13] * F[5] + U[14] * F[9] + U[15] * F[13], U[12] * F[2] + U[13] * F[6] + U[14] * F[10] + U[15] * F[14], U[12] * F[3] + U[13] * F[7] + U[14] * F[11] + U[15] * F[15]);
|
|
176
|
-
}
|
|
177
|
-
clone() {
|
|
178
|
-
const t = this.buffer;
|
|
179
|
-
return new Ut(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15]);
|
|
180
|
-
}
|
|
181
|
-
determinant() {
|
|
182
|
-
const t = this.buffer;
|
|
183
|
-
return t[12] * t[9] * t[6] * t[3] - t[8] * t[13] * t[6] * t[3] - t[12] * t[5] * t[10] * t[3] + t[4] * t[13] * t[10] * t[3] + t[8] * t[5] * t[14] * t[3] - t[4] * t[9] * t[14] * t[3] - t[12] * t[9] * t[2] * t[7] + t[8] * t[13] * t[2] * t[7] + t[12] * t[1] * t[10] * t[7] - t[0] * t[13] * t[10] * t[7] - t[8] * t[1] * t[14] * t[7] + t[0] * t[9] * t[14] * t[7] + t[12] * t[5] * t[2] * t[11] - t[4] * t[13] * t[2] * t[11] - t[12] * t[1] * t[6] * t[11] + t[0] * t[13] * t[6] * t[11] + t[4] * t[1] * t[14] * t[11] - t[0] * t[5] * t[14] * t[11] - t[8] * t[5] * t[2] * t[15] + t[4] * t[9] * t[2] * t[15] + t[8] * t[1] * t[6] * t[15] - t[0] * t[9] * t[6] * t[15] - t[4] * t[1] * t[10] * t[15] + t[0] * t[5] * t[10] * t[15];
|
|
184
|
-
}
|
|
185
|
-
invert() {
|
|
186
|
-
const t = this.buffer, F = this.determinant();
|
|
187
|
-
if (F === 0) throw new Error("Matrix is not invertible.");
|
|
188
|
-
const U = 1 / F;
|
|
189
|
-
return new Ut(U * (t[5] * t[10] * t[15] - t[5] * t[11] * t[14] - t[9] * t[6] * t[15] + t[9] * t[7] * t[14] + t[13] * t[6] * t[11] - t[13] * t[7] * t[10]), U * (-t[1] * t[10] * t[15] + t[1] * t[11] * t[14] + t[9] * t[2] * t[15] - t[9] * t[3] * t[14] - t[13] * t[2] * t[11] + t[13] * t[3] * t[10]), U * (t[1] * t[6] * t[15] - t[1] * t[7] * t[14] - t[5] * t[2] * t[15] + t[5] * t[3] * t[14] + t[13] * t[2] * t[7] - t[13] * t[3] * t[6]), U * (-t[1] * t[6] * t[11] + t[1] * t[7] * t[10] + t[5] * t[2] * t[11] - t[5] * t[3] * t[10] - t[9] * t[2] * t[7] + t[9] * t[3] * t[6]), U * (-t[4] * t[10] * t[15] + t[4] * t[11] * t[14] + t[8] * t[6] * t[15] - t[8] * t[7] * t[14] - t[12] * t[6] * t[11] + t[12] * t[7] * t[10]), U * (t[0] * t[10] * t[15] - t[0] * t[11] * t[14] - t[8] * t[2] * t[15] + t[8] * t[3] * t[14] + t[12] * t[2] * t[11] - t[12] * t[3] * t[10]), U * (-t[0] * t[6] * t[15] + t[0] * t[7] * t[14] + t[4] * t[2] * t[15] - t[4] * t[3] * t[14] - t[12] * t[2] * t[7] + t[12] * t[3] * t[6]), U * (t[0] * t[6] * t[11] - t[0] * t[7] * t[10] - t[4] * t[2] * t[11] + t[4] * t[3] * t[10] + t[8] * t[2] * t[7] - t[8] * t[3] * t[6]), U * (t[4] * t[9] * t[15] - t[4] * t[11] * t[13] - t[8] * t[5] * t[15] + t[8] * t[7] * t[13] + t[12] * t[5] * t[11] - t[12] * t[7] * t[9]), U * (-t[0] * t[9] * t[15] + t[0] * t[11] * t[13] + t[8] * t[1] * t[15] - t[8] * t[3] * t[13] - t[12] * t[1] * t[11] + t[12] * t[3] * t[9]), U * (t[0] * t[5] * t[15] - t[0] * t[7] * t[13] - t[4] * t[1] * t[15] + t[4] * t[3] * t[13] + t[12] * t[1] * t[7] - t[12] * t[3] * t[5]), U * (-t[0] * t[5] * t[11] + t[0] * t[7] * t[9] + t[4] * t[1] * t[11] - t[4] * t[3] * t[9] - t[8] * t[1] * t[7] + t[8] * t[3] * t[5]), U * (-t[4] * t[9] * t[14] + t[4] * t[10] * t[13] + t[8] * t[5] * t[14] - t[8] * t[6] * t[13] - t[12] * t[5] * t[10] + t[12] * t[6] * t[9]), U * (t[0] * t[9] * t[14] - t[0] * t[10] * t[13] - t[8] * t[1] * t[14] + t[8] * t[2] * t[13] + t[12] * t[1] * t[10] - t[12] * t[2] * t[9]), U * (-t[0] * t[5] * t[14] + t[0] * t[6] * t[13] + t[4] * t[1] * t[14] - t[4] * t[2] * t[13] - t[12] * t[1] * t[6] + t[12] * t[2] * t[5]), U * (t[0] * t[5] * t[10] - t[0] * t[6] * t[9] - t[4] * t[1] * t[10] + t[4] * t[2] * t[9] + t[8] * t[1] * t[6] - t[8] * t[2] * t[5]));
|
|
190
|
-
}
|
|
191
|
-
static Compose(t, F, U) {
|
|
192
|
-
const l = F.x, a = F.y, n = F.z, e = F.w, Q = l + l, d = a + a, A = n + n, i = l * Q, r = l * d, c = l * A, B = a * d, W = a * A, J = n * A, h = e * Q, C = e * d, k = e * A, p = U.x, X = U.y, D = U.z;
|
|
193
|
-
return new Ut((1 - (B + J)) * p, (r + k) * p, (c - C) * p, 0, (r - k) * X, (1 - (i + J)) * X, (W + h) * X, 0, (c + C) * D, (W - h) * D, (1 - (i + B)) * D, 0, t.x, t.y, t.z, 1);
|
|
194
|
-
}
|
|
195
|
-
toString() {
|
|
196
|
-
return `[${this.buffer.join(", ")}]`;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
class Lt extends Event {
|
|
200
|
-
constructor(t) {
|
|
201
|
-
super("objectAdded"), this.object = t;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
class Pt extends Event {
|
|
205
|
-
constructor(t) {
|
|
206
|
-
super("objectRemoved"), this.object = t;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
class _t extends Event {
|
|
210
|
-
constructor(t) {
|
|
211
|
-
super("objectChanged"), this.object = t;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
class bt extends Et {
|
|
215
|
-
constructor() {
|
|
216
|
-
super(), this.positionChanged = !1, this.rotationChanged = !1, this.scaleChanged = !1, this._position = new I(), this._rotation = new z(), this._scale = new I(1, 1, 1), this._transform = new Ut(), this._changeEvent = new _t(this), this.update = () => {
|
|
217
|
-
}, this.applyPosition = () => {
|
|
218
|
-
this.position = new I();
|
|
219
|
-
}, this.applyRotation = () => {
|
|
220
|
-
this.rotation = new z();
|
|
221
|
-
}, this.applyScale = () => {
|
|
222
|
-
this.scale = new I(1, 1, 1);
|
|
223
|
-
}, this.raiseChangeEvent = () => {
|
|
224
|
-
this.dispatchEvent(this._changeEvent);
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
_updateMatrix() {
|
|
228
|
-
this._transform = Ut.Compose(this._position, this._rotation, this._scale);
|
|
229
|
-
}
|
|
230
|
-
get position() {
|
|
231
|
-
return this._position;
|
|
232
|
-
}
|
|
233
|
-
set position(t) {
|
|
234
|
-
this._position.equals(t) || (this._position = t, this.positionChanged = !0, this._updateMatrix(), this.dispatchEvent(this._changeEvent));
|
|
235
|
-
}
|
|
236
|
-
get rotation() {
|
|
237
|
-
return this._rotation;
|
|
238
|
-
}
|
|
239
|
-
set rotation(t) {
|
|
240
|
-
this._rotation.equals(t) || (this._rotation = t, this.rotationChanged = !0, this._updateMatrix(), this.dispatchEvent(this._changeEvent));
|
|
241
|
-
}
|
|
242
|
-
get scale() {
|
|
243
|
-
return this._scale;
|
|
244
|
-
}
|
|
245
|
-
set scale(t) {
|
|
246
|
-
this._scale.equals(t) || (this._scale = t, this.scaleChanged = !0, this._updateMatrix(), this.dispatchEvent(this._changeEvent));
|
|
247
|
-
}
|
|
248
|
-
get forward() {
|
|
249
|
-
let t = new I(0, 0, 1);
|
|
250
|
-
return t = this.rotation.apply(t), t;
|
|
251
|
-
}
|
|
252
|
-
get transform() {
|
|
253
|
-
return this._transform;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
class tt {
|
|
257
|
-
constructor(t = 1, F = 0, U = 0, l = 0, a = 1, n = 0, e = 0, Q = 0, d = 1) {
|
|
258
|
-
this.buffer = [t, F, U, l, a, n, e, Q, d];
|
|
259
|
-
}
|
|
260
|
-
equals(t) {
|
|
261
|
-
if (this.buffer.length !== t.buffer.length) return !1;
|
|
262
|
-
if (this.buffer === t.buffer) return !0;
|
|
263
|
-
for (let F = 0; F < this.buffer.length; F++) if (this.buffer[F] !== t.buffer[F]) return !1;
|
|
264
|
-
return !0;
|
|
265
|
-
}
|
|
266
|
-
multiply(t) {
|
|
267
|
-
const F = this.buffer, U = t.buffer;
|
|
268
|
-
return new tt(U[0] * F[0] + U[3] * F[1] + U[6] * F[2], U[1] * F[0] + U[4] * F[1] + U[7] * F[2], U[2] * F[0] + U[5] * F[1] + U[8] * F[2], U[0] * F[3] + U[3] * F[4] + U[6] * F[5], U[1] * F[3] + U[4] * F[4] + U[7] * F[5], U[2] * F[3] + U[5] * F[4] + U[8] * F[5], U[0] * F[6] + U[3] * F[7] + U[6] * F[8], U[1] * F[6] + U[4] * F[7] + U[7] * F[8], U[2] * F[6] + U[5] * F[7] + U[8] * F[8]);
|
|
269
|
-
}
|
|
270
|
-
clone() {
|
|
271
|
-
const t = this.buffer;
|
|
272
|
-
return new tt(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8]);
|
|
273
|
-
}
|
|
274
|
-
static Eye(t = 1) {
|
|
275
|
-
return new tt(t, 0, 0, 0, t, 0, 0, 0, t);
|
|
276
|
-
}
|
|
277
|
-
static Diagonal(t) {
|
|
278
|
-
return new tt(t.x, 0, 0, 0, t.y, 0, 0, 0, t.z);
|
|
279
|
-
}
|
|
280
|
-
static RotationFromQuaternion(t) {
|
|
281
|
-
return new tt(1 - 2 * t.y * t.y - 2 * t.z * t.z, 2 * t.x * t.y - 2 * t.z * t.w, 2 * t.x * t.z + 2 * t.y * t.w, 2 * t.x * t.y + 2 * t.z * t.w, 1 - 2 * t.x * t.x - 2 * t.z * t.z, 2 * t.y * t.z - 2 * t.x * t.w, 2 * t.x * t.z - 2 * t.y * t.w, 2 * t.y * t.z + 2 * t.x * t.w, 1 - 2 * t.x * t.x - 2 * t.y * t.y);
|
|
282
|
-
}
|
|
283
|
-
static RotationFromEuler(t) {
|
|
284
|
-
const F = Math.cos(t.x), U = Math.sin(t.x), l = Math.cos(t.y), a = Math.sin(t.y), n = Math.cos(t.z), e = Math.sin(t.z);
|
|
285
|
-
return new tt(l * n + a * U * e, -l * e + a * U * n, a * F, F * e, F * n, -U, -a * n + l * U * e, a * e + l * U * n, l * F);
|
|
286
|
-
}
|
|
287
|
-
toString() {
|
|
288
|
-
return `[${this.buffer.join(", ")}]`;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
class lt {
|
|
292
|
-
constructor(t = 0, F = null, U = null, l = null, a = null) {
|
|
293
|
-
this.changed = !1, this.detached = !1, this._vertexCount = t, this._positions = F || new Float32Array(0), this._rotations = U || new Float32Array(0), this._scales = l || new Float32Array(0), this._colors = a || new Uint8Array(0), this._selection = new Uint8Array(this.vertexCount), this.translate = (n) => {
|
|
294
|
-
for (let e = 0; e < this.vertexCount; e++) this.positions[3 * e + 0] += n.x, this.positions[3 * e + 1] += n.y, this.positions[3 * e + 2] += n.z;
|
|
295
|
-
this.changed = !0;
|
|
296
|
-
}, this.rotate = (n) => {
|
|
297
|
-
const e = tt.RotationFromQuaternion(n).buffer;
|
|
298
|
-
for (let Q = 0; Q < this.vertexCount; Q++) {
|
|
299
|
-
const d = this.positions[3 * Q + 0], A = this.positions[3 * Q + 1], i = this.positions[3 * Q + 2];
|
|
300
|
-
this.positions[3 * Q + 0] = e[0] * d + e[1] * A + e[2] * i, this.positions[3 * Q + 1] = e[3] * d + e[4] * A + e[5] * i, this.positions[3 * Q + 2] = e[6] * d + e[7] * A + e[8] * i;
|
|
301
|
-
const r = new z(this.rotations[4 * Q + 1], this.rotations[4 * Q + 2], this.rotations[4 * Q + 3], this.rotations[4 * Q + 0]), c = n.multiply(r);
|
|
302
|
-
this.rotations[4 * Q + 1] = c.x, this.rotations[4 * Q + 2] = c.y, this.rotations[4 * Q + 3] = c.z, this.rotations[4 * Q + 0] = c.w;
|
|
303
|
-
}
|
|
304
|
-
this.changed = !0;
|
|
305
|
-
}, this.scale = (n) => {
|
|
306
|
-
for (let e = 0; e < this.vertexCount; e++) this.positions[3 * e + 0] *= n.x, this.positions[3 * e + 1] *= n.y, this.positions[3 * e + 2] *= n.z, this.scales[3 * e + 0] *= n.x, this.scales[3 * e + 1] *= n.y, this.scales[3 * e + 2] *= n.z;
|
|
307
|
-
this.changed = !0;
|
|
308
|
-
}, this.serialize = () => {
|
|
309
|
-
const n = new Uint8Array(this.vertexCount * lt.RowLength), e = new Float32Array(n.buffer), Q = new Uint8Array(n.buffer);
|
|
310
|
-
for (let d = 0; d < this.vertexCount; d++) e[8 * d + 0] = this.positions[3 * d + 0], e[8 * d + 1] = this.positions[3 * d + 1], e[8 * d + 2] = this.positions[3 * d + 2], Q[32 * d + 24 + 0] = this.colors[4 * d + 0], Q[32 * d + 24 + 1] = this.colors[4 * d + 1], Q[32 * d + 24 + 2] = this.colors[4 * d + 2], Q[32 * d + 24 + 3] = this.colors[4 * d + 3], e[8 * d + 3 + 0] = this.scales[3 * d + 0], e[8 * d + 3 + 1] = this.scales[3 * d + 1], e[8 * d + 3 + 2] = this.scales[3 * d + 2], Q[32 * d + 28 + 0] = 128 * this.rotations[4 * d + 0] + 128 & 255, Q[32 * d + 28 + 1] = 128 * this.rotations[4 * d + 1] + 128 & 255, Q[32 * d + 28 + 2] = 128 * this.rotations[4 * d + 2] + 128 & 255, Q[32 * d + 28 + 3] = 128 * this.rotations[4 * d + 3] + 128 & 255;
|
|
311
|
-
return n;
|
|
312
|
-
}, this.reattach = (n, e, Q, d, A) => {
|
|
313
|
-
console.assert(n.byteLength === 3 * this.vertexCount * 4, `Expected ${3 * this.vertexCount * 4} bytes, got ${n.byteLength} bytes`), this._positions = new Float32Array(n), this._rotations = new Float32Array(e), this._scales = new Float32Array(Q), this._colors = new Uint8Array(d), this._selection = new Uint8Array(A), this.detached = !1;
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
static Deserialize(t) {
|
|
317
|
-
const F = t.length / lt.RowLength, U = new Float32Array(3 * F), l = new Float32Array(4 * F), a = new Float32Array(3 * F), n = new Uint8Array(4 * F), e = new Float32Array(t.buffer), Q = new Uint8Array(t.buffer);
|
|
318
|
-
for (let d = 0; d < F; d++) U[3 * d + 0] = e[8 * d + 0], U[3 * d + 1] = e[8 * d + 1], U[3 * d + 2] = e[8 * d + 2], l[4 * d + 0] = (Q[32 * d + 28 + 0] - 128) / 128, l[4 * d + 1] = (Q[32 * d + 28 + 1] - 128) / 128, l[4 * d + 2] = (Q[32 * d + 28 + 2] - 128) / 128, l[4 * d + 3] = (Q[32 * d + 28 + 3] - 128) / 128, a[3 * d + 0] = e[8 * d + 3 + 0], a[3 * d + 1] = e[8 * d + 3 + 1], a[3 * d + 2] = e[8 * d + 3 + 2], n[4 * d + 0] = Q[32 * d + 24 + 0], n[4 * d + 1] = Q[32 * d + 24 + 1], n[4 * d + 2] = Q[32 * d + 24 + 2], n[4 * d + 3] = Q[32 * d + 24 + 3];
|
|
319
|
-
return new lt(F, U, l, a, n);
|
|
320
|
-
}
|
|
321
|
-
get vertexCount() {
|
|
322
|
-
return this._vertexCount;
|
|
323
|
-
}
|
|
324
|
-
get positions() {
|
|
325
|
-
return this._positions;
|
|
326
|
-
}
|
|
327
|
-
get rotations() {
|
|
328
|
-
return this._rotations;
|
|
329
|
-
}
|
|
330
|
-
get scales() {
|
|
331
|
-
return this._scales;
|
|
332
|
-
}
|
|
333
|
-
get colors() {
|
|
334
|
-
return this._colors;
|
|
335
|
-
}
|
|
336
|
-
get selection() {
|
|
337
|
-
return this._selection;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
lt.RowLength = 32;
|
|
341
|
-
class mt {
|
|
342
|
-
constructor(t, F, U, l, a) {
|
|
343
|
-
this._vertexCount = t, this._positions = F, this._data = U, this._width = l, this._height = a, this.serialize = () => new Uint8Array(this._data.buffer);
|
|
344
|
-
}
|
|
345
|
-
static Deserialize(t, F, U) {
|
|
346
|
-
const l = new Uint32Array(t.buffer), a = new Float32Array(t.buffer), n = Math.floor(a.byteLength / this.RowLength), e = new Float32Array(3 * n);
|
|
347
|
-
for (let Q = 0; Q < n; Q++) e[3 * Q + 0] = a[16 * Q + 0], e[3 * Q + 1] = a[16 * Q + 1], e[3 * Q + 2] = a[16 * Q + 2], e[3 * Q + 0] = a[16 * Q + 3];
|
|
348
|
-
return new mt(n, e, l, F, U);
|
|
349
|
-
}
|
|
350
|
-
get vertexCount() {
|
|
351
|
-
return this._vertexCount;
|
|
352
|
-
}
|
|
353
|
-
get positions() {
|
|
354
|
-
return this._positions;
|
|
355
|
-
}
|
|
356
|
-
get data() {
|
|
357
|
-
return this._data;
|
|
358
|
-
}
|
|
359
|
-
get width() {
|
|
360
|
-
return this._width;
|
|
361
|
-
}
|
|
362
|
-
get height() {
|
|
363
|
-
return this._height;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
mt.RowLength = 64;
|
|
367
|
-
class Zt {
|
|
368
|
-
static SplatToPLY(t, F) {
|
|
369
|
-
let U = `ply
|
|
370
|
-
format binary_little_endian 1.0
|
|
371
|
-
`;
|
|
372
|
-
U += `element vertex ${F}
|
|
373
|
-
`;
|
|
374
|
-
const l = ["x", "y", "z", "nx", "ny", "nz", "f_dc_0", "f_dc_1", "f_dc_2"];
|
|
375
|
-
for (let B = 0; B < 45; B++) l.push(`f_rest_${B}`);
|
|
376
|
-
l.push("opacity"), l.push("scale_0"), l.push("scale_1"), l.push("scale_2"), l.push("rot_0"), l.push("rot_1"), l.push("rot_2"), l.push("rot_3");
|
|
377
|
-
for (const B of l) U += `property float ${B}
|
|
378
|
-
`;
|
|
379
|
-
U += `end_header
|
|
380
|
-
`;
|
|
381
|
-
const a = new TextEncoder().encode(U), n = 248, e = F * n, Q = new DataView(new ArrayBuffer(a.length + e));
|
|
382
|
-
new Uint8Array(Q.buffer).set(a, 0);
|
|
383
|
-
const d = new Float32Array(t), A = new Uint8Array(t), i = a.length, r = 220, c = 232;
|
|
384
|
-
for (let B = 0; B < F; B++) {
|
|
385
|
-
const W = d[8 * B + 0], J = d[8 * B + 1], h = d[8 * B + 2], C = (A[32 * B + 24 + 0] / 255 - 0.5) / this.SH_C0, k = (A[32 * B + 24 + 1] / 255 - 0.5) / this.SH_C0, p = (A[32 * B + 24 + 2] / 255 - 0.5) / this.SH_C0, X = A[32 * B + 24 + 3] / 255, D = Math.log(X / (1 - X)), u = Math.log(d[8 * B + 3 + 0]), M = Math.log(d[8 * B + 3 + 1]), E = Math.log(d[8 * B + 3 + 2]);
|
|
386
|
-
let w = new z((A[32 * B + 28 + 1] - 128) / 128, (A[32 * B + 28 + 2] - 128) / 128, (A[32 * B + 28 + 3] - 128) / 128, (A[32 * B + 28 + 0] - 128) / 128);
|
|
387
|
-
w = w.normalize();
|
|
388
|
-
const Ft = w.w, Y = w.x, H = w.y, at = w.z;
|
|
389
|
-
Q.setFloat32(i + n * B + 0, W, !0), Q.setFloat32(i + n * B + 4, J, !0), Q.setFloat32(i + n * B + 8, h, !0), Q.setFloat32(i + n * B + 24 + 0, C, !0), Q.setFloat32(i + n * B + 24 + 4, k, !0), Q.setFloat32(i + n * B + 24 + 8, p, !0), Q.setFloat32(i + n * B + 216, D, !0), Q.setFloat32(i + n * B + r + 0, u, !0), Q.setFloat32(i + n * B + r + 4, M, !0), Q.setFloat32(i + n * B + r + 8, E, !0), Q.setFloat32(i + n * B + c + 0, Ft, !0), Q.setFloat32(i + n * B + c + 4, Y, !0), Q.setFloat32(i + n * B + c + 8, H, !0), Q.setFloat32(i + n * B + c + 12, at, !0);
|
|
390
|
-
}
|
|
391
|
-
return Q.buffer;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
Zt.SH_C0 = 0.28209479177387814;
|
|
395
|
-
class ot {
|
|
396
|
-
constructor(t, F) {
|
|
397
|
-
this.min = t, this.max = F;
|
|
398
|
-
}
|
|
399
|
-
contains(t) {
|
|
400
|
-
return t.x >= this.min.x && t.x <= this.max.x && t.y >= this.min.y && t.y <= this.max.y && t.z >= this.min.z && t.z <= this.max.z;
|
|
401
|
-
}
|
|
402
|
-
intersects(t) {
|
|
403
|
-
return this.max.x >= t.min.x && this.min.x <= t.max.x && this.max.y >= t.min.y && this.min.y <= t.max.y && this.max.z >= t.min.z && this.min.z <= t.max.z;
|
|
404
|
-
}
|
|
405
|
-
size() {
|
|
406
|
-
return this.max.subtract(this.min);
|
|
407
|
-
}
|
|
408
|
-
center() {
|
|
409
|
-
return this.min.add(this.max).divide(2);
|
|
410
|
-
}
|
|
411
|
-
expand(t) {
|
|
412
|
-
this.min = this.min.min(t), this.max = this.max.max(t);
|
|
413
|
-
}
|
|
414
|
-
permute() {
|
|
415
|
-
const t = this.min, F = this.max;
|
|
416
|
-
this.min = new I(Math.min(t.x, F.x), Math.min(t.y, F.y), Math.min(t.z, F.z)), this.max = new I(Math.max(t.x, F.x), Math.max(t.y, F.y), Math.max(t.z, F.z));
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
class dt extends bt {
|
|
420
|
-
constructor(t = void 0) {
|
|
421
|
-
super(), this.selectedChanged = !1, this.colorTransformChanged = !1, this._selected = !1, this._colorTransforms = [], this._colorTransformsMap = /* @__PURE__ */ new Map(), this._data = t || new lt(), this._bounds = new ot(new I(1 / 0, 1 / 0, 1 / 0), new I(-1 / 0, -1 / 0, -1 / 0)), this.recalculateBounds = () => {
|
|
422
|
-
this._bounds = new ot(new I(1 / 0, 1 / 0, 1 / 0), new I(-1 / 0, -1 / 0, -1 / 0));
|
|
423
|
-
for (let F = 0; F < this._data.vertexCount; F++) this._bounds.expand(new I(this._data.positions[3 * F], this._data.positions[3 * F + 1], this._data.positions[3 * F + 2]));
|
|
424
|
-
}, this.applyPosition = () => {
|
|
425
|
-
this.data.translate(this.position), this.position = new I();
|
|
426
|
-
}, this.applyRotation = () => {
|
|
427
|
-
this.data.rotate(this.rotation), this.rotation = new z();
|
|
428
|
-
}, this.applyScale = () => {
|
|
429
|
-
this.data.scale(this.scale), this.scale = new I(1, 1, 1);
|
|
430
|
-
}, this.recalculateBounds();
|
|
431
|
-
}
|
|
432
|
-
saveToFile(t = null, F = null) {
|
|
433
|
-
if (!document) return;
|
|
434
|
-
if (F) {
|
|
435
|
-
if (F !== "splat" && F !== "ply") throw new Error("Invalid format. Must be 'splat' or 'ply'");
|
|
436
|
-
} else F = "splat";
|
|
437
|
-
if (!t) {
|
|
438
|
-
const n = /* @__PURE__ */ new Date();
|
|
439
|
-
t = `splat-${n.getFullYear()}-${n.getMonth() + 1}-${n.getDate()}.${F}`;
|
|
440
|
-
}
|
|
441
|
-
this.applyRotation(), this.applyScale(), this.applyPosition();
|
|
442
|
-
const U = this.data.serialize();
|
|
443
|
-
let l;
|
|
444
|
-
if (F === "ply") {
|
|
445
|
-
const n = Zt.SplatToPLY(U.buffer, this.data.vertexCount);
|
|
446
|
-
l = new Blob([n], { type: "application/octet-stream" });
|
|
447
|
-
} else l = new Blob([U.buffer], { type: "application/octet-stream" });
|
|
448
|
-
const a = document.createElement("a");
|
|
449
|
-
a.download = t, a.href = URL.createObjectURL(l), a.click();
|
|
450
|
-
}
|
|
451
|
-
get data() {
|
|
452
|
-
return this._data;
|
|
453
|
-
}
|
|
454
|
-
get selected() {
|
|
455
|
-
return this._selected;
|
|
456
|
-
}
|
|
457
|
-
set selected(t) {
|
|
458
|
-
this._selected !== t && (this._selected = t, this.selectedChanged = !0, this.dispatchEvent(this._changeEvent));
|
|
459
|
-
}
|
|
460
|
-
get colorTransforms() {
|
|
461
|
-
return this._colorTransforms;
|
|
462
|
-
}
|
|
463
|
-
get colorTransformsMap() {
|
|
464
|
-
return this._colorTransformsMap;
|
|
465
|
-
}
|
|
466
|
-
get bounds() {
|
|
467
|
-
let t = this._bounds.center();
|
|
468
|
-
t = t.add(this.position);
|
|
469
|
-
let F = this._bounds.size();
|
|
470
|
-
return F = F.multiply(this.scale), new ot(t.subtract(F.divide(2)), t.add(F.divide(2)));
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
class ct extends bt {
|
|
474
|
-
constructor(t) {
|
|
475
|
-
super(), this._data = t;
|
|
476
|
-
}
|
|
477
|
-
get data() {
|
|
478
|
-
return this._data;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
class qt {
|
|
482
|
-
constructor() {
|
|
483
|
-
this._fx = 1132, this._fy = 1132, this._near = 0.1, this._far = 100, this._width = 512, this._height = 512, this._projectionMatrix = new Ut(), this._viewMatrix = new Ut(), this._viewProj = new Ut(), this._updateProjectionMatrix = () => {
|
|
484
|
-
this._projectionMatrix = new Ut(2 * this.fx / this.width, 0, 0, 0, 0, -2 * this.fy / this.height, 0, 0, 0, 0, this.far / (this.far - this.near), 1, 0, 0, -this.far * this.near / (this.far - this.near), 0), this._viewProj = this.projectionMatrix.multiply(this.viewMatrix);
|
|
485
|
-
}, this.update = (t, F) => {
|
|
486
|
-
const U = tt.RotationFromQuaternion(F).buffer, l = t.flat();
|
|
487
|
-
this._viewMatrix = new Ut(U[0], U[1], U[2], 0, U[3], U[4], U[5], 0, U[6], U[7], U[8], 0, -l[0] * U[0] - l[1] * U[3] - l[2] * U[6], -l[0] * U[1] - l[1] * U[4] - l[2] * U[7], -l[0] * U[2] - l[1] * U[5] - l[2] * U[8], 1), this._viewProj = this.projectionMatrix.multiply(this.viewMatrix);
|
|
488
|
-
}, this.setSize = (t, F) => {
|
|
489
|
-
this._width = t, this._height = F, this._updateProjectionMatrix();
|
|
490
|
-
};
|
|
491
|
-
}
|
|
492
|
-
get fx() {
|
|
493
|
-
return this._fx;
|
|
494
|
-
}
|
|
495
|
-
set fx(t) {
|
|
496
|
-
this._fx !== t && (this._fx = t, this._updateProjectionMatrix());
|
|
497
|
-
}
|
|
498
|
-
get fy() {
|
|
499
|
-
return this._fy;
|
|
500
|
-
}
|
|
501
|
-
set fy(t) {
|
|
502
|
-
this._fy !== t && (this._fy = t, this._updateProjectionMatrix());
|
|
503
|
-
}
|
|
504
|
-
get near() {
|
|
505
|
-
return this._near;
|
|
506
|
-
}
|
|
507
|
-
set near(t) {
|
|
508
|
-
this._near !== t && (this._near = t, this._updateProjectionMatrix());
|
|
509
|
-
}
|
|
510
|
-
get far() {
|
|
511
|
-
return this._far;
|
|
512
|
-
}
|
|
513
|
-
set far(t) {
|
|
514
|
-
this._far !== t && (this._far = t, this._updateProjectionMatrix());
|
|
515
|
-
}
|
|
516
|
-
get width() {
|
|
517
|
-
return this._width;
|
|
518
|
-
}
|
|
519
|
-
get height() {
|
|
520
|
-
return this._height;
|
|
521
|
-
}
|
|
522
|
-
get projectionMatrix() {
|
|
523
|
-
return this._projectionMatrix;
|
|
524
|
-
}
|
|
525
|
-
get viewMatrix() {
|
|
526
|
-
return this._viewMatrix;
|
|
527
|
-
}
|
|
528
|
-
get viewProj() {
|
|
529
|
-
return this._viewProj;
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
class nt {
|
|
533
|
-
constructor(t = 0, F = 0, U = 0, l = 0) {
|
|
534
|
-
this.x = t, this.y = F, this.z = U, this.w = l;
|
|
535
|
-
}
|
|
536
|
-
equals(t) {
|
|
537
|
-
return this.x === t.x && this.y === t.y && this.z === t.z && this.w === t.w;
|
|
538
|
-
}
|
|
539
|
-
add(t) {
|
|
540
|
-
return typeof t == "number" ? new nt(this.x + t, this.y + t, this.z + t, this.w + t) : new nt(this.x + t.x, this.y + t.y, this.z + t.z, this.w + t.w);
|
|
541
|
-
}
|
|
542
|
-
subtract(t) {
|
|
543
|
-
return typeof t == "number" ? new nt(this.x - t, this.y - t, this.z - t, this.w - t) : new nt(this.x - t.x, this.y - t.y, this.z - t.z, this.w - t.w);
|
|
544
|
-
}
|
|
545
|
-
multiply(t) {
|
|
546
|
-
return typeof t == "number" ? new nt(this.x * t, this.y * t, this.z * t, this.w * t) : t instanceof nt ? new nt(this.x * t.x, this.y * t.y, this.z * t.z, this.w * t.w) : new nt(this.x * t.buffer[0] + this.y * t.buffer[4] + this.z * t.buffer[8] + this.w * t.buffer[12], this.x * t.buffer[1] + this.y * t.buffer[5] + this.z * t.buffer[9] + this.w * t.buffer[13], this.x * t.buffer[2] + this.y * t.buffer[6] + this.z * t.buffer[10] + this.w * t.buffer[14], this.x * t.buffer[3] + this.y * t.buffer[7] + this.z * t.buffer[11] + this.w * t.buffer[15]);
|
|
547
|
-
}
|
|
548
|
-
dot(t) {
|
|
549
|
-
return this.x * t.x + this.y * t.y + this.z * t.z + this.w * t.w;
|
|
550
|
-
}
|
|
551
|
-
lerp(t, F) {
|
|
552
|
-
return new nt(this.x + (t.x - this.x) * F, this.y + (t.y - this.y) * F, this.z + (t.z - this.z) * F, this.w + (t.w - this.w) * F);
|
|
553
|
-
}
|
|
554
|
-
magnitude() {
|
|
555
|
-
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
|
|
556
|
-
}
|
|
557
|
-
distanceTo(t) {
|
|
558
|
-
return Math.sqrt((this.x - t.x) ** 2 + (this.y - t.y) ** 2 + (this.z - t.z) ** 2 + (this.w - t.w) ** 2);
|
|
559
|
-
}
|
|
560
|
-
normalize() {
|
|
561
|
-
const t = this.magnitude();
|
|
562
|
-
return new nt(this.x / t, this.y / t, this.z / t, this.w / t);
|
|
563
|
-
}
|
|
564
|
-
flat() {
|
|
565
|
-
return [this.x, this.y, this.z, this.w];
|
|
566
|
-
}
|
|
567
|
-
clone() {
|
|
568
|
-
return new nt(this.x, this.y, this.z, this.w);
|
|
569
|
-
}
|
|
570
|
-
toString() {
|
|
571
|
-
return `[${this.flat().join(", ")}]`;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
class Ql extends bt {
|
|
575
|
-
constructor(t = void 0) {
|
|
576
|
-
super(), this._data = t || new qt(), this._position = new I(0, 0, -5), this.update = () => {
|
|
577
|
-
this.data.update(this.position, this.rotation);
|
|
578
|
-
}, this.screenPointToRay = (F, U) => {
|
|
579
|
-
const l = new nt(F, U, -1, 1), a = this._data.projectionMatrix.invert(), n = l.multiply(a), e = this._data.viewMatrix.invert(), Q = n.multiply(e);
|
|
580
|
-
return new I(Q.x / Q.w, Q.y / Q.w, Q.z / Q.w).subtract(this.position).normalize();
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
get data() {
|
|
584
|
-
return this._data;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
class dl extends Et {
|
|
588
|
-
constructor() {
|
|
589
|
-
super(), this._objects = [], this.addObject = (t) => {
|
|
590
|
-
this.objects.push(t), this.dispatchEvent(new Lt(t));
|
|
591
|
-
}, this.removeObject = (t) => {
|
|
592
|
-
const F = this.objects.indexOf(t);
|
|
593
|
-
if (F < 0) throw new Error("Object not found in scene");
|
|
594
|
-
this.objects.splice(F, 1), this.dispatchEvent(new Pt(t));
|
|
595
|
-
}, this.findObject = (t) => {
|
|
596
|
-
for (const F of this.objects) if (t(F)) return F;
|
|
597
|
-
}, this.findObjectOfType = (t) => {
|
|
598
|
-
for (const F of this.objects) if (F instanceof t) return F;
|
|
599
|
-
}, this.reset = () => {
|
|
600
|
-
const t = this.objects.slice();
|
|
601
|
-
for (const F of t) this.removeObject(F);
|
|
602
|
-
}, this.reset();
|
|
603
|
-
}
|
|
604
|
-
saveToFile(t = null, F = null) {
|
|
605
|
-
if (!document) return;
|
|
606
|
-
if (F) {
|
|
607
|
-
if (F !== "splat" && F !== "ply") throw new Error("Invalid format. Must be 'splat' or 'ply'");
|
|
608
|
-
} else F = "splat";
|
|
609
|
-
if (!t) {
|
|
610
|
-
const d = /* @__PURE__ */ new Date();
|
|
611
|
-
t = `scene-${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}.${F}`;
|
|
612
|
-
}
|
|
613
|
-
const U = [];
|
|
614
|
-
let l = 0;
|
|
615
|
-
for (const d of this.objects) if (d.applyRotation(), d.applyScale(), d.applyPosition(), d instanceof dt) {
|
|
616
|
-
const A = d.data.serialize();
|
|
617
|
-
U.push(A), l += d.data.vertexCount;
|
|
618
|
-
}
|
|
619
|
-
const a = new Uint8Array(l * lt.RowLength);
|
|
620
|
-
let n, e = 0;
|
|
621
|
-
for (const d of U) a.set(d, e), e += d.length;
|
|
622
|
-
if (F === "ply") {
|
|
623
|
-
const d = Zt.SplatToPLY(a.buffer, l);
|
|
624
|
-
n = new Blob([d], { type: "application/octet-stream" });
|
|
625
|
-
} else n = new Blob([a.buffer], { type: "application/octet-stream" });
|
|
626
|
-
const Q = document.createElement("a");
|
|
627
|
-
Q.download = t, Q.href = URL.createObjectURL(n), Q.click();
|
|
628
|
-
}
|
|
629
|
-
get objects() {
|
|
630
|
-
return this._objects;
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
async function Ct(G, t) {
|
|
634
|
-
const F = await fetch(G, { mode: "cors", credentials: "omit", cache: t ? "force-cache" : "default" });
|
|
635
|
-
if (F.status != 200) throw new Error(F.status + " Unable to load " + F.url);
|
|
636
|
-
return F;
|
|
637
|
-
}
|
|
638
|
-
async function gt(G, t) {
|
|
639
|
-
return G.headers.has("content-length") ? async function(F, U) {
|
|
640
|
-
const l = F.body.getReader(), a = parseInt(F.headers.get("content-length")), n = new Uint8Array(a);
|
|
641
|
-
let e = 0;
|
|
642
|
-
for (; ; ) {
|
|
643
|
-
const { done: Q, value: d } = await l.read();
|
|
644
|
-
if (Q) break;
|
|
645
|
-
n.set(d, e), e += d.length, U == null || U(e / a);
|
|
646
|
-
}
|
|
647
|
-
return n;
|
|
648
|
-
}(G, t) : async function(F, U) {
|
|
649
|
-
const l = F.body.getReader(), a = [];
|
|
650
|
-
let n = 0;
|
|
651
|
-
for (; ; ) {
|
|
652
|
-
const { done: d, value: A } = await l.read();
|
|
653
|
-
if (d) break;
|
|
654
|
-
a.push(A), n += A.length;
|
|
655
|
-
}
|
|
656
|
-
const e = new Uint8Array(n);
|
|
657
|
-
let Q = 0;
|
|
658
|
-
for (const d of a) e.set(d, Q), Q += d.length, U == null || U(Q / n);
|
|
659
|
-
return e;
|
|
660
|
-
}(G, t);
|
|
661
|
-
}
|
|
662
|
-
class al {
|
|
663
|
-
static async LoadAsync(t, F, U, l = !1) {
|
|
664
|
-
const a = await Ct(t, l), n = await gt(a, U);
|
|
665
|
-
return this.LoadFromArrayBuffer(n, F);
|
|
666
|
-
}
|
|
667
|
-
static async LoadFromFileAsync(t, F, U) {
|
|
668
|
-
const l = new FileReader();
|
|
669
|
-
let a = new dt();
|
|
670
|
-
return l.onload = (n) => {
|
|
671
|
-
a = this.LoadFromArrayBuffer(n.target.result, F);
|
|
672
|
-
}, l.onprogress = (n) => {
|
|
673
|
-
U == null || U(n.loaded / n.total);
|
|
674
|
-
}, l.readAsArrayBuffer(t), await new Promise((n) => {
|
|
675
|
-
l.onloadend = () => {
|
|
676
|
-
n();
|
|
677
|
-
};
|
|
678
|
-
}), a;
|
|
679
|
-
}
|
|
680
|
-
static LoadFromArrayBuffer(t, F) {
|
|
681
|
-
const U = new Uint8Array(t), l = lt.Deserialize(U), a = new dt(l);
|
|
682
|
-
return F.addObject(a), a;
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
class Al {
|
|
686
|
-
static async LoadAsync(t, F, U, l = "", a = !1) {
|
|
687
|
-
const n = await Ct(t, a), e = await gt(n, U);
|
|
688
|
-
if (e[0] !== 112 || e[1] !== 108 || e[2] !== 121 || e[3] !== 10) throw new Error("Invalid PLY file");
|
|
689
|
-
return this.LoadFromArrayBuffer(e.buffer, F, l);
|
|
690
|
-
}
|
|
691
|
-
static async LoadFromFileAsync(t, F, U, l = "") {
|
|
692
|
-
const a = new FileReader();
|
|
693
|
-
let n = new dt();
|
|
694
|
-
return a.onload = (e) => {
|
|
695
|
-
n = this.LoadFromArrayBuffer(e.target.result, F, l);
|
|
696
|
-
}, a.onprogress = (e) => {
|
|
697
|
-
U == null || U(e.loaded / e.total);
|
|
698
|
-
}, a.readAsArrayBuffer(t), await new Promise((e) => {
|
|
699
|
-
a.onloadend = () => {
|
|
700
|
-
e();
|
|
701
|
-
};
|
|
702
|
-
}), n;
|
|
703
|
-
}
|
|
704
|
-
static LoadFromArrayBuffer(t, F, U = "") {
|
|
705
|
-
const l = new Uint8Array(this._ParsePLYBuffer(t, U)), a = lt.Deserialize(l), n = new dt(a);
|
|
706
|
-
return F.addObject(n), n;
|
|
707
|
-
}
|
|
708
|
-
static _ParsePLYBuffer(t, F) {
|
|
709
|
-
const U = new Uint8Array(t), l = new TextDecoder().decode(U.slice(0, 10240)), a = `end_header
|
|
710
|
-
`, n = l.indexOf(a);
|
|
711
|
-
if (n < 0) throw new Error("Unable to read .ply file header");
|
|
712
|
-
const e = parseInt(/element vertex (\d+)\n/.exec(l)[1]);
|
|
713
|
-
let Q = 0;
|
|
714
|
-
const d = { double: 8, int: 4, uint: 4, float: 4, short: 2, ushort: 2, uchar: 1 }, A = [];
|
|
715
|
-
for (const B of l.slice(0, n).split(`
|
|
716
|
-
`).filter((W) => W.startsWith("property "))) {
|
|
717
|
-
const [W, J, h] = B.split(" ");
|
|
718
|
-
if (A.push({ name: h, type: J, offset: Q }), console.log(h, J, Q), !d[J]) throw new Error(`Unsupported property type: ${J}`);
|
|
719
|
-
Q += d[J];
|
|
720
|
-
}
|
|
721
|
-
const i = new DataView(t, n + 11), r = new ArrayBuffer(lt.RowLength * e), c = z.FromEuler(new I(Math.PI / 2, 0, 0));
|
|
722
|
-
for (let B = 0; B < e; B++) {
|
|
723
|
-
const W = new Float32Array(r, B * lt.RowLength, 3), J = new Float32Array(r, B * lt.RowLength + 12, 3), h = new Uint8ClampedArray(r, B * lt.RowLength + 24, 4), C = new Uint8ClampedArray(r, B * lt.RowLength + 28, 4);
|
|
724
|
-
let k = 255, p = 0, X = 0, D = 0;
|
|
725
|
-
A.forEach((M) => {
|
|
726
|
-
let E;
|
|
727
|
-
switch (M.type) {
|
|
728
|
-
case "float":
|
|
729
|
-
E = i.getFloat32(M.offset + B * Q, !0);
|
|
730
|
-
break;
|
|
731
|
-
case "int":
|
|
732
|
-
E = i.getInt32(M.offset + B * Q, !0);
|
|
733
|
-
break;
|
|
734
|
-
default:
|
|
735
|
-
throw new Error(`Unsupported property type: ${M.type}`);
|
|
736
|
-
}
|
|
737
|
-
switch (M.name) {
|
|
738
|
-
case "x":
|
|
739
|
-
W[0] = E;
|
|
740
|
-
break;
|
|
741
|
-
case "y":
|
|
742
|
-
W[1] = E;
|
|
743
|
-
break;
|
|
744
|
-
case "z":
|
|
745
|
-
W[2] = E;
|
|
746
|
-
break;
|
|
747
|
-
case "scale_0":
|
|
748
|
-
case "scaling_0":
|
|
749
|
-
J[0] = Math.exp(E);
|
|
750
|
-
break;
|
|
751
|
-
case "scale_1":
|
|
752
|
-
case "scaling_1":
|
|
753
|
-
J[1] = Math.exp(E);
|
|
754
|
-
break;
|
|
755
|
-
case "scale_2":
|
|
756
|
-
case "scaling_2":
|
|
757
|
-
J[2] = Math.exp(E);
|
|
758
|
-
break;
|
|
759
|
-
case "red":
|
|
760
|
-
h[0] = E;
|
|
761
|
-
break;
|
|
762
|
-
case "green":
|
|
763
|
-
h[1] = E;
|
|
764
|
-
break;
|
|
765
|
-
case "blue":
|
|
766
|
-
h[2] = E;
|
|
767
|
-
break;
|
|
768
|
-
case "f_dc_0":
|
|
769
|
-
case "features_0":
|
|
770
|
-
h[0] = 255 * (0.5 + Zt.SH_C0 * E);
|
|
771
|
-
break;
|
|
772
|
-
case "f_dc_1":
|
|
773
|
-
case "features_1":
|
|
774
|
-
h[1] = 255 * (0.5 + Zt.SH_C0 * E);
|
|
775
|
-
break;
|
|
776
|
-
case "f_dc_2":
|
|
777
|
-
case "features_2":
|
|
778
|
-
h[2] = 255 * (0.5 + Zt.SH_C0 * E);
|
|
779
|
-
break;
|
|
780
|
-
case "f_dc_3":
|
|
781
|
-
h[3] = 255 * (0.5 + Zt.SH_C0 * E);
|
|
782
|
-
break;
|
|
783
|
-
case "opacity":
|
|
784
|
-
case "opacity_0":
|
|
785
|
-
h[3] = 1 / (1 + Math.exp(-E)) * 255;
|
|
786
|
-
break;
|
|
787
|
-
case "rot_0":
|
|
788
|
-
case "rotation_0":
|
|
789
|
-
k = E;
|
|
790
|
-
break;
|
|
791
|
-
case "rot_1":
|
|
792
|
-
case "rotation_1":
|
|
793
|
-
p = E;
|
|
794
|
-
break;
|
|
795
|
-
case "rot_2":
|
|
796
|
-
case "rotation_2":
|
|
797
|
-
X = E;
|
|
798
|
-
break;
|
|
799
|
-
case "rot_3":
|
|
800
|
-
case "rotation_3":
|
|
801
|
-
D = E;
|
|
802
|
-
}
|
|
803
|
-
});
|
|
804
|
-
let u = new z(p, X, D, k);
|
|
805
|
-
switch (F) {
|
|
806
|
-
case "polycam": {
|
|
807
|
-
const M = W[1];
|
|
808
|
-
W[1] = -W[2], W[2] = M, u = c.multiply(u);
|
|
809
|
-
break;
|
|
810
|
-
}
|
|
811
|
-
case "":
|
|
812
|
-
break;
|
|
813
|
-
default:
|
|
814
|
-
throw new Error(`Unsupported format: ${F}`);
|
|
815
|
-
}
|
|
816
|
-
u = u.normalize(), C[0] = 128 * u.w + 128, C[1] = 128 * u.x + 128, C[2] = 128 * u.y + 128, C[3] = 128 * u.z + 128;
|
|
817
|
-
}
|
|
818
|
-
return r;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
class Vl {
|
|
822
|
-
static async LoadAsync(t, F, U, l, a = !1) {
|
|
823
|
-
const n = await Ct(t, a), e = await gt(n, l);
|
|
824
|
-
return this._ParseSplatvBuffer(e.buffer, F, U);
|
|
825
|
-
}
|
|
826
|
-
static async LoadFromFileAsync(t, F, U, l) {
|
|
827
|
-
const a = new FileReader();
|
|
828
|
-
let n = null;
|
|
829
|
-
if (a.onload = (e) => {
|
|
830
|
-
n = this._ParseSplatvBuffer(e.target.result, F, U);
|
|
831
|
-
}, a.onprogress = (e) => {
|
|
832
|
-
l == null || l(e.loaded / e.total);
|
|
833
|
-
}, a.readAsArrayBuffer(t), await new Promise((e) => {
|
|
834
|
-
a.onloadend = () => {
|
|
835
|
-
e();
|
|
836
|
-
};
|
|
837
|
-
}), !n) throw new Error("Failed to load splatv file");
|
|
838
|
-
return n;
|
|
839
|
-
}
|
|
840
|
-
static _ParseSplatvBuffer(t, F, U) {
|
|
841
|
-
let l = null;
|
|
842
|
-
const a = (r, c, B) => {
|
|
843
|
-
if (r.type === "magic") {
|
|
844
|
-
const W = new Int32Array(c.buffer);
|
|
845
|
-
if (W[0] !== 26443) throw new Error("Invalid splatv file");
|
|
846
|
-
B.push({ size: W[1], type: "chunks" });
|
|
847
|
-
} else if (r.type === "chunks") {
|
|
848
|
-
const W = JSON.parse(new TextDecoder("utf-8").decode(c));
|
|
849
|
-
if (W.length == 0) throw new Error("Invalid splatv file");
|
|
850
|
-
W.length > 1 && console.warn("Splatv file contains more than one chunk, only the first one will be loaded");
|
|
851
|
-
const J = W[0], h = J.cameras;
|
|
852
|
-
if (U && h && h.length) {
|
|
853
|
-
const C = h[0], k = new I(C.position[0], C.position[1], C.position[2]), p = z.FromMatrix3(new tt(C.rotation[0][0], C.rotation[0][1], C.rotation[0][2], C.rotation[1][0], C.rotation[1][1], C.rotation[1][2], C.rotation[2][0], C.rotation[2][1], C.rotation[2][2]));
|
|
854
|
-
U.position = k, U.rotation = p;
|
|
855
|
-
}
|
|
856
|
-
B.push(J);
|
|
857
|
-
} else if (r.type === "splat") {
|
|
858
|
-
const W = mt.Deserialize(c, r.texwidth, r.texheight), J = new ct(W);
|
|
859
|
-
F.addObject(J), l = J;
|
|
860
|
-
}
|
|
861
|
-
}, n = new Uint8Array(t), e = [{ size: 8, type: "magic", texwidth: 0, texheight: 0 }];
|
|
862
|
-
let Q = e.shift(), d = new Uint8Array(Q.size), A = 0, i = 0;
|
|
863
|
-
for (; Q; ) {
|
|
864
|
-
for (; A < Q.size; ) {
|
|
865
|
-
const r = Math.min(Q.size - A, n.length - i);
|
|
866
|
-
d.set(n.subarray(i, i + r), A), A += r, i += r;
|
|
867
|
-
}
|
|
868
|
-
if (a(Q, d, e), l) return l;
|
|
869
|
-
Q = e.shift(), Q && (d = new Uint8Array(Q.size), A = 0);
|
|
870
|
-
}
|
|
871
|
-
throw new Error("Invalid splatv file");
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
function $t(G, t, F) {
|
|
875
|
-
var U = t === void 0 ? null : t, l = function(Q, d) {
|
|
876
|
-
var A = atob(Q);
|
|
877
|
-
return A;
|
|
878
|
-
}(G), a = l.indexOf(`
|
|
879
|
-
`, 10) + 1, n = l.substring(a) + (U ? "//# sourceMappingURL=" + U : ""), e = new Blob([n], { type: "application/javascript" });
|
|
880
|
-
return URL.createObjectURL(e);
|
|
881
|
-
}
|
|
882
|
-
function yt(G, t, F) {
|
|
883
|
-
var U;
|
|
884
|
-
return function(l) {
|
|
885
|
-
return U = U || $t(G, t), new Worker(U, l);
|
|
886
|
-
};
|
|
887
|
-
}
|
|
888
|
-
var tl = yt("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICd1c2Ugc3RyaWN0JzsKCiAgdmFyIGxvYWRXYXNtID0gKCgpID0+IHsKICAgIAogICAgcmV0dXJuICgKICBmdW5jdGlvbihtb2R1bGVBcmcgPSB7fSkgewoKICB2YXIgTW9kdWxlPW1vZHVsZUFyZzt2YXIgcmVhZHlQcm9taXNlUmVzb2x2ZSxyZWFkeVByb21pc2VSZWplY3Q7TW9kdWxlWyJyZWFkeSJdPW5ldyBQcm9taXNlKChyZXNvbHZlLHJlamVjdCk9PntyZWFkeVByb21pc2VSZXNvbHZlPXJlc29sdmU7cmVhZHlQcm9taXNlUmVqZWN0PXJlamVjdDt9KTt2YXIgbW9kdWxlT3ZlcnJpZGVzPU9iamVjdC5hc3NpZ24oe30sTW9kdWxlKTt2YXIgc2NyaXB0RGlyZWN0b3J5PSIiO2Z1bmN0aW9uIGxvY2F0ZUZpbGUocGF0aCl7aWYoTW9kdWxlWyJsb2NhdGVGaWxlIl0pe3JldHVybiBNb2R1bGVbImxvY2F0ZUZpbGUiXShwYXRoLHNjcmlwdERpcmVjdG9yeSl9cmV0dXJuIHNjcmlwdERpcmVjdG9yeStwYXRofXZhciByZWFkQmluYXJ5O3t7c2NyaXB0RGlyZWN0b3J5PXNlbGYubG9jYXRpb24uaHJlZjt9aWYoc2NyaXB0RGlyZWN0b3J5LmluZGV4T2YoImJsb2I6IikhPT0wKXtzY3JpcHREaXJlY3Rvcnk9c2NyaXB0RGlyZWN0b3J5LnN1YnN0cigwLHNjcmlwdERpcmVjdG9yeS5yZXBsYWNlKC9bPyNdLiovLCIiKS5sYXN0SW5kZXhPZigiLyIpKzEpO31lbHNlIHtzY3JpcHREaXJlY3Rvcnk9IiI7fXt7cmVhZEJpbmFyeT11cmw9Pnt2YXIgeGhyPW5ldyBYTUxIdHRwUmVxdWVzdDt4aHIub3BlbigiR0VUIix1cmwsZmFsc2UpO3hoci5yZXNwb25zZVR5cGU9ImFycmF5YnVmZmVyIjt4aHIuc2VuZChudWxsKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoeGhyLnJlc3BvbnNlKX07fX19TW9kdWxlWyJwcmludCJdfHxjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpO3ZhciBlcnI9TW9kdWxlWyJwcmludEVyciJdfHxjb25zb2xlLmVycm9yLmJpbmQoY29uc29sZSk7T2JqZWN0LmFzc2lnbihNb2R1bGUsbW9kdWxlT3ZlcnJpZGVzKTttb2R1bGVPdmVycmlkZXM9bnVsbDtpZihNb2R1bGVbImFyZ3VtZW50cyJdKU1vZHVsZVsiYXJndW1lbnRzIl07aWYoTW9kdWxlWyJ0aGlzUHJvZ3JhbSJdKU1vZHVsZVsidGhpc1Byb2dyYW0iXTtpZihNb2R1bGVbInF1aXQiXSlNb2R1bGVbInF1aXQiXTt2YXIgd2FzbUJpbmFyeTtpZihNb2R1bGVbIndhc21CaW5hcnkiXSl3YXNtQmluYXJ5PU1vZHVsZVsid2FzbUJpbmFyeSJdO2lmKHR5cGVvZiBXZWJBc3NlbWJseSE9Im9iamVjdCIpe2Fib3J0KCJubyBuYXRpdmUgd2FzbSBzdXBwb3J0IGRldGVjdGVkIik7fXZhciB3YXNtTWVtb3J5O3ZhciBBQk9SVD1mYWxzZTt2YXIgSEVBUDgsSEVBUFU4LEhFQVAxNixIRUFQVTE2LEhFQVAzMixIRUFQVTMyLEhFQVBGMzIsSEVBUEY2NDtmdW5jdGlvbiB1cGRhdGVNZW1vcnlWaWV3cygpe3ZhciBiPXdhc21NZW1vcnkuYnVmZmVyO01vZHVsZVsiSEVBUDgiXT1IRUFQOD1uZXcgSW50OEFycmF5KGIpO01vZHVsZVsiSEVBUDE2Il09SEVBUDE2PW5ldyBJbnQxNkFycmF5KGIpO01vZHVsZVsiSEVBUFU4Il09SEVBUFU4PW5ldyBVaW50OEFycmF5KGIpO01vZHVsZVsiSEVBUFUxNiJdPUhFQVBVMTY9bmV3IFVpbnQxNkFycmF5KGIpO01vZHVsZVsiSEVBUDMyIl09SEVBUDMyPW5ldyBJbnQzMkFycmF5KGIpO01vZHVsZVsiSEVBUFUzMiJdPUhFQVBVMzI9bmV3IFVpbnQzMkFycmF5KGIpO01vZHVsZVsiSEVBUEYzMiJdPUhFQVBGMzI9bmV3IEZsb2F0MzJBcnJheShiKTtNb2R1bGVbIkhFQVBGNjQiXT1IRUFQRjY0PW5ldyBGbG9hdDY0QXJyYXkoYik7fXZhciBfX0FUUFJFUlVOX189W107dmFyIF9fQVRJTklUX189W107dmFyIF9fQVRQT1NUUlVOX189W107ZnVuY3Rpb24gcHJlUnVuKCl7aWYoTW9kdWxlWyJwcmVSdW4iXSl7aWYodHlwZW9mIE1vZHVsZVsicHJlUnVuIl09PSJmdW5jdGlvbiIpTW9kdWxlWyJwcmVSdW4iXT1bTW9kdWxlWyJwcmVSdW4iXV07d2hpbGUoTW9kdWxlWyJwcmVSdW4iXS5sZW5ndGgpe2FkZE9uUHJlUnVuKE1vZHVsZVsicHJlUnVuIl0uc2hpZnQoKSk7fX1jYWxsUnVudGltZUNhbGxiYWNrcyhfX0FUUFJFUlVOX18pO31mdW5jdGlvbiBpbml0UnVudGltZSgpe2NhbGxSdW50aW1lQ2FsbGJhY2tzKF9fQVRJTklUX18pO31mdW5jdGlvbiBwb3N0UnVuKCl7aWYoTW9kdWxlWyJwb3N0UnVuIl0pe2lmKHR5cGVvZiBNb2R1bGVbInBvc3RSdW4iXT09ImZ1bmN0aW9uIilNb2R1bGVbInBvc3RSdW4iXT1bTW9kdWxlWyJwb3N0UnVuIl1dO3doaWxlKE1vZHVsZVsicG9zdFJ1biJdLmxlbmd0aCl7YWRkT25Qb3N0UnVuKE1vZHVsZVsicG9zdFJ1biJdLnNoaWZ0KCkpO319Y2FsbFJ1bnRpbWVDYWxsYmFja3MoX19BVFBPU1RSVU5fXyk7fWZ1bmN0aW9uIGFkZE9uUHJlUnVuKGNiKXtfX0FUUFJFUlVOX18udW5zaGlmdChjYik7fWZ1bmN0aW9uIGFkZE9uSW5pdChjYil7X19BVElOSVRfXy51bnNoaWZ0KGNiKTt9ZnVuY3Rpb24gYWRkT25Qb3N0UnVuKGNiKXtfX0FUUE9TVFJVTl9fLnVuc2hpZnQoY2IpO312YXIgcnVuRGVwZW5kZW5jaWVzPTA7dmFyIGRlcGVuZGVuY2llc0Z1bGZpbGxlZD1udWxsO2Z1bmN0aW9uIGFkZFJ1bkRlcGVuZGVuY3koaWQpe3J1bkRlcGVuZGVuY2llcysrO2lmKE1vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdKXtNb2R1bGVbIm1vbml0b3JSdW5EZXBlbmRlbmNpZXMiXShydW5EZXBlbmRlbmNpZXMpO319ZnVuY3Rpb24gcmVtb3ZlUnVuRGVwZW5kZW5jeShpZCl7cnVuRGVwZW5kZW5jaWVzLS07aWYoTW9kdWxlWyJtb25pdG9yUnVuRGVwZW5kZW5jaWVzIl0pe01vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdKHJ1bkRlcGVuZGVuY2llcyk7fWlmKHJ1bkRlcGVuZGVuY2llcz09MCl7aWYoZGVwZW5kZW5jaWVzRnVsZmlsbGVkKXt2YXIgY2FsbGJhY2s9ZGVwZW5kZW5jaWVzRnVsZmlsbGVkO2RlcGVuZGVuY2llc0Z1bGZpbGxlZD1udWxsO2NhbGxiYWNrKCk7fX19ZnVuY3Rpb24gYWJvcnQod2hhdCl7aWYoTW9kdWxlWyJvbkFib3J0Il0pe01vZHVsZVsib25BYm9ydCJdKHdoYXQpO313aGF0PSJBYm9ydGVkKCIrd2hhdCsiKSI7ZXJyKHdoYXQpO0FCT1JUPXRydWU7d2hhdCs9Ii4gQnVpbGQgd2l0aCAtc0FTU0VSVElPTlMgZm9yIG1vcmUgaW5mby4iO3ZhciBlPW5ldyBXZWJBc3NlbWJseS5SdW50aW1lRXJyb3Iod2hhdCk7cmVhZHlQcm9taXNlUmVqZWN0KGUpO3Rocm93IGV9dmFyIGRhdGFVUklQcmVmaXg9ImRhdGE6YXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtO2Jhc2U2NCwiO3ZhciBpc0RhdGFVUkk9ZmlsZW5hbWU9PmZpbGVuYW1lLnN0YXJ0c1dpdGgoZGF0YVVSSVByZWZpeCk7dmFyIHdhc21CaW5hcnlGaWxlO3dhc21CaW5hcnlGaWxlPSJkYXRhOmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTtiYXNlNjQsQUdGemJRRUFBQUFCV2cxZ0JIOS9mMzhBWUFOL2YzOEFZQVYvZjM5L2Z3QmdCbjkvZjM5L2Z3QmdBWDhCZjJBQUFHQUNmMzhBWUFOL2YzOEJmMkFCZndCZ0IzOS9mMzkvZjM4QVlBSi9md0YvWUFSL2YzNStBR0FKZjM5L2YzOS9mMzkvQUFJOUNnRmhBV0VBQVFGaEFXSUFBZ0ZoQVdNQUFRRmhBV1FBQmdGaEFXVUFBUUZoQVdZQUNRRmhBV2NBQkFGaEFXZ0FCZ0ZoQVdrQUFBRmhBV29BQmdNWkdBY0VDQVVJQ2dVTEFRQUJDQVFGQXdNQ0FnQUFCd2NFREFRRkFYQUJFQkFGQndFQmdBS0FnQUlHQ0FGL0FVSGduUVFMQngwSEFXc0NBQUZzQUEwQmJRQWhBVzRBRndGdkFRQUJjQUFXQVhFQURna1ZBUUJCQVFzUEVDQU1GUlVmREI0WUdoME1HUnNjQ3ZCSUdIRUJBWDhnQWtVRVFDQUFLQUlFSUFFb0FnUkdEd3NnQUNBQlJnUkFRUUVQQ3dKQUlBQW9BZ1FpQWkwQUFDSUFSU0FBSUFFb0FnUWlBUzBBQUNJRFIzSU5BQU5BSUFFdEFBRWhBeUFDTFFBQklnQkZEUUVnQVVFQmFpRUJJQUpCQVdvaEFpQUFJQU5HRFFBTEN5QUFJQU5HQzA4QkFuOUIyQmtvQWdBaUFTQUFRUWRxUVhoeElnSnFJUUFDUUNBQ1FRQWdBQ0FCVFJzTkFDQUFQd0JCRUhSTEJFQWdBQkFHUlEwQkMwSFlHU0FBTmdJQUlBRVBDMEhvR1VFd05nSUFRWDhMQmdBZ0FCQU9DeWtBUWVBWlFRRTJBZ0JCNUJsQkFEWUNBQkFRUWVRWlFkd1pLQUlBTmdJQVFkd1pRZUFaTmdJQUM5SUxBUWQvQWtBZ0FFVU5BQ0FBUVFocklnSWdBRUVFYXlnQ0FDSUJRWGh4SWdCcUlRVUNRQ0FCUVFGeERRQWdBVUVEY1VVTkFTQUNJQUlvQWdBaUFXc2lBa0g4R1NnQ0FFa05BU0FBSUFGcUlRQUNRQUpBUVlBYUtBSUFJQUpIQkVBZ0FVSC9BVTBFUUNBQlFRTjJJUVFnQWlnQ0RDSUJJQUlvQWdnaUEwWUVRRUhzR1VIc0dTZ0NBRUYrSUFSM2NUWUNBQXdGQ3lBRElBRTJBZ3dnQVNBRE5nSUlEQVFMSUFJb0FoZ2hCaUFDSUFJb0Fnd2lBVWNFUUNBQ0tBSUlJZ01nQVRZQ0RDQUJJQU0yQWdnTUF3c2dBa0VVYWlJRUtBSUFJZ05GQkVBZ0FpZ0NFQ0lEUlEwQ0lBSkJFR29oQkFzRFFDQUVJUWNnQXlJQlFSUnFJZ1FvQWdBaUF3MEFJQUZCRUdvaEJDQUJLQUlRSWdNTkFBc2dCMEVBTmdJQURBSUxJQVVvQWdRaUFVRURjVUVEUncwQ1FmUVpJQUEyQWdBZ0JTQUJRWDV4TmdJRUlBSWdBRUVCY2pZQ0JDQUZJQUEyQWdBUEMwRUFJUUVMSUFaRkRRQUNRQ0FDS0FJY0lnTkJBblJCbkJ4cUlnUW9BZ0FnQWtZRVFDQUVJQUUyQWdBZ0FRMEJRZkFaUWZBWktBSUFRWDRnQTNkeE5nSUFEQUlMSUFaQkVFRVVJQVlvQWhBZ0FrWWJhaUFCTmdJQUlBRkZEUUVMSUFFZ0JqWUNHQ0FDS0FJUUlnTUVRQ0FCSUFNMkFoQWdBeUFCTmdJWUN5QUNLQUlVSWdORkRRQWdBU0FETmdJVUlBTWdBVFlDR0FzZ0FpQUZUdzBBSUFVb0FnUWlBVUVCY1VVTkFBSkFBa0FDUUFKQUlBRkJBbkZGQkVCQmhCb29BZ0FnQlVZRVFFR0VHaUFDTmdJQVFmZ1pRZmdaS0FJQUlBQnFJZ0EyQWdBZ0FpQUFRUUZ5TmdJRUlBSkJnQm9vQWdCSERRWkI5QmxCQURZQ0FFR0FHa0VBTmdJQUR3dEJnQm9vQWdBZ0JVWUVRRUdBR2lBQ05nSUFRZlFaUWZRWktBSUFJQUJxSWdBMkFnQWdBaUFBUVFGeU5nSUVJQUFnQW1vZ0FEWUNBQThMSUFGQmVIRWdBR29oQUNBQlFmOEJUUVJBSUFGQkEzWWhCQ0FGS0FJTUlnRWdCU2dDQ0NJRFJnUkFRZXdaUWV3WktBSUFRWDRnQkhkeE5nSUFEQVVMSUFNZ0FUWUNEQ0FCSUFNMkFnZ01CQXNnQlNnQ0dDRUdJQVVnQlNnQ0RDSUJSd1JBUWZ3WktBSUFHaUFGS0FJSUlnTWdBVFlDRENBQklBTTJBZ2dNQXdzZ0JVRVVhaUlFS0FJQUlnTkZCRUFnQlNnQ0VDSURSUTBDSUFWQkVHb2hCQXNEUUNBRUlRY2dBeUlCUVJScUlnUW9BZ0FpQXcwQUlBRkJFR29oQkNBQktBSVFJZ01OQUFzZ0IwRUFOZ0lBREFJTElBVWdBVUYrY1RZQ0JDQUNJQUJCQVhJMkFnUWdBQ0FDYWlBQU5nSUFEQU1MUVFBaEFRc2dCa1VOQUFKQUlBVW9BaHdpQTBFQ2RFR2NIR29pQkNnQ0FDQUZSZ1JBSUFRZ0FUWUNBQ0FCRFFGQjhCbEI4QmtvQWdCQmZpQURkM0UyQWdBTUFnc2dCa0VRUVJRZ0JpZ0NFQ0FGUmh0cUlBRTJBZ0FnQVVVTkFRc2dBU0FHTmdJWUlBVW9BaEFpQXdSQUlBRWdBellDRUNBRElBRTJBaGdMSUFVb0FoUWlBMFVOQUNBQklBTTJBaFFnQXlBQk5nSVlDeUFDSUFCQkFYSTJBZ1FnQUNBQ2FpQUFOZ0lBSUFKQmdCb29BZ0JIRFFCQjlCa2dBRFlDQUE4TElBQkIvd0ZOQkVBZ0FFRjRjVUdVR21vaEFRSi9RZXdaS0FJQUlnTkJBU0FBUVFOMmRDSUFjVVVFUUVIc0dTQUFJQU55TmdJQUlBRU1BUXNnQVNnQ0NBc2hBQ0FCSUFJMkFnZ2dBQ0FDTmdJTUlBSWdBVFlDRENBQ0lBQTJBZ2dQQzBFZklRTWdBRUgvLy84SFRRUkFJQUJCSmlBQVFRaDJaeUlCYTNaQkFYRWdBVUVCZEd0QlBtb2hBd3NnQWlBRE5nSWNJQUpDQURjQ0VDQURRUUowUVp3Y2FpRUJBa0FDUUFKQVFmQVpLQUlBSWdSQkFTQURkQ0lIY1VVRVFFSHdHU0FFSUFkeU5nSUFJQUVnQWpZQ0FDQUNJQUUyQWhnTUFRc2dBRUVaSUFOQkFYWnJRUUFnQTBFZlJ4dDBJUU1nQVNnQ0FDRUJBMEFnQVNJRUtBSUVRWGh4SUFCR0RRSWdBMEVkZGlFQklBTkJBWFFoQXlBRUlBRkJCSEZxSWdkQkVHb29BZ0FpQVEwQUN5QUhJQUkyQWhBZ0FpQUVOZ0lZQ3lBQ0lBSTJBZ3dnQWlBQ05nSUlEQUVMSUFRb0FnZ2lBQ0FDTmdJTUlBUWdBallDQ0NBQ1FRQTJBaGdnQWlBRU5nSU1JQUlnQURZQ0NBdEJqQnBCakJvb0FnQkJBV3NpQUVGL0lBQWJOZ0lBQ3dzcEFRRi9JQUVFUUNBQUlRSURRQ0FDUVFBNkFBQWdBa0VCYWlFQ0lBRkJBV3NpQVEwQUN3c2dBQXZoQXdCQmpCZEJtZ2tRQ1VHWUYwRzVDRUVCUVFBUUNFR2tGMEcwQ0VFQlFZQi9RZjhBRUFGQnZCZEJyUWhCQVVHQWYwSC9BQkFCUWJBWFFhc0lRUUZCQUVIL0FSQUJRY2dYUVlrSVFRSkJnSUIrUWYvL0FSQUJRZFFYUVlBSVFRSkJBRUgvL3dNUUFVSGdGMEdZQ0VFRVFZQ0FnSUI0UWYvLy8vOEhFQUZCN0JkQmp3aEJCRUVBUVg4UUFVSDRGMEhYQ0VFRVFZQ0FnSUI0UWYvLy8vOEhFQUZCaEJoQnpnaEJCRUVBUVg4UUFVR1FHRUdqQ0VLQWdJQ0FnSUNBZ0lCL1F2Ly8vLy8vLy8vLy93QVFFVUdjR0VHaUNFSUFRbjhRRVVHb0dFR2NDRUVFRUFSQnRCaEJrd2xCQ0JBRVFZUVBRZWtJRUFOQnpBOUJsdzBRQTBHVUVFRUVRZHdJRUFKQjRCQkJBa0gxQ0JBQ1Fhd1JRUVJCaEFrUUFrSElFVUcrQ0JBSFFmQVJRUUJCMGd3UUFFR1lFa0VBUWJnTkVBQkJ3QkpCQVVId0RCQUFRZWdTUVFKQm53a1FBRUdRRTBFRFFiNEpFQUJCdUJOQkJFSG1DUkFBUWVBVFFRVkJnd29RQUVHSUZFRUVRZDBORUFCQnNCUkJCVUg3RFJBQVFaZ1NRUUJCNlFvUUFFSEFFa0VCUWNnS0VBQkI2QkpCQWtHckN4QUFRWkFUUVFOQmlRc1FBRUc0RTBFRVFiRU1FQUJCNEJOQkJVR1BEQkFBUWRnVVFRaEI3Z3NRQUVHQUZVRUpRY3dMRUFCQnFCVkJCa0dwQ2hBQVFkQVZRUWRCb2c0UUFBc2NBQ0FBSUFGQkNDQUNweUFDUWlDSXB5QURweUFEUWlDSXB4QUZDeUFBQWtBZ0FDZ0NCQ0FCUncwQUlBQW9BaHhCQVVZTkFDQUFJQUkyQWh3TEM1b0JBQ0FBUVFFNkFEVUNRQ0FBS0FJRUlBSkhEUUFnQUVFQk9nQTBBa0FnQUNnQ0VDSUNSUVJBSUFCQkFUWUNKQ0FBSUFNMkFoZ2dBQ0FCTmdJUUlBTkJBVWNOQWlBQUtBSXdRUUZHRFFFTUFnc2dBU0FDUmdSQUlBQW9BaGdpQWtFQ1JnUkFJQUFnQXpZQ0dDQURJUUlMSUFBb0FqQkJBVWNOQWlBQ1FRRkdEUUVNQWdzZ0FDQUFLQUlrUVFGcU5nSWtDeUFBUVFFNkFEWUxDMTBCQVg4Z0FDZ0NFQ0lEUlFSQUlBQkJBVFlDSkNBQUlBSTJBaGdnQUNBQk5nSVFEd3NDUUNBQklBTkdCRUFnQUNnQ0dFRUNSdzBCSUFBZ0FqWUNHQThMSUFCQkFUb0FOaUFBUVFJMkFoZ2dBQ0FBS0FJa1FRRnFOZ0lrQ3dzQ0FBdTlKd0VNZnlNQVFSQnJJZ29rQUFKQUFrQUNRQUpBQWtBQ1FBSkFBa0FDUUFKQUFrQUNRQUpBQWtBZ0FFSDBBVTBFUUVIc0dTZ0NBQ0lHUVJBZ0FFRUxha0Y0Y1NBQVFRdEpHeUlGUVFOMklnQjJJZ0ZCQTNFRVFBSkFJQUZCZjNOQkFYRWdBR29pQWtFRGRDSUJRWlFhYWlJQUlBRkJuQnBxS0FJQUlnRW9BZ2dpQkVZRVFFSHNHU0FHUVg0Z0FuZHhOZ0lBREFFTElBUWdBRFlDRENBQUlBUTJBZ2dMSUFGQkNHb2hBQ0FCSUFKQkEzUWlBa0VEY2pZQ0JDQUJJQUpxSWdFZ0FTZ0NCRUVCY2pZQ0JBd1BDeUFGUWZRWktBSUFJZ2RORFFFZ0FRUkFBa0JCQWlBQWRDSUNRUUFnQW10eUlBRWdBSFJ4YUNJQlFRTjBJZ0JCbEJwcUlnSWdBRUdjR21vb0FnQWlBQ2dDQ0NJRVJnUkFRZXdaSUFaQmZpQUJkM0VpQmpZQ0FBd0JDeUFFSUFJMkFnd2dBaUFFTmdJSUN5QUFJQVZCQTNJMkFnUWdBQ0FGYWlJSUlBRkJBM1FpQVNBRmF5SUVRUUZ5TmdJRUlBQWdBV29nQkRZQ0FDQUhCRUFnQjBGNGNVR1VHbW9oQVVHQUdpZ0NBQ0VDQW44Z0JrRUJJQWRCQTNaMElnTnhSUVJBUWV3WklBTWdCbkkyQWdBZ0FRd0JDeUFCS0FJSUN5RURJQUVnQWpZQ0NDQURJQUkyQWd3Z0FpQUJOZ0lNSUFJZ0F6WUNDQXNnQUVFSWFpRUFRWUFhSUFnMkFnQkI5QmtnQkRZQ0FBd1BDMEh3R1NnQ0FDSUxSUTBCSUF0b1FRSjBRWndjYWlnQ0FDSUNLQUlFUVhoeElBVnJJUU1nQWlFQkEwQUNRQ0FCS0FJUUlnQkZCRUFnQVNnQ0ZDSUFSUTBCQ3lBQUtBSUVRWGh4SUFWcklnRWdBeUFCSUFOSklnRWJJUU1nQUNBQ0lBRWJJUUlnQUNFQkRBRUxDeUFDS0FJWUlRa2dBaUFDS0FJTUlnUkhCRUJCL0Jrb0FnQWFJQUlvQWdnaUFDQUVOZ0lNSUFRZ0FEWUNDQXdPQ3lBQ1FSUnFJZ0VvQWdBaUFFVUVRQ0FDS0FJUUlnQkZEUU1nQWtFUWFpRUJDd05BSUFFaENDQUFJZ1JCRkdvaUFTZ0NBQ0lBRFFBZ0JFRVFhaUVCSUFRb0FoQWlBQTBBQ3lBSVFRQTJBZ0FNRFF0QmZ5RUZJQUJCdjM5TERRQWdBRUVMYWlJQVFYaHhJUVZCOEJrb0FnQWlDRVVOQUVFQUlBVnJJUU1DUUFKQUFrQUNmMEVBSUFWQmdBSkpEUUFhUVI4Z0JVSC8vLzhIU3cwQUdpQUZRU1lnQUVFSWRtY2lBR3QyUVFGeElBQkJBWFJyUVQ1cUN5SUhRUUowUVp3Y2FpZ0NBQ0lCUlFSQVFRQWhBQXdCQzBFQUlRQWdCVUVaSUFkQkFYWnJRUUFnQjBFZlJ4dDBJUUlEUUFKQUlBRW9BZ1JCZUhFZ0JXc2lCaUFEVHcwQUlBRWhCQ0FHSWdNTkFFRUFJUU1nQVNFQURBTUxJQUFnQVNnQ0ZDSUdJQVlnQVNBQ1FSMTJRUVJ4YWlnQ0VDSUJSaHNnQUNBR0d5RUFJQUpCQVhRaEFpQUJEUUFMQ3lBQUlBUnlSUVJBUVFBaEJFRUNJQWQwSWdCQkFDQUFhM0lnQ0hFaUFFVU5BeUFBYUVFQ2RFR2NIR29vQWdBaEFBc2dBRVVOQVFzRFFDQUFLQUlFUVhoeElBVnJJZ0lnQTBraEFTQUNJQU1nQVJzaEF5QUFJQVFnQVJzaEJDQUFLQUlRSWdFRWZ5QUJCU0FBS0FJVUN5SUFEUUFMQ3lBRVJRMEFJQU5COUJrb0FnQWdCV3RQRFFBZ0JDZ0NHQ0VISUFRZ0JDZ0NEQ0lDUndSQVFmd1pLQUlBR2lBRUtBSUlJZ0FnQWpZQ0RDQUNJQUEyQWdnTURBc2dCRUVVYWlJQktBSUFJZ0JGQkVBZ0JDZ0NFQ0lBUlEwRElBUkJFR29oQVFzRFFDQUJJUVlnQUNJQ1FSUnFJZ0VvQWdBaUFBMEFJQUpCRUdvaEFTQUNLQUlRSWdBTkFBc2dCa0VBTmdJQURBc0xJQVZCOUJrb0FnQWlCRTBFUUVHQUdpZ0NBQ0VBQWtBZ0JDQUZheUlCUVJCUEJFQWdBQ0FGYWlJQ0lBRkJBWEkyQWdRZ0FDQUVhaUFCTmdJQUlBQWdCVUVEY2pZQ0JBd0JDeUFBSUFSQkEzSTJBZ1FnQUNBRWFpSUJJQUVvQWdSQkFYSTJBZ1JCQUNFQ1FRQWhBUXRCOUJrZ0FUWUNBRUdBR2lBQ05nSUFJQUJCQ0dvaEFBd05DeUFGUWZnWktBSUFJZ0pKQkVCQitCa2dBaUFGYXlJQk5nSUFRWVFhUVlRYUtBSUFJZ0FnQldvaUFqWUNBQ0FDSUFGQkFYSTJBZ1FnQUNBRlFRTnlOZ0lFSUFCQkNHb2hBQXdOQzBFQUlRQWdCVUV2YWlJREFuOUJ4QjBvQWdBRVFFSE1IU2dDQUF3QkMwSFFIVUovTndJQVFjZ2RRb0NnZ0lDQWdBUTNBZ0JCeEIwZ0NrRU1ha0Z3Y1VIWXF0V3FCWE0yQWdCQjJCMUJBRFlDQUVHb0hVRUFOZ0lBUVlBZ0N5SUJhaUlHUVFBZ0FXc2lDSEVpQVNBRlRRME1RYVFkS0FJQUlnUUVRRUdjSFNnQ0FDSUhJQUZxSWdrZ0IwMGdCQ0FKU1hJTkRRc0NRRUdvSFMwQUFFRUVjVVVFUUFKQUFrQUNRQUpBUVlRYUtBSUFJZ1FFUUVHc0hTRUFBMEFnQkNBQUtBSUFJZ2RQQkVBZ0J5QUFLQUlFYWlBRVN3MERDeUFBS0FJSUlnQU5BQXNMUVFBUUN5SUNRWDlHRFFNZ0FTRUdRY2dkS0FJQUlnQkJBV3NpQkNBQ2NRUkFJQUVnQW1zZ0FpQUVha0VBSUFCcmNXb2hCZ3NnQlNBR1R3MERRYVFkS0FJQUlnQUVRRUdjSFNnQ0FDSUVJQVpxSWdnZ0JFMGdBQ0FJU1hJTkJBc2dCaEFMSWdBZ0FrY05BUXdGQ3lBR0lBSnJJQWh4SWdZUUN5SUNJQUFvQWdBZ0FDZ0NCR3BHRFFFZ0FpRUFDeUFBUVg5R0RRRWdCVUV3YWlBR1RRUkFJQUFoQWd3RUMwSE1IU2dDQUNJQ0lBTWdCbXRxUVFBZ0FtdHhJZ0lRQzBGL1JnMEJJQUlnQm1vaEJpQUFJUUlNQXdzZ0FrRi9SdzBDQzBHb0hVR29IU2dDQUVFRWNqWUNBQXNnQVJBTElnSkJmMFpCQUJBTElnQkJmMFp5SUFBZ0FrMXlEUVVnQUNBQ2F5SUdJQVZCS0dwTkRRVUxRWndkUVp3ZEtBSUFJQVpxSWdBMkFnQkJvQjBvQWdBZ0FFa0VRRUdnSFNBQU5nSUFDd0pBUVlRYUtBSUFJZ01FUUVHc0hTRUFBMEFnQWlBQUtBSUFJZ0VnQUNnQ0JDSUVha1lOQWlBQUtBSUlJZ0FOQUFzTUJBdEIvQmtvQWdBaUFFRUFJQUFnQWswYlJRUkFRZndaSUFJMkFnQUxRUUFoQUVHd0hTQUdOZ0lBUWF3ZElBSTJBZ0JCakJwQmZ6WUNBRUdRR2tIRUhTZ0NBRFlDQUVHNEhVRUFOZ0lBQTBBZ0FFRURkQ0lCUVp3YWFpQUJRWlFhYWlJRU5nSUFJQUZCb0JwcUlBUTJBZ0FnQUVFQmFpSUFRU0JIRFFBTFFmZ1pJQVpCS0dzaUFFRjRJQUpyUVFkeElnRnJJZ1EyQWdCQmhCb2dBU0FDYWlJQk5nSUFJQUVnQkVFQmNqWUNCQ0FBSUFKcVFTZzJBZ1JCaUJwQjFCMG9BZ0EyQWdBTUJBc2dBaUFEVFNBQklBTkxjZzBDSUFBb0FneEJDSEVOQWlBQUlBUWdCbW8yQWdSQmhCb2dBMEY0SUFOclFRZHhJZ0JxSWdFMkFnQkIrQmxCK0Jrb0FnQWdCbW9pQWlBQWF5SUFOZ0lBSUFFZ0FFRUJjallDQkNBQ0lBTnFRU2cyQWdSQmlCcEIxQjBvQWdBMkFnQU1Bd3RCQUNFRURBb0xRUUFoQWd3SUMwSDhHU2dDQUNBQ1N3UkFRZndaSUFJMkFnQUxJQUlnQm1vaEFVR3NIU0VBQWtBQ1FBSkFBMEFnQVNBQUtBSUFSd1JBSUFBb0FnZ2lBQTBCREFJTEN5QUFMUUFNUVFoeFJRMEJDMEdzSFNFQUEwQWdBeUFBS0FJQUlnRlBCRUFnQVNBQUtBSUVhaUlFSUFOTERRTUxJQUFvQWdnaEFBd0FDd0FMSUFBZ0FqWUNBQ0FBSUFBb0FnUWdCbW8yQWdRZ0FrRjRJQUpyUVFkeGFpSUhJQVZCQTNJMkFnUWdBVUY0SUFGclFRZHhhaUlHSUFVZ0Iyb2lCV3NoQUNBRElBWkdCRUJCaEJvZ0JUWUNBRUg0R1VINEdTZ0NBQ0FBYWlJQU5nSUFJQVVnQUVFQmNqWUNCQXdJQzBHQUdpZ0NBQ0FHUmdSQVFZQWFJQVUyQWdCQjlCbEI5QmtvQWdBZ0FHb2lBRFlDQUNBRklBQkJBWEkyQWdRZ0FDQUZhaUFBTmdJQURBZ0xJQVlvQWdRaUEwRURjVUVCUncwR0lBTkJlSEVoQ1NBRFFmOEJUUVJBSUFZb0Fnd2lBU0FHS0FJSUlnSkdCRUJCN0JsQjdCa29BZ0JCZmlBRFFRTjJkM0UyQWdBTUJ3c2dBaUFCTmdJTUlBRWdBallDQ0F3R0N5QUdLQUlZSVFnZ0JpQUdLQUlNSWdKSEJFQWdCaWdDQ0NJQklBSTJBZ3dnQWlBQk5nSUlEQVVMSUFaQkZHb2lBU2dDQUNJRFJRUkFJQVlvQWhBaUEwVU5CQ0FHUVJCcUlRRUxBMEFnQVNFRUlBTWlBa0VVYWlJQktBSUFJZ01OQUNBQ1FSQnFJUUVnQWlnQ0VDSUREUUFMSUFSQkFEWUNBQXdFQzBINEdTQUdRU2hySWdCQmVDQUNhMEVIY1NJQmF5SUlOZ0lBUVlRYUlBRWdBbW9pQVRZQ0FDQUJJQWhCQVhJMkFnUWdBQ0FDYWtFb05nSUVRWWdhUWRRZEtBSUFOZ0lBSUFNZ0JFRW5JQVJyUVFkeGFrRXZheUlBSUFBZ0EwRVFha2tiSWdGQkd6WUNCQ0FCUWJRZEtRSUFOd0lRSUFGQnJCMHBBZ0EzQWdoQnRCMGdBVUVJYWpZQ0FFR3dIU0FHTmdJQVFhd2RJQUkyQWdCQnVCMUJBRFlDQUNBQlFSaHFJUUFEUUNBQVFRYzJBZ1FnQUVFSWFpRU1JQUJCQkdvaEFDQU1JQVJKRFFBTElBRWdBMFlOQUNBQklBRW9BZ1JCZm5FMkFnUWdBeUFCSUFOcklnSkJBWEkyQWdRZ0FTQUNOZ0lBSUFKQi93Rk5CRUFnQWtGNGNVR1VHbW9oQUFKL1Fld1pLQUlBSWdGQkFTQUNRUU4yZENJQ2NVVUVRRUhzR1NBQklBSnlOZ0lBSUFBTUFRc2dBQ2dDQ0FzaEFTQUFJQU0yQWdnZ0FTQUROZ0lNSUFNZ0FEWUNEQ0FESUFFMkFnZ01BUXRCSHlFQUlBSkIvLy8vQjAwRVFDQUNRU1lnQWtFSWRtY2lBR3QyUVFGeElBQkJBWFJyUVQ1cUlRQUxJQU1nQURZQ0hDQURRZ0EzQWhBZ0FFRUNkRUdjSEdvaEFRSkFBa0JCOEJrb0FnQWlCRUVCSUFCMElnWnhSUVJBUWZBWklBUWdCbkkyQWdBZ0FTQUROZ0lBREFFTElBSkJHU0FBUVFGMmEwRUFJQUJCSDBjYmRDRUFJQUVvQWdBaEJBTkFJQVFpQVNnQ0JFRjRjU0FDUmcwQ0lBQkJIWFloQkNBQVFRRjBJUUFnQVNBRVFRUnhhaUlHS0FJUUlnUU5BQXNnQmlBRE5nSVFDeUFESUFFMkFoZ2dBeUFETmdJTUlBTWdBellDQ0F3QkN5QUJLQUlJSWdBZ0F6WUNEQ0FCSUFNMkFnZ2dBMEVBTmdJWUlBTWdBVFlDRENBRElBQTJBZ2dMUWZnWktBSUFJZ0FnQlUwTkFFSDRHU0FBSUFWcklnRTJBZ0JCaEJwQmhCb29BZ0FpQUNBRmFpSUNOZ0lBSUFJZ0FVRUJjallDQkNBQUlBVkJBM0kyQWdRZ0FFRUlhaUVBREFnTFFlZ1pRVEEyQWdCQkFDRUFEQWNMUVFBaEFnc2dDRVVOQUFKQUlBWW9BaHdpQVVFQ2RFR2NIR29pQkNnQ0FDQUdSZ1JBSUFRZ0FqWUNBQ0FDRFFGQjhCbEI4QmtvQWdCQmZpQUJkM0UyQWdBTUFnc2dDRUVRUVJRZ0NDZ0NFQ0FHUmh0cUlBSTJBZ0FnQWtVTkFRc2dBaUFJTmdJWUlBWW9BaEFpQVFSQUlBSWdBVFlDRUNBQklBSTJBaGdMSUFZb0FoUWlBVVVOQUNBQ0lBRTJBaFFnQVNBQ05nSVlDeUFBSUFscUlRQWdCaUFKYWlJR0tBSUVJUU1MSUFZZ0EwRitjVFlDQkNBRklBQkJBWEkyQWdRZ0FDQUZhaUFBTmdJQUlBQkIvd0ZOQkVBZ0FFRjRjVUdVR21vaEFRSi9RZXdaS0FJQUlnSkJBU0FBUVFOMmRDSUFjVVVFUUVIc0dTQUFJQUp5TmdJQUlBRU1BUXNnQVNnQ0NBc2hBQ0FCSUFVMkFnZ2dBQ0FGTmdJTUlBVWdBVFlDRENBRklBQTJBZ2dNQVF0Qkh5RURJQUJCLy8vL0IwMEVRQ0FBUVNZZ0FFRUlkbWNpQVd0MlFRRnhJQUZCQVhSclFUNXFJUU1MSUFVZ0F6WUNIQ0FGUWdBM0FoQWdBMEVDZEVHY0hHb2hBUUpBQWtCQjhCa29BZ0FpQWtFQklBTjBJZ1J4UlFSQVFmQVpJQUlnQkhJMkFnQWdBU0FGTmdJQURBRUxJQUJCR1NBRFFRRjJhMEVBSUFOQkgwY2JkQ0VESUFFb0FnQWhBZ05BSUFJaUFTZ0NCRUY0Y1NBQVJnMENJQU5CSFhZaEFpQURRUUYwSVFNZ0FTQUNRUVJ4YWlJRUtBSVFJZ0lOQUFzZ0JDQUZOZ0lRQ3lBRklBRTJBaGdnQlNBRk5nSU1JQVVnQlRZQ0NBd0JDeUFCS0FJSUlnQWdCVFlDRENBQklBVTJBZ2dnQlVFQU5nSVlJQVVnQVRZQ0RDQUZJQUEyQWdnTElBZEJDR29oQUF3Q0N3SkFJQWRGRFFBQ1FDQUVLQUljSWdCQkFuUkJuQnhxSWdFb0FnQWdCRVlFUUNBQklBSTJBZ0FnQWcwQlFmQVpJQWhCZmlBQWQzRWlDRFlDQUF3Q0N5QUhRUkJCRkNBSEtBSVFJQVJHRzJvZ0FqWUNBQ0FDUlEwQkN5QUNJQWMyQWhnZ0JDZ0NFQ0lBQkVBZ0FpQUFOZ0lRSUFBZ0FqWUNHQXNnQkNnQ0ZDSUFSUTBBSUFJZ0FEWUNGQ0FBSUFJMkFoZ0xBa0FnQTBFUFRRUkFJQVFnQXlBRmFpSUFRUU55TmdJRUlBQWdCR29pQUNBQUtBSUVRUUZ5TmdJRURBRUxJQVFnQlVFRGNqWUNCQ0FFSUFWcUlnSWdBMEVCY2pZQ0JDQUNJQU5xSUFNMkFnQWdBMEgvQVUwRVFDQURRWGh4UVpRYWFpRUFBbjlCN0Jrb0FnQWlBVUVCSUFOQkEzWjBJZ054UlFSQVFld1pJQUVnQTNJMkFnQWdBQXdCQ3lBQUtBSUlDeUVCSUFBZ0FqWUNDQ0FCSUFJMkFnd2dBaUFBTmdJTUlBSWdBVFlDQ0F3QkMwRWZJUUFnQTBILy8vOEhUUVJBSUFOQkppQURRUWgyWnlJQWEzWkJBWEVnQUVFQmRHdEJQbW9oQUFzZ0FpQUFOZ0ljSUFKQ0FEY0NFQ0FBUVFKMFFad2NhaUVCQWtBQ1FDQUlRUUVnQUhRaUJuRkZCRUJCOEJrZ0JpQUljallDQUNBQklBSTJBZ0FNQVFzZ0EwRVpJQUJCQVhaclFRQWdBRUVmUnh0MElRQWdBU2dDQUNFRkEwQWdCU0lCS0FJRVFYaHhJQU5HRFFJZ0FFRWRkaUVHSUFCQkFYUWhBQ0FCSUFaQkJIRnFJZ1lvQWhBaUJRMEFDeUFHSUFJMkFoQUxJQUlnQVRZQ0dDQUNJQUkyQWd3Z0FpQUNOZ0lJREFFTElBRW9BZ2dpQUNBQ05nSU1JQUVnQWpZQ0NDQUNRUUEyQWhnZ0FpQUJOZ0lNSUFJZ0FEWUNDQXNnQkVFSWFpRUFEQUVMQWtBZ0NVVU5BQUpBSUFJb0Fod2lBRUVDZEVHY0hHb2lBU2dDQUNBQ1JnUkFJQUVnQkRZQ0FDQUVEUUZCOEJrZ0MwRitJQUIzY1RZQ0FBd0NDeUFKUVJCQkZDQUpLQUlRSUFKR0cyb2dCRFlDQUNBRVJRMEJDeUFFSUFrMkFoZ2dBaWdDRUNJQUJFQWdCQ0FBTmdJUUlBQWdCRFlDR0FzZ0FpZ0NGQ0lBUlEwQUlBUWdBRFlDRkNBQUlBUTJBaGdMQWtBZ0EwRVBUUVJBSUFJZ0F5QUZhaUlBUVFOeU5nSUVJQUFnQW1vaUFDQUFLQUlFUVFGeU5nSUVEQUVMSUFJZ0JVRURjallDQkNBQ0lBVnFJZ1FnQTBFQmNqWUNCQ0FESUFScUlBTTJBZ0FnQndSQUlBZEJlSEZCbEJwcUlRQkJnQm9vQWdBaEFRSi9RUUVnQjBFRGRuUWlCU0FHY1VVRVFFSHNHU0FGSUFaeU5nSUFJQUFNQVFzZ0FDZ0NDQXNoQmlBQUlBRTJBZ2dnQmlBQk5nSU1JQUVnQURZQ0RDQUJJQVkyQWdnTFFZQWFJQVEyQWdCQjlCa2dBellDQUFzZ0FrRUlhaUVBQ3lBS1FSQnFKQUFnQUFzakFRRi9RZHdaS0FJQUlnQUVRQU5BSUFBb0FnQVJCUUFnQUNnQ0JDSUFEUUFMQ3dzYUFDQUFJQUVvQWdnZ0JSQUtCRUFnQVNBQ0lBTWdCQkFUQ3dzM0FDQUFJQUVvQWdnZ0JSQUtCRUFnQVNBQ0lBTWdCQkFURHdzZ0FDZ0NDQ0lBSUFFZ0FpQURJQVFnQlNBQUtBSUFLQUlVRVFNQUM1RUJBQ0FBSUFFb0FnZ2dCQkFLQkVBZ0FTQUNJQU1RRWc4TEFrQWdBQ0FCS0FJQUlBUVFDa1VOQUFKQUlBSWdBU2dDRUVjRVFDQUJLQUlVSUFKSERRRUxJQU5CQVVjTkFTQUJRUUUyQWlBUEN5QUJJQUkyQWhRZ0FTQUROZ0lnSUFFZ0FTZ0NLRUVCYWpZQ0tBSkFJQUVvQWlSQkFVY05BQ0FCS0FJWVFRSkhEUUFnQVVFQk9nQTJDeUFCUVFRMkFpd0xDL0lCQUNBQUlBRW9BZ2dnQkJBS0JFQWdBU0FDSUFNUUVnOExBa0FnQUNBQktBSUFJQVFRQ2dSQUFrQWdBaUFCS0FJUVJ3UkFJQUVvQWhRZ0FrY05BUXNnQTBFQlJ3MENJQUZCQVRZQ0lBOExJQUVnQXpZQ0lBSkFJQUVvQWl4QkJFWU5BQ0FCUVFBN0FUUWdBQ2dDQ0NJQUlBRWdBaUFDUVFFZ0JDQUFLQUlBS0FJVUVRTUFJQUV0QURVRVFDQUJRUU0yQWl3Z0FTMEFORVVOQVF3REN5QUJRUVEyQWl3TElBRWdBallDRkNBQklBRW9BaWhCQVdvMkFpZ2dBU2dDSkVFQlJ3MEJJQUVvQWhoQkFrY05BU0FCUVFFNkFEWVBDeUFBS0FJSUlnQWdBU0FDSUFNZ0JDQUFLQUlBS0FJWUVRSUFDd3N4QUNBQUlBRW9BZ2hCQUJBS0JFQWdBU0FDSUFNUUZBOExJQUFvQWdnaUFDQUJJQUlnQXlBQUtBSUFLQUljRVFBQUN4Z0FJQUFnQVNnQ0NFRUFFQW9FUUNBQklBSWdBeEFVQ3d2S0F3RUZmeU1BUVVCcUlnUWtBQUovUVFFZ0FDQUJRUUFRQ2cwQUdrRUFJQUZGRFFBYUl3QkJRR29pQXlRQUlBRW9BZ0FpQlVFRWF5Z0NBQ0VHSUFWQkNHc29BZ0FoQlNBRFFnQTNBaUFnQTBJQU53SW9JQU5DQURjQ01DQURRZ0EzQURjZ0EwSUFOd0lZSUFOQkFEWUNGQ0FEUWZ3Vk5nSVFJQU1nQVRZQ0RDQURRYXdXTmdJSUlBRWdCV29oQVVFQUlRVUNRQ0FHUWF3V1FRQVFDZ1JBSUFOQkFUWUNPQ0FHSUFOQkNHb2dBU0FCUVFGQkFDQUdLQUlBS0FJVUVRTUFJQUZCQUNBREtBSWdRUUZHR3lFRkRBRUxJQVlnQTBFSWFpQUJRUUZCQUNBR0tBSUFLQUlZRVFJQUFrQUNRQ0FES0FJc0RnSUFBUUlMSUFNb0FoeEJBQ0FES0FJb1FRRkdHMEVBSUFNb0FpUkJBVVliUVFBZ0F5Z0NNRUVCUmhzaEJRd0JDeUFES0FJZ1FRRkhCRUFnQXlnQ01BMEJJQU1vQWlSQkFVY05BU0FES0FJb1FRRkhEUUVMSUFNb0FoZ2hCUXNnQTBGQWF5UUFRUUFnQlNJQlJRMEFHaUFFUVF4cVFUUVFEeG9nQkVFQk5nSTRJQVJCZnpZQ0ZDQUVJQUEyQWhBZ0JDQUJOZ0lJSUFFZ0JFRUlhaUFDS0FJQVFRRWdBU2dDQUNnQ0hCRUFBQ0FFS0FJZ0lnQkJBVVlFUUNBQ0lBUW9BaGcyQWdBTElBQkJBVVlMSVFjZ0JFRkFheVFBSUFjTENnQWdBQ0FCUVFBUUNnc0VBQ0FBQy9vRUFnWi9DbjFCLy8vLy93Y2hERUdBZ0lDQWVDRU5RWDhoQ2dOQUlBTWdDMFlFUUVFQUlRa2dDRUdBZ0JBUUR5RUFRd0QvZjBjZ0RTQU1hN0tWSVJBRFFDQURJQWxHQkVCQkFDRUpJQWRCQURZQ0FDQUFRUVJySVFCQkFDRU1RUUVoQ3dOQUlBdEJnSUFFUmtVRVFDQUhJQXRCQW5RaUFXb2dBQ0FCYWlnQ0FDQU1haUlNTmdJQUlBdEJBV29oQ3d3QkN3c0RRQ0FESUFsR1JRUkFJQWNnQlNBSlFRSjBhaWdDQUVFQ2RHb2lBQ0FBS0FJQUlnQkJBV28yQWdBZ0JpQUFRUUowYWlBSk5nSUFJQWxCQVdvaENRd0JDd3NGQW44Z0VDQUZJQWxCQW5ScUlnRW9BZ0FnREd1emxDSVBRd0FBZ0U5ZElBOURBQUFBQUdCeEJFQWdENmtNQVF0QkFBc2hDeUFCSUFzMkFnQWdBQ0FMUVFKMGFpSUJJQUVvQWdCQkFXbzJBZ0FnQ1VFQmFpRUpEQUVMQ3dVZ0JDQUxRUXhzYWlJSktnSUFJUk1nQ1NvQ0NDRVVJQWtxQWdRaEZTQUtJQUlnQzBFQ2RDSU9haWdDQUNJSlJ3UkFJQUVnQ1VIUUFHeHFJZ29xQWp3Z0FDb0NPQ0lQbENBS0tnSTRJQUFxQWlnaUVKUWdDaW9DTUNBQUtnSUlJaEdVSUFBcUFoZ2lFaUFLS2dJMGxKS1NraUVXSUFvcUFpd2dENVFnQ2lvQ0tDQVFsQ0FLS2dJZ0lCR1VJQklnQ2lvQ0pKU1NrcEloRnlBS0tnSWNJQStVSUFvcUFoZ2dFSlFnQ2lvQ0VDQVJsQ0FTSUFvcUFoU1VrcEtTSVJnZ0Npb0NEQ0FQbENBS0tnSUlJQkNVSUFvcUFnQWdFWlFnQ2lvQ0JDQVNsSktTa2lFUElBa2hDZ3NnQlNBT2FnSi9JQllnRnlBVWxDQVBJQk9VSUJVZ0dKU1NrcEpEQUFDQVJaUWlFSXREQUFBQVQxMEVRQ0FRcUF3QkMwR0FnSUNBZUFzaUNUWUNBQ0FNSUFrZ0NTQU1TaHNoRENBTklBa2dDU0FOU0JzaERTQUxRUUZxSVFzTUFRc0xDd3ZuRVFJQVFZQUlDOVlSZFc1emFXZHVaV1FnYzJodmNuUUFkVzV6YVdkdVpXUWdhVzUwQUdac2IyRjBBSFZwYm5RMk5GOTBBSFZ1YzJsbmJtVmtJR05vWVhJQVltOXZiQUJsYlhOamNtbHdkR1Z1T2pwMllXd0FkVzV6YVdkdVpXUWdiRzl1WndCemRHUTZPbmR6ZEhKcGJtY0FjM1JrT2pwemRISnBibWNBYzNSa09qcDFNVFp6ZEhKcGJtY0FjM1JrT2pwMU16SnpkSEpwYm1jQVpHOTFZbXhsQUhadmFXUUFaVzF6WTNKcGNIUmxiam82YldWdGIzSjVYM1pwWlhjOGMyaHZjblErQUdWdGMyTnlhWEIwWlc0Nk9tMWxiVzl5ZVY5MmFXVjNQSFZ1YzJsbmJtVmtJSE5vYjNKMFBnQmxiWE5qY21sd2RHVnVPanB0WlcxdmNubGZkbWxsZHp4cGJuUStBR1Z0YzJOeWFYQjBaVzQ2T20xbGJXOXllVjkyYVdWM1BIVnVjMmxuYm1Wa0lHbHVkRDRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhabXh2WVhRK0FHVnRjMk55YVhCMFpXNDZPbTFsYlc5eWVWOTJhV1YzUEhWcGJuUTRYM1ErQUdWdGMyTnlhWEIwWlc0Nk9tMWxiVzl5ZVY5MmFXVjNQR2x1ZERoZmRENEFaVzF6WTNKcGNIUmxiam82YldWdGIzSjVYM1pwWlhjOGRXbHVkREUyWDNRK0FHVnRjMk55YVhCMFpXNDZPbTFsYlc5eWVWOTJhV1YzUEdsdWRERTJYM1ErQUdWdGMyTnlhWEIwWlc0Nk9tMWxiVzl5ZVY5MmFXVjNQSFZwYm5RMk5GOTBQZ0JsYlhOamNtbHdkR1Z1T2pwdFpXMXZjbmxmZG1sbGR6eHBiblEyTkY5MFBnQmxiWE5qY21sd2RHVnVPanB0WlcxdmNubGZkbWxsZHp4MWFXNTBNekpmZEQ0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4YVc1ME16SmZkRDRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhZMmhoY2o0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4ZFc1emFXZHVaV1FnWTJoaGNqNEFjM1JrT2pwaVlYTnBZMTl6ZEhKcGJtYzhkVzV6YVdkdVpXUWdZMmhoY2o0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4YzJsbmJtVmtJR05vWVhJK0FHVnRjMk55YVhCMFpXNDZPbTFsYlc5eWVWOTJhV1YzUEd4dmJtYytBR1Z0YzJOeWFYQjBaVzQ2T20xbGJXOXllVjkyYVdWM1BIVnVjMmxuYm1Wa0lHeHZibWMrQUdWdGMyTnlhWEIwWlc0Nk9tMWxiVzl5ZVY5MmFXVjNQR1J2ZFdKc1pUNEFUbE4wTTE5Zk1qRXlZbUZ6YVdOZmMzUnlhVzVuU1dOT1UxOHhNV05vWVhKZmRISmhhWFJ6U1dORlJVNVRYemxoYkd4dlkyRjBiM0pKWTBWRlJVVUFBQUFBUkF3QUFFSUhBQUJPVTNRelgxOHlNVEppWVhOcFkxOXpkSEpwYm1kSmFFNVRYekV4WTJoaGNsOTBjbUZwZEhOSmFFVkZUbE5mT1dGc2JHOWpZWFJ2Y2tsb1JVVkZSUUFBUkF3QUFJd0hBQUJPVTNRelgxOHlNVEppWVhOcFkxOXpkSEpwYm1kSmQwNVRYekV4WTJoaGNsOTBjbUZwZEhOSmQwVkZUbE5mT1dGc2JHOWpZWFJ2Y2tsM1JVVkZSUUFBUkF3QUFOUUhBQUJPVTNRelgxOHlNVEppWVhOcFkxOXpkSEpwYm1kSlJITk9VMTh4TVdOb1lYSmZkSEpoYVhSelNVUnpSVVZPVTE4NVlXeHNiMk5oZEc5eVNVUnpSVVZGUlFBQUFFUU1BQUFjQ0FBQVRsTjBNMTlmTWpFeVltRnphV05mYzNSeWFXNW5TVVJwVGxOZk1URmphR0Z5WDNSeVlXbDBjMGxFYVVWRlRsTmZPV0ZzYkc5allYUnZja2xFYVVWRlJVVUFBQUJFREFBQWFBZ0FBRTR4TUdWdGMyTnlhWEIwWlc0emRtRnNSUUFBUkF3QUFMUUlBQUJPTVRCbGJYTmpjbWx3ZEdWdU1URnRaVzF2Y25sZmRtbGxkMGxqUlVVQUFFUU1BQURRQ0FBQVRqRXdaVzF6WTNKcGNIUmxiakV4YldWdGIzSjVYM1pwWlhkSllVVkZBQUJFREFBQStBZ0FBRTR4TUdWdGMyTnlhWEIwWlc0eE1XMWxiVzl5ZVY5MmFXVjNTV2hGUlFBQVJBd0FBQ0FKQUFCT01UQmxiWE5qY21sd2RHVnVNVEZ0WlcxdmNubGZkbWxsZDBselJVVUFBRVFNQUFCSUNRQUFUakV3WlcxelkzSnBjSFJsYmpFeGJXVnRiM0o1WDNacFpYZEpkRVZGQUFCRURBQUFjQWtBQUU0eE1HVnRjMk55YVhCMFpXNHhNVzFsYlc5eWVWOTJhV1YzU1dsRlJRQUFSQXdBQUpnSkFBQk9NVEJsYlhOamNtbHdkR1Z1TVRGdFpXMXZjbmxmZG1sbGQwbHFSVVVBQUVRTUFBREFDUUFBVGpFd1pXMXpZM0pwY0hSbGJqRXhiV1Z0YjNKNVgzWnBaWGRKYkVWRkFBQkVEQUFBNkFrQUFFNHhNR1Z0YzJOeWFYQjBaVzR4TVcxbGJXOXllVjkyYVdWM1NXMUZSUUFBUkF3QUFCQUtBQUJPTVRCbGJYTmpjbWx3ZEdWdU1URnRaVzF2Y25sZmRtbGxkMGw0UlVVQUFFUU1BQUE0Q2dBQVRqRXdaVzF6WTNKcGNIUmxiakV4YldWdGIzSjVYM1pwWlhkSmVVVkZBQUJFREFBQVlBb0FBRTR4TUdWdGMyTnlhWEIwWlc0eE1XMWxiVzl5ZVY5MmFXVjNTV1pGUlFBQVJBd0FBSWdLQUFCT01UQmxiWE5qY21sd2RHVnVNVEZ0WlcxdmNubGZkbWxsZDBsa1JVVUFBRVFNQUFDd0NnQUFUakV3WDE5amVIaGhZbWwyTVRFMlgxOXphR2x0WDNSNWNHVmZhVzVtYjBVQUFBQUFiQXdBQU5nS0FBRFFEQUFBVGpFd1gxOWplSGhoWW1sMk1URTNYMTlqYkdGemMxOTBlWEJsWDJsdVptOUZBQUFBYkF3QUFBZ0xBQUQ4Q2dBQUFBQUFBSHdMQUFBQ0FBQUFBd0FBQUFRQUFBQUZBQUFBQmdBQUFFNHhNRjlmWTNoNFlXSnBkakV5TTE5ZlpuVnVaR0Z0Wlc1MFlXeGZkSGx3WlY5cGJtWnZSUUJzREFBQVZBc0FBUHdLQUFCMkFBQUFRQXNBQUlnTEFBQmlBQUFBUUFzQUFKUUxBQUJqQUFBQVFBc0FBS0FMQUFCb0FBQUFRQXNBQUt3TEFBQmhBQUFBUUFzQUFMZ0xBQUJ6QUFBQVFBc0FBTVFMQUFCMEFBQUFRQXNBQU5BTEFBQnBBQUFBUUFzQUFOd0xBQUJxQUFBQVFBc0FBT2dMQUFCc0FBQUFRQXNBQVBRTEFBQnRBQUFBUUFzQUFBQU1BQUI0QUFBQVFBc0FBQXdNQUFCNUFBQUFRQXNBQUJnTUFBQm1BQUFBUUFzQUFDUU1BQUJrQUFBQVFBc0FBREFNQUFBQUFBQUFMQXNBQUFJQUFBQUhBQUFBQkFBQUFBVUFBQUFJQUFBQUNRQUFBQW9BQUFBTEFBQUFBQUFBQUxRTUFBQUNBQUFBREFBQUFBUUFBQUFGQUFBQUNBQUFBQTBBQUFBT0FBQUFEd0FBQUU0eE1GOWZZM2g0WVdKcGRqRXlNRjlmYzJsZlkyeGhjM05mZEhsd1pWOXBibVp2UlFBQUFBQnNEQUFBakF3QUFDd0xBQUJUZERsMGVYQmxYMmx1Wm04QUFBQUFSQXdBQU1BTUFFSFlHUXNENEE0QiI7aWYoIWlzRGF0YVVSSSh3YXNtQmluYXJ5RmlsZSkpe3dhc21CaW5hcnlGaWxlPWxvY2F0ZUZpbGUod2FzbUJpbmFyeUZpbGUpO31mdW5jdGlvbiBnZXRCaW5hcnlTeW5jKGZpbGUpe2lmKGZpbGU9PXdhc21CaW5hcnlGaWxlJiZ3YXNtQmluYXJ5KXtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkod2FzbUJpbmFyeSl9dmFyIGJpbmFyeT10cnlQYXJzZUFzRGF0YVVSSShmaWxlKTtpZihiaW5hcnkpe3JldHVybiBiaW5hcnl9aWYocmVhZEJpbmFyeSl7cmV0dXJuIHJlYWRCaW5hcnkoZmlsZSl9dGhyb3cgImJvdGggYXN5bmMgYW5kIHN5bmMgZmV0Y2hpbmcgb2YgdGhlIHdhc20gZmFpbGVkIn1mdW5jdGlvbiBnZXRCaW5hcnlQcm9taXNlKGJpbmFyeUZpbGUpe3JldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpPT5nZXRCaW5hcnlTeW5jKGJpbmFyeUZpbGUpKX1mdW5jdGlvbiBpbnN0YW50aWF0ZUFycmF5QnVmZmVyKGJpbmFyeUZpbGUsaW1wb3J0cyxyZWNlaXZlcil7cmV0dXJuIGdldEJpbmFyeVByb21pc2UoYmluYXJ5RmlsZSkudGhlbihiaW5hcnk9PldlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGJpbmFyeSxpbXBvcnRzKSkudGhlbihpbnN0YW5jZT0+aW5zdGFuY2UpLnRoZW4ocmVjZWl2ZXIscmVhc29uPT57ZXJyKGBmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiAke3JlYXNvbn1gKTthYm9ydChyZWFzb24pO30pfWZ1bmN0aW9uIGluc3RhbnRpYXRlQXN5bmMoYmluYXJ5LGJpbmFyeUZpbGUsaW1wb3J0cyxjYWxsYmFjayl7cmV0dXJuIGluc3RhbnRpYXRlQXJyYXlCdWZmZXIoYmluYXJ5RmlsZSxpbXBvcnRzLGNhbGxiYWNrKX1mdW5jdGlvbiBjcmVhdGVXYXNtKCl7dmFyIGluZm89eyJhIjp3YXNtSW1wb3J0c307ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbmNlKGluc3RhbmNlLG1vZHVsZSl7d2FzbUV4cG9ydHM9aW5zdGFuY2UuZXhwb3J0czt3YXNtTWVtb3J5PXdhc21FeHBvcnRzWyJrIl07dXBkYXRlTWVtb3J5Vmlld3MoKTthZGRPbkluaXQod2FzbUV4cG9ydHNbImwiXSk7cmVtb3ZlUnVuRGVwZW5kZW5jeSgpO3JldHVybiB3YXNtRXhwb3J0c31hZGRSdW5EZXBlbmRlbmN5KCk7ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbnRpYXRpb25SZXN1bHQocmVzdWx0KXtyZWNlaXZlSW5zdGFuY2UocmVzdWx0WyJpbnN0YW5jZSJdKTt9aWYoTW9kdWxlWyJpbnN0YW50aWF0ZVdhc20iXSl7dHJ5e3JldHVybiBNb2R1bGVbImluc3RhbnRpYXRlV2FzbSJdKGluZm8scmVjZWl2ZUluc3RhbmNlKX1jYXRjaChlKXtlcnIoYE1vZHVsZS5pbnN0YW50aWF0ZVdhc20gY2FsbGJhY2sgZmFpbGVkIHdpdGggZXJyb3I6ICR7ZX1gKTtyZWFkeVByb21pc2VSZWplY3QoZSk7fX1pbnN0YW50aWF0ZUFzeW5jKHdhc21CaW5hcnksd2FzbUJpbmFyeUZpbGUsaW5mbyxyZWNlaXZlSW5zdGFudGlhdGlvblJlc3VsdCkuY2F0Y2gocmVhZHlQcm9taXNlUmVqZWN0KTtyZXR1cm4ge319dmFyIGNhbGxSdW50aW1lQ2FsbGJhY2tzPWNhbGxiYWNrcz0+e3doaWxlKGNhbGxiYWNrcy5sZW5ndGg+MCl7Y2FsbGJhY2tzLnNoaWZ0KCkoTW9kdWxlKTt9fTtNb2R1bGVbIm5vRXhpdFJ1bnRpbWUiXXx8dHJ1ZTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfYmlnaW50PShwcmltaXRpdmVUeXBlLG5hbWUsc2l6ZSxtaW5SYW5nZSxtYXhSYW5nZSk9Pnt9O3ZhciBlbWJpbmRfaW5pdF9jaGFyQ29kZXM9KCk9Pnt2YXIgY29kZXM9bmV3IEFycmF5KDI1Nik7Zm9yKHZhciBpPTA7aTwyNTY7KytpKXtjb2Rlc1tpXT1TdHJpbmcuZnJvbUNoYXJDb2RlKGkpO31lbWJpbmRfY2hhckNvZGVzPWNvZGVzO307dmFyIGVtYmluZF9jaGFyQ29kZXM7dmFyIHJlYWRMYXRpbjFTdHJpbmc9cHRyPT57dmFyIHJldD0iIjt2YXIgYz1wdHI7d2hpbGUoSEVBUFU4W2NdKXtyZXQrPWVtYmluZF9jaGFyQ29kZXNbSEVBUFU4W2MrK11dO31yZXR1cm4gcmV0fTt2YXIgYXdhaXRpbmdEZXBlbmRlbmNpZXM9e307dmFyIHJlZ2lzdGVyZWRUeXBlcz17fTt2YXIgQmluZGluZ0Vycm9yO3ZhciB0aHJvd0JpbmRpbmdFcnJvcj1tZXNzYWdlPT57dGhyb3cgbmV3IEJpbmRpbmdFcnJvcihtZXNzYWdlKX07ZnVuY3Rpb24gc2hhcmVkUmVnaXN0ZXJUeXBlKHJhd1R5cGUscmVnaXN0ZXJlZEluc3RhbmNlLG9wdGlvbnM9e30pe3ZhciBuYW1lPXJlZ2lzdGVyZWRJbnN0YW5jZS5uYW1lO2lmKCFyYXdUeXBlKXt0aHJvd0JpbmRpbmdFcnJvcihgdHlwZSAiJHtuYW1lfSIgbXVzdCBoYXZlIGEgcG9zaXRpdmUgaW50ZWdlciB0eXBlaWQgcG9pbnRlcmApO31pZihyZWdpc3RlcmVkVHlwZXMuaGFzT3duUHJvcGVydHkocmF3VHlwZSkpe2lmKG9wdGlvbnMuaWdub3JlRHVwbGljYXRlUmVnaXN0cmF0aW9ucyl7cmV0dXJufWVsc2Uge3Rocm93QmluZGluZ0Vycm9yKGBDYW5ub3QgcmVnaXN0ZXIgdHlwZSAnJHtuYW1lfScgdHdpY2VgKTt9fXJlZ2lzdGVyZWRUeXBlc1tyYXdUeXBlXT1yZWdpc3RlcmVkSW5zdGFuY2U7aWYoYXdhaXRpbmdEZXBlbmRlbmNpZXMuaGFzT3duUHJvcGVydHkocmF3VHlwZSkpe3ZhciBjYWxsYmFja3M9YXdhaXRpbmdEZXBlbmRlbmNpZXNbcmF3VHlwZV07ZGVsZXRlIGF3YWl0aW5nRGVwZW5kZW5jaWVzW3Jhd1R5cGVdO2NhbGxiYWNrcy5mb3JFYWNoKGNiPT5jYigpKTt9fWZ1bmN0aW9uIHJlZ2lzdGVyVHlwZShyYXdUeXBlLHJlZ2lzdGVyZWRJbnN0YW5jZSxvcHRpb25zPXt9KXtpZighKCJhcmdQYWNrQWR2YW5jZSJpbiByZWdpc3RlcmVkSW5zdGFuY2UpKXt0aHJvdyBuZXcgVHlwZUVycm9yKCJyZWdpc3RlclR5cGUgcmVnaXN0ZXJlZEluc3RhbmNlIHJlcXVpcmVzIGFyZ1BhY2tBZHZhbmNlIil9cmV0dXJuIHNoYXJlZFJlZ2lzdGVyVHlwZShyYXdUeXBlLHJlZ2lzdGVyZWRJbnN0YW5jZSxvcHRpb25zKX12YXIgR2VuZXJpY1dpcmVUeXBlU2l6ZT04O3ZhciBfX2VtYmluZF9yZWdpc3Rlcl9ib29sPShyYXdUeXBlLG5hbWUsdHJ1ZVZhbHVlLGZhbHNlVmFsdWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSI6ZnVuY3Rpb24od3Qpe3JldHVybiAhIXd0fSwidG9XaXJlVHlwZSI6ZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsbyl7cmV0dXJuIG8/dHJ1ZVZhbHVlOmZhbHNlVmFsdWV9LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOmZ1bmN0aW9uKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQVThbcG9pbnRlcl0pfSxkZXN0cnVjdG9yRnVuY3Rpb246bnVsbH0pO307ZnVuY3Rpb24gaGFuZGxlQWxsb2NhdG9ySW5pdCgpe09iamVjdC5hc3NpZ24oSGFuZGxlQWxsb2NhdG9yLnByb3RvdHlwZSx7Z2V0KGlkKXtyZXR1cm4gdGhpcy5hbGxvY2F0ZWRbaWRdfSxoYXMoaWQpe3JldHVybiB0aGlzLmFsbG9jYXRlZFtpZF0hPT11bmRlZmluZWR9LGFsbG9jYXRlKGhhbmRsZSl7dmFyIGlkPXRoaXMuZnJlZWxpc3QucG9wKCl8fHRoaXMuYWxsb2NhdGVkLmxlbmd0aDt0aGlzLmFsbG9jYXRlZFtpZF09aGFuZGxlO3JldHVybiBpZH0sZnJlZShpZCl7dGhpcy5hbGxvY2F0ZWRbaWRdPXVuZGVmaW5lZDt0aGlzLmZyZWVsaXN0LnB1c2goaWQpO319KTt9ZnVuY3Rpb24gSGFuZGxlQWxsb2NhdG9yKCl7dGhpcy5hbGxvY2F0ZWQ9W3VuZGVmaW5lZF07dGhpcy5mcmVlbGlzdD1bXTt9dmFyIGVtdmFsX2hhbmRsZXM9bmV3IEhhbmRsZUFsbG9jYXRvcjt2YXIgX19lbXZhbF9kZWNyZWY9aGFuZGxlPT57aWYoaGFuZGxlPj1lbXZhbF9oYW5kbGVzLnJlc2VydmVkJiYwPT09LS1lbXZhbF9oYW5kbGVzLmdldChoYW5kbGUpLnJlZmNvdW50KXtlbXZhbF9oYW5kbGVzLmZyZWUoaGFuZGxlKTt9fTt2YXIgY291bnRfZW12YWxfaGFuZGxlcz0oKT0+e3ZhciBjb3VudD0wO2Zvcih2YXIgaT1lbXZhbF9oYW5kbGVzLnJlc2VydmVkO2k8ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQubGVuZ3RoOysraSl7aWYoZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWRbaV0hPT11bmRlZmluZWQpeysrY291bnQ7fX1yZXR1cm4gY291bnR9O3ZhciBpbml0X2VtdmFsPSgpPT57ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQucHVzaCh7dmFsdWU6dW5kZWZpbmVkfSx7dmFsdWU6bnVsbH0se3ZhbHVlOnRydWV9LHt2YWx1ZTpmYWxzZX0pO2VtdmFsX2hhbmRsZXMucmVzZXJ2ZWQ9ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQubGVuZ3RoO01vZHVsZVsiY291bnRfZW12YWxfaGFuZGxlcyJdPWNvdW50X2VtdmFsX2hhbmRsZXM7fTt2YXIgRW12YWw9e3RvVmFsdWU6aGFuZGxlPT57aWYoIWhhbmRsZSl7dGhyb3dCaW5kaW5nRXJyb3IoIkNhbm5vdCB1c2UgZGVsZXRlZCB2YWwuIGhhbmRsZSA9ICIraGFuZGxlKTt9cmV0dXJuIGVtdmFsX2hhbmRsZXMuZ2V0KGhhbmRsZSkudmFsdWV9LHRvSGFuZGxlOnZhbHVlPT57c3dpdGNoKHZhbHVlKXtjYXNlIHVuZGVmaW5lZDpyZXR1cm4gMTtjYXNlIG51bGw6cmV0dXJuIDI7Y2FzZSB0cnVlOnJldHVybiAzO2Nhc2UgZmFsc2U6cmV0dXJuIDQ7ZGVmYXVsdDp7cmV0dXJuIGVtdmFsX2hhbmRsZXMuYWxsb2NhdGUoe3JlZmNvdW50OjEsdmFsdWU6dmFsdWV9KX19fX07ZnVuY3Rpb24gc2ltcGxlUmVhZFZhbHVlRnJvbVBvaW50ZXIocG9pbnRlcil7cmV0dXJuIHRoaXNbImZyb21XaXJlVHlwZSJdKEhFQVAzMltwb2ludGVyPj4yXSl9dmFyIF9fZW1iaW5kX3JlZ2lzdGVyX2VtdmFsPShyYXdUeXBlLG5hbWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSI6aGFuZGxlPT57dmFyIHJ2PUVtdmFsLnRvVmFsdWUoaGFuZGxlKTtfX2VtdmFsX2RlY3JlZihoYW5kbGUpO3JldHVybiBydn0sInRvV2lyZVR5cGUiOihkZXN0cnVjdG9ycyx2YWx1ZSk9PkVtdmFsLnRvSGFuZGxlKHZhbHVlKSwiYXJnUGFja0FkdmFuY2UiOkdlbmVyaWNXaXJlVHlwZVNpemUsInJlYWRWYWx1ZUZyb21Qb2ludGVyIjpzaW1wbGVSZWFkVmFsdWVGcm9tUG9pbnRlcixkZXN0cnVjdG9yRnVuY3Rpb246bnVsbH0pO307dmFyIGZsb2F0UmVhZFZhbHVlRnJvbVBvaW50ZXI9KG5hbWUsd2lkdGgpPT57c3dpdGNoKHdpZHRoKXtjYXNlIDQ6cmV0dXJuIGZ1bmN0aW9uKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQRjMyW3BvaW50ZXI+PjJdKX07Y2FzZSA4OnJldHVybiBmdW5jdGlvbihwb2ludGVyKXtyZXR1cm4gdGhpc1siZnJvbVdpcmVUeXBlIl0oSEVBUEY2NFtwb2ludGVyPj4zXSl9O2RlZmF1bHQ6dGhyb3cgbmV3IFR5cGVFcnJvcihgaW52YWxpZCBmbG9hdCB3aWR0aCAoJHt3aWR0aH0pOiAke25hbWV9YCl9fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfZmxvYXQ9KHJhd1R5cGUsbmFtZSxzaXplKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTtyZWdpc3RlclR5cGUocmF3VHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOnZhbHVlPT52YWx1ZSwidG9XaXJlVHlwZSI6KGRlc3RydWN0b3JzLHZhbHVlKT0+dmFsdWUsImFyZ1BhY2tBZHZhbmNlIjpHZW5lcmljV2lyZVR5cGVTaXplLCJyZWFkVmFsdWVGcm9tUG9pbnRlciI6ZmxvYXRSZWFkVmFsdWVGcm9tUG9pbnRlcihuYW1lLHNpemUpLGRlc3RydWN0b3JGdW5jdGlvbjpudWxsfSk7fTt2YXIgaW50ZWdlclJlYWRWYWx1ZUZyb21Qb2ludGVyPShuYW1lLHdpZHRoLHNpZ25lZCk9Pntzd2l0Y2god2lkdGgpe2Nhc2UgMTpyZXR1cm4gc2lnbmVkP3BvaW50ZXI9PkhFQVA4W3BvaW50ZXI+PjBdOnBvaW50ZXI9PkhFQVBVOFtwb2ludGVyPj4wXTtjYXNlIDI6cmV0dXJuIHNpZ25lZD9wb2ludGVyPT5IRUFQMTZbcG9pbnRlcj4+MV06cG9pbnRlcj0+SEVBUFUxNltwb2ludGVyPj4xXTtjYXNlIDQ6cmV0dXJuIHNpZ25lZD9wb2ludGVyPT5IRUFQMzJbcG9pbnRlcj4+Ml06cG9pbnRlcj0+SEVBUFUzMltwb2ludGVyPj4yXTtkZWZhdWx0OnRocm93IG5ldyBUeXBlRXJyb3IoYGludmFsaWQgaW50ZWdlciB3aWR0aCAoJHt3aWR0aH0pOiAke25hbWV9YCl9fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfaW50ZWdlcj0ocHJpbWl0aXZlVHlwZSxuYW1lLHNpemUsbWluUmFuZ2UsbWF4UmFuZ2UpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3ZhciBmcm9tV2lyZVR5cGU9dmFsdWU9PnZhbHVlO2lmKG1pblJhbmdlPT09MCl7dmFyIGJpdHNoaWZ0PTMyLTgqc2l6ZTtmcm9tV2lyZVR5cGU9dmFsdWU9PnZhbHVlPDxiaXRzaGlmdD4+PmJpdHNoaWZ0O312YXIgaXNVbnNpZ25lZFR5cGU9bmFtZS5pbmNsdWRlcygidW5zaWduZWQiKTt2YXIgY2hlY2tBc3NlcnRpb25zPSh2YWx1ZSx0b1R5cGVOYW1lKT0+e307dmFyIHRvV2lyZVR5cGU7aWYoaXNVbnNpZ25lZFR5cGUpe3RvV2lyZVR5cGU9ZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsdmFsdWUpe2NoZWNrQXNzZXJ0aW9ucyh2YWx1ZSx0aGlzLm5hbWUpO3JldHVybiB2YWx1ZT4+PjB9O31lbHNlIHt0b1dpcmVUeXBlPWZ1bmN0aW9uKGRlc3RydWN0b3JzLHZhbHVlKXtjaGVja0Fzc2VydGlvbnModmFsdWUsdGhpcy5uYW1lKTtyZXR1cm4gdmFsdWV9O31yZWdpc3RlclR5cGUocHJpbWl0aXZlVHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOmZyb21XaXJlVHlwZSwidG9XaXJlVHlwZSI6dG9XaXJlVHlwZSwiYXJnUGFja0FkdmFuY2UiOkdlbmVyaWNXaXJlVHlwZVNpemUsInJlYWRWYWx1ZUZyb21Qb2ludGVyIjppbnRlZ2VyUmVhZFZhbHVlRnJvbVBvaW50ZXIobmFtZSxzaXplLG1pblJhbmdlIT09MCksZGVzdHJ1Y3RvckZ1bmN0aW9uOm51bGx9KTt9O3ZhciBfX2VtYmluZF9yZWdpc3Rlcl9tZW1vcnlfdmlldz0ocmF3VHlwZSxkYXRhVHlwZUluZGV4LG5hbWUpPT57dmFyIHR5cGVNYXBwaW5nPVtJbnQ4QXJyYXksVWludDhBcnJheSxJbnQxNkFycmF5LFVpbnQxNkFycmF5LEludDMyQXJyYXksVWludDMyQXJyYXksRmxvYXQzMkFycmF5LEZsb2F0NjRBcnJheV07dmFyIFRBPXR5cGVNYXBwaW5nW2RhdGFUeXBlSW5kZXhdO2Z1bmN0aW9uIGRlY29kZU1lbW9yeVZpZXcoaGFuZGxlKXt2YXIgc2l6ZT1IRUFQVTMyW2hhbmRsZT4+Ml07dmFyIGRhdGE9SEVBUFUzMltoYW5kbGUrND4+Ml07cmV0dXJuIG5ldyBUQShIRUFQOC5idWZmZXIsZGF0YSxzaXplKX1uYW1lPXJlYWRMYXRpbjFTdHJpbmcobmFtZSk7cmVnaXN0ZXJUeXBlKHJhd1R5cGUse25hbWU6bmFtZSwiZnJvbVdpcmVUeXBlIjpkZWNvZGVNZW1vcnlWaWV3LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOmRlY29kZU1lbW9yeVZpZXd9LHtpZ25vcmVEdXBsaWNhdGVSZWdpc3RyYXRpb25zOnRydWV9KTt9O2Z1bmN0aW9uIHJlYWRQb2ludGVyKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQVTMyW3BvaW50ZXI+PjJdKX12YXIgc3RyaW5nVG9VVEY4QXJyYXk9KHN0cixoZWFwLG91dElkeCxtYXhCeXRlc1RvV3JpdGUpPT57aWYoIShtYXhCeXRlc1RvV3JpdGU+MCkpcmV0dXJuIDA7dmFyIHN0YXJ0SWR4PW91dElkeDt2YXIgZW5kSWR4PW91dElkeCttYXhCeXRlc1RvV3JpdGUtMTtmb3IodmFyIGk9MDtpPHN0ci5sZW5ndGg7KytpKXt2YXIgdT1zdHIuY2hhckNvZGVBdChpKTtpZih1Pj01NTI5NiYmdTw9NTczNDMpe3ZhciB1MT1zdHIuY2hhckNvZGVBdCgrK2kpO3U9NjU1MzYrKCh1JjEwMjMpPDwxMCl8dTEmMTAyMzt9aWYodTw9MTI3KXtpZihvdXRJZHg+PWVuZElkeClicmVhaztoZWFwW291dElkeCsrXT11O31lbHNlIGlmKHU8PTIwNDcpe2lmKG91dElkeCsxPj1lbmRJZHgpYnJlYWs7aGVhcFtvdXRJZHgrK109MTkyfHU+PjY7aGVhcFtvdXRJZHgrK109MTI4fHUmNjM7fWVsc2UgaWYodTw9NjU1MzUpe2lmKG91dElkeCsyPj1lbmRJZHgpYnJlYWs7aGVhcFtvdXRJZHgrK109MjI0fHU+PjEyO2hlYXBbb3V0SWR4KytdPTEyOHx1Pj42JjYzO2hlYXBbb3V0SWR4KytdPTEyOHx1JjYzO31lbHNlIHtpZihvdXRJZHgrMz49ZW5kSWR4KWJyZWFrO2hlYXBbb3V0SWR4KytdPTI0MHx1Pj4xODtoZWFwW291dElkeCsrXT0xMjh8dT4+MTImNjM7aGVhcFtvdXRJZHgrK109MTI4fHU+PjYmNjM7aGVhcFtvdXRJZHgrK109MTI4fHUmNjM7fX1oZWFwW291dElkeF09MDtyZXR1cm4gb3V0SWR4LXN0YXJ0SWR4fTt2YXIgc3RyaW5nVG9VVEY4PShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PnN0cmluZ1RvVVRGOEFycmF5KHN0cixIRUFQVTgsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk7dmFyIGxlbmd0aEJ5dGVzVVRGOD1zdHI9Pnt2YXIgbGVuPTA7Zm9yKHZhciBpPTA7aTxzdHIubGVuZ3RoOysraSl7dmFyIGM9c3RyLmNoYXJDb2RlQXQoaSk7aWYoYzw9MTI3KXtsZW4rKzt9ZWxzZSBpZihjPD0yMDQ3KXtsZW4rPTI7fWVsc2UgaWYoYz49NTUyOTYmJmM8PTU3MzQzKXtsZW4rPTQ7KytpO31lbHNlIHtsZW4rPTM7fX1yZXR1cm4gbGVufTt2YXIgVVRGOERlY29kZXI9dHlwZW9mIFRleHREZWNvZGVyIT0idW5kZWZpbmVkIj9uZXcgVGV4dERlY29kZXIoInV0ZjgiKTp1bmRlZmluZWQ7dmFyIFVURjhBcnJheVRvU3RyaW5nPShoZWFwT3JBcnJheSxpZHgsbWF4Qnl0ZXNUb1JlYWQpPT57dmFyIGVuZElkeD1pZHgrbWF4Qnl0ZXNUb1JlYWQ7dmFyIGVuZFB0cj1pZHg7d2hpbGUoaGVhcE9yQXJyYXlbZW5kUHRyXSYmIShlbmRQdHI+PWVuZElkeCkpKytlbmRQdHI7aWYoZW5kUHRyLWlkeD4xNiYmaGVhcE9yQXJyYXkuYnVmZmVyJiZVVEY4RGVjb2Rlcil7cmV0dXJuIFVURjhEZWNvZGVyLmRlY29kZShoZWFwT3JBcnJheS5zdWJhcnJheShpZHgsZW5kUHRyKSl9dmFyIHN0cj0iIjt3aGlsZShpZHg8ZW5kUHRyKXt2YXIgdTA9aGVhcE9yQXJyYXlbaWR4KytdO2lmKCEodTAmMTI4KSl7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHUwKTtjb250aW51ZX12YXIgdTE9aGVhcE9yQXJyYXlbaWR4KytdJjYzO2lmKCh1MCYyMjQpPT0xOTIpe3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZSgodTAmMzEpPDw2fHUxKTtjb250aW51ZX12YXIgdTI9aGVhcE9yQXJyYXlbaWR4KytdJjYzO2lmKCh1MCYyNDApPT0yMjQpe3UwPSh1MCYxNSk8PDEyfHUxPDw2fHUyO31lbHNlIHt1MD0odTAmNyk8PDE4fHUxPDwxMnx1Mjw8NnxoZWFwT3JBcnJheVtpZHgrK10mNjM7fWlmKHUwPDY1NTM2KXtzdHIrPVN0cmluZy5mcm9tQ2hhckNvZGUodTApO31lbHNlIHt2YXIgY2g9dTAtNjU1MzY7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGNoPj4xMCw1NjMyMHxjaCYxMDIzKTt9fXJldHVybiBzdHJ9O3ZhciBVVEY4VG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9PnB0cj9VVEY4QXJyYXlUb1N0cmluZyhIRUFQVTgscHRyLG1heEJ5dGVzVG9SZWFkKToiIjt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZz0ocmF3VHlwZSxuYW1lKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTt2YXIgc3RkU3RyaW5nSXNVVEY4PW5hbWU9PT0ic3RkOjpzdHJpbmciO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSIodmFsdWUpe3ZhciBsZW5ndGg9SEVBUFUzMlt2YWx1ZT4+Ml07dmFyIHBheWxvYWQ9dmFsdWUrNDt2YXIgc3RyO2lmKHN0ZFN0cmluZ0lzVVRGOCl7dmFyIGRlY29kZVN0YXJ0UHRyPXBheWxvYWQ7Zm9yKHZhciBpPTA7aTw9bGVuZ3RoOysraSl7dmFyIGN1cnJlbnRCeXRlUHRyPXBheWxvYWQraTtpZihpPT1sZW5ndGh8fEhFQVBVOFtjdXJyZW50Qnl0ZVB0cl09PTApe3ZhciBtYXhSZWFkPWN1cnJlbnRCeXRlUHRyLWRlY29kZVN0YXJ0UHRyO3ZhciBzdHJpbmdTZWdtZW50PVVURjhUb1N0cmluZyhkZWNvZGVTdGFydFB0cixtYXhSZWFkKTtpZihzdHI9PT11bmRlZmluZWQpe3N0cj1zdHJpbmdTZWdtZW50O31lbHNlIHtzdHIrPVN0cmluZy5mcm9tQ2hhckNvZGUoMCk7c3RyKz1zdHJpbmdTZWdtZW50O31kZWNvZGVTdGFydFB0cj1jdXJyZW50Qnl0ZVB0cisxO319fWVsc2Uge3ZhciBhPW5ldyBBcnJheShsZW5ndGgpO2Zvcih2YXIgaT0wO2k8bGVuZ3RoOysraSl7YVtpXT1TdHJpbmcuZnJvbUNoYXJDb2RlKEhFQVBVOFtwYXlsb2FkK2ldKTt9c3RyPWEuam9pbigiIik7fV9mcmVlKHZhbHVlKTtyZXR1cm4gc3RyfSwidG9XaXJlVHlwZSIoZGVzdHJ1Y3RvcnMsdmFsdWUpe2lmKHZhbHVlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpe3ZhbHVlPW5ldyBVaW50OEFycmF5KHZhbHVlKTt9dmFyIGxlbmd0aDt2YXIgdmFsdWVJc09mVHlwZVN0cmluZz10eXBlb2YgdmFsdWU9PSJzdHJpbmciO2lmKCEodmFsdWVJc09mVHlwZVN0cmluZ3x8dmFsdWUgaW5zdGFuY2VvZiBVaW50OEFycmF5fHx2YWx1ZSBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5fHx2YWx1ZSBpbnN0YW5jZW9mIEludDhBcnJheSkpe3Rocm93QmluZGluZ0Vycm9yKCJDYW5ub3QgcGFzcyBub24tc3RyaW5nIHRvIHN0ZDo6c3RyaW5nIik7fWlmKHN0ZFN0cmluZ0lzVVRGOCYmdmFsdWVJc09mVHlwZVN0cmluZyl7bGVuZ3RoPWxlbmd0aEJ5dGVzVVRGOCh2YWx1ZSk7fWVsc2Uge2xlbmd0aD12YWx1ZS5sZW5ndGg7fXZhciBiYXNlPV9tYWxsb2MoNCtsZW5ndGgrMSk7dmFyIHB0cj1iYXNlKzQ7SEVBUFUzMltiYXNlPj4yXT1sZW5ndGg7aWYoc3RkU3RyaW5nSXNVVEY4JiZ2YWx1ZUlzT2ZUeXBlU3RyaW5nKXtzdHJpbmdUb1VURjgodmFsdWUscHRyLGxlbmd0aCsxKTt9ZWxzZSB7aWYodmFsdWVJc09mVHlwZVN0cmluZyl7Zm9yKHZhciBpPTA7aTxsZW5ndGg7KytpKXt2YXIgY2hhckNvZGU9dmFsdWUuY2hhckNvZGVBdChpKTtpZihjaGFyQ29kZT4yNTUpe19mcmVlKHB0cik7dGhyb3dCaW5kaW5nRXJyb3IoIlN0cmluZyBoYXMgVVRGLTE2IGNvZGUgdW5pdHMgdGhhdCBkbyBub3QgZml0IGluIDggYml0cyIpO31IRUFQVThbcHRyK2ldPWNoYXJDb2RlO319ZWxzZSB7Zm9yKHZhciBpPTA7aTxsZW5ndGg7KytpKXtIRUFQVThbcHRyK2ldPXZhbHVlW2ldO319fWlmKGRlc3RydWN0b3JzIT09bnVsbCl7ZGVzdHJ1Y3RvcnMucHVzaChfZnJlZSxiYXNlKTt9cmV0dXJuIGJhc2V9LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOnJlYWRQb2ludGVyLGRlc3RydWN0b3JGdW5jdGlvbihwdHIpe19mcmVlKHB0cik7fX0pO307dmFyIFVURjE2RGVjb2Rlcj10eXBlb2YgVGV4dERlY29kZXIhPSJ1bmRlZmluZWQiP25ldyBUZXh0RGVjb2RlcigidXRmLTE2bGUiKTp1bmRlZmluZWQ7dmFyIFVURjE2VG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9Pnt2YXIgZW5kUHRyPXB0cjt2YXIgaWR4PWVuZFB0cj4+MTt2YXIgbWF4SWR4PWlkeCttYXhCeXRlc1RvUmVhZC8yO3doaWxlKCEoaWR4Pj1tYXhJZHgpJiZIRUFQVTE2W2lkeF0pKytpZHg7ZW5kUHRyPWlkeDw8MTtpZihlbmRQdHItcHRyPjMyJiZVVEYxNkRlY29kZXIpcmV0dXJuIFVURjE2RGVjb2Rlci5kZWNvZGUoSEVBUFU4LnN1YmFycmF5KHB0cixlbmRQdHIpKTt2YXIgc3RyPSIiO2Zvcih2YXIgaT0wOyEoaT49bWF4Qnl0ZXNUb1JlYWQvMik7KytpKXt2YXIgY29kZVVuaXQ9SEVBUDE2W3B0citpKjI+PjFdO2lmKGNvZGVVbml0PT0wKWJyZWFrO3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZShjb2RlVW5pdCk7fXJldHVybiBzdHJ9O3ZhciBzdHJpbmdUb1VURjE2PShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PntpZihtYXhCeXRlc1RvV3JpdGU9PT11bmRlZmluZWQpe21heEJ5dGVzVG9Xcml0ZT0yMTQ3NDgzNjQ3O31pZihtYXhCeXRlc1RvV3JpdGU8MilyZXR1cm4gMDttYXhCeXRlc1RvV3JpdGUtPTI7dmFyIHN0YXJ0UHRyPW91dFB0cjt2YXIgbnVtQ2hhcnNUb1dyaXRlPW1heEJ5dGVzVG9Xcml0ZTxzdHIubGVuZ3RoKjI/bWF4Qnl0ZXNUb1dyaXRlLzI6c3RyLmxlbmd0aDtmb3IodmFyIGk9MDtpPG51bUNoYXJzVG9Xcml0ZTsrK2kpe3ZhciBjb2RlVW5pdD1zdHIuY2hhckNvZGVBdChpKTtIRUFQMTZbb3V0UHRyPj4xXT1jb2RlVW5pdDtvdXRQdHIrPTI7fUhFQVAxNltvdXRQdHI+PjFdPTA7cmV0dXJuIG91dFB0ci1zdGFydFB0cn07dmFyIGxlbmd0aEJ5dGVzVVRGMTY9c3RyPT5zdHIubGVuZ3RoKjI7dmFyIFVURjMyVG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9Pnt2YXIgaT0wO3ZhciBzdHI9IiI7d2hpbGUoIShpPj1tYXhCeXRlc1RvUmVhZC80KSl7dmFyIHV0ZjMyPUhFQVAzMltwdHIraSo0Pj4yXTtpZih1dGYzMj09MClicmVhazsrK2k7aWYodXRmMzI+PTY1NTM2KXt2YXIgY2g9dXRmMzItNjU1MzY7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGNoPj4xMCw1NjMyMHxjaCYxMDIzKTt9ZWxzZSB7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHV0ZjMyKTt9fXJldHVybiBzdHJ9O3ZhciBzdHJpbmdUb1VURjMyPShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PntpZihtYXhCeXRlc1RvV3JpdGU9PT11bmRlZmluZWQpe21heEJ5dGVzVG9Xcml0ZT0yMTQ3NDgzNjQ3O31pZihtYXhCeXRlc1RvV3JpdGU8NClyZXR1cm4gMDt2YXIgc3RhcnRQdHI9b3V0UHRyO3ZhciBlbmRQdHI9c3RhcnRQdHIrbWF4Qnl0ZXNUb1dyaXRlLTQ7Zm9yKHZhciBpPTA7aTxzdHIubGVuZ3RoOysraSl7dmFyIGNvZGVVbml0PXN0ci5jaGFyQ29kZUF0KGkpO2lmKGNvZGVVbml0Pj01NTI5NiYmY29kZVVuaXQ8PTU3MzQzKXt2YXIgdHJhaWxTdXJyb2dhdGU9c3RyLmNoYXJDb2RlQXQoKytpKTtjb2RlVW5pdD02NTUzNisoKGNvZGVVbml0JjEwMjMpPDwxMCl8dHJhaWxTdXJyb2dhdGUmMTAyMzt9SEVBUDMyW291dFB0cj4+Ml09Y29kZVVuaXQ7b3V0UHRyKz00O2lmKG91dFB0cis0PmVuZFB0cilicmVha31IRUFQMzJbb3V0UHRyPj4yXT0wO3JldHVybiBvdXRQdHItc3RhcnRQdHJ9O3ZhciBsZW5ndGhCeXRlc1VURjMyPXN0cj0+e3ZhciBsZW49MDtmb3IodmFyIGk9MDtpPHN0ci5sZW5ndGg7KytpKXt2YXIgY29kZVVuaXQ9c3RyLmNoYXJDb2RlQXQoaSk7aWYoY29kZVVuaXQ+PTU1Mjk2JiZjb2RlVW5pdDw9NTczNDMpKytpO2xlbis9NDt9cmV0dXJuIGxlbn07dmFyIF9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nPShyYXdUeXBlLGNoYXJTaXplLG5hbWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3ZhciBkZWNvZGVTdHJpbmcsZW5jb2RlU3RyaW5nLGdldEhlYXAsbGVuZ3RoQnl0ZXNVVEYsc2hpZnQ7aWYoY2hhclNpemU9PT0yKXtkZWNvZGVTdHJpbmc9VVRGMTZUb1N0cmluZztlbmNvZGVTdHJpbmc9c3RyaW5nVG9VVEYxNjtsZW5ndGhCeXRlc1VURj1sZW5ndGhCeXRlc1VURjE2O2dldEhlYXA9KCk9PkhFQVBVMTY7c2hpZnQ9MTt9ZWxzZSBpZihjaGFyU2l6ZT09PTQpe2RlY29kZVN0cmluZz1VVEYzMlRvU3RyaW5nO2VuY29kZVN0cmluZz1zdHJpbmdUb1VURjMyO2xlbmd0aEJ5dGVzVVRGPWxlbmd0aEJ5dGVzVVRGMzI7Z2V0SGVhcD0oKT0+SEVBUFUzMjtzaGlmdD0yO31yZWdpc3RlclR5cGUocmF3VHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOnZhbHVlPT57dmFyIGxlbmd0aD1IRUFQVTMyW3ZhbHVlPj4yXTt2YXIgSEVBUD1nZXRIZWFwKCk7dmFyIHN0cjt2YXIgZGVjb2RlU3RhcnRQdHI9dmFsdWUrNDtmb3IodmFyIGk9MDtpPD1sZW5ndGg7KytpKXt2YXIgY3VycmVudEJ5dGVQdHI9dmFsdWUrNCtpKmNoYXJTaXplO2lmKGk9PWxlbmd0aHx8SEVBUFtjdXJyZW50Qnl0ZVB0cj4+c2hpZnRdPT0wKXt2YXIgbWF4UmVhZEJ5dGVzPWN1cnJlbnRCeXRlUHRyLWRlY29kZVN0YXJ0UHRyO3ZhciBzdHJpbmdTZWdtZW50PWRlY29kZVN0cmluZyhkZWNvZGVTdGFydFB0cixtYXhSZWFkQnl0ZXMpO2lmKHN0cj09PXVuZGVmaW5lZCl7c3RyPXN0cmluZ1NlZ21lbnQ7fWVsc2Uge3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZSgwKTtzdHIrPXN0cmluZ1NlZ21lbnQ7fWRlY29kZVN0YXJ0UHRyPWN1cnJlbnRCeXRlUHRyK2NoYXJTaXplO319X2ZyZWUodmFsdWUpO3JldHVybiBzdHJ9LCJ0b1dpcmVUeXBlIjooZGVzdHJ1Y3RvcnMsdmFsdWUpPT57aWYoISh0eXBlb2YgdmFsdWU9PSJzdHJpbmciKSl7dGhyb3dCaW5kaW5nRXJyb3IoYENhbm5vdCBwYXNzIG5vbi1zdHJpbmcgdG8gQysrIHN0cmluZyB0eXBlICR7bmFtZX1gKTt9dmFyIGxlbmd0aD1sZW5ndGhCeXRlc1VURih2YWx1ZSk7dmFyIHB0cj1fbWFsbG9jKDQrbGVuZ3RoK2NoYXJTaXplKTtIRUFQVTMyW3B0cj4+Ml09bGVuZ3RoPj5zaGlmdDtlbmNvZGVTdHJpbmcodmFsdWUscHRyKzQsbGVuZ3RoK2NoYXJTaXplKTtpZihkZXN0cnVjdG9ycyE9PW51bGwpe2Rlc3RydWN0b3JzLnB1c2goX2ZyZWUscHRyKTt9cmV0dXJuIHB0cn0sImFyZ1BhY2tBZHZhbmNlIjpHZW5lcmljV2lyZVR5cGVTaXplLCJyZWFkVmFsdWVGcm9tUG9pbnRlciI6c2ltcGxlUmVhZFZhbHVlRnJvbVBvaW50ZXIsZGVzdHJ1Y3RvckZ1bmN0aW9uKHB0cil7X2ZyZWUocHRyKTt9fSk7fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfdm9pZD0ocmF3VHlwZSxuYW1lKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTtyZWdpc3RlclR5cGUocmF3VHlwZSx7aXNWb2lkOnRydWUsbmFtZTpuYW1lLCJhcmdQYWNrQWR2YW5jZSI6MCwiZnJvbVdpcmVUeXBlIjooKT0+dW5kZWZpbmVkLCJ0b1dpcmVUeXBlIjooZGVzdHJ1Y3RvcnMsbyk9PnVuZGVmaW5lZH0pO307dmFyIGdldEhlYXBNYXg9KCk9PjIxNDc0ODM2NDg7dmFyIGdyb3dNZW1vcnk9c2l6ZT0+e3ZhciBiPXdhc21NZW1vcnkuYnVmZmVyO3ZhciBwYWdlcz0oc2l6ZS1iLmJ5dGVMZW5ndGgrNjU1MzUpLzY1NTM2O3RyeXt3YXNtTWVtb3J5Lmdyb3cocGFnZXMpO3VwZGF0ZU1lbW9yeVZpZXdzKCk7cmV0dXJuIDF9Y2F0Y2goZSl7fX07dmFyIF9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwPXJlcXVlc3RlZFNpemU9Pnt2YXIgb2xkU2l6ZT1IRUFQVTgubGVuZ3RoO3JlcXVlc3RlZFNpemU+Pj49MDt2YXIgbWF4SGVhcFNpemU9Z2V0SGVhcE1heCgpO2lmKHJlcXVlc3RlZFNpemU+bWF4SGVhcFNpemUpe3JldHVybiBmYWxzZX12YXIgYWxpZ25VcD0oeCxtdWx0aXBsZSk9PngrKG11bHRpcGxlLXglbXVsdGlwbGUpJW11bHRpcGxlO2Zvcih2YXIgY3V0RG93bj0xO2N1dERvd248PTQ7Y3V0RG93bio9Mil7dmFyIG92ZXJHcm93bkhlYXBTaXplPW9sZFNpemUqKDErLjIvY3V0RG93bik7b3Zlckdyb3duSGVhcFNpemU9TWF0aC5taW4ob3Zlckdyb3duSGVhcFNpemUscmVxdWVzdGVkU2l6ZSsxMDA2NjMyOTYpO3ZhciBuZXdTaXplPU1hdGgubWluKG1heEhlYXBTaXplLGFsaWduVXAoTWF0aC5tYXgocmVxdWVzdGVkU2l6ZSxvdmVyR3Jvd25IZWFwU2l6ZSksNjU1MzYpKTt2YXIgcmVwbGFjZW1lbnQ9Z3Jvd01lbW9yeShuZXdTaXplKTtpZihyZXBsYWNlbWVudCl7cmV0dXJuIHRydWV9fXJldHVybiBmYWxzZX07ZW1iaW5kX2luaXRfY2hhckNvZGVzKCk7QmluZGluZ0Vycm9yPU1vZHVsZVsiQmluZGluZ0Vycm9yIl09Y2xhc3MgQmluZGluZ0Vycm9yIGV4dGVuZHMgRXJyb3J7Y29uc3RydWN0b3IobWVzc2FnZSl7c3VwZXIobWVzc2FnZSk7dGhpcy5uYW1lPSJCaW5kaW5nRXJyb3IiO319O01vZHVsZVsiSW50ZXJuYWxFcnJvciJdPWNsYXNzIEludGVybmFsRXJyb3IgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihtZXNzYWdlKXtzdXBlcihtZXNzYWdlKTt0aGlzLm5hbWU9IkludGVybmFsRXJyb3IiO319O2hhbmRsZUFsbG9jYXRvckluaXQoKTtpbml0X2VtdmFsKCk7dmFyIHdhc21JbXBvcnRzPXtmOl9fZW1iaW5kX3JlZ2lzdGVyX2JpZ2ludCxpOl9fZW1iaW5kX3JlZ2lzdGVyX2Jvb2wsaDpfX2VtYmluZF9yZWdpc3Rlcl9lbXZhbCxlOl9fZW1iaW5kX3JlZ2lzdGVyX2Zsb2F0LGI6X19lbWJpbmRfcmVnaXN0ZXJfaW50ZWdlcixhOl9fZW1iaW5kX3JlZ2lzdGVyX21lbW9yeV92aWV3LGQ6X19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZyxjOl9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nLGo6X19lbWJpbmRfcmVnaXN0ZXJfdm9pZCxnOl9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwfTt2YXIgd2FzbUV4cG9ydHM9Y3JlYXRlV2FzbSgpO01vZHVsZVsiX3NvcnQiXT0oYTAsYTEsYTIsYTMsYTQsYTUsYTYsYTcsYTgpPT4oTW9kdWxlWyJfc29ydCJdPXdhc21FeHBvcnRzWyJtIl0pKGEwLGExLGEyLGEzLGE0LGE1LGE2LGE3LGE4KTtNb2R1bGVbIl9fZW1iaW5kX2luaXRpYWxpemVfYmluZGluZ3MiXT0oKT0+KE1vZHVsZVsiX19lbWJpbmRfaW5pdGlhbGl6ZV9iaW5kaW5ncyJdPXdhc21FeHBvcnRzWyJuIl0pKCk7dmFyIF9tYWxsb2M9TW9kdWxlWyJfbWFsbG9jIl09YTA9PihfbWFsbG9jPU1vZHVsZVsiX21hbGxvYyJdPXdhc21FeHBvcnRzWyJwIl0pKGEwKTt2YXIgX2ZyZWU9TW9kdWxlWyJfZnJlZSJdPWEwPT4oX2ZyZWU9TW9kdWxlWyJfZnJlZSJdPXdhc21FeHBvcnRzWyJxIl0pKGEwKTtmdW5jdGlvbiBpbnRBcnJheUZyb21CYXNlNjQocyl7dmFyIGRlY29kZWQ9YXRvYihzKTt2YXIgYnl0ZXM9bmV3IFVpbnQ4QXJyYXkoZGVjb2RlZC5sZW5ndGgpO2Zvcih2YXIgaT0wO2k8ZGVjb2RlZC5sZW5ndGg7KytpKXtieXRlc1tpXT1kZWNvZGVkLmNoYXJDb2RlQXQoaSk7fXJldHVybiBieXRlc31mdW5jdGlvbiB0cnlQYXJzZUFzRGF0YVVSSShmaWxlbmFtZSl7aWYoIWlzRGF0YVVSSShmaWxlbmFtZSkpe3JldHVybn1yZXR1cm4gaW50QXJyYXlGcm9tQmFzZTY0KGZpbGVuYW1lLnNsaWNlKGRhdGFVUklQcmVmaXgubGVuZ3RoKSl9dmFyIGNhbGxlZFJ1bjtkZXBlbmRlbmNpZXNGdWxmaWxsZWQ9ZnVuY3Rpb24gcnVuQ2FsbGVyKCl7aWYoIWNhbGxlZFJ1bilydW4oKTtpZighY2FsbGVkUnVuKWRlcGVuZGVuY2llc0Z1bGZpbGxlZD1ydW5DYWxsZXI7fTtmdW5jdGlvbiBydW4oKXtpZihydW5EZXBlbmRlbmNpZXM+MCl7cmV0dXJufXByZVJ1bigpO2lmKHJ1bkRlcGVuZGVuY2llcz4wKXtyZXR1cm59ZnVuY3Rpb24gZG9SdW4oKXtpZihjYWxsZWRSdW4pcmV0dXJuO2NhbGxlZFJ1bj10cnVlO01vZHVsZVsiY2FsbGVkUnVuIl09dHJ1ZTtpZihBQk9SVClyZXR1cm47aW5pdFJ1bnRpbWUoKTtyZWFkeVByb21pc2VSZXNvbHZlKE1vZHVsZSk7aWYoTW9kdWxlWyJvblJ1bnRpbWVJbml0aWFsaXplZCJdKU1vZHVsZVsib25SdW50aW1lSW5pdGlhbGl6ZWQiXSgpO3Bvc3RSdW4oKTt9aWYoTW9kdWxlWyJzZXRTdGF0dXMiXSl7TW9kdWxlWyJzZXRTdGF0dXMiXSgiUnVubmluZy4uLiIpO3NldFRpbWVvdXQoZnVuY3Rpb24oKXtzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7TW9kdWxlWyJzZXRTdGF0dXMiXSgiIik7fSwxKTtkb1J1bigpO30sMSk7fWVsc2Uge2RvUnVuKCk7fX1pZihNb2R1bGVbInByZUluaXQiXSl7aWYodHlwZW9mIE1vZHVsZVsicHJlSW5pdCJdPT0iZnVuY3Rpb24iKU1vZHVsZVsicHJlSW5pdCJdPVtNb2R1bGVbInByZUluaXQiXV07d2hpbGUoTW9kdWxlWyJwcmVJbml0Il0ubGVuZ3RoPjApe01vZHVsZVsicHJlSW5pdCJdLnBvcCgpKCk7fX1ydW4oKTsKCgogICAgcmV0dXJuIG1vZHVsZUFyZy5yZWFkeQogIH0KCiAgKTsKICB9KSgpOwoKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueQogIGxldCB3YXNtTW9kdWxlOwogIGFzeW5jIGZ1bmN0aW9uIGluaXRXYXNtKCkgewogICAgICB3YXNtTW9kdWxlID0gYXdhaXQgbG9hZFdhc20oKTsKICB9CiAgbGV0IHNvcnREYXRhOwogIGxldCB2aWV3UHJvalB0cjsKICBsZXQgdHJhbnNmb3Jtc1B0cjsKICBsZXQgdHJhbnNmb3JtSW5kaWNlc1B0cjsKICBsZXQgcG9zaXRpb25zUHRyOwogIGxldCBkZXB0aEJ1ZmZlclB0cjsKICBsZXQgZGVwdGhJbmRleFB0cjsKICBsZXQgc3RhcnRzUHRyOwogIGxldCBjb3VudHNQdHI7CiAgbGV0IGFsbG9jYXRlZFZlcnRleENvdW50ID0gMDsKICBsZXQgYWxsb2NhdGVkVHJhbnNmb3JtQ291bnQgPSAwOwogIGxldCB2aWV3UHJvaiA9IG5ldyBGbG9hdDMyQXJyYXkoMTYpOwogIGxldCBsb2NrID0gZmFsc2U7CiAgbGV0IGFsbG9jYXRpb25QZW5kaW5nID0gZmFsc2U7CiAgbGV0IHNvcnRpbmcgPSBmYWxzZTsKICBjb25zdCBhbGxvY2F0ZUJ1ZmZlcnMgPSBhc3luYyAoKSA9PiB7CiAgICAgIGlmIChsb2NrKSB7CiAgICAgICAgICBhbGxvY2F0aW9uUGVuZGluZyA9IHRydWU7CiAgICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgbG9jayA9IHRydWU7CiAgICAgIGFsbG9jYXRpb25QZW5kaW5nID0gZmFsc2U7CiAgICAgIGlmICghd2FzbU1vZHVsZSkKICAgICAgICAgIGF3YWl0IGluaXRXYXNtKCk7CiAgICAgIGNvbnN0IHRhcmdldEFsbG9jYXRlZFZlcnRleENvdW50ID0gTWF0aC5wb3coMiwgTWF0aC5jZWlsKE1hdGgubG9nMihzb3J0RGF0YS52ZXJ0ZXhDb3VudCkpKTsKICAgICAgaWYgKGFsbG9jYXRlZFZlcnRleENvdW50IDwgdGFyZ2V0QWxsb2NhdGVkVmVydGV4Q291bnQpIHsKICAgICAgICAgIGlmIChhbGxvY2F0ZWRWZXJ0ZXhDb3VudCA+IDApIHsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHZpZXdQcm9qUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHRyYW5zZm9ybUluZGljZXNQdHIpOwogICAgICAgICAgICAgIHdhc21Nb2R1bGUuX2ZyZWUocG9zaXRpb25zUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKGRlcHRoQnVmZmVyUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKGRlcHRoSW5kZXhQdHIpOwogICAgICAgICAgICAgIHdhc21Nb2R1bGUuX2ZyZWUoc3RhcnRzUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKGNvdW50c1B0cik7CiAgICAgICAgICB9CiAgICAgICAgICBhbGxvY2F0ZWRWZXJ0ZXhDb3VudCA9IHRhcmdldEFsbG9jYXRlZFZlcnRleENvdW50OwogICAgICAgICAgdmlld1Byb2pQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoMTYgKiA0KTsKICAgICAgICAgIHRyYW5zZm9ybUluZGljZXNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoYWxsb2NhdGVkVmVydGV4Q291bnQgKiA0KTsKICAgICAgICAgIHBvc2l0aW9uc1B0ciA9IHdhc21Nb2R1bGUuX21hbGxvYygzICogYWxsb2NhdGVkVmVydGV4Q291bnQgKiA0KTsKICAgICAgICAgIGRlcHRoQnVmZmVyUHRyID0gd2FzbU1vZHVsZS5fbWFsbG9jKGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICBkZXB0aEluZGV4UHRyID0gd2FzbU1vZHVsZS5fbWFsbG9jKGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICBzdGFydHNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoYWxsb2NhdGVkVmVydGV4Q291bnQgKiA0KTsKICAgICAgICAgIGNvdW50c1B0ciA9IHdhc21Nb2R1bGUuX21hbGxvYyhhbGxvY2F0ZWRWZXJ0ZXhDb3VudCAqIDQpOwogICAgICB9CiAgICAgIGlmIChhbGxvY2F0ZWRUcmFuc2Zvcm1Db3VudCA8IHNvcnREYXRhLnRyYW5zZm9ybXMubGVuZ3RoKSB7CiAgICAgICAgICBpZiAoYWxsb2NhdGVkVHJhbnNmb3JtQ291bnQgPiAwKSB7CiAgICAgICAgICAgICAgd2FzbU1vZHVsZS5fZnJlZSh0cmFuc2Zvcm1zUHRyKTsKICAgICAgICAgIH0KICAgICAgICAgIGFsbG9jYXRlZFRyYW5zZm9ybUNvdW50ID0gc29ydERhdGEudHJhbnNmb3Jtcy5sZW5ndGg7CiAgICAgICAgICB0cmFuc2Zvcm1zUHRyID0gd2FzbU1vZHVsZS5fbWFsbG9jKGFsbG9jYXRlZFRyYW5zZm9ybUNvdW50ICogNCk7CiAgICAgIH0KICAgICAgbG9jayA9IGZhbHNlOwogICAgICBpZiAoYWxsb2NhdGlvblBlbmRpbmcpIHsKICAgICAgICAgIGFsbG9jYXRpb25QZW5kaW5nID0gZmFsc2U7CiAgICAgICAgICBhd2FpdCBhbGxvY2F0ZUJ1ZmZlcnMoKTsKICAgICAgfQogIH07CiAgY29uc3QgcnVuU29ydCA9ICgpID0+IHsKICAgICAgaWYgKGxvY2sgfHwgYWxsb2NhdGlvblBlbmRpbmcgfHwgIXdhc21Nb2R1bGUpCiAgICAgICAgICByZXR1cm47CiAgICAgIGxvY2sgPSB0cnVlOwogICAgICB3YXNtTW9kdWxlLkhFQVBGMzIuc2V0KHNvcnREYXRhLnBvc2l0aW9ucywgcG9zaXRpb25zUHRyIC8gNCk7CiAgICAgIHdhc21Nb2R1bGUuSEVBUEYzMi5zZXQoc29ydERhdGEudHJhbnNmb3JtcywgdHJhbnNmb3Jtc1B0ciAvIDQpOwogICAgICB3YXNtTW9kdWxlLkhFQVBVMzIuc2V0KHNvcnREYXRhLnRyYW5zZm9ybUluZGljZXMsIHRyYW5zZm9ybUluZGljZXNQdHIgLyA0KTsKICAgICAgd2FzbU1vZHVsZS5IRUFQRjMyLnNldCh2aWV3UHJvaiwgdmlld1Byb2pQdHIgLyA0KTsKICAgICAgd2FzbU1vZHVsZS5fc29ydCh2aWV3UHJvalB0ciwgdHJhbnNmb3Jtc1B0ciwgdHJhbnNmb3JtSW5kaWNlc1B0ciwgc29ydERhdGEudmVydGV4Q291bnQsIHBvc2l0aW9uc1B0ciwgZGVwdGhCdWZmZXJQdHIsIGRlcHRoSW5kZXhQdHIsIHN0YXJ0c1B0ciwgY291bnRzUHRyKTsKICAgICAgY29uc3QgZGVwdGhJbmRleCA9IG5ldyBVaW50MzJBcnJheSh3YXNtTW9kdWxlLkhFQVBVMzIuYnVmZmVyLCBkZXB0aEluZGV4UHRyLCBzb3J0RGF0YS52ZXJ0ZXhDb3VudCk7CiAgICAgIGNvbnN0IGRldGFjaGVkRGVwdGhJbmRleCA9IG5ldyBVaW50MzJBcnJheShkZXB0aEluZGV4LnNsaWNlKCkuYnVmZmVyKTsKICAgICAgc2VsZi5wb3N0TWVzc2FnZSh7IGRlcHRoSW5kZXg6IGRldGFjaGVkRGVwdGhJbmRleCB9LCBbZGV0YWNoZWREZXB0aEluZGV4LmJ1ZmZlcl0pOwogICAgICBsb2NrID0gZmFsc2U7CiAgfTsKICBjb25zdCB0aHJvdHRsZWRTb3J0ID0gKCkgPT4gewogICAgICBpZiAoIXNvcnRpbmcpIHsKICAgICAgICAgIHNvcnRpbmcgPSB0cnVlOwogICAgICAgICAgcnVuU29ydCgpOwogICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7CiAgICAgICAgICAgICAgc29ydGluZyA9IGZhbHNlOwogICAgICAgICAgICAgIHRocm90dGxlZFNvcnQoKTsKICAgICAgICAgIH0pOwogICAgICB9CiAgfTsKICBzZWxmLm9ubWVzc2FnZSA9IChlKSA9PiB7CiAgICAgIGlmIChlLmRhdGEuc29ydERhdGEpIHsKICAgICAgICAgIC8vUmVjcmVhdGluZyB0aGUgdHlwZWQgYXJyYXlzIGV2ZXJ5IHRpbWUsIHdpbGwgY2F1c2UgZmlyZWZveCB0byBsZWFrIG1lbW9yeQogICAgICAgICAgaWYgKCFzb3J0RGF0YSkgewogICAgICAgICAgICAgIHNvcnREYXRhID0gewogICAgICAgICAgICAgICAgICBwb3NpdGlvbnM6IG5ldyBGbG9hdDMyQXJyYXkoZS5kYXRhLnNvcnREYXRhLnBvc2l0aW9ucyksCiAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybXM6IG5ldyBGbG9hdDMyQXJyYXkoZS5kYXRhLnNvcnREYXRhLnRyYW5zZm9ybXMpLAogICAgICAgICAgICAgICAgICB0cmFuc2Zvcm1JbmRpY2VzOiBuZXcgVWludDMyQXJyYXkoZS5kYXRhLnNvcnREYXRhLnRyYW5zZm9ybUluZGljZXMpLAogICAgICAgICAgICAgICAgICB2ZXJ0ZXhDb3VudDogZS5kYXRhLnNvcnREYXRhLnZlcnRleENvdW50LAogICAgICAgICAgICAgIH07CiAgICAgICAgICB9CiAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICBzb3J0RGF0YS5wb3NpdGlvbnMuc2V0KGUuZGF0YS5zb3J0RGF0YS5wb3NpdGlvbnMpOwogICAgICAgICAgICAgIHNvcnREYXRhLnRyYW5zZm9ybXMuc2V0KGUuZGF0YS5zb3J0RGF0YS50cmFuc2Zvcm1zKTsKICAgICAgICAgICAgICBzb3J0RGF0YS50cmFuc2Zvcm1JbmRpY2VzLnNldChlLmRhdGEuc29ydERhdGEudHJhbnNmb3JtSW5kaWNlcyk7CiAgICAgICAgICAgICAgc29ydERhdGEudmVydGV4Q291bnQgPSBlLmRhdGEuc29ydERhdGEudmVydGV4Q291bnQ7CiAgICAgICAgICB9CiAgICAgICAgICBhbGxvY2F0ZUJ1ZmZlcnMoKTsKICAgICAgfQogICAgICBpZiAoZS5kYXRhLnZpZXdQcm9qKSB7CiAgICAgICAgICB2aWV3UHJvaiA9IEZsb2F0MzJBcnJheS5mcm9tKGUuZGF0YS52aWV3UHJvaik7CiAgICAgICAgICB0aHJvdHRsZWRTb3J0KCk7CiAgICAgIH0KICB9OwoKfSkoKTsKLy8jIHNvdXJjZU1hcHBpbmdVUkw9U29ydFdvcmtlci5qcy5tYXAKCg==", null);
|
|
889
|
-
class St {
|
|
890
|
-
constructor(t, F) {
|
|
891
|
-
this._scene = null, this._camera = null, this._started = !1, this._initialized = !1, this._renderer = t;
|
|
892
|
-
const U = t.gl;
|
|
893
|
-
this._program = U.createProgram(), this._passes = F || [];
|
|
894
|
-
const l = U.createShader(U.VERTEX_SHADER);
|
|
895
|
-
U.shaderSource(l, this._getVertexSource()), U.compileShader(l), U.getShaderParameter(l, U.COMPILE_STATUS) || console.error(U.getShaderInfoLog(l));
|
|
896
|
-
const a = U.createShader(U.FRAGMENT_SHADER);
|
|
897
|
-
U.shaderSource(a, this._getFragmentSource()), U.compileShader(a), U.getShaderParameter(a, U.COMPILE_STATUS) || console.error(U.getShaderInfoLog(a)), U.attachShader(this.program, l), U.attachShader(this.program, a), U.linkProgram(this.program), U.getProgramParameter(this.program, U.LINK_STATUS) || console.error(U.getProgramInfoLog(this.program)), this.resize = () => {
|
|
898
|
-
U.useProgram(this._program), this._resize();
|
|
899
|
-
}, this.initialize = () => {
|
|
900
|
-
console.assert(!this._initialized, "ShaderProgram already initialized"), U.useProgram(this._program), this._initialize();
|
|
901
|
-
for (const n of this.passes) n.initialize(this);
|
|
902
|
-
this._initialized = !0, this._started = !0;
|
|
903
|
-
}, this.render = (n, e) => {
|
|
904
|
-
U.useProgram(this._program), this._scene === n && this._camera === e || (this.dispose(), this._scene = n, this._camera = e, this.initialize());
|
|
905
|
-
for (const Q of this.passes) Q.render();
|
|
906
|
-
this._render();
|
|
907
|
-
}, this.dispose = () => {
|
|
908
|
-
if (this._initialized) {
|
|
909
|
-
U.useProgram(this._program);
|
|
910
|
-
for (const n of this.passes) n.dispose();
|
|
911
|
-
this._dispose(), this._scene = null, this._camera = null, this._initialized = !1;
|
|
912
|
-
}
|
|
913
|
-
};
|
|
914
|
-
}
|
|
915
|
-
get renderer() {
|
|
916
|
-
return this._renderer;
|
|
917
|
-
}
|
|
918
|
-
get scene() {
|
|
919
|
-
return this._scene;
|
|
920
|
-
}
|
|
921
|
-
get camera() {
|
|
922
|
-
return this._camera;
|
|
923
|
-
}
|
|
924
|
-
get program() {
|
|
925
|
-
return this._program;
|
|
926
|
-
}
|
|
927
|
-
get passes() {
|
|
928
|
-
return this._passes;
|
|
929
|
-
}
|
|
930
|
-
get started() {
|
|
931
|
-
return this._started;
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
var ll = yt("Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICd1c2Ugc3RyaWN0JzsKCiAgdmFyIGxvYWRXYXNtID0gKCgpID0+IHsKICAgIAogICAgcmV0dXJuICgKICBmdW5jdGlvbihtb2R1bGVBcmcgPSB7fSkgewoKICB2YXIgTW9kdWxlPW1vZHVsZUFyZzt2YXIgcmVhZHlQcm9taXNlUmVzb2x2ZSxyZWFkeVByb21pc2VSZWplY3Q7TW9kdWxlWyJyZWFkeSJdPW5ldyBQcm9taXNlKChyZXNvbHZlLHJlamVjdCk9PntyZWFkeVByb21pc2VSZXNvbHZlPXJlc29sdmU7cmVhZHlQcm9taXNlUmVqZWN0PXJlamVjdDt9KTt2YXIgbW9kdWxlT3ZlcnJpZGVzPU9iamVjdC5hc3NpZ24oe30sTW9kdWxlKTt2YXIgc2NyaXB0RGlyZWN0b3J5PSIiO2Z1bmN0aW9uIGxvY2F0ZUZpbGUocGF0aCl7aWYoTW9kdWxlWyJsb2NhdGVGaWxlIl0pe3JldHVybiBNb2R1bGVbImxvY2F0ZUZpbGUiXShwYXRoLHNjcmlwdERpcmVjdG9yeSl9cmV0dXJuIHNjcmlwdERpcmVjdG9yeStwYXRofXZhciByZWFkQmluYXJ5O3t7c2NyaXB0RGlyZWN0b3J5PXNlbGYubG9jYXRpb24uaHJlZjt9aWYoc2NyaXB0RGlyZWN0b3J5LmluZGV4T2YoImJsb2I6IikhPT0wKXtzY3JpcHREaXJlY3Rvcnk9c2NyaXB0RGlyZWN0b3J5LnN1YnN0cigwLHNjcmlwdERpcmVjdG9yeS5yZXBsYWNlKC9bPyNdLiovLCIiKS5sYXN0SW5kZXhPZigiLyIpKzEpO31lbHNlIHtzY3JpcHREaXJlY3Rvcnk9IiI7fXt7cmVhZEJpbmFyeT11cmw9Pnt2YXIgeGhyPW5ldyBYTUxIdHRwUmVxdWVzdDt4aHIub3BlbigiR0VUIix1cmwsZmFsc2UpO3hoci5yZXNwb25zZVR5cGU9ImFycmF5YnVmZmVyIjt4aHIuc2VuZChudWxsKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoeGhyLnJlc3BvbnNlKX07fX19TW9kdWxlWyJwcmludCJdfHxjb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpO3ZhciBlcnI9TW9kdWxlWyJwcmludEVyciJdfHxjb25zb2xlLmVycm9yLmJpbmQoY29uc29sZSk7T2JqZWN0LmFzc2lnbihNb2R1bGUsbW9kdWxlT3ZlcnJpZGVzKTttb2R1bGVPdmVycmlkZXM9bnVsbDtpZihNb2R1bGVbImFyZ3VtZW50cyJdKU1vZHVsZVsiYXJndW1lbnRzIl07aWYoTW9kdWxlWyJ0aGlzUHJvZ3JhbSJdKU1vZHVsZVsidGhpc1Byb2dyYW0iXTtpZihNb2R1bGVbInF1aXQiXSlNb2R1bGVbInF1aXQiXTt2YXIgd2FzbUJpbmFyeTtpZihNb2R1bGVbIndhc21CaW5hcnkiXSl3YXNtQmluYXJ5PU1vZHVsZVsid2FzbUJpbmFyeSJdO2lmKHR5cGVvZiBXZWJBc3NlbWJseSE9Im9iamVjdCIpe2Fib3J0KCJubyBuYXRpdmUgd2FzbSBzdXBwb3J0IGRldGVjdGVkIik7fXZhciB3YXNtTWVtb3J5O3ZhciBBQk9SVD1mYWxzZTt2YXIgSEVBUDgsSEVBUFU4LEhFQVAxNixIRUFQVTE2LEhFQVAzMixIRUFQVTMyLEhFQVBGMzIsSEVBUEY2NDtmdW5jdGlvbiB1cGRhdGVNZW1vcnlWaWV3cygpe3ZhciBiPXdhc21NZW1vcnkuYnVmZmVyO01vZHVsZVsiSEVBUDgiXT1IRUFQOD1uZXcgSW50OEFycmF5KGIpO01vZHVsZVsiSEVBUDE2Il09SEVBUDE2PW5ldyBJbnQxNkFycmF5KGIpO01vZHVsZVsiSEVBUFU4Il09SEVBUFU4PW5ldyBVaW50OEFycmF5KGIpO01vZHVsZVsiSEVBUFUxNiJdPUhFQVBVMTY9bmV3IFVpbnQxNkFycmF5KGIpO01vZHVsZVsiSEVBUDMyIl09SEVBUDMyPW5ldyBJbnQzMkFycmF5KGIpO01vZHVsZVsiSEVBUFUzMiJdPUhFQVBVMzI9bmV3IFVpbnQzMkFycmF5KGIpO01vZHVsZVsiSEVBUEYzMiJdPUhFQVBGMzI9bmV3IEZsb2F0MzJBcnJheShiKTtNb2R1bGVbIkhFQVBGNjQiXT1IRUFQRjY0PW5ldyBGbG9hdDY0QXJyYXkoYik7fXZhciBfX0FUUFJFUlVOX189W107dmFyIF9fQVRJTklUX189W107dmFyIF9fQVRQT1NUUlVOX189W107ZnVuY3Rpb24gcHJlUnVuKCl7aWYoTW9kdWxlWyJwcmVSdW4iXSl7aWYodHlwZW9mIE1vZHVsZVsicHJlUnVuIl09PSJmdW5jdGlvbiIpTW9kdWxlWyJwcmVSdW4iXT1bTW9kdWxlWyJwcmVSdW4iXV07d2hpbGUoTW9kdWxlWyJwcmVSdW4iXS5sZW5ndGgpe2FkZE9uUHJlUnVuKE1vZHVsZVsicHJlUnVuIl0uc2hpZnQoKSk7fX1jYWxsUnVudGltZUNhbGxiYWNrcyhfX0FUUFJFUlVOX18pO31mdW5jdGlvbiBpbml0UnVudGltZSgpe2NhbGxSdW50aW1lQ2FsbGJhY2tzKF9fQVRJTklUX18pO31mdW5jdGlvbiBwb3N0UnVuKCl7aWYoTW9kdWxlWyJwb3N0UnVuIl0pe2lmKHR5cGVvZiBNb2R1bGVbInBvc3RSdW4iXT09ImZ1bmN0aW9uIilNb2R1bGVbInBvc3RSdW4iXT1bTW9kdWxlWyJwb3N0UnVuIl1dO3doaWxlKE1vZHVsZVsicG9zdFJ1biJdLmxlbmd0aCl7YWRkT25Qb3N0UnVuKE1vZHVsZVsicG9zdFJ1biJdLnNoaWZ0KCkpO319Y2FsbFJ1bnRpbWVDYWxsYmFja3MoX19BVFBPU1RSVU5fXyk7fWZ1bmN0aW9uIGFkZE9uUHJlUnVuKGNiKXtfX0FUUFJFUlVOX18udW5zaGlmdChjYik7fWZ1bmN0aW9uIGFkZE9uSW5pdChjYil7X19BVElOSVRfXy51bnNoaWZ0KGNiKTt9ZnVuY3Rpb24gYWRkT25Qb3N0UnVuKGNiKXtfX0FUUE9TVFJVTl9fLnVuc2hpZnQoY2IpO312YXIgcnVuRGVwZW5kZW5jaWVzPTA7dmFyIGRlcGVuZGVuY2llc0Z1bGZpbGxlZD1udWxsO2Z1bmN0aW9uIGFkZFJ1bkRlcGVuZGVuY3koaWQpe3J1bkRlcGVuZGVuY2llcysrO2lmKE1vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdKXtNb2R1bGVbIm1vbml0b3JSdW5EZXBlbmRlbmNpZXMiXShydW5EZXBlbmRlbmNpZXMpO319ZnVuY3Rpb24gcmVtb3ZlUnVuRGVwZW5kZW5jeShpZCl7cnVuRGVwZW5kZW5jaWVzLS07aWYoTW9kdWxlWyJtb25pdG9yUnVuRGVwZW5kZW5jaWVzIl0pe01vZHVsZVsibW9uaXRvclJ1bkRlcGVuZGVuY2llcyJdKHJ1bkRlcGVuZGVuY2llcyk7fWlmKHJ1bkRlcGVuZGVuY2llcz09MCl7aWYoZGVwZW5kZW5jaWVzRnVsZmlsbGVkKXt2YXIgY2FsbGJhY2s9ZGVwZW5kZW5jaWVzRnVsZmlsbGVkO2RlcGVuZGVuY2llc0Z1bGZpbGxlZD1udWxsO2NhbGxiYWNrKCk7fX19ZnVuY3Rpb24gYWJvcnQod2hhdCl7aWYoTW9kdWxlWyJvbkFib3J0Il0pe01vZHVsZVsib25BYm9ydCJdKHdoYXQpO313aGF0PSJBYm9ydGVkKCIrd2hhdCsiKSI7ZXJyKHdoYXQpO0FCT1JUPXRydWU7d2hhdCs9Ii4gQnVpbGQgd2l0aCAtc0FTU0VSVElPTlMgZm9yIG1vcmUgaW5mby4iO3ZhciBlPW5ldyBXZWJBc3NlbWJseS5SdW50aW1lRXJyb3Iod2hhdCk7cmVhZHlQcm9taXNlUmVqZWN0KGUpO3Rocm93IGV9dmFyIGRhdGFVUklQcmVmaXg9ImRhdGE6YXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtO2Jhc2U2NCwiO3ZhciBpc0RhdGFVUkk9ZmlsZW5hbWU9PmZpbGVuYW1lLnN0YXJ0c1dpdGgoZGF0YVVSSVByZWZpeCk7dmFyIHdhc21CaW5hcnlGaWxlO3dhc21CaW5hcnlGaWxlPSJkYXRhOmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTtiYXNlNjQsQUdGemJRRUFBQUFCWVE1Z0JIOS9mMzhBWUFOL2YzOEFZQVYvZjM5L2Z3QmdCbjkvZjM5L2Z3QmdBbjkvQUdBQmZ3Ri9ZQUFBWUFOL2YzOEJmMkFCZndCZ0IzOS9mMzkvZjM4QVlBSjlmUUYvWUFSL2YzNStBR0FCZlFGL1lBdC9mMzkvZjM5L2YzOS9md0FDUFFvQllRRmhBQUVCWVFGaUFBSUJZUUZqQUFFQllRRmtBQVFCWVFGbEFBRUJZUUZtQUFrQllRRm5BQVVCWVFGb0FBUUJZUUZwQUFBQllRRnFBQVFER3hvSEJRb0lCZ1FHQ3dFQUFRZ0lEQVlOQXdNQ0FnQUFCd2NGQlFRRkFYQUJFQkFGQndFQmdBS0FnQUlHQ0FGL0FVSGduUVFMQngwSEFXc0NBQUZzQUE0QmJRQVpBVzRBR0FGdkFRQUJjQUFqQVhFQUZna1ZBUUJCQVFzUEVDSU5GUlVoRFNBYUhCOE5HeDBlQ3JKUUduRUJBWDhnQWtVRVFDQUFLQUlFSUFFb0FnUkdEd3NnQUNBQlJnUkFRUUVQQ3dKQUlBQW9BZ1FpQWkwQUFDSUFSU0FBSUFFb0FnUWlBUzBBQUNJRFIzSU5BQU5BSUFFdEFBRWhBeUFDTFFBQklnQkZEUUVnQVVFQmFpRUJJQUpCQVdvaEFpQUFJQU5HRFFBTEN5QUFJQU5HQzA4QkFuOUIyQmtvQWdBaUFTQUFRUWRxUVhoeElnSnFJUUFDUUNBQ1FRQWdBQ0FCVFJzTkFDQUFQd0JCRUhSTEJFQWdBQkFHUlEwQkMwSFlHU0FBTmdJQUlBRVBDMEhvR1VFd05nSUFRWDhMRGdBZ0FCQVhJQUVRRjBFUWRISUxCZ0FnQUJBV0N5a0FRZUFaUVFFMkFnQkI1QmxCQURZQ0FCQVFRZVFaUWR3WktBSUFOZ0lBUWR3WlFlQVpOZ0lBQ3lFQUlBRUVRQU5BSUFCQkFEb0FBQ0FBUVFGcUlRQWdBVUVCYXlJQkRRQUxDd3ZoQXdCQmpCZEJtZ2tRQ1VHWUYwRzVDRUVCUVFBUUNFR2tGMEcwQ0VFQlFZQi9RZjhBRUFGQnZCZEJyUWhCQVVHQWYwSC9BQkFCUWJBWFFhc0lRUUZCQUVIL0FSQUJRY2dYUVlrSVFRSkJnSUIrUWYvL0FSQUJRZFFYUVlBSVFRSkJBRUgvL3dNUUFVSGdGMEdZQ0VFRVFZQ0FnSUI0UWYvLy8vOEhFQUZCN0JkQmp3aEJCRUVBUVg4UUFVSDRGMEhYQ0VFRVFZQ0FnSUI0UWYvLy8vOEhFQUZCaEJoQnpnaEJCRUVBUVg4UUFVR1FHRUdqQ0VLQWdJQ0FnSUNBZ0lCL1F2Ly8vLy8vLy8vLy93QVFFVUdjR0VHaUNFSUFRbjhRRVVHb0dFR2NDRUVFRUFSQnRCaEJrd2xCQ0JBRVFZUVBRZWtJRUFOQnpBOUJsdzBRQTBHVUVFRUVRZHdJRUFKQjRCQkJBa0gxQ0JBQ1Fhd1JRUVJCaEFrUUFrSElFVUcrQ0JBSFFmQVJRUUJCMGd3UUFFR1lFa0VBUWJnTkVBQkJ3QkpCQVVId0RCQUFRZWdTUVFKQm53a1FBRUdRRTBFRFFiNEpFQUJCdUJOQkJFSG1DUkFBUWVBVFFRVkJnd29RQUVHSUZFRUVRZDBORUFCQnNCUkJCVUg3RFJBQVFaZ1NRUUJCNlFvUUFFSEFFa0VCUWNnS0VBQkI2QkpCQWtHckN4QUFRWkFUUVFOQmlRc1FBRUc0RTBFRVFiRU1FQUJCNEJOQkJVR1BEQkFBUWRnVVFRaEI3Z3NRQUVHQUZVRUpRY3dMRUFCQnFCVkJCa0dwQ2hBQVFkQVZRUWRCb2c0UUFBc2NBQ0FBSUFGQkNDQUNweUFDUWlDSXB5QURweUFEUWlDSXB4QUZDeUFBQWtBZ0FDZ0NCQ0FCUncwQUlBQW9BaHhCQVVZTkFDQUFJQUkyQWh3TEM1b0JBQ0FBUVFFNkFEVUNRQ0FBS0FJRUlBSkhEUUFnQUVFQk9nQTBBa0FnQUNnQ0VDSUNSUVJBSUFCQkFUWUNKQ0FBSUFNMkFoZ2dBQ0FCTmdJUUlBTkJBVWNOQWlBQUtBSXdRUUZHRFFFTUFnc2dBU0FDUmdSQUlBQW9BaGdpQWtFQ1JnUkFJQUFnQXpZQ0dDQURJUUlMSUFBb0FqQkJBVWNOQWlBQ1FRRkdEUUVNQWdzZ0FDQUFLQUlrUVFGcU5nSWtDeUFBUVFFNkFEWUxDMTBCQVg4Z0FDZ0NFQ0lEUlFSQUlBQkJBVFlDSkNBQUlBSTJBaGdnQUNBQk5nSVFEd3NDUUNBQklBTkdCRUFnQUNnQ0dFRUNSdzBCSUFBZ0FqWUNHQThMSUFCQkFUb0FOaUFBUVFJMkFoZ2dBQ0FBS0FJa1FRRnFOZ0lrQ3dzQ0FBdlNDd0VIZndKQUlBQkZEUUFnQUVFSWF5SUNJQUJCQkdzb0FnQWlBVUY0Y1NJQWFpRUZBa0FnQVVFQmNRMEFJQUZCQTNGRkRRRWdBaUFDS0FJQUlnRnJJZ0pCL0Jrb0FnQkpEUUVnQUNBQmFpRUFBa0FDUUVHQUdpZ0NBQ0FDUndSQUlBRkIvd0ZOQkVBZ0FVRURkaUVFSUFJb0Fnd2lBU0FDS0FJSUlnTkdCRUJCN0JsQjdCa29BZ0JCZmlBRWQzRTJBZ0FNQlFzZ0F5QUJOZ0lNSUFFZ0F6WUNDQXdFQ3lBQ0tBSVlJUVlnQWlBQ0tBSU1JZ0ZIQkVBZ0FpZ0NDQ0lESUFFMkFnd2dBU0FETmdJSURBTUxJQUpCRkdvaUJDZ0NBQ0lEUlFSQUlBSW9BaEFpQTBVTkFpQUNRUkJxSVFRTEEwQWdCQ0VISUFNaUFVRVVhaUlFS0FJQUlnTU5BQ0FCUVJCcUlRUWdBU2dDRUNJRERRQUxJQWRCQURZQ0FBd0NDeUFGS0FJRUlnRkJBM0ZCQTBjTkFrSDBHU0FBTmdJQUlBVWdBVUYrY1RZQ0JDQUNJQUJCQVhJMkFnUWdCU0FBTmdJQUR3dEJBQ0VCQ3lBR1JRMEFBa0FnQWlnQ0hDSURRUUowUVp3Y2FpSUVLQUlBSUFKR0JFQWdCQ0FCTmdJQUlBRU5BVUh3R1VId0dTZ0NBRUYrSUFOM2NUWUNBQXdDQ3lBR1FSQkJGQ0FHS0FJUUlBSkdHMm9nQVRZQ0FDQUJSUTBCQ3lBQklBWTJBaGdnQWlnQ0VDSURCRUFnQVNBRE5nSVFJQU1nQVRZQ0dBc2dBaWdDRkNJRFJRMEFJQUVnQXpZQ0ZDQURJQUUyQWhnTElBSWdCVThOQUNBRktBSUVJZ0ZCQVhGRkRRQUNRQUpBQWtBQ1FDQUJRUUp4UlFSQVFZUWFLQUlBSUFWR0JFQkJoQm9nQWpZQ0FFSDRHVUg0R1NnQ0FDQUFhaUlBTmdJQUlBSWdBRUVCY2pZQ0JDQUNRWUFhS0FJQVJ3MEdRZlFaUVFBMkFnQkJnQnBCQURZQ0FBOExRWUFhS0FJQUlBVkdCRUJCZ0JvZ0FqWUNBRUgwR1VIMEdTZ0NBQ0FBYWlJQU5nSUFJQUlnQUVFQmNqWUNCQ0FBSUFKcUlBQTJBZ0FQQ3lBQlFYaHhJQUJxSVFBZ0FVSC9BVTBFUUNBQlFRTjJJUVFnQlNnQ0RDSUJJQVVvQWdnaUEwWUVRRUhzR1VIc0dTZ0NBRUYrSUFSM2NUWUNBQXdGQ3lBRElBRTJBZ3dnQVNBRE5nSUlEQVFMSUFVb0FoZ2hCaUFGSUFVb0Fnd2lBVWNFUUVIOEdTZ0NBQm9nQlNnQ0NDSURJQUUyQWd3Z0FTQUROZ0lJREFNTElBVkJGR29pQkNnQ0FDSURSUVJBSUFVb0FoQWlBMFVOQWlBRlFSQnFJUVFMQTBBZ0JDRUhJQU1pQVVFVWFpSUVLQUlBSWdNTkFDQUJRUkJxSVFRZ0FTZ0NFQ0lERFFBTElBZEJBRFlDQUF3Q0N5QUZJQUZCZm5FMkFnUWdBaUFBUVFGeU5nSUVJQUFnQW1vZ0FEWUNBQXdEQzBFQUlRRUxJQVpGRFFBQ1FDQUZLQUljSWdOQkFuUkJuQnhxSWdRb0FnQWdCVVlFUUNBRUlBRTJBZ0FnQVEwQlFmQVpRZkFaS0FJQVFYNGdBM2R4TmdJQURBSUxJQVpCRUVFVUlBWW9BaEFnQlVZYmFpQUJOZ0lBSUFGRkRRRUxJQUVnQmpZQ0dDQUZLQUlRSWdNRVFDQUJJQU0yQWhBZ0F5QUJOZ0lZQ3lBRktBSVVJZ05GRFFBZ0FTQUROZ0lVSUFNZ0FUWUNHQXNnQWlBQVFRRnlOZ0lFSUFBZ0Ftb2dBRFlDQUNBQ1FZQWFLQUlBUncwQVFmUVpJQUEyQWdBUEN5QUFRZjhCVFFSQUlBQkJlSEZCbEJwcUlRRUNmMEhzR1NnQ0FDSURRUUVnQUVFRGRuUWlBSEZGQkVCQjdCa2dBQ0FEY2pZQ0FDQUJEQUVMSUFFb0FnZ0xJUUFnQVNBQ05nSUlJQUFnQWpZQ0RDQUNJQUUyQWd3Z0FpQUFOZ0lJRHd0Qkh5RURJQUJCLy8vL0IwMEVRQ0FBUVNZZ0FFRUlkbWNpQVd0MlFRRnhJQUZCQVhSclFUNXFJUU1MSUFJZ0F6WUNIQ0FDUWdBM0FoQWdBMEVDZEVHY0hHb2hBUUpBQWtBQ1FFSHdHU2dDQUNJRVFRRWdBM1FpQjNGRkJFQkI4QmtnQkNBSGNqWUNBQ0FCSUFJMkFnQWdBaUFCTmdJWURBRUxJQUJCR1NBRFFRRjJhMEVBSUFOQkgwY2JkQ0VESUFFb0FnQWhBUU5BSUFFaUJDZ0NCRUY0Y1NBQVJnMENJQU5CSFhZaEFTQURRUUYwSVFNZ0JDQUJRUVJ4YWlJSFFSQnFLQUlBSWdFTkFBc2dCeUFDTmdJUUlBSWdCRFlDR0FzZ0FpQUNOZ0lNSUFJZ0FqWUNDQXdCQ3lBRUtBSUlJZ0FnQWpZQ0RDQUVJQUkyQWdnZ0FrRUFOZ0lZSUFJZ0JEWUNEQ0FDSUFBMkFnZ0xRWXdhUVl3YUtBSUFRUUZySWdCQmZ5QUFHellDQUFzTGR3RUVmeUFBdkNJRVFmLy8vd054SVFFQ1FDQUVRUmQyUWY4QmNTSUNSUTBBSUFKQjhBQk5CRUFnQVVHQWdJQUVja0h4QUNBQ2EzWWhBUXdCQ3lBQ1FZMEJTd1JBUVlENEFTRURRUUFoQVF3QkN5QUNRUXAwUVlDQUIyc2hBd3NnQXlBRVFSQjJRWUNBQW5GeUlBRkJEWFp5UWYvL0EzRUxJd0VCZjBIY0dTZ0NBQ0lBQkVBRFFDQUFLQUlBRVFZQUlBQW9BZ1FpQUEwQUN3c0x2Z3NDQzM4SmZTTUFRYUFCYXlJTEpBQWdDMEV3YWtFa0VBOERRQ0FCSUExSEJFQWdBaUFOUVFOc0lneEJBbXBCQW5RaURtb3FBZ0FoRnlBQ0lBeEJBV3BCQW5RaUQyb3FBZ0FoR0NBSUlBeEJBblFpRUdvZ0FpQVFhaW9DQUNJWk9BSUFJQWdnRDJvZ0dEZ0NBQ0FJSUE1cUlCYzRBZ0FnQnlBTlFRVjBhaUlNSUJnNEFnUWdEQ0FaT0FJQUlBd2dGemdDQ0NBTVFRQTJBZ3dDUUNBQVJRUkFJQVlnRFdvdEFBQkZEUUVMSUF4QmdJQ0FDRFlDREFzZ0J5QU5RUVYwSWhGQkhISnFJQVVnRFVFQ2RDSU1RUUZ5SWhKcUxRQUFRUWgwSUFVZ0RHb3RBQUJ5SUFVZ0RFRUNjaUlUYWkwQUFFRVFkSElnQlNBTVFRTnlJZ3hxTFFBQVFSaDBjallDQUNBTElBTWdFa0VDZENJU2Fpb0NBQ0lYT0FLUUFTQUxJQU1nRTBFQ2RDSVRhaW9DQUNJWU9BS1VBU0FMSUFNZ0RFRUNkQ0lVYWlvQ0FDSVpPQUtZQVNBTElBTWdEVUVFZENJVmFpb0NBSXdpR2pnQ25BRWdDMEhnQUdvaURDQUxLZ0tZQVNJV1F3QUFBTUNVSUJhVUlBc3FBcFFCSWhaREFBQUF3SlFnRnBSREFBQ0FQNUtTT0FJQUlBd2dDeW9Da0FFaUZpQVdraUFMS2dLVUFaUWdDeW9DbUFGREFBQUF3SlFnQ3lvQ25BR1VramdDQkNBTUlBc3FBcEFCSWhZZ0ZwSWdDeW9DbUFHVUlBc3FBcFFCSWhZZ0ZwSWdDeW9DbkFHVWtqZ0NDQ0FNSUFzcUFwQUJJaFlnRnBJZ0N5b0NsQUdVSUFzcUFwZ0JJaFlnRnBJZ0N5b0NuQUdVa2pnQ0RDQU1JQXNxQXBnQkloWkRBQUFBd0pRZ0ZwUWdDeW9Da0FFaUZrTUFBQURBbENBV2xFTUFBSUEva3BJNEFoQWdEQ0FMS2dLVUFTSVdJQmFTSUFzcUFwZ0JsQ0FMS2dLUUFVTUFBQURBbENBTEtnS2NBWlNTT0FJVUlBd2dDeW9Da0FFaUZpQVdraUFMS2dLWUFaUWdDeW9DbEFGREFBQUF3SlFnQ3lvQ25BR1VramdDR0NBTUlBc3FBcFFCSWhZZ0ZwSWdDeW9DbUFHVUlBc3FBcEFCSWhZZ0ZwSWdDeW9DbkFHVWtqZ0NIQ0FNSUFzcUFwUUJJaFpEQUFBQXdKUWdGcFFnQ3lvQ2tBRWlGa01BQUFEQWxDQVdsRU1BQUlBL2twSTRBaUFnQ1NBVmFpQVhPQUlBSUFrZ0Vtb2dHRGdDQUNBSklCTnFJQms0QWdBZ0NTQVVhaUFhT0FJQUlBc2dCQ0FRYWlvQ0FDSVhPQUl3SUFzZ0JDQVBhaW9DQUNJWU9BSkFJQXNnQkNBT2Fpb0NBQ0laT0FKUUlBb2dFR29nRnpnQ0FDQUtJQTlxSUJnNEFnQWdDaUFPYWlBWk9BSUFJQXNnRENvQ0dDQUxLZ0k0bENBTUtnSUFJQXNxQWpDVUlBd3FBZ3dnQ3lvQ05KU1NramdDQUNBTElBd3FBaHdnQ3lvQ09KUWdEQ29DQkNBTEtnSXdsQ0FNS2dJUUlBc3FBalNVa3BJNEFnUWdDeUFNS2dJZ0lBc3FBamlVSUF3cUFnZ2dDeW9DTUpRZ0RDb0NGQ0FMS2dJMGxKS1NPQUlJSUFzZ0RDb0NHQ0FMS2dKRWxDQU1LZ0lBSUFzcUFqeVVJQXdxQWd3Z0N5b0NRSlNTa2pnQ0RDQUxJQXdxQWh3Z0N5b0NSSlFnRENvQ0JDQUxLZ0k4bENBTUtnSVFJQXNxQWtDVWtwSTRBaEFnQ3lBTUtnSWdJQXNxQWtTVUlBd3FBZ2dnQ3lvQ1BKUWdEQ29DRkNBTEtnSkFsSktTT0FJVUlBc2dEQ29DR0NBTEtnSlFsQ0FNS2dJQUlBc3FBa2lVSUF3cUFnd2dDeW9DVEpTU2tqZ0NHQ0FMSUF3cUFod2dDeW9DVUpRZ0RDb0NCQ0FMS2dKSWxDQU1LZ0lRSUFzcUFreVVrcEk0QWh3Z0N5QU1LZ0lnSUFzcUFsQ1VJQXdxQWdnZ0N5b0NTSlFnRENvQ0ZDQUxLZ0pNbEpLU09BSWdJQXNxQWlBaEZ5QUxLZ0lJSVJnZ0N5b0NGQ0VaSUFjZ0VVRVFjbW9nQ3lvQ0dDSWFJQnFVSUFzcUFnQWlGaUFXbENBTEtnSU1JaHNnRzVTU2trTUFBSUJBbENBYUlBc3FBaHdpSEpRZ0ZpQUxLZ0lFSWgyVUlCc2dDeW9DRUNJZWxKS1NRd0FBZ0VDVUVBdzJBZ0FnQnlBUlFSUnlhaUFhSUJlVUlCWWdHSlFnR3lBWmxKS1NRd0FBZ0VDVUlCd2dISlFnSFNBZGxDQWVJQjZVa3BKREFBQ0FRSlFRRERZQ0FDQUhJQkZCR0hKcUlCd2dGNVFnSFNBWWxDQWVJQm1Va3BKREFBQ0FRSlFnRnlBWGxDQVlJQmlVSUJrZ0daU1Nra01BQUlCQWxCQU1OZ0lBSUExQkFXb2hEUXdCQ3dzZ0MwR2dBV29rQUFzYUFDQUFJQUVvQWdnZ0JSQUtCRUFnQVNBQ0lBTWdCQkFUQ3dzM0FDQUFJQUVvQWdnZ0JSQUtCRUFnQVNBQ0lBTWdCQkFURHdzZ0FDZ0NDQ0lBSUFFZ0FpQURJQVFnQlNBQUtBSUFLQUlVRVFNQUM1RUJBQ0FBSUFFb0FnZ2dCQkFLQkVBZ0FTQUNJQU1RRWc4TEFrQWdBQ0FCS0FJQUlBUVFDa1VOQUFKQUlBSWdBU2dDRUVjRVFDQUJLQUlVSUFKSERRRUxJQU5CQVVjTkFTQUJRUUUyQWlBUEN5QUJJQUkyQWhRZ0FTQUROZ0lnSUFFZ0FTZ0NLRUVCYWpZQ0tBSkFJQUVvQWlSQkFVY05BQ0FCS0FJWVFRSkhEUUFnQVVFQk9nQTJDeUFCUVFRMkFpd0xDL0lCQUNBQUlBRW9BZ2dnQkJBS0JFQWdBU0FDSUFNUUVnOExBa0FnQUNBQktBSUFJQVFRQ2dSQUFrQWdBaUFCS0FJUVJ3UkFJQUVvQWhRZ0FrY05BUXNnQTBFQlJ3MENJQUZCQVRZQ0lBOExJQUVnQXpZQ0lBSkFJQUVvQWl4QkJFWU5BQ0FCUVFBN0FUUWdBQ2dDQ0NJQUlBRWdBaUFDUVFFZ0JDQUFLQUlBS0FJVUVRTUFJQUV0QURVRVFDQUJRUU0yQWl3Z0FTMEFORVVOQVF3REN5QUJRUVEyQWl3TElBRWdBallDRkNBQklBRW9BaWhCQVdvMkFpZ2dBU2dDSkVFQlJ3MEJJQUVvQWhoQkFrY05BU0FCUVFFNkFEWVBDeUFBS0FJSUlnQWdBU0FDSUFNZ0JDQUFLQUlBS0FJWUVRSUFDd3N4QUNBQUlBRW9BZ2hCQUJBS0JFQWdBU0FDSUFNUUZBOExJQUFvQWdnaUFDQUJJQUlnQXlBQUtBSUFLQUljRVFBQUN4Z0FJQUFnQVNnQ0NFRUFFQW9FUUNBQklBSWdBeEFVQ3d2SkF3RUZmeU1BUVVCcUlnUWtBQUovUVFFZ0FDQUJRUUFRQ2cwQUdrRUFJQUZGRFFBYUl3QkJRR29pQXlRQUlBRW9BZ0FpQlVFRWF5Z0NBQ0VHSUFWQkNHc29BZ0FoQlNBRFFnQTNBaUFnQTBJQU53SW9JQU5DQURjQ01DQURRZ0EzQURjZ0EwSUFOd0lZSUFOQkFEWUNGQ0FEUWZ3Vk5nSVFJQU1nQVRZQ0RDQURRYXdXTmdJSUlBRWdCV29oQVVFQUlRVUNRQ0FHUWF3V1FRQVFDZ1JBSUFOQkFUWUNPQ0FHSUFOQkNHb2dBU0FCUVFGQkFDQUdLQUlBS0FJVUVRTUFJQUZCQUNBREtBSWdRUUZHR3lFRkRBRUxJQVlnQTBFSWFpQUJRUUZCQUNBR0tBSUFLQUlZRVFJQUFrQUNRQ0FES0FJc0RnSUFBUUlMSUFNb0FoeEJBQ0FES0FJb1FRRkdHMEVBSUFNb0FpUkJBVVliUVFBZ0F5Z0NNRUVCUmhzaEJRd0JDeUFES0FJZ1FRRkhCRUFnQXlnQ01BMEJJQU1vQWlSQkFVY05BU0FES0FJb1FRRkhEUUVMSUFNb0FoZ2hCUXNnQTBGQWF5UUFRUUFnQlNJQlJRMEFHaUFFUVF4cVFUUVFEeUFFUVFFMkFqZ2dCRUYvTmdJVUlBUWdBRFlDRUNBRUlBRTJBZ2dnQVNBRVFRaHFJQUlvQWdCQkFTQUJLQUlBS0FJY0VRQUFJQVFvQWlBaUFFRUJSZ1JBSUFJZ0JDZ0NHRFlDQUFzZ0FFRUJSZ3NoQnlBRVFVQnJKQUFnQndzS0FDQUFJQUZCQUJBS0N3UUFJQUFMdlNjQkRIOGpBRUVRYXlJS0pBQUNRQUpBQWtBQ1FBSkFBa0FDUUFKQUFrQUNRQUpBQWtBQ1FBSkFJQUJCOUFGTkJFQkI3QmtvQWdBaUJrRVFJQUJCQzJwQmVIRWdBRUVMU1JzaUJVRURkaUlBZGlJQlFRTnhCRUFDUUNBQlFYOXpRUUZ4SUFCcUlnSkJBM1FpQVVHVUdtb2lBQ0FCUVp3YWFpZ0NBQ0lCS0FJSUlnUkdCRUJCN0JrZ0JrRitJQUozY1RZQ0FBd0JDeUFFSUFBMkFnd2dBQ0FFTmdJSUN5QUJRUWhxSVFBZ0FTQUNRUU4wSWdKQkEzSTJBZ1FnQVNBQ2FpSUJJQUVvQWdSQkFYSTJBZ1FNRHdzZ0JVSDBHU2dDQUNJSFRRMEJJQUVFUUFKQVFRSWdBSFFpQWtFQUlBSnJjaUFCSUFCMGNXZ2lBVUVEZENJQVFaUWFhaUlDSUFCQm5CcHFLQUlBSWdBb0FnZ2lCRVlFUUVIc0dTQUdRWDRnQVhkeElnWTJBZ0FNQVFzZ0JDQUNOZ0lNSUFJZ0JEWUNDQXNnQUNBRlFRTnlOZ0lFSUFBZ0JXb2lDQ0FCUVFOMElnRWdCV3NpQkVFQmNqWUNCQ0FBSUFGcUlBUTJBZ0FnQndSQUlBZEJlSEZCbEJwcUlRRkJnQm9vQWdBaEFnSi9JQVpCQVNBSFFRTjJkQ0lEY1VVRVFFSHNHU0FESUFaeU5nSUFJQUVNQVFzZ0FTZ0NDQXNoQXlBQklBSTJBZ2dnQXlBQ05nSU1JQUlnQVRZQ0RDQUNJQU0yQWdnTElBQkJDR29oQUVHQUdpQUlOZ0lBUWZRWklBUTJBZ0FNRHd0QjhCa29BZ0FpQzBVTkFTQUxhRUVDZEVHY0hHb29BZ0FpQWlnQ0JFRjRjU0FGYXlFRElBSWhBUU5BQWtBZ0FTZ0NFQ0lBUlFSQUlBRW9BaFFpQUVVTkFRc2dBQ2dDQkVGNGNTQUZheUlCSUFNZ0FTQURTU0lCR3lFRElBQWdBaUFCR3lFQ0lBQWhBUXdCQ3dzZ0FpZ0NHQ0VKSUFJZ0FpZ0NEQ0lFUndSQVFmd1pLQUlBR2lBQ0tBSUlJZ0FnQkRZQ0RDQUVJQUEyQWdnTURnc2dBa0VVYWlJQktBSUFJZ0JGQkVBZ0FpZ0NFQ0lBUlEwRElBSkJFR29oQVFzRFFDQUJJUWdnQUNJRVFSUnFJZ0VvQWdBaUFBMEFJQVJCRUdvaEFTQUVLQUlRSWdBTkFBc2dDRUVBTmdJQURBMExRWDhoQlNBQVFiOS9TdzBBSUFCQkMyb2lBRUY0Y1NFRlFmQVpLQUlBSWdoRkRRQkJBQ0FGYXlFREFrQUNRQUpBQW45QkFDQUZRWUFDU1EwQUdrRWZJQVZCLy8vL0Iwc05BQm9nQlVFbUlBQkJDSFpuSWdCcmRrRUJjU0FBUVFGMGEwRSthZ3NpQjBFQ2RFR2NIR29vQWdBaUFVVUVRRUVBSVFBTUFRdEJBQ0VBSUFWQkdTQUhRUUYyYTBFQUlBZEJIMGNiZENFQ0EwQUNRQ0FCS0FJRVFYaHhJQVZySWdZZ0EwOE5BQ0FCSVFRZ0JpSUREUUJCQUNFRElBRWhBQXdEQ3lBQUlBRW9BaFFpQmlBR0lBRWdBa0VkZGtFRWNXb29BaEFpQVVZYklBQWdCaHNoQUNBQ1FRRjBJUUlnQVEwQUN3c2dBQ0FFY2tVRVFFRUFJUVJCQWlBSGRDSUFRUUFnQUd0eUlBaHhJZ0JGRFFNZ0FHaEJBblJCbkJ4cUtBSUFJUUFMSUFCRkRRRUxBMEFnQUNnQ0JFRjRjU0FGYXlJQ0lBTkpJUUVnQWlBRElBRWJJUU1nQUNBRUlBRWJJUVFnQUNnQ0VDSUJCSDhnQVFVZ0FDZ0NGQXNpQUEwQUN3c2dCRVVOQUNBRFFmUVpLQUlBSUFWclR3MEFJQVFvQWhnaEJ5QUVJQVFvQWd3aUFrY0VRRUg4R1NnQ0FCb2dCQ2dDQ0NJQUlBSTJBZ3dnQWlBQU5nSUlEQXdMSUFSQkZHb2lBU2dDQUNJQVJRUkFJQVFvQWhBaUFFVU5BeUFFUVJCcUlRRUxBMEFnQVNFR0lBQWlBa0VVYWlJQktBSUFJZ0FOQUNBQ1FSQnFJUUVnQWlnQ0VDSUFEUUFMSUFaQkFEWUNBQXdMQ3lBRlFmUVpLQUlBSWdSTkJFQkJnQm9vQWdBaEFBSkFJQVFnQldzaUFVRVFUd1JBSUFBZ0JXb2lBaUFCUVFGeU5nSUVJQUFnQkdvZ0FUWUNBQ0FBSUFWQkEzSTJBZ1FNQVFzZ0FDQUVRUU55TmdJRUlBQWdCR29pQVNBQktBSUVRUUZ5TmdJRVFRQWhBa0VBSVFFTFFmUVpJQUUyQWdCQmdCb2dBallDQUNBQVFRaHFJUUFNRFFzZ0JVSDRHU2dDQUNJQ1NRUkFRZmdaSUFJZ0JXc2lBVFlDQUVHRUdrR0VHaWdDQUNJQUlBVnFJZ0kyQWdBZ0FpQUJRUUZ5TmdJRUlBQWdCVUVEY2pZQ0JDQUFRUWhxSVFBTURRdEJBQ0VBSUFWQkwyb2lBd0ovUWNRZEtBSUFCRUJCekIwb0FnQU1BUXRCMEIxQ2Z6Y0NBRUhJSFVLQW9JQ0FnSUFFTndJQVFjUWRJQXBCREdwQmNIRkIyS3JWcWdWek5nSUFRZGdkUVFBMkFnQkJxQjFCQURZQ0FFR0FJQXNpQVdvaUJrRUFJQUZySWdoeElnRWdCVTBOREVHa0hTZ0NBQ0lFQkVCQm5CMG9BZ0FpQnlBQmFpSUpJQWROSUFRZ0NVbHlEUTBMQWtCQnFCMHRBQUJCQkhGRkJFQUNRQUpBQWtBQ1FFR0VHaWdDQUNJRUJFQkJyQjBoQUFOQUlBUWdBQ2dDQUNJSFR3UkFJQWNnQUNnQ0JHb2dCRXNOQXdzZ0FDZ0NDQ0lBRFFBTEMwRUFFQXNpQWtGL1JnMERJQUVoQmtISUhTZ0NBQ0lBUVFGcklnUWdBbkVFUUNBQklBSnJJQUlnQkdwQkFDQUFhM0ZxSVFZTElBVWdCazhOQTBHa0hTZ0NBQ0lBQkVCQm5CMG9BZ0FpQkNBR2FpSUlJQVJOSUFBZ0NFbHlEUVFMSUFZUUN5SUFJQUpIRFFFTUJRc2dCaUFDYXlBSWNTSUdFQXNpQWlBQUtBSUFJQUFvQWdScVJnMEJJQUloQUFzZ0FFRi9SZzBCSUFWQk1Hb2dCazBFUUNBQUlRSU1CQXRCekIwb0FnQWlBaUFESUFacmFrRUFJQUpyY1NJQ0VBdEJmMFlOQVNBQ0lBWnFJUVlnQUNFQ0RBTUxJQUpCZjBjTkFndEJxQjFCcUIwb0FnQkJCSEkyQWdBTElBRVFDeUlDUVg5R1FRQVFDeUlBUVg5R2NpQUFJQUpOY2cwRklBQWdBbXNpQmlBRlFTaHFUUTBGQzBHY0hVR2NIU2dDQUNBR2FpSUFOZ0lBUWFBZEtBSUFJQUJKQkVCQm9CMGdBRFlDQUFzQ1FFR0VHaWdDQUNJREJFQkJyQjBoQUFOQUlBSWdBQ2dDQUNJQklBQW9BZ1FpQkdwR0RRSWdBQ2dDQ0NJQURRQUxEQVFMUWZ3WktBSUFJZ0JCQUNBQUlBSk5HMFVFUUVIOEdTQUNOZ0lBQzBFQUlRQkJzQjBnQmpZQ0FFR3NIU0FDTmdJQVFZd2FRWDgyQWdCQmtCcEJ4QjBvQWdBMkFnQkJ1QjFCQURZQ0FBTkFJQUJCQTNRaUFVR2NHbW9nQVVHVUdtb2lCRFlDQUNBQlFhQWFhaUFFTmdJQUlBQkJBV29pQUVFZ1J3MEFDMEg0R1NBR1FTaHJJZ0JCZUNBQ2EwRUhjU0lCYXlJRU5nSUFRWVFhSUFFZ0Ftb2lBVFlDQUNBQklBUkJBWEkyQWdRZ0FDQUNha0VvTmdJRVFZZ2FRZFFkS0FJQU5nSUFEQVFMSUFJZ0EwMGdBU0FEUzNJTkFpQUFLQUlNUVFoeERRSWdBQ0FFSUFacU5nSUVRWVFhSUFOQmVDQURhMEVIY1NJQWFpSUJOZ0lBUWZnWlFmZ1pLQUlBSUFacUlnSWdBR3NpQURZQ0FDQUJJQUJCQVhJMkFnUWdBaUFEYWtFb05nSUVRWWdhUWRRZEtBSUFOZ0lBREFNTFFRQWhCQXdLQzBFQUlRSU1DQXRCL0Jrb0FnQWdBa3NFUUVIOEdTQUNOZ0lBQ3lBQ0lBWnFJUUZCckIwaEFBSkFBa0FDUUFOQUlBRWdBQ2dDQUVjRVFDQUFLQUlJSWdBTkFRd0NDd3NnQUMwQURFRUljVVVOQVF0QnJCMGhBQU5BSUFNZ0FDZ0NBQ0lCVHdSQUlBRWdBQ2dDQkdvaUJDQURTdzBEQ3lBQUtBSUlJUUFNQUFzQUN5QUFJQUkyQWdBZ0FDQUFLQUlFSUFacU5nSUVJQUpCZUNBQ2EwRUhjV29pQnlBRlFRTnlOZ0lFSUFGQmVDQUJhMEVIY1dvaUJpQUZJQWRxSWdWcklRQWdBeUFHUmdSQVFZUWFJQVUyQWdCQitCbEIrQmtvQWdBZ0FHb2lBRFlDQUNBRklBQkJBWEkyQWdRTUNBdEJnQm9vQWdBZ0JrWUVRRUdBR2lBRk5nSUFRZlFaUWZRWktBSUFJQUJxSWdBMkFnQWdCU0FBUVFGeU5nSUVJQUFnQldvZ0FEWUNBQXdJQ3lBR0tBSUVJZ05CQTNGQkFVY05CaUFEUVhoeElRa2dBMEgvQVUwRVFDQUdLQUlNSWdFZ0JpZ0NDQ0lDUmdSQVFld1pRZXdaS0FJQVFYNGdBMEVEZG5keE5nSUFEQWNMSUFJZ0FUWUNEQ0FCSUFJMkFnZ01CZ3NnQmlnQ0dDRUlJQVlnQmlnQ0RDSUNSd1JBSUFZb0FnZ2lBU0FDTmdJTUlBSWdBVFlDQ0F3RkN5QUdRUlJxSWdFb0FnQWlBMFVFUUNBR0tBSVFJZ05GRFFRZ0JrRVFhaUVCQ3dOQUlBRWhCQ0FESWdKQkZHb2lBU2dDQUNJRERRQWdBa0VRYWlFQklBSW9BaEFpQXcwQUN5QUVRUUEyQWdBTUJBdEIrQmtnQmtFb2F5SUFRWGdnQW10QkIzRWlBV3NpQ0RZQ0FFR0VHaUFCSUFKcUlnRTJBZ0FnQVNBSVFRRnlOZ0lFSUFBZ0FtcEJLRFlDQkVHSUdrSFVIU2dDQURZQ0FDQURJQVJCSnlBRWEwRUhjV3BCTDJzaUFDQUFJQU5CRUdwSkd5SUJRUnMyQWdRZ0FVRzBIU2tDQURjQ0VDQUJRYXdkS1FJQU53SUlRYlFkSUFGQkNHbzJBZ0JCc0IwZ0JqWUNBRUdzSFNBQ05nSUFRYmdkUVFBMkFnQWdBVUVZYWlFQUEwQWdBRUVITmdJRUlBQkJDR29oRENBQVFRUnFJUUFnRENBRVNRMEFDeUFCSUFOR0RRQWdBU0FCS0FJRVFYNXhOZ0lFSUFNZ0FTQURheUlDUVFGeU5nSUVJQUVnQWpZQ0FDQUNRZjhCVFFSQUlBSkJlSEZCbEJwcUlRQUNmMEhzR1NnQ0FDSUJRUUVnQWtFRGRuUWlBbkZGQkVCQjdCa2dBU0FDY2pZQ0FDQUFEQUVMSUFBb0FnZ0xJUUVnQUNBRE5nSUlJQUVnQXpZQ0RDQURJQUEyQWd3Z0F5QUJOZ0lJREFFTFFSOGhBQ0FDUWYvLy93ZE5CRUFnQWtFbUlBSkJDSFpuSWdCcmRrRUJjU0FBUVFGMGEwRSthaUVBQ3lBRElBQTJBaHdnQTBJQU53SVFJQUJCQW5SQm5CeHFJUUVDUUFKQVFmQVpLQUlBSWdSQkFTQUFkQ0lHY1VVRVFFSHdHU0FFSUFaeU5nSUFJQUVnQXpZQ0FBd0JDeUFDUVJrZ0FFRUJkbXRCQUNBQVFSOUhHM1FoQUNBQktBSUFJUVFEUUNBRUlnRW9BZ1JCZUhFZ0FrWU5BaUFBUVIxMklRUWdBRUVCZENFQUlBRWdCRUVFY1dvaUJpZ0NFQ0lFRFFBTElBWWdBellDRUFzZ0F5QUJOZ0lZSUFNZ0F6WUNEQ0FESUFNMkFnZ01BUXNnQVNnQ0NDSUFJQU0yQWd3Z0FTQUROZ0lJSUFOQkFEWUNHQ0FESUFFMkFnd2dBeUFBTmdJSUMwSDRHU2dDQUNJQUlBVk5EUUJCK0JrZ0FDQUZheUlCTmdJQVFZUWFRWVFhS0FJQUlnQWdCV29pQWpZQ0FDQUNJQUZCQVhJMkFnUWdBQ0FGUVFOeU5nSUVJQUJCQ0dvaEFBd0lDMEhvR1VFd05nSUFRUUFoQUF3SEMwRUFJUUlMSUFoRkRRQUNRQ0FHS0FJY0lnRkJBblJCbkJ4cUlnUW9BZ0FnQmtZRVFDQUVJQUkyQWdBZ0FnMEJRZkFaUWZBWktBSUFRWDRnQVhkeE5nSUFEQUlMSUFoQkVFRVVJQWdvQWhBZ0JrWWJhaUFDTmdJQUlBSkZEUUVMSUFJZ0NEWUNHQ0FHS0FJUUlnRUVRQ0FDSUFFMkFoQWdBU0FDTmdJWUN5QUdLQUlVSWdGRkRRQWdBaUFCTmdJVUlBRWdBallDR0FzZ0FDQUphaUVBSUFZZ0NXb2lCaWdDQkNFREN5QUdJQU5CZm5FMkFnUWdCU0FBUVFGeU5nSUVJQUFnQldvZ0FEWUNBQ0FBUWY4QlRRUkFJQUJCZUhGQmxCcHFJUUVDZjBIc0dTZ0NBQ0lDUVFFZ0FFRURkblFpQUhGRkJFQkI3QmtnQUNBQ2NqWUNBQ0FCREFFTElBRW9BZ2dMSVFBZ0FTQUZOZ0lJSUFBZ0JUWUNEQ0FGSUFFMkFnd2dCU0FBTmdJSURBRUxRUjhoQXlBQVFmLy8vd2ROQkVBZ0FFRW1JQUJCQ0habklnRnJka0VCY1NBQlFRRjBhMEUrYWlFREN5QUZJQU0yQWh3Z0JVSUFOd0lRSUFOQkFuUkJuQnhxSVFFQ1FBSkFRZkFaS0FJQUlnSkJBU0FEZENJRWNVVUVRRUh3R1NBQ0lBUnlOZ0lBSUFFZ0JUWUNBQXdCQ3lBQVFSa2dBMEVCZG10QkFDQURRUjlIRzNRaEF5QUJLQUlBSVFJRFFDQUNJZ0VvQWdSQmVIRWdBRVlOQWlBRFFSMTJJUUlnQTBFQmRDRURJQUVnQWtFRWNXb2lCQ2dDRUNJQ0RRQUxJQVFnQlRZQ0VBc2dCU0FCTmdJWUlBVWdCVFlDRENBRklBVTJBZ2dNQVFzZ0FTZ0NDQ0lBSUFVMkFnd2dBU0FGTmdJSUlBVkJBRFlDR0NBRklBRTJBZ3dnQlNBQU5nSUlDeUFIUVFocUlRQU1BZ3NDUUNBSFJRMEFBa0FnQkNnQ0hDSUFRUUowUVp3Y2FpSUJLQUlBSUFSR0JFQWdBU0FDTmdJQUlBSU5BVUh3R1NBSVFYNGdBSGR4SWdnMkFnQU1BZ3NnQjBFUVFSUWdCeWdDRUNBRVJodHFJQUkyQWdBZ0FrVU5BUXNnQWlBSE5nSVlJQVFvQWhBaUFBUkFJQUlnQURZQ0VDQUFJQUkyQWhnTElBUW9BaFFpQUVVTkFDQUNJQUEyQWhRZ0FDQUNOZ0lZQ3dKQUlBTkJEMDBFUUNBRUlBTWdCV29pQUVFRGNqWUNCQ0FBSUFScUlnQWdBQ2dDQkVFQmNqWUNCQXdCQ3lBRUlBVkJBM0kyQWdRZ0JDQUZhaUlDSUFOQkFYSTJBZ1FnQWlBRGFpQUROZ0lBSUFOQi93Rk5CRUFnQTBGNGNVR1VHbW9oQUFKL1Fld1pLQUlBSWdGQkFTQURRUU4yZENJRGNVVUVRRUhzR1NBQklBTnlOZ0lBSUFBTUFRc2dBQ2dDQ0FzaEFTQUFJQUkyQWdnZ0FTQUNOZ0lNSUFJZ0FEWUNEQ0FDSUFFMkFnZ01BUXRCSHlFQUlBTkIvLy8vQjAwRVFDQURRU1lnQTBFSWRtY2lBR3QyUVFGeElBQkJBWFJyUVQ1cUlRQUxJQUlnQURZQ0hDQUNRZ0EzQWhBZ0FFRUNkRUdjSEdvaEFRSkFBa0FnQ0VFQklBQjBJZ1p4UlFSQVFmQVpJQVlnQ0hJMkFnQWdBU0FDTmdJQURBRUxJQU5CR1NBQVFRRjJhMEVBSUFCQkgwY2JkQ0VBSUFFb0FnQWhCUU5BSUFVaUFTZ0NCRUY0Y1NBRFJnMENJQUJCSFhZaEJpQUFRUUYwSVFBZ0FTQUdRUVJ4YWlJR0tBSVFJZ1VOQUFzZ0JpQUNOZ0lRQ3lBQ0lBRTJBaGdnQWlBQ05nSU1JQUlnQWpZQ0NBd0JDeUFCS0FJSUlnQWdBallDRENBQklBSTJBZ2dnQWtFQU5nSVlJQUlnQVRZQ0RDQUNJQUEyQWdnTElBUkJDR29oQUF3QkN3SkFJQWxGRFFBQ1FDQUNLQUljSWdCQkFuUkJuQnhxSWdFb0FnQWdBa1lFUUNBQklBUTJBZ0FnQkEwQlFmQVpJQXRCZmlBQWQzRTJBZ0FNQWdzZ0NVRVFRUlFnQ1NnQ0VDQUNSaHRxSUFRMkFnQWdCRVVOQVFzZ0JDQUpOZ0lZSUFJb0FoQWlBQVJBSUFRZ0FEWUNFQ0FBSUFRMkFoZ0xJQUlvQWhRaUFFVU5BQ0FFSUFBMkFoUWdBQ0FFTmdJWUN3SkFJQU5CRDAwRVFDQUNJQU1nQldvaUFFRURjallDQkNBQUlBSnFJZ0FnQUNnQ0JFRUJjallDQkF3QkN5QUNJQVZCQTNJMkFnUWdBaUFGYWlJRUlBTkJBWEkyQWdRZ0F5QUVhaUFETmdJQUlBY0VRQ0FIUVhoeFFaUWFhaUVBUVlBYUtBSUFJUUVDZjBFQklBZEJBM1owSWdVZ0JuRkZCRUJCN0JrZ0JTQUdjallDQUNBQURBRUxJQUFvQWdnTElRWWdBQ0FCTmdJSUlBWWdBVFlDRENBQklBQTJBZ3dnQVNBR05nSUlDMEdBR2lBRU5nSUFRZlFaSUFNMkFnQUxJQUpCQ0dvaEFBc2dDa0VRYWlRQUlBQUxDK2NSQWdCQmdBZ0wxaEYxYm5OcFoyNWxaQ0J6YUc5eWRBQjFibk5wWjI1bFpDQnBiblFBWm14dllYUUFkV2x1ZERZMFgzUUFkVzV6YVdkdVpXUWdZMmhoY2dCaWIyOXNBR1Z0YzJOeWFYQjBaVzQ2T25aaGJBQjFibk5wWjI1bFpDQnNiMjVuQUhOMFpEbzZkM04wY21sdVp3QnpkR1E2T25OMGNtbHVad0J6ZEdRNk9uVXhObk4wY21sdVp3QnpkR1E2T25Vek1uTjBjbWx1WndCa2IzVmliR1VBZG05cFpBQmxiWE5qY21sd2RHVnVPanB0WlcxdmNubGZkbWxsZHp4emFHOXlkRDRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhkVzV6YVdkdVpXUWdjMmh2Y25RK0FHVnRjMk55YVhCMFpXNDZPbTFsYlc5eWVWOTJhV1YzUEdsdWRENEFaVzF6WTNKcGNIUmxiam82YldWdGIzSjVYM1pwWlhjOGRXNXphV2R1WldRZ2FXNTBQZ0JsYlhOamNtbHdkR1Z1T2pwdFpXMXZjbmxmZG1sbGR6eG1iRzloZEQ0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4ZFdsdWREaGZkRDRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhhVzUwT0Y5MFBnQmxiWE5qY21sd2RHVnVPanB0WlcxdmNubGZkbWxsZHp4MWFXNTBNVFpmZEQ0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4YVc1ME1UWmZkRDRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhkV2x1ZERZMFgzUStBR1Z0YzJOeWFYQjBaVzQ2T20xbGJXOXllVjkyYVdWM1BHbHVkRFkwWDNRK0FHVnRjMk55YVhCMFpXNDZPbTFsYlc5eWVWOTJhV1YzUEhWcGJuUXpNbDkwUGdCbGJYTmpjbWx3ZEdWdU9qcHRaVzF2Y25sZmRtbGxkenhwYm5Rek1sOTBQZ0JsYlhOamNtbHdkR1Z1T2pwdFpXMXZjbmxmZG1sbGR6eGphR0Z5UGdCbGJYTmpjbWx3ZEdWdU9qcHRaVzF2Y25sZmRtbGxkengxYm5OcFoyNWxaQ0JqYUdGeVBnQnpkR1E2T21KaGMybGpYM04wY21sdVp6eDFibk5wWjI1bFpDQmphR0Z5UGdCbGJYTmpjbWx3ZEdWdU9qcHRaVzF2Y25sZmRtbGxkenh6YVdkdVpXUWdZMmhoY2o0QVpXMXpZM0pwY0hSbGJqbzZiV1Z0YjNKNVgzWnBaWGM4Ykc5dVp6NEFaVzF6WTNKcGNIUmxiam82YldWdGIzSjVYM1pwWlhjOGRXNXphV2R1WldRZ2JHOXVaejRBWlcxelkzSnBjSFJsYmpvNmJXVnRiM0o1WDNacFpYYzhaRzkxWW14bFBnQk9VM1F6WDE4eU1USmlZWE5wWTE5emRISnBibWRKWTA1VFh6RXhZMmhoY2w5MGNtRnBkSE5KWTBWRlRsTmZPV0ZzYkc5allYUnZja2xqUlVWRlJRQUFBQUJFREFBQVFnY0FBRTVUZEROZlh6SXhNbUpoYzJsalgzTjBjbWx1WjBsb1RsTmZNVEZqYUdGeVgzUnlZV2wwYzBsb1JVVk9VMTg1WVd4c2IyTmhkRzl5U1doRlJVVkZBQUJFREFBQWpBY0FBRTVUZEROZlh6SXhNbUpoYzJsalgzTjBjbWx1WjBsM1RsTmZNVEZqYUdGeVgzUnlZV2wwYzBsM1JVVk9VMTg1WVd4c2IyTmhkRzl5U1hkRlJVVkZBQUJFREFBQTFBY0FBRTVUZEROZlh6SXhNbUpoYzJsalgzTjBjbWx1WjBsRWMwNVRYekV4WTJoaGNsOTBjbUZwZEhOSlJITkZSVTVUWHpsaGJHeHZZMkYwYjNKSlJITkZSVVZGQUFBQVJBd0FBQndJQUFCT1UzUXpYMTh5TVRKaVlYTnBZMTl6ZEhKcGJtZEpSR2xPVTE4eE1XTm9ZWEpmZEhKaGFYUnpTVVJwUlVWT1UxODVZV3hzYjJOaGRHOXlTVVJwUlVWRlJRQUFBRVFNQUFCb0NBQUFUakV3WlcxelkzSnBjSFJsYmpOMllXeEZBQUJFREFBQXRBZ0FBRTR4TUdWdGMyTnlhWEIwWlc0eE1XMWxiVzl5ZVY5MmFXVjNTV05GUlFBQVJBd0FBTkFJQUFCT01UQmxiWE5qY21sd2RHVnVNVEZ0WlcxdmNubGZkbWxsZDBsaFJVVUFBRVFNQUFENENBQUFUakV3WlcxelkzSnBjSFJsYmpFeGJXVnRiM0o1WDNacFpYZEphRVZGQUFCRURBQUFJQWtBQUU0eE1HVnRjMk55YVhCMFpXNHhNVzFsYlc5eWVWOTJhV1YzU1hORlJRQUFSQXdBQUVnSkFBQk9NVEJsYlhOamNtbHdkR1Z1TVRGdFpXMXZjbmxmZG1sbGQwbDBSVVVBQUVRTUFBQndDUUFBVGpFd1pXMXpZM0pwY0hSbGJqRXhiV1Z0YjNKNVgzWnBaWGRKYVVWRkFBQkVEQUFBbUFrQUFFNHhNR1Z0YzJOeWFYQjBaVzR4TVcxbGJXOXllVjkyYVdWM1NXcEZSUUFBUkF3QUFNQUpBQUJPTVRCbGJYTmpjbWx3ZEdWdU1URnRaVzF2Y25sZmRtbGxkMGxzUlVVQUFFUU1BQURvQ1FBQVRqRXdaVzF6WTNKcGNIUmxiakV4YldWdGIzSjVYM1pwWlhkSmJVVkZBQUJFREFBQUVBb0FBRTR4TUdWdGMyTnlhWEIwWlc0eE1XMWxiVzl5ZVY5MmFXVjNTWGhGUlFBQVJBd0FBRGdLQUFCT01UQmxiWE5qY21sd2RHVnVNVEZ0WlcxdmNubGZkbWxsZDBsNVJVVUFBRVFNQUFCZ0NnQUFUakV3WlcxelkzSnBjSFJsYmpFeGJXVnRiM0o1WDNacFpYZEpaa1ZGQUFCRURBQUFpQW9BQUU0eE1HVnRjMk55YVhCMFpXNHhNVzFsYlc5eWVWOTJhV1YzU1dSRlJRQUFSQXdBQUxBS0FBQk9NVEJmWDJONGVHRmlhWFl4TVRaZlgzTm9hVzFmZEhsd1pWOXBibVp2UlFBQUFBQnNEQUFBMkFvQUFOQU1BQUJPTVRCZlgyTjRlR0ZpYVhZeE1UZGZYMk5zWVhOelgzUjVjR1ZmYVc1bWIwVUFBQUJzREFBQUNBc0FBUHdLQUFBQUFBQUFmQXNBQUFJQUFBQURBQUFBQkFBQUFBVUFBQUFHQUFBQVRqRXdYMTlqZUhoaFltbDJNVEl6WDE5bWRXNWtZVzFsYm5SaGJGOTBlWEJsWDJsdVptOUZBR3dNQUFCVUN3QUEvQW9BQUhZQUFBQkFDd0FBaUFzQUFHSUFBQUJBQ3dBQWxBc0FBR01BQUFCQUN3QUFvQXNBQUdnQUFBQkFDd0FBckFzQUFHRUFBQUJBQ3dBQXVBc0FBSE1BQUFCQUN3QUF4QXNBQUhRQUFBQkFDd0FBMEFzQUFHa0FBQUJBQ3dBQTNBc0FBR29BQUFCQUN3QUE2QXNBQUd3QUFBQkFDd0FBOUFzQUFHMEFBQUJBQ3dBQUFBd0FBSGdBQUFCQUN3QUFEQXdBQUhrQUFBQkFDd0FBR0F3QUFHWUFBQUJBQ3dBQUpBd0FBR1FBQUFCQUN3QUFNQXdBQUFBQUFBQXNDd0FBQWdBQUFBY0FBQUFFQUFBQUJRQUFBQWdBQUFBSkFBQUFDZ0FBQUFzQUFBQUFBQUFBdEF3QUFBSUFBQUFNQUFBQUJBQUFBQVVBQUFBSUFBQUFEUUFBQUE0QUFBQVBBQUFBVGpFd1gxOWplSGhoWW1sMk1USXdYMTl6YVY5amJHRnpjMTkwZVhCbFgybHVabTlGQUFBQUFHd01BQUNNREFBQUxBc0FBRk4wT1hSNWNHVmZhVzVtYndBQUFBQkVEQUFBd0F3QVFkZ1pDd1BnRGdFPSI7aWYoIWlzRGF0YVVSSSh3YXNtQmluYXJ5RmlsZSkpe3dhc21CaW5hcnlGaWxlPWxvY2F0ZUZpbGUod2FzbUJpbmFyeUZpbGUpO31mdW5jdGlvbiBnZXRCaW5hcnlTeW5jKGZpbGUpe2lmKGZpbGU9PXdhc21CaW5hcnlGaWxlJiZ3YXNtQmluYXJ5KXtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkod2FzbUJpbmFyeSl9dmFyIGJpbmFyeT10cnlQYXJzZUFzRGF0YVVSSShmaWxlKTtpZihiaW5hcnkpe3JldHVybiBiaW5hcnl9aWYocmVhZEJpbmFyeSl7cmV0dXJuIHJlYWRCaW5hcnkoZmlsZSl9dGhyb3cgImJvdGggYXN5bmMgYW5kIHN5bmMgZmV0Y2hpbmcgb2YgdGhlIHdhc20gZmFpbGVkIn1mdW5jdGlvbiBnZXRCaW5hcnlQcm9taXNlKGJpbmFyeUZpbGUpe3JldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpPT5nZXRCaW5hcnlTeW5jKGJpbmFyeUZpbGUpKX1mdW5jdGlvbiBpbnN0YW50aWF0ZUFycmF5QnVmZmVyKGJpbmFyeUZpbGUsaW1wb3J0cyxyZWNlaXZlcil7cmV0dXJuIGdldEJpbmFyeVByb21pc2UoYmluYXJ5RmlsZSkudGhlbihiaW5hcnk9PldlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGJpbmFyeSxpbXBvcnRzKSkudGhlbihpbnN0YW5jZT0+aW5zdGFuY2UpLnRoZW4ocmVjZWl2ZXIscmVhc29uPT57ZXJyKGBmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiAke3JlYXNvbn1gKTthYm9ydChyZWFzb24pO30pfWZ1bmN0aW9uIGluc3RhbnRpYXRlQXN5bmMoYmluYXJ5LGJpbmFyeUZpbGUsaW1wb3J0cyxjYWxsYmFjayl7cmV0dXJuIGluc3RhbnRpYXRlQXJyYXlCdWZmZXIoYmluYXJ5RmlsZSxpbXBvcnRzLGNhbGxiYWNrKX1mdW5jdGlvbiBjcmVhdGVXYXNtKCl7dmFyIGluZm89eyJhIjp3YXNtSW1wb3J0c307ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbmNlKGluc3RhbmNlLG1vZHVsZSl7d2FzbUV4cG9ydHM9aW5zdGFuY2UuZXhwb3J0czt3YXNtTWVtb3J5PXdhc21FeHBvcnRzWyJrIl07dXBkYXRlTWVtb3J5Vmlld3MoKTthZGRPbkluaXQod2FzbUV4cG9ydHNbImwiXSk7cmVtb3ZlUnVuRGVwZW5kZW5jeSgpO3JldHVybiB3YXNtRXhwb3J0c31hZGRSdW5EZXBlbmRlbmN5KCk7ZnVuY3Rpb24gcmVjZWl2ZUluc3RhbnRpYXRpb25SZXN1bHQocmVzdWx0KXtyZWNlaXZlSW5zdGFuY2UocmVzdWx0WyJpbnN0YW5jZSJdKTt9aWYoTW9kdWxlWyJpbnN0YW50aWF0ZVdhc20iXSl7dHJ5e3JldHVybiBNb2R1bGVbImluc3RhbnRpYXRlV2FzbSJdKGluZm8scmVjZWl2ZUluc3RhbmNlKX1jYXRjaChlKXtlcnIoYE1vZHVsZS5pbnN0YW50aWF0ZVdhc20gY2FsbGJhY2sgZmFpbGVkIHdpdGggZXJyb3I6ICR7ZX1gKTtyZWFkeVByb21pc2VSZWplY3QoZSk7fX1pbnN0YW50aWF0ZUFzeW5jKHdhc21CaW5hcnksd2FzbUJpbmFyeUZpbGUsaW5mbyxyZWNlaXZlSW5zdGFudGlhdGlvblJlc3VsdCkuY2F0Y2gocmVhZHlQcm9taXNlUmVqZWN0KTtyZXR1cm4ge319dmFyIGNhbGxSdW50aW1lQ2FsbGJhY2tzPWNhbGxiYWNrcz0+e3doaWxlKGNhbGxiYWNrcy5sZW5ndGg+MCl7Y2FsbGJhY2tzLnNoaWZ0KCkoTW9kdWxlKTt9fTtNb2R1bGVbIm5vRXhpdFJ1bnRpbWUiXXx8dHJ1ZTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfYmlnaW50PShwcmltaXRpdmVUeXBlLG5hbWUsc2l6ZSxtaW5SYW5nZSxtYXhSYW5nZSk9Pnt9O3ZhciBlbWJpbmRfaW5pdF9jaGFyQ29kZXM9KCk9Pnt2YXIgY29kZXM9bmV3IEFycmF5KDI1Nik7Zm9yKHZhciBpPTA7aTwyNTY7KytpKXtjb2Rlc1tpXT1TdHJpbmcuZnJvbUNoYXJDb2RlKGkpO31lbWJpbmRfY2hhckNvZGVzPWNvZGVzO307dmFyIGVtYmluZF9jaGFyQ29kZXM7dmFyIHJlYWRMYXRpbjFTdHJpbmc9cHRyPT57dmFyIHJldD0iIjt2YXIgYz1wdHI7d2hpbGUoSEVBUFU4W2NdKXtyZXQrPWVtYmluZF9jaGFyQ29kZXNbSEVBUFU4W2MrK11dO31yZXR1cm4gcmV0fTt2YXIgYXdhaXRpbmdEZXBlbmRlbmNpZXM9e307dmFyIHJlZ2lzdGVyZWRUeXBlcz17fTt2YXIgQmluZGluZ0Vycm9yO3ZhciB0aHJvd0JpbmRpbmdFcnJvcj1tZXNzYWdlPT57dGhyb3cgbmV3IEJpbmRpbmdFcnJvcihtZXNzYWdlKX07ZnVuY3Rpb24gc2hhcmVkUmVnaXN0ZXJUeXBlKHJhd1R5cGUscmVnaXN0ZXJlZEluc3RhbmNlLG9wdGlvbnM9e30pe3ZhciBuYW1lPXJlZ2lzdGVyZWRJbnN0YW5jZS5uYW1lO2lmKCFyYXdUeXBlKXt0aHJvd0JpbmRpbmdFcnJvcihgdHlwZSAiJHtuYW1lfSIgbXVzdCBoYXZlIGEgcG9zaXRpdmUgaW50ZWdlciB0eXBlaWQgcG9pbnRlcmApO31pZihyZWdpc3RlcmVkVHlwZXMuaGFzT3duUHJvcGVydHkocmF3VHlwZSkpe2lmKG9wdGlvbnMuaWdub3JlRHVwbGljYXRlUmVnaXN0cmF0aW9ucyl7cmV0dXJufWVsc2Uge3Rocm93QmluZGluZ0Vycm9yKGBDYW5ub3QgcmVnaXN0ZXIgdHlwZSAnJHtuYW1lfScgdHdpY2VgKTt9fXJlZ2lzdGVyZWRUeXBlc1tyYXdUeXBlXT1yZWdpc3RlcmVkSW5zdGFuY2U7aWYoYXdhaXRpbmdEZXBlbmRlbmNpZXMuaGFzT3duUHJvcGVydHkocmF3VHlwZSkpe3ZhciBjYWxsYmFja3M9YXdhaXRpbmdEZXBlbmRlbmNpZXNbcmF3VHlwZV07ZGVsZXRlIGF3YWl0aW5nRGVwZW5kZW5jaWVzW3Jhd1R5cGVdO2NhbGxiYWNrcy5mb3JFYWNoKGNiPT5jYigpKTt9fWZ1bmN0aW9uIHJlZ2lzdGVyVHlwZShyYXdUeXBlLHJlZ2lzdGVyZWRJbnN0YW5jZSxvcHRpb25zPXt9KXtpZighKCJhcmdQYWNrQWR2YW5jZSJpbiByZWdpc3RlcmVkSW5zdGFuY2UpKXt0aHJvdyBuZXcgVHlwZUVycm9yKCJyZWdpc3RlclR5cGUgcmVnaXN0ZXJlZEluc3RhbmNlIHJlcXVpcmVzIGFyZ1BhY2tBZHZhbmNlIil9cmV0dXJuIHNoYXJlZFJlZ2lzdGVyVHlwZShyYXdUeXBlLHJlZ2lzdGVyZWRJbnN0YW5jZSxvcHRpb25zKX12YXIgR2VuZXJpY1dpcmVUeXBlU2l6ZT04O3ZhciBfX2VtYmluZF9yZWdpc3Rlcl9ib29sPShyYXdUeXBlLG5hbWUsdHJ1ZVZhbHVlLGZhbHNlVmFsdWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSI6ZnVuY3Rpb24od3Qpe3JldHVybiAhIXd0fSwidG9XaXJlVHlwZSI6ZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsbyl7cmV0dXJuIG8/dHJ1ZVZhbHVlOmZhbHNlVmFsdWV9LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOmZ1bmN0aW9uKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQVThbcG9pbnRlcl0pfSxkZXN0cnVjdG9yRnVuY3Rpb246bnVsbH0pO307ZnVuY3Rpb24gaGFuZGxlQWxsb2NhdG9ySW5pdCgpe09iamVjdC5hc3NpZ24oSGFuZGxlQWxsb2NhdG9yLnByb3RvdHlwZSx7Z2V0KGlkKXtyZXR1cm4gdGhpcy5hbGxvY2F0ZWRbaWRdfSxoYXMoaWQpe3JldHVybiB0aGlzLmFsbG9jYXRlZFtpZF0hPT11bmRlZmluZWR9LGFsbG9jYXRlKGhhbmRsZSl7dmFyIGlkPXRoaXMuZnJlZWxpc3QucG9wKCl8fHRoaXMuYWxsb2NhdGVkLmxlbmd0aDt0aGlzLmFsbG9jYXRlZFtpZF09aGFuZGxlO3JldHVybiBpZH0sZnJlZShpZCl7dGhpcy5hbGxvY2F0ZWRbaWRdPXVuZGVmaW5lZDt0aGlzLmZyZWVsaXN0LnB1c2goaWQpO319KTt9ZnVuY3Rpb24gSGFuZGxlQWxsb2NhdG9yKCl7dGhpcy5hbGxvY2F0ZWQ9W3VuZGVmaW5lZF07dGhpcy5mcmVlbGlzdD1bXTt9dmFyIGVtdmFsX2hhbmRsZXM9bmV3IEhhbmRsZUFsbG9jYXRvcjt2YXIgX19lbXZhbF9kZWNyZWY9aGFuZGxlPT57aWYoaGFuZGxlPj1lbXZhbF9oYW5kbGVzLnJlc2VydmVkJiYwPT09LS1lbXZhbF9oYW5kbGVzLmdldChoYW5kbGUpLnJlZmNvdW50KXtlbXZhbF9oYW5kbGVzLmZyZWUoaGFuZGxlKTt9fTt2YXIgY291bnRfZW12YWxfaGFuZGxlcz0oKT0+e3ZhciBjb3VudD0wO2Zvcih2YXIgaT1lbXZhbF9oYW5kbGVzLnJlc2VydmVkO2k8ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQubGVuZ3RoOysraSl7aWYoZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWRbaV0hPT11bmRlZmluZWQpeysrY291bnQ7fX1yZXR1cm4gY291bnR9O3ZhciBpbml0X2VtdmFsPSgpPT57ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQucHVzaCh7dmFsdWU6dW5kZWZpbmVkfSx7dmFsdWU6bnVsbH0se3ZhbHVlOnRydWV9LHt2YWx1ZTpmYWxzZX0pO2VtdmFsX2hhbmRsZXMucmVzZXJ2ZWQ9ZW12YWxfaGFuZGxlcy5hbGxvY2F0ZWQubGVuZ3RoO01vZHVsZVsiY291bnRfZW12YWxfaGFuZGxlcyJdPWNvdW50X2VtdmFsX2hhbmRsZXM7fTt2YXIgRW12YWw9e3RvVmFsdWU6aGFuZGxlPT57aWYoIWhhbmRsZSl7dGhyb3dCaW5kaW5nRXJyb3IoIkNhbm5vdCB1c2UgZGVsZXRlZCB2YWwuIGhhbmRsZSA9ICIraGFuZGxlKTt9cmV0dXJuIGVtdmFsX2hhbmRsZXMuZ2V0KGhhbmRsZSkudmFsdWV9LHRvSGFuZGxlOnZhbHVlPT57c3dpdGNoKHZhbHVlKXtjYXNlIHVuZGVmaW5lZDpyZXR1cm4gMTtjYXNlIG51bGw6cmV0dXJuIDI7Y2FzZSB0cnVlOnJldHVybiAzO2Nhc2UgZmFsc2U6cmV0dXJuIDQ7ZGVmYXVsdDp7cmV0dXJuIGVtdmFsX2hhbmRsZXMuYWxsb2NhdGUoe3JlZmNvdW50OjEsdmFsdWU6dmFsdWV9KX19fX07ZnVuY3Rpb24gc2ltcGxlUmVhZFZhbHVlRnJvbVBvaW50ZXIocG9pbnRlcil7cmV0dXJuIHRoaXNbImZyb21XaXJlVHlwZSJdKEhFQVAzMltwb2ludGVyPj4yXSl9dmFyIF9fZW1iaW5kX3JlZ2lzdGVyX2VtdmFsPShyYXdUeXBlLG5hbWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSI6aGFuZGxlPT57dmFyIHJ2PUVtdmFsLnRvVmFsdWUoaGFuZGxlKTtfX2VtdmFsX2RlY3JlZihoYW5kbGUpO3JldHVybiBydn0sInRvV2lyZVR5cGUiOihkZXN0cnVjdG9ycyx2YWx1ZSk9PkVtdmFsLnRvSGFuZGxlKHZhbHVlKSwiYXJnUGFja0FkdmFuY2UiOkdlbmVyaWNXaXJlVHlwZVNpemUsInJlYWRWYWx1ZUZyb21Qb2ludGVyIjpzaW1wbGVSZWFkVmFsdWVGcm9tUG9pbnRlcixkZXN0cnVjdG9yRnVuY3Rpb246bnVsbH0pO307dmFyIGZsb2F0UmVhZFZhbHVlRnJvbVBvaW50ZXI9KG5hbWUsd2lkdGgpPT57c3dpdGNoKHdpZHRoKXtjYXNlIDQ6cmV0dXJuIGZ1bmN0aW9uKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQRjMyW3BvaW50ZXI+PjJdKX07Y2FzZSA4OnJldHVybiBmdW5jdGlvbihwb2ludGVyKXtyZXR1cm4gdGhpc1siZnJvbVdpcmVUeXBlIl0oSEVBUEY2NFtwb2ludGVyPj4zXSl9O2RlZmF1bHQ6dGhyb3cgbmV3IFR5cGVFcnJvcihgaW52YWxpZCBmbG9hdCB3aWR0aCAoJHt3aWR0aH0pOiAke25hbWV9YCl9fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfZmxvYXQ9KHJhd1R5cGUsbmFtZSxzaXplKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTtyZWdpc3RlclR5cGUocmF3VHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOnZhbHVlPT52YWx1ZSwidG9XaXJlVHlwZSI6KGRlc3RydWN0b3JzLHZhbHVlKT0+dmFsdWUsImFyZ1BhY2tBZHZhbmNlIjpHZW5lcmljV2lyZVR5cGVTaXplLCJyZWFkVmFsdWVGcm9tUG9pbnRlciI6ZmxvYXRSZWFkVmFsdWVGcm9tUG9pbnRlcihuYW1lLHNpemUpLGRlc3RydWN0b3JGdW5jdGlvbjpudWxsfSk7fTt2YXIgaW50ZWdlclJlYWRWYWx1ZUZyb21Qb2ludGVyPShuYW1lLHdpZHRoLHNpZ25lZCk9Pntzd2l0Y2god2lkdGgpe2Nhc2UgMTpyZXR1cm4gc2lnbmVkP3BvaW50ZXI9PkhFQVA4W3BvaW50ZXI+PjBdOnBvaW50ZXI9PkhFQVBVOFtwb2ludGVyPj4wXTtjYXNlIDI6cmV0dXJuIHNpZ25lZD9wb2ludGVyPT5IRUFQMTZbcG9pbnRlcj4+MV06cG9pbnRlcj0+SEVBUFUxNltwb2ludGVyPj4xXTtjYXNlIDQ6cmV0dXJuIHNpZ25lZD9wb2ludGVyPT5IRUFQMzJbcG9pbnRlcj4+Ml06cG9pbnRlcj0+SEVBUFUzMltwb2ludGVyPj4yXTtkZWZhdWx0OnRocm93IG5ldyBUeXBlRXJyb3IoYGludmFsaWQgaW50ZWdlciB3aWR0aCAoJHt3aWR0aH0pOiAke25hbWV9YCl9fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfaW50ZWdlcj0ocHJpbWl0aXZlVHlwZSxuYW1lLHNpemUsbWluUmFuZ2UsbWF4UmFuZ2UpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3ZhciBmcm9tV2lyZVR5cGU9dmFsdWU9PnZhbHVlO2lmKG1pblJhbmdlPT09MCl7dmFyIGJpdHNoaWZ0PTMyLTgqc2l6ZTtmcm9tV2lyZVR5cGU9dmFsdWU9PnZhbHVlPDxiaXRzaGlmdD4+PmJpdHNoaWZ0O312YXIgaXNVbnNpZ25lZFR5cGU9bmFtZS5pbmNsdWRlcygidW5zaWduZWQiKTt2YXIgY2hlY2tBc3NlcnRpb25zPSh2YWx1ZSx0b1R5cGVOYW1lKT0+e307dmFyIHRvV2lyZVR5cGU7aWYoaXNVbnNpZ25lZFR5cGUpe3RvV2lyZVR5cGU9ZnVuY3Rpb24oZGVzdHJ1Y3RvcnMsdmFsdWUpe2NoZWNrQXNzZXJ0aW9ucyh2YWx1ZSx0aGlzLm5hbWUpO3JldHVybiB2YWx1ZT4+PjB9O31lbHNlIHt0b1dpcmVUeXBlPWZ1bmN0aW9uKGRlc3RydWN0b3JzLHZhbHVlKXtjaGVja0Fzc2VydGlvbnModmFsdWUsdGhpcy5uYW1lKTtyZXR1cm4gdmFsdWV9O31yZWdpc3RlclR5cGUocHJpbWl0aXZlVHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOmZyb21XaXJlVHlwZSwidG9XaXJlVHlwZSI6dG9XaXJlVHlwZSwiYXJnUGFja0FkdmFuY2UiOkdlbmVyaWNXaXJlVHlwZVNpemUsInJlYWRWYWx1ZUZyb21Qb2ludGVyIjppbnRlZ2VyUmVhZFZhbHVlRnJvbVBvaW50ZXIobmFtZSxzaXplLG1pblJhbmdlIT09MCksZGVzdHJ1Y3RvckZ1bmN0aW9uOm51bGx9KTt9O3ZhciBfX2VtYmluZF9yZWdpc3Rlcl9tZW1vcnlfdmlldz0ocmF3VHlwZSxkYXRhVHlwZUluZGV4LG5hbWUpPT57dmFyIHR5cGVNYXBwaW5nPVtJbnQ4QXJyYXksVWludDhBcnJheSxJbnQxNkFycmF5LFVpbnQxNkFycmF5LEludDMyQXJyYXksVWludDMyQXJyYXksRmxvYXQzMkFycmF5LEZsb2F0NjRBcnJheV07dmFyIFRBPXR5cGVNYXBwaW5nW2RhdGFUeXBlSW5kZXhdO2Z1bmN0aW9uIGRlY29kZU1lbW9yeVZpZXcoaGFuZGxlKXt2YXIgc2l6ZT1IRUFQVTMyW2hhbmRsZT4+Ml07dmFyIGRhdGE9SEVBUFUzMltoYW5kbGUrND4+Ml07cmV0dXJuIG5ldyBUQShIRUFQOC5idWZmZXIsZGF0YSxzaXplKX1uYW1lPXJlYWRMYXRpbjFTdHJpbmcobmFtZSk7cmVnaXN0ZXJUeXBlKHJhd1R5cGUse25hbWU6bmFtZSwiZnJvbVdpcmVUeXBlIjpkZWNvZGVNZW1vcnlWaWV3LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOmRlY29kZU1lbW9yeVZpZXd9LHtpZ25vcmVEdXBsaWNhdGVSZWdpc3RyYXRpb25zOnRydWV9KTt9O2Z1bmN0aW9uIHJlYWRQb2ludGVyKHBvaW50ZXIpe3JldHVybiB0aGlzWyJmcm9tV2lyZVR5cGUiXShIRUFQVTMyW3BvaW50ZXI+PjJdKX12YXIgc3RyaW5nVG9VVEY4QXJyYXk9KHN0cixoZWFwLG91dElkeCxtYXhCeXRlc1RvV3JpdGUpPT57aWYoIShtYXhCeXRlc1RvV3JpdGU+MCkpcmV0dXJuIDA7dmFyIHN0YXJ0SWR4PW91dElkeDt2YXIgZW5kSWR4PW91dElkeCttYXhCeXRlc1RvV3JpdGUtMTtmb3IodmFyIGk9MDtpPHN0ci5sZW5ndGg7KytpKXt2YXIgdT1zdHIuY2hhckNvZGVBdChpKTtpZih1Pj01NTI5NiYmdTw9NTczNDMpe3ZhciB1MT1zdHIuY2hhckNvZGVBdCgrK2kpO3U9NjU1MzYrKCh1JjEwMjMpPDwxMCl8dTEmMTAyMzt9aWYodTw9MTI3KXtpZihvdXRJZHg+PWVuZElkeClicmVhaztoZWFwW291dElkeCsrXT11O31lbHNlIGlmKHU8PTIwNDcpe2lmKG91dElkeCsxPj1lbmRJZHgpYnJlYWs7aGVhcFtvdXRJZHgrK109MTkyfHU+PjY7aGVhcFtvdXRJZHgrK109MTI4fHUmNjM7fWVsc2UgaWYodTw9NjU1MzUpe2lmKG91dElkeCsyPj1lbmRJZHgpYnJlYWs7aGVhcFtvdXRJZHgrK109MjI0fHU+PjEyO2hlYXBbb3V0SWR4KytdPTEyOHx1Pj42JjYzO2hlYXBbb3V0SWR4KytdPTEyOHx1JjYzO31lbHNlIHtpZihvdXRJZHgrMz49ZW5kSWR4KWJyZWFrO2hlYXBbb3V0SWR4KytdPTI0MHx1Pj4xODtoZWFwW291dElkeCsrXT0xMjh8dT4+MTImNjM7aGVhcFtvdXRJZHgrK109MTI4fHU+PjYmNjM7aGVhcFtvdXRJZHgrK109MTI4fHUmNjM7fX1oZWFwW291dElkeF09MDtyZXR1cm4gb3V0SWR4LXN0YXJ0SWR4fTt2YXIgc3RyaW5nVG9VVEY4PShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PnN0cmluZ1RvVVRGOEFycmF5KHN0cixIRUFQVTgsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk7dmFyIGxlbmd0aEJ5dGVzVVRGOD1zdHI9Pnt2YXIgbGVuPTA7Zm9yKHZhciBpPTA7aTxzdHIubGVuZ3RoOysraSl7dmFyIGM9c3RyLmNoYXJDb2RlQXQoaSk7aWYoYzw9MTI3KXtsZW4rKzt9ZWxzZSBpZihjPD0yMDQ3KXtsZW4rPTI7fWVsc2UgaWYoYz49NTUyOTYmJmM8PTU3MzQzKXtsZW4rPTQ7KytpO31lbHNlIHtsZW4rPTM7fX1yZXR1cm4gbGVufTt2YXIgVVRGOERlY29kZXI9dHlwZW9mIFRleHREZWNvZGVyIT0idW5kZWZpbmVkIj9uZXcgVGV4dERlY29kZXIoInV0ZjgiKTp1bmRlZmluZWQ7dmFyIFVURjhBcnJheVRvU3RyaW5nPShoZWFwT3JBcnJheSxpZHgsbWF4Qnl0ZXNUb1JlYWQpPT57dmFyIGVuZElkeD1pZHgrbWF4Qnl0ZXNUb1JlYWQ7dmFyIGVuZFB0cj1pZHg7d2hpbGUoaGVhcE9yQXJyYXlbZW5kUHRyXSYmIShlbmRQdHI+PWVuZElkeCkpKytlbmRQdHI7aWYoZW5kUHRyLWlkeD4xNiYmaGVhcE9yQXJyYXkuYnVmZmVyJiZVVEY4RGVjb2Rlcil7cmV0dXJuIFVURjhEZWNvZGVyLmRlY29kZShoZWFwT3JBcnJheS5zdWJhcnJheShpZHgsZW5kUHRyKSl9dmFyIHN0cj0iIjt3aGlsZShpZHg8ZW5kUHRyKXt2YXIgdTA9aGVhcE9yQXJyYXlbaWR4KytdO2lmKCEodTAmMTI4KSl7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHUwKTtjb250aW51ZX12YXIgdTE9aGVhcE9yQXJyYXlbaWR4KytdJjYzO2lmKCh1MCYyMjQpPT0xOTIpe3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZSgodTAmMzEpPDw2fHUxKTtjb250aW51ZX12YXIgdTI9aGVhcE9yQXJyYXlbaWR4KytdJjYzO2lmKCh1MCYyNDApPT0yMjQpe3UwPSh1MCYxNSk8PDEyfHUxPDw2fHUyO31lbHNlIHt1MD0odTAmNyk8PDE4fHUxPDwxMnx1Mjw8NnxoZWFwT3JBcnJheVtpZHgrK10mNjM7fWlmKHUwPDY1NTM2KXtzdHIrPVN0cmluZy5mcm9tQ2hhckNvZGUodTApO31lbHNlIHt2YXIgY2g9dTAtNjU1MzY7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGNoPj4xMCw1NjMyMHxjaCYxMDIzKTt9fXJldHVybiBzdHJ9O3ZhciBVVEY4VG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9PnB0cj9VVEY4QXJyYXlUb1N0cmluZyhIRUFQVTgscHRyLG1heEJ5dGVzVG9SZWFkKToiIjt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZz0ocmF3VHlwZSxuYW1lKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTt2YXIgc3RkU3RyaW5nSXNVVEY4PW5hbWU9PT0ic3RkOjpzdHJpbmciO3JlZ2lzdGVyVHlwZShyYXdUeXBlLHtuYW1lOm5hbWUsImZyb21XaXJlVHlwZSIodmFsdWUpe3ZhciBsZW5ndGg9SEVBUFUzMlt2YWx1ZT4+Ml07dmFyIHBheWxvYWQ9dmFsdWUrNDt2YXIgc3RyO2lmKHN0ZFN0cmluZ0lzVVRGOCl7dmFyIGRlY29kZVN0YXJ0UHRyPXBheWxvYWQ7Zm9yKHZhciBpPTA7aTw9bGVuZ3RoOysraSl7dmFyIGN1cnJlbnRCeXRlUHRyPXBheWxvYWQraTtpZihpPT1sZW5ndGh8fEhFQVBVOFtjdXJyZW50Qnl0ZVB0cl09PTApe3ZhciBtYXhSZWFkPWN1cnJlbnRCeXRlUHRyLWRlY29kZVN0YXJ0UHRyO3ZhciBzdHJpbmdTZWdtZW50PVVURjhUb1N0cmluZyhkZWNvZGVTdGFydFB0cixtYXhSZWFkKTtpZihzdHI9PT11bmRlZmluZWQpe3N0cj1zdHJpbmdTZWdtZW50O31lbHNlIHtzdHIrPVN0cmluZy5mcm9tQ2hhckNvZGUoMCk7c3RyKz1zdHJpbmdTZWdtZW50O31kZWNvZGVTdGFydFB0cj1jdXJyZW50Qnl0ZVB0cisxO319fWVsc2Uge3ZhciBhPW5ldyBBcnJheShsZW5ndGgpO2Zvcih2YXIgaT0wO2k8bGVuZ3RoOysraSl7YVtpXT1TdHJpbmcuZnJvbUNoYXJDb2RlKEhFQVBVOFtwYXlsb2FkK2ldKTt9c3RyPWEuam9pbigiIik7fV9mcmVlKHZhbHVlKTtyZXR1cm4gc3RyfSwidG9XaXJlVHlwZSIoZGVzdHJ1Y3RvcnMsdmFsdWUpe2lmKHZhbHVlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpe3ZhbHVlPW5ldyBVaW50OEFycmF5KHZhbHVlKTt9dmFyIGxlbmd0aDt2YXIgdmFsdWVJc09mVHlwZVN0cmluZz10eXBlb2YgdmFsdWU9PSJzdHJpbmciO2lmKCEodmFsdWVJc09mVHlwZVN0cmluZ3x8dmFsdWUgaW5zdGFuY2VvZiBVaW50OEFycmF5fHx2YWx1ZSBpbnN0YW5jZW9mIFVpbnQ4Q2xhbXBlZEFycmF5fHx2YWx1ZSBpbnN0YW5jZW9mIEludDhBcnJheSkpe3Rocm93QmluZGluZ0Vycm9yKCJDYW5ub3QgcGFzcyBub24tc3RyaW5nIHRvIHN0ZDo6c3RyaW5nIik7fWlmKHN0ZFN0cmluZ0lzVVRGOCYmdmFsdWVJc09mVHlwZVN0cmluZyl7bGVuZ3RoPWxlbmd0aEJ5dGVzVVRGOCh2YWx1ZSk7fWVsc2Uge2xlbmd0aD12YWx1ZS5sZW5ndGg7fXZhciBiYXNlPV9tYWxsb2MoNCtsZW5ndGgrMSk7dmFyIHB0cj1iYXNlKzQ7SEVBUFUzMltiYXNlPj4yXT1sZW5ndGg7aWYoc3RkU3RyaW5nSXNVVEY4JiZ2YWx1ZUlzT2ZUeXBlU3RyaW5nKXtzdHJpbmdUb1VURjgodmFsdWUscHRyLGxlbmd0aCsxKTt9ZWxzZSB7aWYodmFsdWVJc09mVHlwZVN0cmluZyl7Zm9yKHZhciBpPTA7aTxsZW5ndGg7KytpKXt2YXIgY2hhckNvZGU9dmFsdWUuY2hhckNvZGVBdChpKTtpZihjaGFyQ29kZT4yNTUpe19mcmVlKHB0cik7dGhyb3dCaW5kaW5nRXJyb3IoIlN0cmluZyBoYXMgVVRGLTE2IGNvZGUgdW5pdHMgdGhhdCBkbyBub3QgZml0IGluIDggYml0cyIpO31IRUFQVThbcHRyK2ldPWNoYXJDb2RlO319ZWxzZSB7Zm9yKHZhciBpPTA7aTxsZW5ndGg7KytpKXtIRUFQVThbcHRyK2ldPXZhbHVlW2ldO319fWlmKGRlc3RydWN0b3JzIT09bnVsbCl7ZGVzdHJ1Y3RvcnMucHVzaChfZnJlZSxiYXNlKTt9cmV0dXJuIGJhc2V9LCJhcmdQYWNrQWR2YW5jZSI6R2VuZXJpY1dpcmVUeXBlU2l6ZSwicmVhZFZhbHVlRnJvbVBvaW50ZXIiOnJlYWRQb2ludGVyLGRlc3RydWN0b3JGdW5jdGlvbihwdHIpe19mcmVlKHB0cik7fX0pO307dmFyIFVURjE2RGVjb2Rlcj10eXBlb2YgVGV4dERlY29kZXIhPSJ1bmRlZmluZWQiP25ldyBUZXh0RGVjb2RlcigidXRmLTE2bGUiKTp1bmRlZmluZWQ7dmFyIFVURjE2VG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9Pnt2YXIgZW5kUHRyPXB0cjt2YXIgaWR4PWVuZFB0cj4+MTt2YXIgbWF4SWR4PWlkeCttYXhCeXRlc1RvUmVhZC8yO3doaWxlKCEoaWR4Pj1tYXhJZHgpJiZIRUFQVTE2W2lkeF0pKytpZHg7ZW5kUHRyPWlkeDw8MTtpZihlbmRQdHItcHRyPjMyJiZVVEYxNkRlY29kZXIpcmV0dXJuIFVURjE2RGVjb2Rlci5kZWNvZGUoSEVBUFU4LnN1YmFycmF5KHB0cixlbmRQdHIpKTt2YXIgc3RyPSIiO2Zvcih2YXIgaT0wOyEoaT49bWF4Qnl0ZXNUb1JlYWQvMik7KytpKXt2YXIgY29kZVVuaXQ9SEVBUDE2W3B0citpKjI+PjFdO2lmKGNvZGVVbml0PT0wKWJyZWFrO3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZShjb2RlVW5pdCk7fXJldHVybiBzdHJ9O3ZhciBzdHJpbmdUb1VURjE2PShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PntpZihtYXhCeXRlc1RvV3JpdGU9PT11bmRlZmluZWQpe21heEJ5dGVzVG9Xcml0ZT0yMTQ3NDgzNjQ3O31pZihtYXhCeXRlc1RvV3JpdGU8MilyZXR1cm4gMDttYXhCeXRlc1RvV3JpdGUtPTI7dmFyIHN0YXJ0UHRyPW91dFB0cjt2YXIgbnVtQ2hhcnNUb1dyaXRlPW1heEJ5dGVzVG9Xcml0ZTxzdHIubGVuZ3RoKjI/bWF4Qnl0ZXNUb1dyaXRlLzI6c3RyLmxlbmd0aDtmb3IodmFyIGk9MDtpPG51bUNoYXJzVG9Xcml0ZTsrK2kpe3ZhciBjb2RlVW5pdD1zdHIuY2hhckNvZGVBdChpKTtIRUFQMTZbb3V0UHRyPj4xXT1jb2RlVW5pdDtvdXRQdHIrPTI7fUhFQVAxNltvdXRQdHI+PjFdPTA7cmV0dXJuIG91dFB0ci1zdGFydFB0cn07dmFyIGxlbmd0aEJ5dGVzVVRGMTY9c3RyPT5zdHIubGVuZ3RoKjI7dmFyIFVURjMyVG9TdHJpbmc9KHB0cixtYXhCeXRlc1RvUmVhZCk9Pnt2YXIgaT0wO3ZhciBzdHI9IiI7d2hpbGUoIShpPj1tYXhCeXRlc1RvUmVhZC80KSl7dmFyIHV0ZjMyPUhFQVAzMltwdHIraSo0Pj4yXTtpZih1dGYzMj09MClicmVhazsrK2k7aWYodXRmMzI+PTY1NTM2KXt2YXIgY2g9dXRmMzItNjU1MzY7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGNoPj4xMCw1NjMyMHxjaCYxMDIzKTt9ZWxzZSB7c3RyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHV0ZjMyKTt9fXJldHVybiBzdHJ9O3ZhciBzdHJpbmdUb1VURjMyPShzdHIsb3V0UHRyLG1heEJ5dGVzVG9Xcml0ZSk9PntpZihtYXhCeXRlc1RvV3JpdGU9PT11bmRlZmluZWQpe21heEJ5dGVzVG9Xcml0ZT0yMTQ3NDgzNjQ3O31pZihtYXhCeXRlc1RvV3JpdGU8NClyZXR1cm4gMDt2YXIgc3RhcnRQdHI9b3V0UHRyO3ZhciBlbmRQdHI9c3RhcnRQdHIrbWF4Qnl0ZXNUb1dyaXRlLTQ7Zm9yKHZhciBpPTA7aTxzdHIubGVuZ3RoOysraSl7dmFyIGNvZGVVbml0PXN0ci5jaGFyQ29kZUF0KGkpO2lmKGNvZGVVbml0Pj01NTI5NiYmY29kZVVuaXQ8PTU3MzQzKXt2YXIgdHJhaWxTdXJyb2dhdGU9c3RyLmNoYXJDb2RlQXQoKytpKTtjb2RlVW5pdD02NTUzNisoKGNvZGVVbml0JjEwMjMpPDwxMCl8dHJhaWxTdXJyb2dhdGUmMTAyMzt9SEVBUDMyW291dFB0cj4+Ml09Y29kZVVuaXQ7b3V0UHRyKz00O2lmKG91dFB0cis0PmVuZFB0cilicmVha31IRUFQMzJbb3V0UHRyPj4yXT0wO3JldHVybiBvdXRQdHItc3RhcnRQdHJ9O3ZhciBsZW5ndGhCeXRlc1VURjMyPXN0cj0+e3ZhciBsZW49MDtmb3IodmFyIGk9MDtpPHN0ci5sZW5ndGg7KytpKXt2YXIgY29kZVVuaXQ9c3RyLmNoYXJDb2RlQXQoaSk7aWYoY29kZVVuaXQ+PTU1Mjk2JiZjb2RlVW5pdDw9NTczNDMpKytpO2xlbis9NDt9cmV0dXJuIGxlbn07dmFyIF9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nPShyYXdUeXBlLGNoYXJTaXplLG5hbWUpPT57bmFtZT1yZWFkTGF0aW4xU3RyaW5nKG5hbWUpO3ZhciBkZWNvZGVTdHJpbmcsZW5jb2RlU3RyaW5nLGdldEhlYXAsbGVuZ3RoQnl0ZXNVVEYsc2hpZnQ7aWYoY2hhclNpemU9PT0yKXtkZWNvZGVTdHJpbmc9VVRGMTZUb1N0cmluZztlbmNvZGVTdHJpbmc9c3RyaW5nVG9VVEYxNjtsZW5ndGhCeXRlc1VURj1sZW5ndGhCeXRlc1VURjE2O2dldEhlYXA9KCk9PkhFQVBVMTY7c2hpZnQ9MTt9ZWxzZSBpZihjaGFyU2l6ZT09PTQpe2RlY29kZVN0cmluZz1VVEYzMlRvU3RyaW5nO2VuY29kZVN0cmluZz1zdHJpbmdUb1VURjMyO2xlbmd0aEJ5dGVzVVRGPWxlbmd0aEJ5dGVzVVRGMzI7Z2V0SGVhcD0oKT0+SEVBUFUzMjtzaGlmdD0yO31yZWdpc3RlclR5cGUocmF3VHlwZSx7bmFtZTpuYW1lLCJmcm9tV2lyZVR5cGUiOnZhbHVlPT57dmFyIGxlbmd0aD1IRUFQVTMyW3ZhbHVlPj4yXTt2YXIgSEVBUD1nZXRIZWFwKCk7dmFyIHN0cjt2YXIgZGVjb2RlU3RhcnRQdHI9dmFsdWUrNDtmb3IodmFyIGk9MDtpPD1sZW5ndGg7KytpKXt2YXIgY3VycmVudEJ5dGVQdHI9dmFsdWUrNCtpKmNoYXJTaXplO2lmKGk9PWxlbmd0aHx8SEVBUFtjdXJyZW50Qnl0ZVB0cj4+c2hpZnRdPT0wKXt2YXIgbWF4UmVhZEJ5dGVzPWN1cnJlbnRCeXRlUHRyLWRlY29kZVN0YXJ0UHRyO3ZhciBzdHJpbmdTZWdtZW50PWRlY29kZVN0cmluZyhkZWNvZGVTdGFydFB0cixtYXhSZWFkQnl0ZXMpO2lmKHN0cj09PXVuZGVmaW5lZCl7c3RyPXN0cmluZ1NlZ21lbnQ7fWVsc2Uge3N0cis9U3RyaW5nLmZyb21DaGFyQ29kZSgwKTtzdHIrPXN0cmluZ1NlZ21lbnQ7fWRlY29kZVN0YXJ0UHRyPWN1cnJlbnRCeXRlUHRyK2NoYXJTaXplO319X2ZyZWUodmFsdWUpO3JldHVybiBzdHJ9LCJ0b1dpcmVUeXBlIjooZGVzdHJ1Y3RvcnMsdmFsdWUpPT57aWYoISh0eXBlb2YgdmFsdWU9PSJzdHJpbmciKSl7dGhyb3dCaW5kaW5nRXJyb3IoYENhbm5vdCBwYXNzIG5vbi1zdHJpbmcgdG8gQysrIHN0cmluZyB0eXBlICR7bmFtZX1gKTt9dmFyIGxlbmd0aD1sZW5ndGhCeXRlc1VURih2YWx1ZSk7dmFyIHB0cj1fbWFsbG9jKDQrbGVuZ3RoK2NoYXJTaXplKTtIRUFQVTMyW3B0cj4+Ml09bGVuZ3RoPj5zaGlmdDtlbmNvZGVTdHJpbmcodmFsdWUscHRyKzQsbGVuZ3RoK2NoYXJTaXplKTtpZihkZXN0cnVjdG9ycyE9PW51bGwpe2Rlc3RydWN0b3JzLnB1c2goX2ZyZWUscHRyKTt9cmV0dXJuIHB0cn0sImFyZ1BhY2tBZHZhbmNlIjpHZW5lcmljV2lyZVR5cGVTaXplLCJyZWFkVmFsdWVGcm9tUG9pbnRlciI6c2ltcGxlUmVhZFZhbHVlRnJvbVBvaW50ZXIsZGVzdHJ1Y3RvckZ1bmN0aW9uKHB0cil7X2ZyZWUocHRyKTt9fSk7fTt2YXIgX19lbWJpbmRfcmVnaXN0ZXJfdm9pZD0ocmF3VHlwZSxuYW1lKT0+e25hbWU9cmVhZExhdGluMVN0cmluZyhuYW1lKTtyZWdpc3RlclR5cGUocmF3VHlwZSx7aXNWb2lkOnRydWUsbmFtZTpuYW1lLCJhcmdQYWNrQWR2YW5jZSI6MCwiZnJvbVdpcmVUeXBlIjooKT0+dW5kZWZpbmVkLCJ0b1dpcmVUeXBlIjooZGVzdHJ1Y3RvcnMsbyk9PnVuZGVmaW5lZH0pO307dmFyIGdldEhlYXBNYXg9KCk9PjIxNDc0ODM2NDg7dmFyIGdyb3dNZW1vcnk9c2l6ZT0+e3ZhciBiPXdhc21NZW1vcnkuYnVmZmVyO3ZhciBwYWdlcz0oc2l6ZS1iLmJ5dGVMZW5ndGgrNjU1MzUpLzY1NTM2O3RyeXt3YXNtTWVtb3J5Lmdyb3cocGFnZXMpO3VwZGF0ZU1lbW9yeVZpZXdzKCk7cmV0dXJuIDF9Y2F0Y2goZSl7fX07dmFyIF9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwPXJlcXVlc3RlZFNpemU9Pnt2YXIgb2xkU2l6ZT1IRUFQVTgubGVuZ3RoO3JlcXVlc3RlZFNpemU+Pj49MDt2YXIgbWF4SGVhcFNpemU9Z2V0SGVhcE1heCgpO2lmKHJlcXVlc3RlZFNpemU+bWF4SGVhcFNpemUpe3JldHVybiBmYWxzZX12YXIgYWxpZ25VcD0oeCxtdWx0aXBsZSk9PngrKG11bHRpcGxlLXglbXVsdGlwbGUpJW11bHRpcGxlO2Zvcih2YXIgY3V0RG93bj0xO2N1dERvd248PTQ7Y3V0RG93bio9Mil7dmFyIG92ZXJHcm93bkhlYXBTaXplPW9sZFNpemUqKDErLjIvY3V0RG93bik7b3Zlckdyb3duSGVhcFNpemU9TWF0aC5taW4ob3Zlckdyb3duSGVhcFNpemUscmVxdWVzdGVkU2l6ZSsxMDA2NjMyOTYpO3ZhciBuZXdTaXplPU1hdGgubWluKG1heEhlYXBTaXplLGFsaWduVXAoTWF0aC5tYXgocmVxdWVzdGVkU2l6ZSxvdmVyR3Jvd25IZWFwU2l6ZSksNjU1MzYpKTt2YXIgcmVwbGFjZW1lbnQ9Z3Jvd01lbW9yeShuZXdTaXplKTtpZihyZXBsYWNlbWVudCl7cmV0dXJuIHRydWV9fXJldHVybiBmYWxzZX07ZW1iaW5kX2luaXRfY2hhckNvZGVzKCk7QmluZGluZ0Vycm9yPU1vZHVsZVsiQmluZGluZ0Vycm9yIl09Y2xhc3MgQmluZGluZ0Vycm9yIGV4dGVuZHMgRXJyb3J7Y29uc3RydWN0b3IobWVzc2FnZSl7c3VwZXIobWVzc2FnZSk7dGhpcy5uYW1lPSJCaW5kaW5nRXJyb3IiO319O01vZHVsZVsiSW50ZXJuYWxFcnJvciJdPWNsYXNzIEludGVybmFsRXJyb3IgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3RvcihtZXNzYWdlKXtzdXBlcihtZXNzYWdlKTt0aGlzLm5hbWU9IkludGVybmFsRXJyb3IiO319O2hhbmRsZUFsbG9jYXRvckluaXQoKTtpbml0X2VtdmFsKCk7dmFyIHdhc21JbXBvcnRzPXtmOl9fZW1iaW5kX3JlZ2lzdGVyX2JpZ2ludCxpOl9fZW1iaW5kX3JlZ2lzdGVyX2Jvb2wsaDpfX2VtYmluZF9yZWdpc3Rlcl9lbXZhbCxlOl9fZW1iaW5kX3JlZ2lzdGVyX2Zsb2F0LGI6X19lbWJpbmRfcmVnaXN0ZXJfaW50ZWdlcixhOl9fZW1iaW5kX3JlZ2lzdGVyX21lbW9yeV92aWV3LGQ6X19lbWJpbmRfcmVnaXN0ZXJfc3RkX3N0cmluZyxjOl9fZW1iaW5kX3JlZ2lzdGVyX3N0ZF93c3RyaW5nLGo6X19lbWJpbmRfcmVnaXN0ZXJfdm9pZCxnOl9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwfTt2YXIgd2FzbUV4cG9ydHM9Y3JlYXRlV2FzbSgpO01vZHVsZVsiX3BhY2siXT0oYTAsYTEsYTIsYTMsYTQsYTUsYTYsYTcsYTgsYTksYTEwKT0+KE1vZHVsZVsiX3BhY2siXT13YXNtRXhwb3J0c1sibSJdKShhMCxhMSxhMixhMyxhNCxhNSxhNixhNyxhOCxhOSxhMTApO01vZHVsZVsiX19lbWJpbmRfaW5pdGlhbGl6ZV9iaW5kaW5ncyJdPSgpPT4oTW9kdWxlWyJfX2VtYmluZF9pbml0aWFsaXplX2JpbmRpbmdzIl09d2FzbUV4cG9ydHNbIm4iXSkoKTt2YXIgX21hbGxvYz1Nb2R1bGVbIl9tYWxsb2MiXT1hMD0+KF9tYWxsb2M9TW9kdWxlWyJfbWFsbG9jIl09d2FzbUV4cG9ydHNbInAiXSkoYTApO3ZhciBfZnJlZT1Nb2R1bGVbIl9mcmVlIl09YTA9PihfZnJlZT1Nb2R1bGVbIl9mcmVlIl09d2FzbUV4cG9ydHNbInEiXSkoYTApO2Z1bmN0aW9uIGludEFycmF5RnJvbUJhc2U2NChzKXt2YXIgZGVjb2RlZD1hdG9iKHMpO3ZhciBieXRlcz1uZXcgVWludDhBcnJheShkZWNvZGVkLmxlbmd0aCk7Zm9yKHZhciBpPTA7aTxkZWNvZGVkLmxlbmd0aDsrK2kpe2J5dGVzW2ldPWRlY29kZWQuY2hhckNvZGVBdChpKTt9cmV0dXJuIGJ5dGVzfWZ1bmN0aW9uIHRyeVBhcnNlQXNEYXRhVVJJKGZpbGVuYW1lKXtpZighaXNEYXRhVVJJKGZpbGVuYW1lKSl7cmV0dXJufXJldHVybiBpbnRBcnJheUZyb21CYXNlNjQoZmlsZW5hbWUuc2xpY2UoZGF0YVVSSVByZWZpeC5sZW5ndGgpKX12YXIgY2FsbGVkUnVuO2RlcGVuZGVuY2llc0Z1bGZpbGxlZD1mdW5jdGlvbiBydW5DYWxsZXIoKXtpZighY2FsbGVkUnVuKXJ1bigpO2lmKCFjYWxsZWRSdW4pZGVwZW5kZW5jaWVzRnVsZmlsbGVkPXJ1bkNhbGxlcjt9O2Z1bmN0aW9uIHJ1bigpe2lmKHJ1bkRlcGVuZGVuY2llcz4wKXtyZXR1cm59cHJlUnVuKCk7aWYocnVuRGVwZW5kZW5jaWVzPjApe3JldHVybn1mdW5jdGlvbiBkb1J1bigpe2lmKGNhbGxlZFJ1bilyZXR1cm47Y2FsbGVkUnVuPXRydWU7TW9kdWxlWyJjYWxsZWRSdW4iXT10cnVlO2lmKEFCT1JUKXJldHVybjtpbml0UnVudGltZSgpO3JlYWR5UHJvbWlzZVJlc29sdmUoTW9kdWxlKTtpZihNb2R1bGVbIm9uUnVudGltZUluaXRpYWxpemVkIl0pTW9kdWxlWyJvblJ1bnRpbWVJbml0aWFsaXplZCJdKCk7cG9zdFJ1bigpO31pZihNb2R1bGVbInNldFN0YXR1cyJdKXtNb2R1bGVbInNldFN0YXR1cyJdKCJSdW5uaW5nLi4uIik7c2V0VGltZW91dChmdW5jdGlvbigpe3NldFRpbWVvdXQoZnVuY3Rpb24oKXtNb2R1bGVbInNldFN0YXR1cyJdKCIiKTt9LDEpO2RvUnVuKCk7fSwxKTt9ZWxzZSB7ZG9SdW4oKTt9fWlmKE1vZHVsZVsicHJlSW5pdCJdKXtpZih0eXBlb2YgTW9kdWxlWyJwcmVJbml0Il09PSJmdW5jdGlvbiIpTW9kdWxlWyJwcmVJbml0Il09W01vZHVsZVsicHJlSW5pdCJdXTt3aGlsZShNb2R1bGVbInByZUluaXQiXS5sZW5ndGg+MCl7TW9kdWxlWyJwcmVJbml0Il0ucG9wKCkoKTt9fXJ1bigpOwoKCiAgICByZXR1cm4gbW9kdWxlQXJnLnJlYWR5CiAgfQoKICApOwogIH0pKCk7CgogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55CiAgbGV0IHdhc21Nb2R1bGU7CiAgYXN5bmMgZnVuY3Rpb24gaW5pdFdhc20oKSB7CiAgICAgIHdhc21Nb2R1bGUgPSBhd2FpdCBsb2FkV2FzbSgpOwogIH0KICBsZXQgYWxsb2NhdGVkVmVydGV4Q291bnQgPSAwOwogIGNvbnN0IHVwZGF0ZVF1ZXVlID0gbmV3IEFycmF5KCk7CiAgbGV0IHJ1bm5pbmcgPSBmYWxzZTsKICBsZXQgbG9hZGluZyA9IGZhbHNlOwogIGxldCBwb3NpdGlvbnNQdHI7CiAgbGV0IHJvdGF0aW9uc1B0cjsKICBsZXQgc2NhbGVzUHRyOwogIGxldCBjb2xvcnNQdHI7CiAgbGV0IHNlbGVjdGlvblB0cjsKICBsZXQgZGF0YVB0cjsKICBsZXQgd29ybGRQb3NpdGlvbnNQdHI7CiAgbGV0IHdvcmxkUm90YXRpb25zUHRyOwogIGxldCB3b3JsZFNjYWxlc1B0cjsKICBjb25zdCBwYWNrID0gYXN5bmMgKHNwbGF0KSA9PiB7CiAgICAgIHdoaWxlIChsb2FkaW5nKSB7CiAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAwKSk7CiAgICAgIH0KICAgICAgaWYgKCF3YXNtTW9kdWxlKSB7CiAgICAgICAgICBsb2FkaW5nID0gdHJ1ZTsKICAgICAgICAgIGF3YWl0IGluaXRXYXNtKCk7CiAgICAgICAgICBsb2FkaW5nID0gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgdGFyZ2V0QWxsb2NhdGVkVmVydGV4Q291bnQgPSBNYXRoLnBvdygyLCBNYXRoLmNlaWwoTWF0aC5sb2cyKHNwbGF0LnZlcnRleENvdW50KSkpOwogICAgICBpZiAodGFyZ2V0QWxsb2NhdGVkVmVydGV4Q291bnQgPiBhbGxvY2F0ZWRWZXJ0ZXhDb3VudCkgewogICAgICAgICAgaWYgKGFsbG9jYXRlZFZlcnRleENvdW50ID4gMCkgewogICAgICAgICAgICAgIHdhc21Nb2R1bGUuX2ZyZWUocG9zaXRpb25zUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHJvdGF0aW9uc1B0cik7CiAgICAgICAgICAgICAgd2FzbU1vZHVsZS5fZnJlZShzY2FsZXNQdHIpOwogICAgICAgICAgICAgIHdhc21Nb2R1bGUuX2ZyZWUoY29sb3JzUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHNlbGVjdGlvblB0cik7CiAgICAgICAgICAgICAgd2FzbU1vZHVsZS5fZnJlZShkYXRhUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHdvcmxkUG9zaXRpb25zUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHdvcmxkUm90YXRpb25zUHRyKTsKICAgICAgICAgICAgICB3YXNtTW9kdWxlLl9mcmVlKHdvcmxkU2NhbGVzUHRyKTsKICAgICAgICAgIH0KICAgICAgICAgIGFsbG9jYXRlZFZlcnRleENvdW50ID0gdGFyZ2V0QWxsb2NhdGVkVmVydGV4Q291bnQ7CiAgICAgICAgICBwb3NpdGlvbnNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoMyAqIGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICByb3RhdGlvbnNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoNCAqIGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICBzY2FsZXNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoMyAqIGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICBjb2xvcnNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoNCAqIGFsbG9jYXRlZFZlcnRleENvdW50KTsKICAgICAgICAgIHNlbGVjdGlvblB0ciA9IHdhc21Nb2R1bGUuX21hbGxvYyhhbGxvY2F0ZWRWZXJ0ZXhDb3VudCk7CiAgICAgICAgICBkYXRhUHRyID0gd2FzbU1vZHVsZS5fbWFsbG9jKDggKiBhbGxvY2F0ZWRWZXJ0ZXhDb3VudCAqIDQpOwogICAgICAgICAgd29ybGRQb3NpdGlvbnNQdHIgPSB3YXNtTW9kdWxlLl9tYWxsb2MoMyAqIGFsbG9jYXRlZFZlcnRleENvdW50ICogNCk7CiAgICAgICAgICB3b3JsZFJvdGF0aW9uc1B0ciA9IHdhc21Nb2R1bGUuX21hbGxvYyg0ICogYWxsb2NhdGVkVmVydGV4Q291bnQgKiA0KTsKICAgICAgICAgIHdvcmxkU2NhbGVzUHRyID0gd2FzbU1vZHVsZS5fbWFsbG9jKDMgKiBhbGxvY2F0ZWRWZXJ0ZXhDb3VudCAqIDQpOwogICAgICB9CiAgICAgIHdhc21Nb2R1bGUuSEVBUEYzMi5zZXQoc3BsYXQucG9zaXRpb25zLCBwb3NpdGlvbnNQdHIgLyA0KTsKICAgICAgd2FzbU1vZHVsZS5IRUFQRjMyLnNldChzcGxhdC5yb3RhdGlvbnMsIHJvdGF0aW9uc1B0ciAvIDQpOwogICAgICB3YXNtTW9kdWxlLkhFQVBGMzIuc2V0KHNwbGF0LnNjYWxlcywgc2NhbGVzUHRyIC8gNCk7CiAgICAgIHdhc21Nb2R1bGUuSEVBUFU4LnNldChzcGxhdC5jb2xvcnMsIGNvbG9yc1B0cik7CiAgICAgIHdhc21Nb2R1bGUuSEVBUFU4LnNldChzcGxhdC5zZWxlY3Rpb24sIHNlbGVjdGlvblB0cik7CiAgICAgIHdhc21Nb2R1bGUuX3BhY2soc3BsYXQuc2VsZWN0ZWQsIHNwbGF0LnZlcnRleENvdW50LCBwb3NpdGlvbnNQdHIsIHJvdGF0aW9uc1B0ciwgc2NhbGVzUHRyLCBjb2xvcnNQdHIsIHNlbGVjdGlvblB0ciwgZGF0YVB0ciwgd29ybGRQb3NpdGlvbnNQdHIsIHdvcmxkUm90YXRpb25zUHRyLCB3b3JsZFNjYWxlc1B0cik7CiAgICAgIGNvbnN0IG91dERhdGEgPSBuZXcgVWludDMyQXJyYXkod2FzbU1vZHVsZS5IRUFQVTMyLmJ1ZmZlciwgZGF0YVB0ciwgc3BsYXQudmVydGV4Q291bnQgKiA4KTsKICAgICAgY29uc3QgZGV0YWNoZWREYXRhID0gbmV3IFVpbnQzMkFycmF5KG91dERhdGEuc2xpY2UoKS5idWZmZXIpOwogICAgICBjb25zdCB3b3JsZFBvc2l0aW9ucyA9IG5ldyBGbG9hdDMyQXJyYXkod2FzbU1vZHVsZS5IRUFQRjMyLmJ1ZmZlciwgd29ybGRQb3NpdGlvbnNQdHIsIHNwbGF0LnZlcnRleENvdW50ICogMyk7CiAgICAgIGNvbnN0IGRldGFjaGVkV29ybGRQb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KHdvcmxkUG9zaXRpb25zLnNsaWNlKCkuYnVmZmVyKTsKICAgICAgY29uc3Qgd29ybGRSb3RhdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KHdhc21Nb2R1bGUuSEVBUEYzMi5idWZmZXIsIHdvcmxkUm90YXRpb25zUHRyLCBzcGxhdC52ZXJ0ZXhDb3VudCAqIDQpOwogICAgICBjb25zdCBkZXRhY2hlZFdvcmxkUm90YXRpb25zID0gbmV3IEZsb2F0MzJBcnJheSh3b3JsZFJvdGF0aW9ucy5zbGljZSgpLmJ1ZmZlcik7CiAgICAgIGNvbnN0IHdvcmxkU2NhbGVzID0gbmV3IEZsb2F0MzJBcnJheSh3YXNtTW9kdWxlLkhFQVBGMzIuYnVmZmVyLCB3b3JsZFNjYWxlc1B0ciwgc3BsYXQudmVydGV4Q291bnQgKiAzKTsKICAgICAgY29uc3QgZGV0YWNoZWRXb3JsZFNjYWxlcyA9IG5ldyBGbG9hdDMyQXJyYXkod29ybGRTY2FsZXMuc2xpY2UoKS5idWZmZXIpOwogICAgICBjb25zdCByZXNwb25zZSA9IHsKICAgICAgICAgIGRhdGE6IGRldGFjaGVkRGF0YSwKICAgICAgICAgIHdvcmxkUG9zaXRpb25zOiBkZXRhY2hlZFdvcmxkUG9zaXRpb25zLAogICAgICAgICAgd29ybGRSb3RhdGlvbnM6IGRldGFjaGVkV29ybGRSb3RhdGlvbnMsCiAgICAgICAgICB3b3JsZFNjYWxlczogZGV0YWNoZWRXb3JsZFNjYWxlcywKICAgICAgICAgIG9mZnNldDogc3BsYXQub2Zmc2V0LAogICAgICAgICAgdmVydGV4Q291bnQ6IHNwbGF0LnZlcnRleENvdW50LAogICAgICAgICAgcG9zaXRpb25zOiBzcGxhdC5wb3NpdGlvbnMuYnVmZmVyLAogICAgICAgICAgcm90YXRpb25zOiBzcGxhdC5yb3RhdGlvbnMuYnVmZmVyLAogICAgICAgICAgc2NhbGVzOiBzcGxhdC5zY2FsZXMuYnVmZmVyLAogICAgICAgICAgY29sb3JzOiBzcGxhdC5jb2xvcnMuYnVmZmVyLAogICAgICAgICAgc2VsZWN0aW9uOiBzcGxhdC5zZWxlY3Rpb24uYnVmZmVyLAogICAgICB9OwogICAgICBzZWxmLnBvc3RNZXNzYWdlKHsgcmVzcG9uc2U6IHJlc3BvbnNlIH0sIFsKICAgICAgICAgIHJlc3BvbnNlLmRhdGEuYnVmZmVyLAogICAgICAgICAgcmVzcG9uc2Uud29ybGRQb3NpdGlvbnMuYnVmZmVyLAogICAgICAgICAgcmVzcG9uc2Uud29ybGRSb3RhdGlvbnMuYnVmZmVyLAogICAgICAgICAgcmVzcG9uc2Uud29ybGRTY2FsZXMuYnVmZmVyLAogICAgICAgICAgcmVzcG9uc2UucG9zaXRpb25zLAogICAgICAgICAgcmVzcG9uc2Uucm90YXRpb25zLAogICAgICAgICAgcmVzcG9uc2Uuc2NhbGVzLAogICAgICAgICAgcmVzcG9uc2UuY29sb3JzLAogICAgICAgICAgcmVzcG9uc2Uuc2VsZWN0aW9uLAogICAgICBdKTsKICAgICAgcnVubmluZyA9IGZhbHNlOwogIH07CiAgY29uc3QgcGFja1Rocm90dGxlZCA9ICgpID0+IHsKICAgICAgaWYgKHVwZGF0ZVF1ZXVlLmxlbmd0aCA9PT0gMCkKICAgICAgICAgIHJldHVybjsKICAgICAgaWYgKCFydW5uaW5nKSB7CiAgICAgICAgICBydW5uaW5nID0gdHJ1ZTsKICAgICAgICAgIGNvbnN0IHNwbGF0ID0gdXBkYXRlUXVldWUuc2hpZnQoKTsKICAgICAgICAgIHBhY2soc3BsYXQpOwogICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7CiAgICAgICAgICAgICAgcnVubmluZyA9IGZhbHNlOwogICAgICAgICAgICAgIHBhY2tUaHJvdHRsZWQoKTsKICAgICAgICAgIH0sIDApOwogICAgICB9CiAgfTsKICBzZWxmLm9ubWVzc2FnZSA9IChlKSA9PiB7CiAgICAgIGlmIChlLmRhdGEuc3BsYXQpIHsKICAgICAgICAgIGNvbnN0IHNwbGF0ID0gZS5kYXRhLnNwbGF0OwogICAgICAgICAgZm9yIChjb25zdCBbaW5kZXgsIGV4aXN0aW5nXSBvZiB1cGRhdGVRdWV1ZS5lbnRyaWVzKCkpIHsKICAgICAgICAgICAgICBpZiAoZXhpc3Rpbmcub2Zmc2V0ID09PSBzcGxhdC5vZmZzZXQpIHsKICAgICAgICAgICAgICAgICAgdXBkYXRlUXVldWVbaW5kZXhdID0gc3BsYXQ7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB1cGRhdGVRdWV1ZS5wdXNoKHNwbGF0KTsKICAgICAgICAgIHBhY2tUaHJvdHRsZWQoKTsKICAgICAgfQogIH07Cgp9KSgpOwovLyMgc291cmNlTWFwcGluZ1VSTD1EYXRhV29ya2VyLmpzLm1hcAoK", null), Ul = function(G = {}) {
|
|
935
|
-
var t, F, U = G;
|
|
936
|
-
U.ready = new Promise((V, s) => {
|
|
937
|
-
t = V, F = s;
|
|
938
|
-
});
|
|
939
|
-
var l, a = Object.assign({}, U), n = "";
|
|
940
|
-
n = (n = self.location.href).indexOf("blob:") !== 0 ? n.substr(0, n.replace(/[?#].*/, "").lastIndexOf("/") + 1) : "", l = (V) => {
|
|
941
|
-
var s = new XMLHttpRequest();
|
|
942
|
-
return s.open("GET", V, !1), s.responseType = "arraybuffer", s.send(null), new Uint8Array(s.response);
|
|
943
|
-
}, U.print || console.log.bind(console);
|
|
944
|
-
var e, Q, d = U.printErr || console.error.bind(console);
|
|
945
|
-
Object.assign(U, a), a = null, U.arguments && U.arguments, U.thisProgram && U.thisProgram, U.quit && U.quit, U.wasmBinary && (e = U.wasmBinary), typeof WebAssembly != "object" && E("no native wasm support detected");
|
|
946
|
-
var A, i, r, c, B, W, J, h, C = !1;
|
|
947
|
-
function k() {
|
|
948
|
-
var V = Q.buffer;
|
|
949
|
-
U.HEAP8 = A = new Int8Array(V), U.HEAP16 = r = new Int16Array(V), U.HEAPU8 = i = new Uint8Array(V), U.HEAPU16 = c = new Uint16Array(V), U.HEAP32 = B = new Int32Array(V), U.HEAPU32 = W = new Uint32Array(V), U.HEAPF32 = J = new Float32Array(V), U.HEAPF64 = h = new Float64Array(V);
|
|
950
|
-
}
|
|
951
|
-
var p = [], X = [], D = [], u = 0, M = null;
|
|
952
|
-
function E(V) {
|
|
953
|
-
U.onAbort && U.onAbort(V), d(V = "Aborted(" + V + ")"), C = !0, V += ". Build with -sASSERTIONS for more info.";
|
|
954
|
-
var s = new WebAssembly.RuntimeError(V);
|
|
955
|
-
throw F(s), s;
|
|
956
|
-
}
|
|
957
|
-
var w, Ft, Y = "data:application/octet-stream;base64,", H = (V) => V.startsWith(Y);
|
|
958
|
-
function at(V) {
|
|
959
|
-
if (V == w && e) return new Uint8Array(e);
|
|
960
|
-
var s = function(R) {
|
|
961
|
-
if (H(R)) return function(Z) {
|
|
962
|
-
for (var m = atob(Z), b = new Uint8Array(m.length), g = 0; g < m.length; ++g) b[g] = m.charCodeAt(g);
|
|
963
|
-
return b;
|
|
964
|
-
}(R.slice(Y.length));
|
|
965
|
-
}(V);
|
|
966
|
-
if (s) return s;
|
|
967
|
-
if (l) return l(V);
|
|
968
|
-
throw "both async and sync fetching of the wasm failed";
|
|
969
|
-
}
|
|
970
|
-
function L(V, s, R) {
|
|
971
|
-
return function(Z) {
|
|
972
|
-
return Promise.resolve().then(() => at(Z));
|
|
973
|
-
}(V).then((Z) => WebAssembly.instantiate(Z, s)).then((Z) => Z).then(R, (Z) => {
|
|
974
|
-
d(`failed to asynchronously prepare wasm: ${Z}`), E(Z);
|
|
975
|
-
});
|
|
976
|
-
}
|
|
977
|
-
H(w = "data:application/octet-stream;base64,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aWduZWQgc2hvcnQ+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dW5zaWduZWQgaW50PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxmbG9hdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dWludDhfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8aW50OF90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1aW50MTZfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8aW50MTZfdD4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dWludDY0X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PGludDY0X3Q+AGVtc2NyaXB0ZW46Om1lbW9yeV92aWV3PHVpbnQzMl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxpbnQzMl90PgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxjaGFyPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzx1bnNpZ25lZCBjaGFyPgBzdGQ6OmJhc2ljX3N0cmluZzx1bnNpZ25lZCBjaGFyPgBlbXNjcmlwdGVuOjptZW1vcnlfdmlldzxzaWduZWQgY2hhcj4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8bG9uZz4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8dW5zaWduZWQgbG9uZz4AZW1zY3JpcHRlbjo6bWVtb3J5X3ZpZXc8ZG91YmxlPgBOU3QzX18yMTJiYXNpY19zdHJpbmdJY05TXzExY2hhcl90cmFpdHNJY0VFTlNfOWFsbG9jYXRvckljRUVFRQAAAABEDAAAQgcAAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0loTlNfMTFjaGFyX3RyYWl0c0loRUVOU185YWxsb2NhdG9ySWhFRUVFAABEDAAAjAcAAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0l3TlNfMTFjaGFyX3RyYWl0c0l3RUVOU185YWxsb2NhdG9ySXdFRUVFAABEDAAA1AcAAE5TdDNfXzIxMmJhc2ljX3N0cmluZ0lEc05TXzExY2hhcl90cmFpdHNJRHNFRU5TXzlhbGxvY2F0b3JJRHNFRUVFAAAARAwAABwIAABOU3QzX18yMTJiYXNpY19zdHJpbmdJRGlOU18xMWNoYXJfdHJhaXRzSURpRUVOU185YWxsb2NhdG9ySURpRUVFRQAAAEQMAABoCAAATjEwZW1zY3JpcHRlbjN2YWxFAABEDAAAtAgAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWNFRQAARAwAANAIAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lhRUUAAEQMAAD4CAAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJaEVFAABEDAAAIAkAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SXNFRQAARAwAAEgJAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0l0RUUAAEQMAABwCQAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJaUVFAABEDAAAmAkAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWpFRQAARAwAAMAJAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0lsRUUAAEQMAADoCQAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJbUVFAABEDAAAEAoAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SXhFRQAARAwAADgKAABOMTBlbXNjcmlwdGVuMTFtZW1vcnlfdmlld0l5RUUAAEQMAABgCgAATjEwZW1zY3JpcHRlbjExbWVtb3J5X3ZpZXdJZkVFAABEDAAAiAoAAE4xMGVtc2NyaXB0ZW4xMW1lbW9yeV92aWV3SWRFRQAARAwAALAKAABOMTBfX2N4eGFiaXYxMTZfX3NoaW1fdHlwZV9pbmZvRQAAAABsDAAA2AoAANAMAABOMTBfX2N4eGFiaXYxMTdfX2NsYXNzX3R5cGVfaW5mb0UAAABsDAAACAsAAPwKAAAAAAAAfAsAAAIAAAADAAAABAAAAAUAAAAGAAAATjEwX19jeHhhYml2MTIzX19mdW5kYW1lbnRhbF90eXBlX2luZm9FAGwMAABUCwAA/AoAAHYAAABACwAAiAsAAGIAAABACwAAlAsAAGMAAABACwAAoAsAAGgAAABACwAArAsAAGEAAABACwAAuAsAAHMAAABACwAAxAsAAHQAAABACwAA0AsAAGkAAABACwAA3AsAAGoAAABACwAA6AsAAGwAAABACwAA9AsAAG0AAABACwAAAAwAAHgAAABACwAADAwAAHkAAABACwAAGAwAAGYAAABACwAAJAwAAGQAAABACwAAMAwAAAAAAAAsCwAAAgAAAAcAAAAEAAAABQAAAAgAAAAJAAAACgAAAAsAAAAAAAAAtAwAAAIAAAAMAAAABAAAAAUAAAAIAAAADQAAAA4AAAAPAAAATjEwX19jeHhhYml2MTIwX19zaV9jbGFzc190eXBlX2luZm9FAAAAAGwMAACMDAAALAsAAFN0OXR5cGVfaW5mbwAAAABEDAAAwAwAQdgZCwPgDgE=") || (Ft = w, w = U.locateFile ? U.locateFile(Ft, n) : n + Ft);
|
|
978
|
-
var o = (V) => {
|
|
979
|
-
for (; V.length > 0; ) V.shift()(U);
|
|
980
|
-
};
|
|
981
|
-
U.noExitRuntime;
|
|
982
|
-
var T, v, x = (V) => {
|
|
983
|
-
for (var s = "", R = V; i[R]; ) s += T[i[R++]];
|
|
984
|
-
return s;
|
|
985
|
-
}, At = {}, Vt = {}, K = (V) => {
|
|
986
|
-
throw new v(V);
|
|
987
|
-
};
|
|
988
|
-
function _(V, s, R = {}) {
|
|
989
|
-
if (!("argPackAdvance" in s)) throw new TypeError("registerType registeredInstance requires argPackAdvance");
|
|
990
|
-
return function(Z, m, b = {}) {
|
|
991
|
-
var g = m.name;
|
|
992
|
-
if (Z || K(`type "${g}" must have a positive integer typeid pointer`), Vt.hasOwnProperty(Z)) {
|
|
993
|
-
if (b.ignoreDuplicateRegistrations) return;
|
|
994
|
-
K(`Cannot register type '${g}' twice`);
|
|
995
|
-
}
|
|
996
|
-
if (Vt[Z] = m, At.hasOwnProperty(Z)) {
|
|
997
|
-
var y = At[Z];
|
|
998
|
-
delete At[Z], y.forEach((N) => N());
|
|
999
|
-
}
|
|
1000
|
-
}(V, s, R);
|
|
1001
|
-
}
|
|
1002
|
-
function et() {
|
|
1003
|
-
this.allocated = [void 0], this.freelist = [];
|
|
1004
|
-
}
|
|
1005
|
-
var j = new et(), Rt = () => {
|
|
1006
|
-
for (var V = 0, s = j.reserved; s < j.allocated.length; ++s) j.allocated[s] !== void 0 && ++V;
|
|
1007
|
-
return V;
|
|
1008
|
-
}, It = (V) => (V || K("Cannot use deleted val. handle = " + V), j.get(V).value), kt = (V) => {
|
|
1009
|
-
switch (V) {
|
|
1010
|
-
case void 0:
|
|
1011
|
-
return 1;
|
|
1012
|
-
case null:
|
|
1013
|
-
return 2;
|
|
1014
|
-
case !0:
|
|
1015
|
-
return 3;
|
|
1016
|
-
case !1:
|
|
1017
|
-
return 4;
|
|
1018
|
-
default:
|
|
1019
|
-
return j.allocate({ refcount: 1, value: V });
|
|
1020
|
-
}
|
|
1021
|
-
};
|
|
1022
|
-
function Nt(V) {
|
|
1023
|
-
return this.fromWireType(B[V >> 2]);
|
|
1024
|
-
}
|
|
1025
|
-
var Tt = (V, s) => {
|
|
1026
|
-
switch (s) {
|
|
1027
|
-
case 4:
|
|
1028
|
-
return function(R) {
|
|
1029
|
-
return this.fromWireType(J[R >> 2]);
|
|
1030
|
-
};
|
|
1031
|
-
case 8:
|
|
1032
|
-
return function(R) {
|
|
1033
|
-
return this.fromWireType(h[R >> 3]);
|
|
1034
|
-
};
|
|
1035
|
-
default:
|
|
1036
|
-
throw new TypeError(`invalid float width (${s}): ${V}`);
|
|
1037
|
-
}
|
|
1038
|
-
}, Ht = (V, s, R) => {
|
|
1039
|
-
switch (s) {
|
|
1040
|
-
case 1:
|
|
1041
|
-
return R ? (Z) => A[Z >> 0] : (Z) => i[Z >> 0];
|
|
1042
|
-
case 2:
|
|
1043
|
-
return R ? (Z) => r[Z >> 1] : (Z) => c[Z >> 1];
|
|
1044
|
-
case 4:
|
|
1045
|
-
return R ? (Z) => B[Z >> 2] : (Z) => W[Z >> 2];
|
|
1046
|
-
default:
|
|
1047
|
-
throw new TypeError(`invalid integer width (${s}): ${V}`);
|
|
1048
|
-
}
|
|
1049
|
-
};
|
|
1050
|
-
function xt(V) {
|
|
1051
|
-
return this.fromWireType(W[V >> 2]);
|
|
1052
|
-
}
|
|
1053
|
-
var Gt = typeof TextDecoder < "u" ? new TextDecoder("utf8") : void 0, ft = (V, s) => V ? ((R, Z, m) => {
|
|
1054
|
-
for (var b = Z + m, g = Z; R[g] && !(g >= b); ) ++g;
|
|
1055
|
-
if (g - Z > 16 && R.buffer && Gt) return Gt.decode(R.subarray(Z, g));
|
|
1056
|
-
for (var y = ""; Z < g; ) {
|
|
1057
|
-
var N = R[Z++];
|
|
1058
|
-
if (128 & N) {
|
|
1059
|
-
var S = 63 & R[Z++];
|
|
1060
|
-
if ((224 & N) != 192) {
|
|
1061
|
-
var q = 63 & R[Z++];
|
|
1062
|
-
if ((N = (240 & N) == 224 ? (15 & N) << 12 | S << 6 | q : (7 & N) << 18 | S << 12 | q << 6 | 63 & R[Z++]) < 65536) y += String.fromCharCode(N);
|
|
1063
|
-
else {
|
|
1064
|
-
var P = N - 65536;
|
|
1065
|
-
y += String.fromCharCode(55296 | P >> 10, 56320 | 1023 & P);
|
|
1066
|
-
}
|
|
1067
|
-
} else y += String.fromCharCode((31 & N) << 6 | S);
|
|
1068
|
-
} else y += String.fromCharCode(N);
|
|
1069
|
-
}
|
|
1070
|
-
return y;
|
|
1071
|
-
})(i, V, s) : "", pt = typeof TextDecoder < "u" ? new TextDecoder("utf-16le") : void 0, Dt = (V, s) => {
|
|
1072
|
-
for (var R = V, Z = R >> 1, m = Z + s / 2; !(Z >= m) && c[Z]; ) ++Z;
|
|
1073
|
-
if ((R = Z << 1) - V > 32 && pt) return pt.decode(i.subarray(V, R));
|
|
1074
|
-
for (var b = "", g = 0; !(g >= s / 2); ++g) {
|
|
1075
|
-
var y = r[V + 2 * g >> 1];
|
|
1076
|
-
if (y == 0) break;
|
|
1077
|
-
b += String.fromCharCode(y);
|
|
1078
|
-
}
|
|
1079
|
-
return b;
|
|
1080
|
-
}, wt = (V, s, R) => {
|
|
1081
|
-
if (R === void 0 && (R = 2147483647), R < 2) return 0;
|
|
1082
|
-
for (var Z = s, m = (R -= 2) < 2 * V.length ? R / 2 : V.length, b = 0; b < m; ++b) {
|
|
1083
|
-
var g = V.charCodeAt(b);
|
|
1084
|
-
r[s >> 1] = g, s += 2;
|
|
1085
|
-
}
|
|
1086
|
-
return r[s >> 1] = 0, s - Z;
|
|
1087
|
-
}, vt = (V) => 2 * V.length, zt = (V, s) => {
|
|
1088
|
-
for (var R = 0, Z = ""; !(R >= s / 4); ) {
|
|
1089
|
-
var m = B[V + 4 * R >> 2];
|
|
1090
|
-
if (m == 0) break;
|
|
1091
|
-
if (++R, m >= 65536) {
|
|
1092
|
-
var b = m - 65536;
|
|
1093
|
-
Z += String.fromCharCode(55296 | b >> 10, 56320 | 1023 & b);
|
|
1094
|
-
} else Z += String.fromCharCode(m);
|
|
1095
|
-
}
|
|
1096
|
-
return Z;
|
|
1097
|
-
}, Mt = (V, s, R) => {
|
|
1098
|
-
if (R === void 0 && (R = 2147483647), R < 4) return 0;
|
|
1099
|
-
for (var Z = s, m = Z + R - 4, b = 0; b < V.length; ++b) {
|
|
1100
|
-
var g = V.charCodeAt(b);
|
|
1101
|
-
if (g >= 55296 && g <= 57343 && (g = 65536 + ((1023 & g) << 10) | 1023 & V.charCodeAt(++b)), B[s >> 2] = g, (s += 4) + 4 > m) break;
|
|
1102
|
-
}
|
|
1103
|
-
return B[s >> 2] = 0, s - Z;
|
|
1104
|
-
}, Kt = (V) => {
|
|
1105
|
-
for (var s = 0, R = 0; R < V.length; ++R) {
|
|
1106
|
-
var Z = V.charCodeAt(R);
|
|
1107
|
-
Z >= 55296 && Z <= 57343 && ++R, s += 4;
|
|
1108
|
-
}
|
|
1109
|
-
return s;
|
|
1110
|
-
}, jt = (V) => {
|
|
1111
|
-
var s = (V - Q.buffer.byteLength + 65535) / 65536;
|
|
1112
|
-
try {
|
|
1113
|
-
return Q.grow(s), k(), 1;
|
|
1114
|
-
} catch {
|
|
1115
|
-
}
|
|
1116
|
-
};
|
|
1117
|
-
(() => {
|
|
1118
|
-
for (var V = new Array(256), s = 0; s < 256; ++s) V[s] = String.fromCharCode(s);
|
|
1119
|
-
T = V;
|
|
1120
|
-
})(), v = U.BindingError = class extends Error {
|
|
1121
|
-
constructor(V) {
|
|
1122
|
-
super(V), this.name = "BindingError";
|
|
1123
|
-
}
|
|
1124
|
-
}, U.InternalError = class extends Error {
|
|
1125
|
-
constructor(V) {
|
|
1126
|
-
super(V), this.name = "InternalError";
|
|
1127
|
-
}
|
|
1128
|
-
}, Object.assign(et.prototype, { get(V) {
|
|
1129
|
-
return this.allocated[V];
|
|
1130
|
-
}, has(V) {
|
|
1131
|
-
return this.allocated[V] !== void 0;
|
|
1132
|
-
}, allocate(V) {
|
|
1133
|
-
var s = this.freelist.pop() || this.allocated.length;
|
|
1134
|
-
return this.allocated[s] = V, s;
|
|
1135
|
-
}, free(V) {
|
|
1136
|
-
this.allocated[V] = void 0, this.freelist.push(V);
|
|
1137
|
-
} }), j.allocated.push({ value: void 0 }, { value: null }, { value: !0 }, { value: !1 }), j.reserved = j.allocated.length, U.count_emval_handles = Rt;
|
|
1138
|
-
var Ot = { f: (V, s, R, Z, m) => {
|
|
1139
|
-
}, i: (V, s, R, Z) => {
|
|
1140
|
-
_(V, { name: s = x(s), fromWireType: function(m) {
|
|
1141
|
-
return !!m;
|
|
1142
|
-
}, toWireType: function(m, b) {
|
|
1143
|
-
return b ? R : Z;
|
|
1144
|
-
}, argPackAdvance: 8, readValueFromPointer: function(m) {
|
|
1145
|
-
return this.fromWireType(i[m]);
|
|
1146
|
-
}, destructorFunction: null });
|
|
1147
|
-
}, h: (V, s) => {
|
|
1148
|
-
_(V, { name: s = x(s), fromWireType: (R) => {
|
|
1149
|
-
var Z = It(R);
|
|
1150
|
-
return ((m) => {
|
|
1151
|
-
m >= j.reserved && --j.get(m).refcount == 0 && j.free(m);
|
|
1152
|
-
})(R), Z;
|
|
1153
|
-
}, toWireType: (R, Z) => kt(Z), argPackAdvance: 8, readValueFromPointer: Nt, destructorFunction: null });
|
|
1154
|
-
}, e: (V, s, R) => {
|
|
1155
|
-
_(V, { name: s = x(s), fromWireType: (Z) => Z, toWireType: (Z, m) => m, argPackAdvance: 8, readValueFromPointer: Tt(s, R), destructorFunction: null });
|
|
1156
|
-
}, b: (V, s, R, Z, m) => {
|
|
1157
|
-
s = x(s);
|
|
1158
|
-
var b = (N) => N;
|
|
1159
|
-
if (Z === 0) {
|
|
1160
|
-
var g = 32 - 8 * R;
|
|
1161
|
-
b = (N) => N << g >>> g;
|
|
1162
|
-
}
|
|
1163
|
-
var y = s.includes("unsigned");
|
|
1164
|
-
_(V, { name: s, fromWireType: b, toWireType: y ? function(N, S) {
|
|
1165
|
-
return this.name, S >>> 0;
|
|
1166
|
-
} : function(N, S) {
|
|
1167
|
-
return this.name, S;
|
|
1168
|
-
}, argPackAdvance: 8, readValueFromPointer: Ht(s, R, Z !== 0), destructorFunction: null });
|
|
1169
|
-
}, a: (V, s, R) => {
|
|
1170
|
-
var Z = [Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array][s];
|
|
1171
|
-
function m(b) {
|
|
1172
|
-
var g = W[b >> 2], y = W[b + 4 >> 2];
|
|
1173
|
-
return new Z(A.buffer, y, g);
|
|
1174
|
-
}
|
|
1175
|
-
_(V, { name: R = x(R), fromWireType: m, argPackAdvance: 8, readValueFromPointer: m }, { ignoreDuplicateRegistrations: !0 });
|
|
1176
|
-
}, d: (V, s) => {
|
|
1177
|
-
var R = (s = x(s)) === "std::string";
|
|
1178
|
-
_(V, { name: s, fromWireType(Z) {
|
|
1179
|
-
var m, b = W[Z >> 2], g = Z + 4;
|
|
1180
|
-
if (R) for (var y = g, N = 0; N <= b; ++N) {
|
|
1181
|
-
var S = g + N;
|
|
1182
|
-
if (N == b || i[S] == 0) {
|
|
1183
|
-
var q = ft(y, S - y);
|
|
1184
|
-
m === void 0 ? m = q : (m += "\0", m += q), y = S + 1;
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
else {
|
|
1188
|
-
var P = new Array(b);
|
|
1189
|
-
for (N = 0; N < b; ++N) P[N] = String.fromCharCode(i[g + N]);
|
|
1190
|
-
m = P.join("");
|
|
1191
|
-
}
|
|
1192
|
-
return it(Z), m;
|
|
1193
|
-
}, toWireType(Z, m) {
|
|
1194
|
-
var b;
|
|
1195
|
-
m instanceof ArrayBuffer && (m = new Uint8Array(m));
|
|
1196
|
-
var g = typeof m == "string";
|
|
1197
|
-
g || m instanceof Uint8Array || m instanceof Uint8ClampedArray || m instanceof Int8Array || K("Cannot pass non-string to std::string"), b = R && g ? ((P) => {
|
|
1198
|
-
for (var O = 0, f = 0; f < P.length; ++f) {
|
|
1199
|
-
var Qt = P.charCodeAt(f);
|
|
1200
|
-
Qt <= 127 ? O++ : Qt <= 2047 ? O += 2 : Qt >= 55296 && Qt <= 57343 ? (O += 4, ++f) : O += 3;
|
|
1201
|
-
}
|
|
1202
|
-
return O;
|
|
1203
|
-
})(m) : m.length;
|
|
1204
|
-
var y = Jt(4 + b + 1), N = y + 4;
|
|
1205
|
-
if (W[y >> 2] = b, R && g) ((P, O, f, Qt) => {
|
|
1206
|
-
if (!(Qt > 0)) return 0;
|
|
1207
|
-
for (var st = f + Qt - 1, Wt = 0; Wt < P.length; ++Wt) {
|
|
1208
|
-
var $ = P.charCodeAt(Wt);
|
|
1209
|
-
if ($ >= 55296 && $ <= 57343 && ($ = 65536 + ((1023 & $) << 10) | 1023 & P.charCodeAt(++Wt)), $ <= 127) {
|
|
1210
|
-
if (f >= st) break;
|
|
1211
|
-
O[f++] = $;
|
|
1212
|
-
} else if ($ <= 2047) {
|
|
1213
|
-
if (f + 1 >= st) break;
|
|
1214
|
-
O[f++] = 192 | $ >> 6, O[f++] = 128 | 63 & $;
|
|
1215
|
-
} else if ($ <= 65535) {
|
|
1216
|
-
if (f + 2 >= st) break;
|
|
1217
|
-
O[f++] = 224 | $ >> 12, O[f++] = 128 | $ >> 6 & 63, O[f++] = 128 | 63 & $;
|
|
1218
|
-
} else {
|
|
1219
|
-
if (f + 3 >= st) break;
|
|
1220
|
-
O[f++] = 240 | $ >> 18, O[f++] = 128 | $ >> 12 & 63, O[f++] = 128 | $ >> 6 & 63, O[f++] = 128 | 63 & $;
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
|
-
O[f] = 0;
|
|
1224
|
-
})(m, i, N, b + 1);
|
|
1225
|
-
else if (g) for (var S = 0; S < b; ++S) {
|
|
1226
|
-
var q = m.charCodeAt(S);
|
|
1227
|
-
q > 255 && (it(N), K("String has UTF-16 code units that do not fit in 8 bits")), i[N + S] = q;
|
|
1228
|
-
}
|
|
1229
|
-
else for (S = 0; S < b; ++S) i[N + S] = m[S];
|
|
1230
|
-
return Z !== null && Z.push(it, y), y;
|
|
1231
|
-
}, argPackAdvance: 8, readValueFromPointer: xt, destructorFunction(Z) {
|
|
1232
|
-
it(Z);
|
|
1233
|
-
} });
|
|
1234
|
-
}, c: (V, s, R) => {
|
|
1235
|
-
var Z, m, b, g, y;
|
|
1236
|
-
R = x(R), s === 2 ? (Z = Dt, m = wt, g = vt, b = () => c, y = 1) : s === 4 && (Z = zt, m = Mt, g = Kt, b = () => W, y = 2), _(V, { name: R, fromWireType: (N) => {
|
|
1237
|
-
for (var S, q = W[N >> 2], P = b(), O = N + 4, f = 0; f <= q; ++f) {
|
|
1238
|
-
var Qt = N + 4 + f * s;
|
|
1239
|
-
if (f == q || P[Qt >> y] == 0) {
|
|
1240
|
-
var st = Z(O, Qt - O);
|
|
1241
|
-
S === void 0 ? S = st : (S += "\0", S += st), O = Qt + s;
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
return it(N), S;
|
|
1245
|
-
}, toWireType: (N, S) => {
|
|
1246
|
-
typeof S != "string" && K(`Cannot pass non-string to C++ string type ${R}`);
|
|
1247
|
-
var q = g(S), P = Jt(4 + q + s);
|
|
1248
|
-
return W[P >> 2] = q >> y, m(S, P + 4, q + s), N !== null && N.push(it, P), P;
|
|
1249
|
-
}, argPackAdvance: 8, readValueFromPointer: Nt, destructorFunction(N) {
|
|
1250
|
-
it(N);
|
|
1251
|
-
} });
|
|
1252
|
-
}, j: (V, s) => {
|
|
1253
|
-
_(V, { isVoid: !0, name: s = x(s), argPackAdvance: 0, fromWireType: () => {
|
|
1254
|
-
}, toWireType: (R, Z) => {
|
|
1255
|
-
} });
|
|
1256
|
-
}, g: (V) => {
|
|
1257
|
-
var s = i.length, R = 2147483648;
|
|
1258
|
-
if ((V >>>= 0) > R) return !1;
|
|
1259
|
-
for (var Z, m, b = 1; b <= 4; b *= 2) {
|
|
1260
|
-
var g = s * (1 + 0.2 / b);
|
|
1261
|
-
g = Math.min(g, V + 100663296);
|
|
1262
|
-
var y = Math.min(R, (Z = Math.max(V, g)) + ((m = 65536) - Z % m) % m);
|
|
1263
|
-
if (jt(y)) return !0;
|
|
1264
|
-
}
|
|
1265
|
-
return !1;
|
|
1266
|
-
} }, Bt = function() {
|
|
1267
|
-
var V, s, R, Z = { a: Ot };
|
|
1268
|
-
function m(b, g) {
|
|
1269
|
-
var y;
|
|
1270
|
-
return Bt = b.exports, Q = Bt.k, k(), y = Bt.l, X.unshift(y), function(N) {
|
|
1271
|
-
if (u--, U.monitorRunDependencies && U.monitorRunDependencies(u), u == 0 && M) {
|
|
1272
|
-
var S = M;
|
|
1273
|
-
M = null, S();
|
|
1274
|
-
}
|
|
1275
|
-
}(), Bt;
|
|
1276
|
-
}
|
|
1277
|
-
if (u++, U.monitorRunDependencies && U.monitorRunDependencies(u), U.instantiateWasm) try {
|
|
1278
|
-
return U.instantiateWasm(Z, m);
|
|
1279
|
-
} catch (b) {
|
|
1280
|
-
d(`Module.instantiateWasm callback failed with error: ${b}`), F(b);
|
|
1281
|
-
}
|
|
1282
|
-
return (V = w, s = Z, R = function(b) {
|
|
1283
|
-
m(b.instance);
|
|
1284
|
-
}, L(V, s, R)).catch(F), {};
|
|
1285
|
-
}();
|
|
1286
|
-
U._pack = (V, s, R, Z, m, b, g, y, N, S, q) => (U._pack = Bt.m)(V, s, R, Z, m, b, g, y, N, S, q), U.__embind_initialize_bindings = () => (U.__embind_initialize_bindings = Bt.n)();
|
|
1287
|
-
var rt, Jt = U._malloc = (V) => (Jt = U._malloc = Bt.p)(V), it = U._free = (V) => (it = U._free = Bt.q)(V);
|
|
1288
|
-
function Xt() {
|
|
1289
|
-
function V() {
|
|
1290
|
-
rt || (rt = !0, U.calledRun = !0, C || (o(X), t(U), U.onRuntimeInitialized && U.onRuntimeInitialized(), function() {
|
|
1291
|
-
if (U.postRun) for (typeof U.postRun == "function" && (U.postRun = [U.postRun]); U.postRun.length; ) s = U.postRun.shift(), D.unshift(s);
|
|
1292
|
-
var s;
|
|
1293
|
-
o(D);
|
|
1294
|
-
}()));
|
|
1295
|
-
}
|
|
1296
|
-
u > 0 || (function() {
|
|
1297
|
-
if (U.preRun) for (typeof U.preRun == "function" && (U.preRun = [U.preRun]); U.preRun.length; ) s = U.preRun.shift(), p.unshift(s);
|
|
1298
|
-
var s;
|
|
1299
|
-
o(p);
|
|
1300
|
-
}(), u > 0 || (U.setStatus ? (U.setStatus("Running..."), setTimeout(function() {
|
|
1301
|
-
setTimeout(function() {
|
|
1302
|
-
U.setStatus("");
|
|
1303
|
-
}, 1), V();
|
|
1304
|
-
}, 1)) : V()));
|
|
1305
|
-
}
|
|
1306
|
-
if (M = function V() {
|
|
1307
|
-
rt || Xt(), rt || (M = V);
|
|
1308
|
-
}, U.preInit) for (typeof U.preInit == "function" && (U.preInit = [U.preInit]); U.preInit.length > 0; ) U.preInit.pop()();
|
|
1309
|
-
return Xt(), G.ready;
|
|
1310
|
-
};
|
|
1311
|
-
class Fl {
|
|
1312
|
-
constructor(t) {
|
|
1313
|
-
this.dataChanged = !1, this.transformsChanged = !1, this.colorTransformsChanged = !1, this._updating = /* @__PURE__ */ new Set(), this._dirty = /* @__PURE__ */ new Set();
|
|
1314
|
-
let F = 0, U = 0;
|
|
1315
|
-
this._splatIndices = /* @__PURE__ */ new Map(), this._offsets = /* @__PURE__ */ new Map();
|
|
1316
|
-
const l = /* @__PURE__ */ new Map();
|
|
1317
|
-
for (const A of t.objects) A instanceof dt && (this._splatIndices.set(A, U), this._offsets.set(A, F), l.set(F, A), F += A.data.vertexCount, U++);
|
|
1318
|
-
this._vertexCount = F, this._width = 2048, this._height = Math.ceil(2 * this.vertexCount / this.width), this._data = new Uint32Array(this.width * this.height * 4), this._transformsWidth = 5, this._transformsHeight = l.size, this._transforms = new Float32Array(this._transformsWidth * this._transformsHeight * 4), this._transformIndicesWidth = 1024, this._transformIndicesHeight = Math.ceil(this.vertexCount / this._transformIndicesWidth), this._transformIndices = new Uint32Array(this._transformIndicesWidth * this._transformIndicesHeight), this._colorTransformsWidth = 4, this._colorTransformsHeight = 64, this._colorTransforms = new Float32Array(this._colorTransformsWidth * this._colorTransformsHeight * 4), this._colorTransforms.fill(0), this._colorTransforms[0] = 1, this._colorTransforms[5] = 1, this._colorTransforms[10] = 1, this._colorTransforms[15] = 1, this._colorTransformIndicesWidth = 1024, this._colorTransformIndicesHeight = Math.ceil(this.vertexCount / this._colorTransformIndicesWidth), this._colorTransformIndices = new Uint32Array(this._colorTransformIndicesWidth * this._colorTransformIndicesHeight), this.colorTransformIndices.fill(0), this._positions = new Float32Array(3 * this.vertexCount), this._rotations = new Float32Array(4 * this.vertexCount), this._scales = new Float32Array(3 * this.vertexCount), this._worker = new ll();
|
|
1319
|
-
const a = (A) => {
|
|
1320
|
-
const i = this._splatIndices.get(A);
|
|
1321
|
-
this._transforms.set(A.transform.buffer, 20 * i), this._transforms[20 * i + 16] = A.selected ? 1 : 0, A.positionChanged = !1, A.rotationChanged = !1, A.scaleChanged = !1, A.selectedChanged = !1, this.transformsChanged = !0;
|
|
1322
|
-
}, n = () => {
|
|
1323
|
-
let A = !1;
|
|
1324
|
-
for (const c of this._splatIndices.keys()) if (c.colorTransformChanged) {
|
|
1325
|
-
A = !0;
|
|
1326
|
-
break;
|
|
1327
|
-
}
|
|
1328
|
-
if (!A) return;
|
|
1329
|
-
const i = [new Ut()];
|
|
1330
|
-
this._colorTransformIndices.fill(0);
|
|
1331
|
-
let r = 1;
|
|
1332
|
-
for (const c of this._splatIndices.keys()) {
|
|
1333
|
-
const B = this._offsets.get(c);
|
|
1334
|
-
for (const W of c.colorTransforms) i.includes(W) || (i.push(W), r++);
|
|
1335
|
-
for (const W of c.colorTransformsMap.keys()) {
|
|
1336
|
-
const J = c.colorTransformsMap.get(W);
|
|
1337
|
-
this._colorTransformIndices[W + B] = J + r - 1;
|
|
1338
|
-
}
|
|
1339
|
-
c.colorTransformChanged = !1;
|
|
1340
|
-
}
|
|
1341
|
-
for (let c = 0; c < i.length; c++) {
|
|
1342
|
-
const B = i[c];
|
|
1343
|
-
this._colorTransforms.set(B.buffer, 16 * c);
|
|
1344
|
-
}
|
|
1345
|
-
this.colorTransformsChanged = !0;
|
|
1346
|
-
};
|
|
1347
|
-
let e;
|
|
1348
|
-
this._worker.onmessage = (A) => {
|
|
1349
|
-
if (A.data.response) {
|
|
1350
|
-
const i = A.data.response, r = l.get(i.offset);
|
|
1351
|
-
a(r), n();
|
|
1352
|
-
const c = this._splatIndices.get(r);
|
|
1353
|
-
for (let B = 0; B < r.data.vertexCount; B++) this._transformIndices[i.offset + B] = c;
|
|
1354
|
-
this._data.set(i.data, 8 * i.offset), r.data.reattach(i.positions, i.rotations, i.scales, i.colors, i.selection), this._positions.set(i.worldPositions, 3 * i.offset), this._rotations.set(i.worldRotations, 4 * i.offset), this._scales.set(i.worldScales, 3 * i.offset), this._updating.delete(r), r.selectedChanged = !1, this.dataChanged = !0;
|
|
1355
|
-
}
|
|
1356
|
-
}, async function() {
|
|
1357
|
-
e = await Ul();
|
|
1358
|
-
}();
|
|
1359
|
-
const Q = (A) => {
|
|
1360
|
-
if (!e) return void async function() {
|
|
1361
|
-
for (; !e; ) await new Promise((w) => setTimeout(w, 0));
|
|
1362
|
-
}().then(() => {
|
|
1363
|
-
Q(A);
|
|
1364
|
-
});
|
|
1365
|
-
a(A);
|
|
1366
|
-
const i = e._malloc(3 * A.data.vertexCount * 4), r = e._malloc(4 * A.data.vertexCount * 4), c = e._malloc(3 * A.data.vertexCount * 4), B = e._malloc(4 * A.data.vertexCount), W = e._malloc(A.data.vertexCount), J = e._malloc(8 * A.data.vertexCount * 4), h = e._malloc(3 * A.data.vertexCount * 4), C = e._malloc(4 * A.data.vertexCount * 4), k = e._malloc(3 * A.data.vertexCount * 4);
|
|
1367
|
-
e.HEAPF32.set(A.data.positions, i / 4), e.HEAPF32.set(A.data.rotations, r / 4), e.HEAPF32.set(A.data.scales, c / 4), e.HEAPU8.set(A.data.colors, B), e.HEAPU8.set(A.data.selection, W), e._pack(A.selected, A.data.vertexCount, i, r, c, B, W, J, h, C, k);
|
|
1368
|
-
const p = new Uint32Array(e.HEAPU32.buffer, J, 8 * A.data.vertexCount), X = new Float32Array(e.HEAPF32.buffer, h, 3 * A.data.vertexCount), D = new Float32Array(e.HEAPF32.buffer, C, 4 * A.data.vertexCount), u = new Float32Array(e.HEAPF32.buffer, k, 3 * A.data.vertexCount), M = this._splatIndices.get(A), E = this._offsets.get(A);
|
|
1369
|
-
for (let w = 0; w < A.data.vertexCount; w++) this._transformIndices[E + w] = M;
|
|
1370
|
-
this._data.set(p, 8 * E), this._positions.set(X, 3 * E), this._rotations.set(D, 4 * E), this._scales.set(u, 3 * E), e._free(i), e._free(r), e._free(c), e._free(B), e._free(W), e._free(J), e._free(h), e._free(C), e._free(k), this.dataChanged = !0, this.colorTransformsChanged = !0;
|
|
1371
|
-
}, d = (A) => {
|
|
1372
|
-
if ((A.positionChanged || A.rotationChanged || A.scaleChanged || A.selectedChanged) && a(A), A.colorTransformChanged && n(), !A.data.changed || A.data.detached) return;
|
|
1373
|
-
const i = { position: new Float32Array(A.position.flat()), rotation: new Float32Array(A.rotation.flat()), scale: new Float32Array(A.scale.flat()), selected: A.selected, vertexCount: A.data.vertexCount, positions: A.data.positions, rotations: A.data.rotations, scales: A.data.scales, colors: A.data.colors, selection: A.data.selection, offset: this._offsets.get(A) };
|
|
1374
|
-
this._worker.postMessage({ splat: i }, [i.position.buffer, i.rotation.buffer, i.scale.buffer, i.positions.buffer, i.rotations.buffer, i.scales.buffer, i.colors.buffer, i.selection.buffer]), this._updating.add(A), A.data.detached = !0;
|
|
1375
|
-
};
|
|
1376
|
-
this.getSplat = (A) => {
|
|
1377
|
-
let i = null;
|
|
1378
|
-
for (const [r, c] of this._offsets) {
|
|
1379
|
-
if (!(A >= c)) break;
|
|
1380
|
-
i = r;
|
|
1381
|
-
}
|
|
1382
|
-
return i;
|
|
1383
|
-
}, this.getLocalIndex = (A, i) => i - this._offsets.get(A), this.markDirty = (A) => {
|
|
1384
|
-
this._dirty.add(A);
|
|
1385
|
-
}, this.rebuild = () => {
|
|
1386
|
-
for (const A of this._dirty) d(A);
|
|
1387
|
-
this._dirty.clear();
|
|
1388
|
-
}, this.dispose = () => {
|
|
1389
|
-
this._worker.terminate();
|
|
1390
|
-
};
|
|
1391
|
-
for (const A of this._splatIndices.keys()) Q(A);
|
|
1392
|
-
n();
|
|
1393
|
-
}
|
|
1394
|
-
get offsets() {
|
|
1395
|
-
return this._offsets;
|
|
1396
|
-
}
|
|
1397
|
-
get data() {
|
|
1398
|
-
return this._data;
|
|
1399
|
-
}
|
|
1400
|
-
get width() {
|
|
1401
|
-
return this._width;
|
|
1402
|
-
}
|
|
1403
|
-
get height() {
|
|
1404
|
-
return this._height;
|
|
1405
|
-
}
|
|
1406
|
-
get transforms() {
|
|
1407
|
-
return this._transforms;
|
|
1408
|
-
}
|
|
1409
|
-
get transformsWidth() {
|
|
1410
|
-
return this._transformsWidth;
|
|
1411
|
-
}
|
|
1412
|
-
get transformsHeight() {
|
|
1413
|
-
return this._transformsHeight;
|
|
1414
|
-
}
|
|
1415
|
-
get transformIndices() {
|
|
1416
|
-
return this._transformIndices;
|
|
1417
|
-
}
|
|
1418
|
-
get transformIndicesWidth() {
|
|
1419
|
-
return this._transformIndicesWidth;
|
|
1420
|
-
}
|
|
1421
|
-
get transformIndicesHeight() {
|
|
1422
|
-
return this._transformIndicesHeight;
|
|
1423
|
-
}
|
|
1424
|
-
get colorTransforms() {
|
|
1425
|
-
return this._colorTransforms;
|
|
1426
|
-
}
|
|
1427
|
-
get colorTransformsWidth() {
|
|
1428
|
-
return this._colorTransformsWidth;
|
|
1429
|
-
}
|
|
1430
|
-
get colorTransformsHeight() {
|
|
1431
|
-
return this._colorTransformsHeight;
|
|
1432
|
-
}
|
|
1433
|
-
get colorTransformIndices() {
|
|
1434
|
-
return this._colorTransformIndices;
|
|
1435
|
-
}
|
|
1436
|
-
get colorTransformIndicesWidth() {
|
|
1437
|
-
return this._colorTransformIndicesWidth;
|
|
1438
|
-
}
|
|
1439
|
-
get colorTransformIndicesHeight() {
|
|
1440
|
-
return this._colorTransformIndicesHeight;
|
|
1441
|
-
}
|
|
1442
|
-
get positions() {
|
|
1443
|
-
return this._positions;
|
|
1444
|
-
}
|
|
1445
|
-
get rotations() {
|
|
1446
|
-
return this._rotations;
|
|
1447
|
-
}
|
|
1448
|
-
get scales() {
|
|
1449
|
-
return this._scales;
|
|
1450
|
-
}
|
|
1451
|
-
get vertexCount() {
|
|
1452
|
-
return this._vertexCount;
|
|
1453
|
-
}
|
|
1454
|
-
get needsRebuild() {
|
|
1455
|
-
return this._dirty.size > 0;
|
|
1456
|
-
}
|
|
1457
|
-
get updating() {
|
|
1458
|
-
return this._updating.size > 0;
|
|
1459
|
-
}
|
|
1460
|
-
}
|
|
1461
|
-
class ut {
|
|
1462
|
-
constructor(t = 0, F = 0, U = 0, l = 255) {
|
|
1463
|
-
this.r = t, this.g = F, this.b = U, this.a = l;
|
|
1464
|
-
}
|
|
1465
|
-
flat() {
|
|
1466
|
-
return [this.r, this.g, this.b, this.a];
|
|
1467
|
-
}
|
|
1468
|
-
flatNorm() {
|
|
1469
|
-
return [this.r / 255, this.g / 255, this.b / 255, this.a / 255];
|
|
1470
|
-
}
|
|
1471
|
-
toHexString() {
|
|
1472
|
-
return "#" + this.flat().map((t) => t.toString(16).padStart(2, "0")).join("");
|
|
1473
|
-
}
|
|
1474
|
-
toString() {
|
|
1475
|
-
return `[${this.flat().join(", ")}]`;
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
class Yt extends St {
|
|
1479
|
-
constructor(t, F) {
|
|
1480
|
-
super(t, F), this._outlineThickness = 10, this._outlineColor = new ut(255, 165, 0, 255), this._renderData = null, this._depthIndex = new Uint32Array(), this._splatTexture = null, this._worker = null;
|
|
1481
|
-
const U = t.canvas, l = t.gl;
|
|
1482
|
-
let a, n, e, Q, d, A, i, r, c, B, W, J, h, C, k, p, X, D, u;
|
|
1483
|
-
this._resize = () => {
|
|
1484
|
-
this._camera && (this._camera.data.setSize(U.width, U.height), this._camera.update(), a = l.getUniformLocation(this.program, "projection"), l.uniformMatrix4fv(a, !1, this._camera.data.projectionMatrix.buffer), n = l.getUniformLocation(this.program, "viewport"), l.uniform2fv(n, new Float32Array([U.width, U.height])));
|
|
1485
|
-
};
|
|
1486
|
-
const M = () => {
|
|
1487
|
-
this._worker = new tl(), this._worker.onmessage = (Y) => {
|
|
1488
|
-
if (Y.data.depthIndex) {
|
|
1489
|
-
const { depthIndex: H } = Y.data;
|
|
1490
|
-
this._depthIndex = H, l.bindBuffer(l.ARRAY_BUFFER, u), l.bufferData(l.ARRAY_BUFFER, H, l.STATIC_DRAW);
|
|
1491
|
-
}
|
|
1492
|
-
};
|
|
1493
|
-
};
|
|
1494
|
-
this._initialize = () => {
|
|
1495
|
-
if (this._scene && this._camera) {
|
|
1496
|
-
this._resize(), this._scene.addEventListener("objectAdded", E), this._scene.addEventListener("objectRemoved", w);
|
|
1497
|
-
for (const Y of this._scene.objects) Y instanceof dt && Y.addEventListener("objectChanged", Ft);
|
|
1498
|
-
this._renderData = new Fl(this._scene), e = l.getUniformLocation(this.program, "focal"), l.uniform2fv(e, new Float32Array([this._camera.data.fx, this._camera.data.fy])), Q = l.getUniformLocation(this.program, "view"), l.uniformMatrix4fv(Q, !1, this._camera.data.viewMatrix.buffer), B = l.getUniformLocation(this.program, "outlineThickness"), l.uniform1f(B, this.outlineThickness), W = l.getUniformLocation(this.program, "outlineColor"), l.uniform4fv(W, new Float32Array(this.outlineColor.flatNorm())), this._splatTexture = l.createTexture(), d = l.getUniformLocation(this.program, "u_texture"), l.uniform1i(d, 0), C = l.createTexture(), A = l.getUniformLocation(this.program, "u_transforms"), l.uniform1i(A, 1), k = l.createTexture(), i = l.getUniformLocation(this.program, "u_transformIndices"), l.uniform1i(i, 2), p = l.createTexture(), r = l.getUniformLocation(this.program, "u_colorTransforms"), l.uniform1i(r, 3), X = l.createTexture(), c = l.getUniformLocation(this.program, "u_colorTransformIndices"), l.uniform1i(c, 4), D = l.createBuffer(), l.bindBuffer(l.ARRAY_BUFFER, D), l.bufferData(l.ARRAY_BUFFER, new Float32Array([-2, -2, 2, -2, 2, 2, -2, 2]), l.STATIC_DRAW), J = l.getAttribLocation(this.program, "position"), l.enableVertexAttribArray(J), l.vertexAttribPointer(J, 2, l.FLOAT, !1, 0, 0), u = l.createBuffer(), h = l.getAttribLocation(this.program, "index"), l.enableVertexAttribArray(h), l.bindBuffer(l.ARRAY_BUFFER, u), M();
|
|
1499
|
-
} else console.error("Cannot render without scene and camera");
|
|
1500
|
-
};
|
|
1501
|
-
const E = (Y) => {
|
|
1502
|
-
const H = Y;
|
|
1503
|
-
H.object instanceof dt && H.object.addEventListener("objectChanged", Ft), this.dispose();
|
|
1504
|
-
}, w = (Y) => {
|
|
1505
|
-
const H = Y;
|
|
1506
|
-
H.object instanceof dt && H.object.removeEventListener("objectChanged", Ft), this.dispose();
|
|
1507
|
-
}, Ft = (Y) => {
|
|
1508
|
-
const H = Y;
|
|
1509
|
-
H.object instanceof dt && this._renderData && this._renderData.markDirty(H.object);
|
|
1510
|
-
};
|
|
1511
|
-
this._render = () => {
|
|
1512
|
-
var Y, H;
|
|
1513
|
-
if (this._scene && this._camera && this.renderData) {
|
|
1514
|
-
if (this.renderData.needsRebuild && this.renderData.rebuild(), this.renderData.dataChanged || this.renderData.transformsChanged || this.renderData.colorTransformsChanged) {
|
|
1515
|
-
this.renderData.dataChanged && (l.activeTexture(l.TEXTURE0), l.bindTexture(l.TEXTURE_2D, this.splatTexture), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_S, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_T, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MIN_FILTER, l.NEAREST), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MAG_FILTER, l.NEAREST), l.texImage2D(l.TEXTURE_2D, 0, l.RGBA32UI, this.renderData.width, this.renderData.height, 0, l.RGBA_INTEGER, l.UNSIGNED_INT, this.renderData.data)), this.renderData.transformsChanged && (l.activeTexture(l.TEXTURE1), l.bindTexture(l.TEXTURE_2D, C), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_S, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_T, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MIN_FILTER, l.NEAREST), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MAG_FILTER, l.NEAREST), l.texImage2D(l.TEXTURE_2D, 0, l.RGBA32F, this.renderData.transformsWidth, this.renderData.transformsHeight, 0, l.RGBA, l.FLOAT, this.renderData.transforms), l.activeTexture(l.TEXTURE2), l.bindTexture(l.TEXTURE_2D, k), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_S, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_T, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MIN_FILTER, l.NEAREST), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MAG_FILTER, l.NEAREST), l.texImage2D(l.TEXTURE_2D, 0, l.R32UI, this.renderData.transformIndicesWidth, this.renderData.transformIndicesHeight, 0, l.RED_INTEGER, l.UNSIGNED_INT, this.renderData.transformIndices)), this.renderData.colorTransformsChanged && (l.activeTexture(l.TEXTURE3), l.bindTexture(l.TEXTURE_2D, p), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_S, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_T, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MIN_FILTER, l.NEAREST), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MAG_FILTER, l.NEAREST), l.texImage2D(l.TEXTURE_2D, 0, l.RGBA32F, this.renderData.colorTransformsWidth, this.renderData.colorTransformsHeight, 0, l.RGBA, l.FLOAT, this.renderData.colorTransforms), l.activeTexture(l.TEXTURE4), l.bindTexture(l.TEXTURE_2D, X), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_S, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_T, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MIN_FILTER, l.NEAREST), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MAG_FILTER, l.NEAREST), l.texImage2D(l.TEXTURE_2D, 0, l.R32UI, this.renderData.colorTransformIndicesWidth, this.renderData.colorTransformIndicesHeight, 0, l.RED_INTEGER, l.UNSIGNED_INT, this.renderData.colorTransformIndices));
|
|
1516
|
-
const at = new Float32Array(this.renderData.positions.slice().buffer), L = new Float32Array(this.renderData.transforms.slice().buffer), o = new Uint32Array(this.renderData.transformIndices.slice().buffer);
|
|
1517
|
-
(Y = this._worker) === null || Y === void 0 || Y.postMessage({ sortData: { positions: at, transforms: L, transformIndices: o, vertexCount: this.renderData.vertexCount } }, [at.buffer, L.buffer, o.buffer]), this.renderData.dataChanged = !1, this.renderData.transformsChanged = !1, this.renderData.colorTransformsChanged = !1;
|
|
1518
|
-
}
|
|
1519
|
-
this._camera.update(), (H = this._worker) === null || H === void 0 || H.postMessage({ viewProj: this._camera.data.viewProj.buffer }), l.viewport(0, 0, U.width, U.height), l.clearColor(0, 0, 0, 0), l.clear(l.COLOR_BUFFER_BIT), l.disable(l.DEPTH_TEST), l.enable(l.BLEND), l.blendFuncSeparate(l.ONE_MINUS_DST_ALPHA, l.ONE, l.ONE_MINUS_DST_ALPHA, l.ONE), l.blendEquationSeparate(l.FUNC_ADD, l.FUNC_ADD), l.uniformMatrix4fv(a, !1, this._camera.data.projectionMatrix.buffer), l.uniformMatrix4fv(Q, !1, this._camera.data.viewMatrix.buffer), l.bindBuffer(l.ARRAY_BUFFER, D), l.vertexAttribPointer(J, 2, l.FLOAT, !1, 0, 0), l.bindBuffer(l.ARRAY_BUFFER, u), l.bufferData(l.ARRAY_BUFFER, this.depthIndex, l.STATIC_DRAW), l.vertexAttribIPointer(h, 1, l.INT, 0, 0), l.vertexAttribDivisor(h, 1), l.drawArraysInstanced(l.TRIANGLE_FAN, 0, 4, this.renderData.vertexCount);
|
|
1520
|
-
} else console.error("Cannot render without scene and camera");
|
|
1521
|
-
}, this._dispose = () => {
|
|
1522
|
-
var Y;
|
|
1523
|
-
if (this._scene && this._camera && this.renderData) {
|
|
1524
|
-
this._scene.removeEventListener("objectAdded", E), this._scene.removeEventListener("objectRemoved", w);
|
|
1525
|
-
for (const H of this._scene.objects) H instanceof dt && H.removeEventListener("objectChanged", Ft);
|
|
1526
|
-
(Y = this._worker) === null || Y === void 0 || Y.terminate(), this.renderData.dispose(), l.deleteTexture(this.splatTexture), l.deleteTexture(C), l.deleteTexture(k), l.deleteBuffer(u), l.deleteBuffer(D);
|
|
1527
|
-
} else console.error("Cannot dispose without scene and camera");
|
|
1528
|
-
}, this._setOutlineThickness = (Y) => {
|
|
1529
|
-
this._outlineThickness = Y, this._initialized && l.uniform1f(B, Y);
|
|
1530
|
-
}, this._setOutlineColor = (Y) => {
|
|
1531
|
-
this._outlineColor = Y, this._initialized && l.uniform4fv(W, new Float32Array(Y.flatNorm()));
|
|
1532
|
-
};
|
|
1533
|
-
}
|
|
1534
|
-
get renderData() {
|
|
1535
|
-
return this._renderData;
|
|
1536
|
-
}
|
|
1537
|
-
get depthIndex() {
|
|
1538
|
-
return this._depthIndex;
|
|
1539
|
-
}
|
|
1540
|
-
get splatTexture() {
|
|
1541
|
-
return this._splatTexture;
|
|
1542
|
-
}
|
|
1543
|
-
get outlineThickness() {
|
|
1544
|
-
return this._outlineThickness;
|
|
1545
|
-
}
|
|
1546
|
-
set outlineThickness(t) {
|
|
1547
|
-
this._setOutlineThickness(t);
|
|
1548
|
-
}
|
|
1549
|
-
get outlineColor() {
|
|
1550
|
-
return this._outlineColor;
|
|
1551
|
-
}
|
|
1552
|
-
set outlineColor(t) {
|
|
1553
|
-
this._setOutlineColor(t);
|
|
1554
|
-
}
|
|
1555
|
-
get worker() {
|
|
1556
|
-
return this._worker;
|
|
1557
|
-
}
|
|
1558
|
-
_getVertexSource() {
|
|
1559
|
-
return `#version 300 es
|
|
1560
|
-
precision highp float;
|
|
1561
|
-
precision highp int;
|
|
1562
|
-
|
|
1563
|
-
uniform highp usampler2D u_texture;
|
|
1564
|
-
uniform highp sampler2D u_transforms;
|
|
1565
|
-
uniform highp usampler2D u_transformIndices;
|
|
1566
|
-
uniform highp sampler2D u_colorTransforms;
|
|
1567
|
-
uniform highp usampler2D u_colorTransformIndices;
|
|
1568
|
-
uniform mat4 projection, view;
|
|
1569
|
-
uniform vec2 focal;
|
|
1570
|
-
uniform vec2 viewport;
|
|
1571
|
-
|
|
1572
|
-
uniform bool useDepthFade;
|
|
1573
|
-
uniform float depthFade;
|
|
1574
|
-
|
|
1575
|
-
in vec2 position;
|
|
1576
|
-
in int index;
|
|
1577
|
-
|
|
1578
|
-
out vec4 vColor;
|
|
1579
|
-
out vec2 vPosition;
|
|
1580
|
-
out float vSize;
|
|
1581
|
-
out float vSelected;
|
|
1582
|
-
|
|
1583
|
-
void main () {
|
|
1584
|
-
uvec4 cen = texelFetch(u_texture, ivec2((uint(index) & 0x3ffu) << 1, uint(index) >> 10), 0);
|
|
1585
|
-
float selected = float((cen.w >> 24) & 0xffu);
|
|
1586
|
-
|
|
1587
|
-
uint transformIndex = texelFetch(u_transformIndices, ivec2(uint(index) & 0x3ffu, uint(index) >> 10), 0).x;
|
|
1588
|
-
mat4 transform = mat4(
|
|
1589
|
-
texelFetch(u_transforms, ivec2(0, transformIndex), 0),
|
|
1590
|
-
texelFetch(u_transforms, ivec2(1, transformIndex), 0),
|
|
1591
|
-
texelFetch(u_transforms, ivec2(2, transformIndex), 0),
|
|
1592
|
-
texelFetch(u_transforms, ivec2(3, transformIndex), 0)
|
|
1593
|
-
);
|
|
1594
|
-
|
|
1595
|
-
if (selected < 0.5) {
|
|
1596
|
-
selected = texelFetch(u_transforms, ivec2(4, transformIndex), 0).x;
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1599
|
-
mat4 viewTransform = view * transform;
|
|
1600
|
-
|
|
1601
|
-
vec4 cam = viewTransform * vec4(uintBitsToFloat(cen.xyz), 1);
|
|
1602
|
-
vec4 pos2d = projection * cam;
|
|
1603
|
-
|
|
1604
|
-
float clip = 1.2 * pos2d.w;
|
|
1605
|
-
if (pos2d.z < -pos2d.w || pos2d.z > pos2d.w || pos2d.x < -clip || pos2d.x > clip || pos2d.y < -clip || pos2d.y > clip) {
|
|
1606
|
-
gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
|
|
1607
|
-
return;
|
|
1608
|
-
}
|
|
1609
|
-
|
|
1610
|
-
uvec4 cov = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 1) | 1u, uint(index) >> 10), 0);
|
|
1611
|
-
vec2 u1 = unpackHalf2x16(cov.x), u2 = unpackHalf2x16(cov.y), u3 = unpackHalf2x16(cov.z);
|
|
1612
|
-
mat3 Vrk = mat3(u1.x, u1.y, u2.x, u1.y, u2.y, u3.x, u2.x, u3.x, u3.y);
|
|
1613
|
-
|
|
1614
|
-
mat3 J = mat3(
|
|
1615
|
-
focal.x / cam.z, 0., -(focal.x * cam.x) / (cam.z * cam.z),
|
|
1616
|
-
0., -focal.y / cam.z, (focal.y * cam.y) / (cam.z * cam.z),
|
|
1617
|
-
0., 0., 0.
|
|
1618
|
-
);
|
|
1619
|
-
|
|
1620
|
-
mat3 T = transpose(mat3(viewTransform)) * J;
|
|
1621
|
-
mat3 cov2d = transpose(T) * Vrk * T;
|
|
1622
|
-
|
|
1623
|
-
//ref: https://github.com/graphdeco-inria/diff-gaussian-rasterization/blob/main/cuda_rasterizer/forward.cu#L110-L111
|
|
1624
|
-
cov2d[0][0] += 0.3;
|
|
1625
|
-
cov2d[1][1] += 0.3;
|
|
1626
|
-
|
|
1627
|
-
float mid = (cov2d[0][0] + cov2d[1][1]) / 2.0;
|
|
1628
|
-
float radius = length(vec2((cov2d[0][0] - cov2d[1][1]) / 2.0, cov2d[0][1]));
|
|
1629
|
-
float lambda1 = mid + radius, lambda2 = mid - radius;
|
|
1630
|
-
|
|
1631
|
-
if (lambda2 < 0.0) return;
|
|
1632
|
-
vec2 diagonalVector = normalize(vec2(cov2d[0][1], lambda1 - cov2d[0][0]));
|
|
1633
|
-
vec2 majorAxis = min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector;
|
|
1634
|
-
vec2 minorAxis = min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x);
|
|
1635
|
-
|
|
1636
|
-
uint colorTransformIndex = texelFetch(u_colorTransformIndices, ivec2(uint(index) & 0x3ffu, uint(index) >> 10), 0).x;
|
|
1637
|
-
mat4 colorTransform = mat4(
|
|
1638
|
-
texelFetch(u_colorTransforms, ivec2(0, colorTransformIndex), 0),
|
|
1639
|
-
texelFetch(u_colorTransforms, ivec2(1, colorTransformIndex), 0),
|
|
1640
|
-
texelFetch(u_colorTransforms, ivec2(2, colorTransformIndex), 0),
|
|
1641
|
-
texelFetch(u_colorTransforms, ivec2(3, colorTransformIndex), 0)
|
|
1642
|
-
);
|
|
1643
|
-
|
|
1644
|
-
vec4 color = vec4((cov.w) & 0xffu, (cov.w >> 8) & 0xffu, (cov.w >> 16) & 0xffu, (cov.w >> 24) & 0xffu) / 255.0;
|
|
1645
|
-
vColor = colorTransform * color;
|
|
1646
|
-
|
|
1647
|
-
vPosition = position;
|
|
1648
|
-
vSize = length(majorAxis);
|
|
1649
|
-
vSelected = selected;
|
|
1650
|
-
|
|
1651
|
-
float scalingFactor = 1.0;
|
|
1652
|
-
|
|
1653
|
-
if (useDepthFade) {
|
|
1654
|
-
float depthNorm = (pos2d.z / pos2d.w + 1.0) / 2.0;
|
|
1655
|
-
float near = 0.1; float far = 100.0;
|
|
1656
|
-
float normalizedDepth = (2.0 * near) / (far + near - depthNorm * (far - near));
|
|
1657
|
-
float start = max(normalizedDepth - 0.1, 0.0);
|
|
1658
|
-
float end = min(normalizedDepth + 0.1, 1.0);
|
|
1659
|
-
scalingFactor = clamp((depthFade - start) / (end - start), 0.0, 1.0);
|
|
1660
|
-
}
|
|
1661
|
-
|
|
1662
|
-
vec2 vCenter = vec2(pos2d) / pos2d.w;
|
|
1663
|
-
gl_Position = vec4(
|
|
1664
|
-
vCenter
|
|
1665
|
-
+ position.x * majorAxis * scalingFactor / viewport
|
|
1666
|
-
+ position.y * minorAxis * scalingFactor / viewport, 0.0, 1.0);
|
|
1667
|
-
}
|
|
1668
|
-
`;
|
|
1669
|
-
}
|
|
1670
|
-
_getFragmentSource() {
|
|
1671
|
-
return `#version 300 es
|
|
1672
|
-
precision highp float;
|
|
1673
|
-
|
|
1674
|
-
uniform float outlineThickness;
|
|
1675
|
-
uniform vec4 outlineColor;
|
|
1676
|
-
|
|
1677
|
-
in vec4 vColor;
|
|
1678
|
-
in vec2 vPosition;
|
|
1679
|
-
in float vSize;
|
|
1680
|
-
in float vSelected;
|
|
1681
|
-
|
|
1682
|
-
out vec4 fragColor;
|
|
1683
|
-
|
|
1684
|
-
void main () {
|
|
1685
|
-
float A = -dot(vPosition, vPosition);
|
|
1686
|
-
|
|
1687
|
-
if (A < -4.0) discard;
|
|
1688
|
-
|
|
1689
|
-
if (vSelected < 0.5) {
|
|
1690
|
-
float B = exp(A) * vColor.a;
|
|
1691
|
-
fragColor = vec4(B * vColor.rgb, B);
|
|
1692
|
-
return;
|
|
1693
|
-
}
|
|
1694
|
-
|
|
1695
|
-
float outlineThreshold = -4.0 + (outlineThickness / vSize);
|
|
1696
|
-
|
|
1697
|
-
if (A < outlineThreshold) {
|
|
1698
|
-
fragColor = outlineColor;
|
|
1699
|
-
}
|
|
1700
|
-
else {
|
|
1701
|
-
float B = exp(A) * vColor.a;
|
|
1702
|
-
fragColor = vec4(B * vColor.rgb, B);
|
|
1703
|
-
}
|
|
1704
|
-
}
|
|
1705
|
-
`;
|
|
1706
|
-
}
|
|
1707
|
-
}
|
|
1708
|
-
class el {
|
|
1709
|
-
constructor(t = 1) {
|
|
1710
|
-
let F, U, l, a, n = 0, e = !1;
|
|
1711
|
-
this.initialize = (Q) => {
|
|
1712
|
-
if (!(Q instanceof Yt)) throw new Error("FadeInPass requires a RenderProgram");
|
|
1713
|
-
n = Q.started ? 1 : 0, e = !0, F = Q, U = Q.renderer.gl, l = U.getUniformLocation(F.program, "useDepthFade"), U.uniform1i(l, 1), a = U.getUniformLocation(F.program, "depthFade"), U.uniform1f(a, n);
|
|
1714
|
-
}, this.render = () => {
|
|
1715
|
-
var Q;
|
|
1716
|
-
e && !(!((Q = F.renderData) === null || Q === void 0) && Q.updating) && (U.useProgram(F.program), n = Math.min(n + 0.01 * t, 1), n >= 1 && (e = !1, U.uniform1i(l, 0)), U.uniform1f(a, n));
|
|
1717
|
-
};
|
|
1718
|
-
}
|
|
1719
|
-
dispose() {
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
|
-
class Bl {
|
|
1723
|
-
constructor(t = null, F = null) {
|
|
1724
|
-
this._backgroundColor = new ut();
|
|
1725
|
-
const U = t || document.createElement("canvas");
|
|
1726
|
-
t || (U.style.display = "block", U.style.boxSizing = "border-box", U.style.width = "100%", U.style.height = "100%", U.style.margin = "0", U.style.padding = "0", document.body.appendChild(U)), U.style.background = this._backgroundColor.toHexString(), this._canvas = U, this._gl = U.getContext("webgl2", { antialias: !1 });
|
|
1727
|
-
const l = F || [];
|
|
1728
|
-
F || l.push(new el()), this._renderProgram = new Yt(this, l);
|
|
1729
|
-
const a = [this._renderProgram];
|
|
1730
|
-
this.resize = () => {
|
|
1731
|
-
const n = U.clientWidth, e = U.clientHeight;
|
|
1732
|
-
U.width === n && U.height === e || this.setSize(n, e);
|
|
1733
|
-
}, this.setSize = (n, e) => {
|
|
1734
|
-
U.width = n, U.height = e, this._gl.viewport(0, 0, U.width, U.height);
|
|
1735
|
-
for (const Q of a) Q.resize();
|
|
1736
|
-
}, this.render = (n, e) => {
|
|
1737
|
-
for (const Q of a) Q.render(n, e);
|
|
1738
|
-
}, this.dispose = () => {
|
|
1739
|
-
for (const n of a) n.dispose();
|
|
1740
|
-
}, this.addProgram = (n) => {
|
|
1741
|
-
a.push(n);
|
|
1742
|
-
}, this.removeProgram = (n) => {
|
|
1743
|
-
const e = a.indexOf(n);
|
|
1744
|
-
if (e < 0) throw new Error("Program not found");
|
|
1745
|
-
a.splice(e, 1);
|
|
1746
|
-
}, this.resize();
|
|
1747
|
-
}
|
|
1748
|
-
get canvas() {
|
|
1749
|
-
return this._canvas;
|
|
1750
|
-
}
|
|
1751
|
-
get gl() {
|
|
1752
|
-
return this._gl;
|
|
1753
|
-
}
|
|
1754
|
-
get renderProgram() {
|
|
1755
|
-
return this._renderProgram;
|
|
1756
|
-
}
|
|
1757
|
-
get backgroundColor() {
|
|
1758
|
-
return this._backgroundColor;
|
|
1759
|
-
}
|
|
1760
|
-
set backgroundColor(t) {
|
|
1761
|
-
this._backgroundColor = t, this._canvas.style.background = t.toHexString();
|
|
1762
|
-
}
|
|
1763
|
-
}
|
|
1764
|
-
class il {
|
|
1765
|
-
constructor(t, F, U = 0.5, l = 0.5, a = 5, n = !0, e = new I()) {
|
|
1766
|
-
this.minAngle = -90, this.maxAngle = 90, this.minZoom = 0.1, this.maxZoom = 30, this.orbitSpeed = 1, this.panSpeed = 1, this.zoomSpeed = 1, this.dampening = 0.12, this.setCameraTarget = () => {
|
|
1767
|
-
};
|
|
1768
|
-
let Q = e.clone(), d = Q.clone(), A = U, i = l, r = a, c = !1, B = !1, W = 0, J = 0, h = 0;
|
|
1769
|
-
const C = {};
|
|
1770
|
-
let k = !1;
|
|
1771
|
-
t.addEventListener("objectChanged", () => {
|
|
1772
|
-
if (k) return;
|
|
1773
|
-
const o = t.rotation.toEuler();
|
|
1774
|
-
A = -o.y, i = -o.x;
|
|
1775
|
-
const T = t.position.x - r * Math.sin(A) * Math.cos(i), v = t.position.y + r * Math.sin(i), x = t.position.z + r * Math.cos(A) * Math.cos(i);
|
|
1776
|
-
d = new I(T, v, x);
|
|
1777
|
-
}), this.setCameraTarget = (o) => {
|
|
1778
|
-
const T = o.x - t.position.x, v = o.y - t.position.y, x = o.z - t.position.z;
|
|
1779
|
-
r = Math.sqrt(T * T + v * v + x * x), i = Math.atan2(v, Math.sqrt(T * T + x * x)), A = -Math.atan2(T, x), d = new I(o.x, o.y, o.z);
|
|
1780
|
-
};
|
|
1781
|
-
const p = () => 0.1 + 0.9 * (r - this.minZoom) / (this.maxZoom - this.minZoom), X = (o) => {
|
|
1782
|
-
C[o.code] = !0, o.code === "ArrowUp" && (C.KeyW = !0), o.code === "ArrowDown" && (C.KeyS = !0), o.code === "ArrowLeft" && (C.KeyA = !0), o.code === "ArrowRight" && (C.KeyD = !0);
|
|
1783
|
-
}, D = (o) => {
|
|
1784
|
-
C[o.code] = !1, o.code === "ArrowUp" && (C.KeyW = !1), o.code === "ArrowDown" && (C.KeyS = !1), o.code === "ArrowLeft" && (C.KeyA = !1), o.code === "ArrowRight" && (C.KeyD = !1);
|
|
1785
|
-
}, u = (o) => {
|
|
1786
|
-
L(o), c = !0, B = o.button === 2, J = o.clientX, h = o.clientY, window.addEventListener("mouseup", M);
|
|
1787
|
-
}, M = (o) => {
|
|
1788
|
-
L(o), c = !1, B = !1, window.removeEventListener("mouseup", M);
|
|
1789
|
-
}, E = (o) => {
|
|
1790
|
-
if (L(o), !c || !t) return;
|
|
1791
|
-
const T = o.clientX - J, v = o.clientY - h;
|
|
1792
|
-
if (B) {
|
|
1793
|
-
const x = p(), At = -T * this.panSpeed * 0.01 * x, Vt = -v * this.panSpeed * 0.01 * x, K = tt.RotationFromQuaternion(t.rotation).buffer, _ = new I(K[0], K[3], K[6]), et = new I(K[1], K[4], K[7]);
|
|
1794
|
-
d = d.add(_.multiply(At)), d = d.add(et.multiply(Vt));
|
|
1795
|
-
} else A -= T * this.orbitSpeed * 3e-3, i += v * this.orbitSpeed * 3e-3, i = Math.min(Math.max(i, this.minAngle * Math.PI / 180), this.maxAngle * Math.PI / 180);
|
|
1796
|
-
J = o.clientX, h = o.clientY;
|
|
1797
|
-
}, w = (o) => {
|
|
1798
|
-
L(o);
|
|
1799
|
-
const T = p();
|
|
1800
|
-
r += o.deltaY * this.zoomSpeed * 0.025 * T, r = Math.min(Math.max(r, this.minZoom), this.maxZoom);
|
|
1801
|
-
}, Ft = (o) => {
|
|
1802
|
-
if (L(o), o.touches.length === 1) c = !0, B = !1, J = o.touches[0].clientX, h = o.touches[0].clientY, W = 0;
|
|
1803
|
-
else if (o.touches.length === 2) {
|
|
1804
|
-
c = !0, B = !0, J = (o.touches[0].clientX + o.touches[1].clientX) / 2, h = (o.touches[0].clientY + o.touches[1].clientY) / 2;
|
|
1805
|
-
const T = o.touches[0].clientX - o.touches[1].clientX, v = o.touches[0].clientY - o.touches[1].clientY;
|
|
1806
|
-
W = Math.sqrt(T * T + v * v);
|
|
1807
|
-
}
|
|
1808
|
-
}, Y = (o) => {
|
|
1809
|
-
L(o), c = !1, B = !1;
|
|
1810
|
-
}, H = (o) => {
|
|
1811
|
-
if (L(o), c && t) if (B) {
|
|
1812
|
-
const T = p(), v = o.touches[0].clientX - o.touches[1].clientX, x = o.touches[0].clientY - o.touches[1].clientY, At = Math.sqrt(v * v + x * x);
|
|
1813
|
-
r += (W - At) * this.zoomSpeed * 0.1 * T, r = Math.min(Math.max(r, this.minZoom), this.maxZoom), W = At;
|
|
1814
|
-
const Vt = (o.touches[0].clientX + o.touches[1].clientX) / 2, K = (o.touches[0].clientY + o.touches[1].clientY) / 2, _ = Vt - J, et = K - h, j = tt.RotationFromQuaternion(t.rotation).buffer, Rt = new I(j[0], j[3], j[6]), It = new I(j[1], j[4], j[7]);
|
|
1815
|
-
d = d.add(Rt.multiply(-_ * this.panSpeed * 0.025 * T)), d = d.add(It.multiply(-et * this.panSpeed * 0.025 * T)), J = Vt, h = K;
|
|
1816
|
-
} else {
|
|
1817
|
-
const T = o.touches[0].clientX - J, v = o.touches[0].clientY - h;
|
|
1818
|
-
A -= T * this.orbitSpeed * 3e-3, i += v * this.orbitSpeed * 3e-3, i = Math.min(Math.max(i, this.minAngle * Math.PI / 180), this.maxAngle * Math.PI / 180), J = o.touches[0].clientX, h = o.touches[0].clientY;
|
|
1819
|
-
}
|
|
1820
|
-
}, at = (o, T, v) => (1 - v) * o + v * T;
|
|
1821
|
-
this.update = () => {
|
|
1822
|
-
k = !0, U = at(U, A, this.dampening), l = at(l, i, this.dampening), a = at(a, r, this.dampening), Q = Q.lerp(d, this.dampening);
|
|
1823
|
-
const o = Q.x + a * Math.sin(U) * Math.cos(l), T = Q.y - a * Math.sin(l), v = Q.z - a * Math.cos(U) * Math.cos(l);
|
|
1824
|
-
t.position = new I(o, T, v);
|
|
1825
|
-
const x = Q.subtract(t.position).normalize(), At = Math.asin(-x.y), Vt = Math.atan2(x.x, x.z);
|
|
1826
|
-
t.rotation = z.FromEuler(new I(At, Vt, 0));
|
|
1827
|
-
const K = 0.025, _ = 0.01, et = tt.RotationFromQuaternion(t.rotation).buffer, j = new I(-et[2], -et[5], -et[8]), Rt = new I(et[0], et[3], et[6]);
|
|
1828
|
-
C.KeyS && (d = d.add(j.multiply(K))), C.KeyW && (d = d.subtract(j.multiply(K))), C.KeyA && (d = d.subtract(Rt.multiply(K))), C.KeyD && (d = d.add(Rt.multiply(K))), C.KeyE && (A += _), C.KeyQ && (A -= _), C.KeyR && (i += _), C.KeyF && (i -= _), k = !1;
|
|
1829
|
-
};
|
|
1830
|
-
const L = (o) => {
|
|
1831
|
-
o.preventDefault(), o.stopPropagation();
|
|
1832
|
-
};
|
|
1833
|
-
this.dispose = () => {
|
|
1834
|
-
F.removeEventListener("dragenter", L), F.removeEventListener("dragover", L), F.removeEventListener("dragleave", L), F.removeEventListener("contextmenu", L), F.removeEventListener("mousedown", u), F.removeEventListener("mousemove", E), F.removeEventListener("wheel", w), F.removeEventListener("touchstart", Ft), F.removeEventListener("touchend", Y), F.removeEventListener("touchmove", H), n && (window.removeEventListener("keydown", X), window.removeEventListener("keyup", D));
|
|
1835
|
-
}, n && (window.addEventListener("keydown", X), window.addEventListener("keyup", D)), F.addEventListener("dragenter", L), F.addEventListener("dragover", L), F.addEventListener("dragleave", L), F.addEventListener("contextmenu", L), F.addEventListener("mousedown", u), F.addEventListener("mousemove", E), F.addEventListener("wheel", w), F.addEventListener("touchstart", Ft), F.addEventListener("touchend", Y), F.addEventListener("touchmove", H), this.update();
|
|
1836
|
-
}
|
|
1837
|
-
}
|
|
1838
|
-
class sl {
|
|
1839
|
-
constructor(t, F) {
|
|
1840
|
-
this.moveSpeed = 1.5, this.lookSpeed = 0.7, this.dampening = 0.5;
|
|
1841
|
-
const U = {};
|
|
1842
|
-
let l = t.rotation.toEuler().x, a = t.rotation.toEuler().y, n = t.position, e = !1;
|
|
1843
|
-
const Q = () => {
|
|
1844
|
-
F.requestPointerLock();
|
|
1845
|
-
}, d = () => {
|
|
1846
|
-
e = document.pointerLockElement === F, e ? F.addEventListener("mousemove", A) : F.removeEventListener("mousemove", A);
|
|
1847
|
-
}, A = (B) => {
|
|
1848
|
-
const W = B.movementX, J = B.movementY;
|
|
1849
|
-
a += W * this.lookSpeed * 1e-3, l -= J * this.lookSpeed * 1e-3, l = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, l));
|
|
1850
|
-
}, i = (B) => {
|
|
1851
|
-
U[B.code] = !0, B.code === "ArrowUp" && (U.KeyW = !0), B.code === "ArrowDown" && (U.KeyS = !0), B.code === "ArrowLeft" && (U.KeyA = !0), B.code === "ArrowRight" && (U.KeyD = !0);
|
|
1852
|
-
}, r = (B) => {
|
|
1853
|
-
U[B.code] = !1, B.code === "ArrowUp" && (U.KeyW = !1), B.code === "ArrowDown" && (U.KeyS = !1), B.code === "ArrowLeft" && (U.KeyA = !1), B.code === "ArrowRight" && (U.KeyD = !1), B.code === "Escape" && document.exitPointerLock();
|
|
1854
|
-
};
|
|
1855
|
-
this.update = () => {
|
|
1856
|
-
const B = tt.RotationFromQuaternion(t.rotation).buffer, W = new I(-B[2], -B[5], -B[8]), J = new I(B[0], B[3], B[6]);
|
|
1857
|
-
let h = new I(0, 0, 0);
|
|
1858
|
-
U.KeyS && (h = h.add(W)), U.KeyW && (h = h.subtract(W)), U.KeyA && (h = h.subtract(J)), U.KeyD && (h = h.add(J)), h = new I(h.x, 0, h.z), h.magnitude() > 0 && (h = h.normalize()), n = n.add(h.multiply(0.01 * this.moveSpeed)), t.position = t.position.add(n.subtract(t.position).multiply(this.dampening)), t.rotation = z.FromEuler(new I(l, a, 0));
|
|
1859
|
-
};
|
|
1860
|
-
const c = (B) => {
|
|
1861
|
-
B.preventDefault(), B.stopPropagation();
|
|
1862
|
-
};
|
|
1863
|
-
this.dispose = () => {
|
|
1864
|
-
F.removeEventListener("dragenter", c), F.removeEventListener("dragover", c), F.removeEventListener("dragleave", c), F.removeEventListener("contextmenu", c), F.removeEventListener("mousedown", Q), document.removeEventListener("pointerlockchange", d), window.removeEventListener("keydown", i), window.removeEventListener("keyup", r);
|
|
1865
|
-
}, window.addEventListener("keydown", i), window.addEventListener("keyup", r), F.addEventListener("dragenter", c), F.addEventListener("dragover", c), F.addEventListener("dragleave", c), F.addEventListener("contextmenu", c), F.addEventListener("mousedown", Q), document.addEventListener("pointerlockchange", d), this.update();
|
|
1866
|
-
}
|
|
1867
|
-
}
|
|
1868
|
-
class Zl {
|
|
1869
|
-
constructor(t, F) {
|
|
1870
|
-
this.normal = t, this.point = F;
|
|
1871
|
-
}
|
|
1872
|
-
intersect(t, F) {
|
|
1873
|
-
const U = this.normal.dot(F);
|
|
1874
|
-
if (Math.abs(U) < 1e-4) return null;
|
|
1875
|
-
const l = this.normal.dot(this.point.subtract(t)) / U;
|
|
1876
|
-
return l < 0 ? null : t.add(F.multiply(l));
|
|
1877
|
-
}
|
|
1878
|
-
}
|
|
1879
|
-
class Rl {
|
|
1880
|
-
initialize(t) {
|
|
1881
|
-
}
|
|
1882
|
-
render() {
|
|
1883
|
-
}
|
|
1884
|
-
dispose() {
|
|
1885
|
-
}
|
|
1886
|
-
}
|
|
1887
|
-
class cl extends St {
|
|
1888
|
-
constructor(t, F = []) {
|
|
1889
|
-
super(t, F), this._renderData = null, this._depthIndex = new Uint32Array(), this._splatTexture = null;
|
|
1890
|
-
const U = t.canvas, l = t.gl;
|
|
1891
|
-
let a, n, e, Q, d, A, i, r, c, B, W;
|
|
1892
|
-
this._resize = () => {
|
|
1893
|
-
this._camera && (this._camera.data.setSize(U.width, U.height), this._camera.update(), n = l.getUniformLocation(this.program, "projection"), l.uniformMatrix4fv(n, !1, this._camera.data.projectionMatrix.buffer), e = l.getUniformLocation(this.program, "viewport"), l.uniform2fv(e, new Float32Array([U.width, U.height])));
|
|
1894
|
-
};
|
|
1895
|
-
const J = () => {
|
|
1896
|
-
t.renderProgram.worker !== null ? (a = t.renderProgram.worker, a.onmessage = (p) => {
|
|
1897
|
-
if (p.data.depthIndex) {
|
|
1898
|
-
const { depthIndex: X } = p.data;
|
|
1899
|
-
this._depthIndex = X, l.bindBuffer(l.ARRAY_BUFFER, W), l.bufferData(l.ARRAY_BUFFER, X, l.STATIC_DRAW);
|
|
1900
|
-
}
|
|
1901
|
-
}) : console.error("Render program is not initialized. Cannot render without worker");
|
|
1902
|
-
};
|
|
1903
|
-
this._initialize = () => {
|
|
1904
|
-
if (!this._scene || !this._camera) return void console.error("Cannot render without scene and camera");
|
|
1905
|
-
this._resize(), this._scene.addEventListener("objectAdded", h), this._scene.addEventListener("objectRemoved", C);
|
|
1906
|
-
for (const u of this._scene.objects) u instanceof ct && (this._renderData === null ? (this._renderData = u.data, u.addEventListener("objectChanged", k)) : console.warn("Multiple Splatv objects are not currently supported"));
|
|
1907
|
-
if (this._renderData === null) return void console.error("Cannot render without Splatv object");
|
|
1908
|
-
Q = l.getUniformLocation(this.program, "focal"), l.uniform2fv(Q, new Float32Array([this._camera.data.fx, this._camera.data.fy])), d = l.getUniformLocation(this.program, "view"), l.uniformMatrix4fv(d, !1, this._camera.data.viewMatrix.buffer), this._splatTexture = l.createTexture(), A = l.getUniformLocation(this.program, "u_texture"), l.uniform1i(A, 0), i = l.getUniformLocation(this.program, "time"), l.uniform1f(i, Math.sin(Date.now() / 1e3) / 2 + 0.5), B = l.createBuffer(), l.bindBuffer(l.ARRAY_BUFFER, B), l.bufferData(l.ARRAY_BUFFER, new Float32Array([-2, -2, 2, -2, 2, 2, -2, 2]), l.STATIC_DRAW), r = l.getAttribLocation(this.program, "position"), l.enableVertexAttribArray(r), l.vertexAttribPointer(r, 2, l.FLOAT, !1, 0, 0), W = l.createBuffer(), c = l.getAttribLocation(this.program, "index"), l.enableVertexAttribArray(c), l.bindBuffer(l.ARRAY_BUFFER, W), J(), l.activeTexture(l.TEXTURE0), l.bindTexture(l.TEXTURE_2D, this._splatTexture), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_S, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_WRAP_T, l.CLAMP_TO_EDGE), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MIN_FILTER, l.NEAREST), l.texParameteri(l.TEXTURE_2D, l.TEXTURE_MAG_FILTER, l.NEAREST), l.texImage2D(l.TEXTURE_2D, 0, l.RGBA32UI, this._renderData.width, this._renderData.height, 0, l.RGBA_INTEGER, l.UNSIGNED_INT, this._renderData.data);
|
|
1909
|
-
const p = this._renderData.positions, X = new Float32Array(new Ut().buffer), D = new Uint32Array(this._renderData.vertexCount);
|
|
1910
|
-
D.fill(0), a.postMessage({ sortData: { positions: p, transforms: X, transformIndices: D, vertexCount: this._renderData.vertexCount } }, [p.buffer, X.buffer, D.buffer]);
|
|
1911
|
-
};
|
|
1912
|
-
const h = (p) => {
|
|
1913
|
-
const X = p;
|
|
1914
|
-
X.object instanceof ct && (this._renderData === null ? (this._renderData = X.object.data, X.object.addEventListener("objectChanged", k)) : console.warn("Splatv not supported by default RenderProgram. Use VideoRenderProgram instead.")), this.dispose();
|
|
1915
|
-
}, C = (p) => {
|
|
1916
|
-
const X = p;
|
|
1917
|
-
X.object instanceof ct && this._renderData === X.object.data && (this._renderData = null, X.object.removeEventListener("objectChanged", k)), this.dispose();
|
|
1918
|
-
}, k = (p) => {
|
|
1919
|
-
const X = p;
|
|
1920
|
-
X.object instanceof ct && this._renderData === X.object.data && this.dispose();
|
|
1921
|
-
};
|
|
1922
|
-
this._render = () => {
|
|
1923
|
-
this._scene && this._camera ? this._renderData ? (this._camera.update(), a.postMessage({ viewProj: this._camera.data.viewProj.buffer }), l.viewport(0, 0, U.width, U.height), l.clearColor(0, 0, 0, 0), l.clear(l.COLOR_BUFFER_BIT), l.disable(l.DEPTH_TEST), l.enable(l.BLEND), l.blendFuncSeparate(l.ONE_MINUS_DST_ALPHA, l.ONE, l.ONE_MINUS_DST_ALPHA, l.ONE), l.blendEquationSeparate(l.FUNC_ADD, l.FUNC_ADD), l.uniformMatrix4fv(n, !1, this._camera.data.projectionMatrix.buffer), l.uniformMatrix4fv(d, !1, this._camera.data.viewMatrix.buffer), l.uniform1f(i, Math.sin(Date.now() / 1e3) / 2 + 0.5), l.bindBuffer(l.ARRAY_BUFFER, B), l.vertexAttribPointer(r, 2, l.FLOAT, !1, 0, 0), l.bindBuffer(l.ARRAY_BUFFER, W), l.bufferData(l.ARRAY_BUFFER, this._depthIndex, l.STATIC_DRAW), l.vertexAttribIPointer(c, 1, l.INT, 0, 0), l.vertexAttribDivisor(c, 1), l.drawArraysInstanced(l.TRIANGLE_FAN, 0, 4, this._renderData.vertexCount)) : console.warn("Cannot render without Splatv object") : console.error("Cannot render without scene and camera");
|
|
1924
|
-
}, this._dispose = () => {
|
|
1925
|
-
if (this._scene && this._camera) {
|
|
1926
|
-
this._scene.removeEventListener("objectAdded", h), this._scene.removeEventListener("objectRemoved", C);
|
|
1927
|
-
for (const p of this._scene.objects) p instanceof ct && this._renderData === p.data && (this._renderData = null, p.removeEventListener("objectChanged", k));
|
|
1928
|
-
a == null || a.terminate(), l.deleteTexture(this._splatTexture), l.deleteBuffer(W), l.deleteBuffer(B);
|
|
1929
|
-
} else console.error("Cannot dispose without scene and camera");
|
|
1930
|
-
};
|
|
1931
|
-
}
|
|
1932
|
-
get renderData() {
|
|
1933
|
-
return this._renderData;
|
|
1934
|
-
}
|
|
1935
|
-
_getVertexSource() {
|
|
1936
|
-
return `#version 300 es
|
|
1937
|
-
precision highp float;
|
|
1938
|
-
precision highp int;
|
|
1939
|
-
|
|
1940
|
-
uniform highp usampler2D u_texture;
|
|
1941
|
-
uniform mat4 projection, view;
|
|
1942
|
-
uniform vec2 focal;
|
|
1943
|
-
uniform vec2 viewport;
|
|
1944
|
-
uniform float time;
|
|
1945
|
-
|
|
1946
|
-
in vec2 position;
|
|
1947
|
-
in int index;
|
|
1948
|
-
|
|
1949
|
-
out vec4 vColor;
|
|
1950
|
-
out vec2 vPosition;
|
|
1951
|
-
|
|
1952
|
-
void main () {
|
|
1953
|
-
gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
|
|
1954
|
-
|
|
1955
|
-
uvec4 motion1 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2) | 3u, uint(index) >> 10), 0);
|
|
1956
|
-
vec2 trbf = unpackHalf2x16(motion1.w);
|
|
1957
|
-
float dt = time - trbf.x;
|
|
1958
|
-
|
|
1959
|
-
float topacity = exp(-1.0 * pow(dt / trbf.y, 2.0));
|
|
1960
|
-
if(topacity < 0.02) return;
|
|
1961
|
-
|
|
1962
|
-
uvec4 motion0 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2) | 2u, uint(index) >> 10), 0);
|
|
1963
|
-
uvec4 static0 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2), uint(index) >> 10), 0);
|
|
1964
|
-
|
|
1965
|
-
vec2 m0 = unpackHalf2x16(motion0.x), m1 = unpackHalf2x16(motion0.y), m2 = unpackHalf2x16(motion0.z),
|
|
1966
|
-
m3 = unpackHalf2x16(motion0.w), m4 = unpackHalf2x16(motion1.x);
|
|
1967
|
-
|
|
1968
|
-
vec4 trot = vec4(unpackHalf2x16(motion1.y).xy, unpackHalf2x16(motion1.z).xy) * dt;
|
|
1969
|
-
vec3 tpos = (vec3(m0.xy, m1.x) * dt + vec3(m1.y, m2.xy) * dt*dt + vec3(m3.xy, m4.x) * dt*dt*dt);
|
|
1970
|
-
|
|
1971
|
-
vec4 cam = view * vec4(uintBitsToFloat(static0.xyz) + tpos, 1);
|
|
1972
|
-
vec4 pos = projection * cam;
|
|
1973
|
-
|
|
1974
|
-
float clip = 1.2 * pos.w;
|
|
1975
|
-
if (pos.z < -clip || pos.x < -clip || pos.x > clip || pos.y < -clip || pos.y > clip) return;
|
|
1976
|
-
uvec4 static1 = texelFetch(u_texture, ivec2(((uint(index) & 0x3ffu) << 2) | 1u, uint(index) >> 10), 0);
|
|
1977
|
-
|
|
1978
|
-
vec4 rot = vec4(unpackHalf2x16(static0.w).xy, unpackHalf2x16(static1.x).xy) + trot;
|
|
1979
|
-
vec3 scale = vec3(unpackHalf2x16(static1.y).xy, unpackHalf2x16(static1.z).x);
|
|
1980
|
-
rot /= sqrt(dot(rot, rot));
|
|
1981
|
-
|
|
1982
|
-
mat3 S = mat3(scale.x, 0.0, 0.0, 0.0, scale.y, 0.0, 0.0, 0.0, scale.z);
|
|
1983
|
-
mat3 R = mat3(
|
|
1984
|
-
1.0 - 2.0 * (rot.z * rot.z + rot.w * rot.w), 2.0 * (rot.y * rot.z - rot.x * rot.w), 2.0 * (rot.y * rot.w + rot.x * rot.z),
|
|
1985
|
-
2.0 * (rot.y * rot.z + rot.x * rot.w), 1.0 - 2.0 * (rot.y * rot.y + rot.w * rot.w), 2.0 * (rot.z * rot.w - rot.x * rot.y),
|
|
1986
|
-
2.0 * (rot.y * rot.w - rot.x * rot.z), 2.0 * (rot.z * rot.w + rot.x * rot.y), 1.0 - 2.0 * (rot.y * rot.y + rot.z * rot.z));
|
|
1987
|
-
mat3 M = S * R;
|
|
1988
|
-
mat3 Vrk = 4.0 * transpose(M) * M;
|
|
1989
|
-
mat3 J = mat3(
|
|
1990
|
-
focal.x / cam.z, 0., -(focal.x * cam.x) / (cam.z * cam.z),
|
|
1991
|
-
0., -focal.y / cam.z, (focal.y * cam.y) / (cam.z * cam.z),
|
|
1992
|
-
0., 0., 0.
|
|
1993
|
-
);
|
|
1994
|
-
|
|
1995
|
-
mat3 T = transpose(mat3(view)) * J;
|
|
1996
|
-
mat3 cov2d = transpose(T) * Vrk * T;
|
|
1997
|
-
|
|
1998
|
-
float mid = (cov2d[0][0] + cov2d[1][1]) / 2.0;
|
|
1999
|
-
float radius = length(vec2((cov2d[0][0] - cov2d[1][1]) / 2.0, cov2d[0][1]));
|
|
2000
|
-
float lambda1 = mid + radius, lambda2 = mid - radius;
|
|
2001
|
-
|
|
2002
|
-
if(lambda2 < 0.0) return;
|
|
2003
|
-
vec2 diagonalVector = normalize(vec2(cov2d[0][1], lambda1 - cov2d[0][0]));
|
|
2004
|
-
vec2 majorAxis = min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector;
|
|
2005
|
-
vec2 minorAxis = min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x);
|
|
2006
|
-
|
|
2007
|
-
uint rgba = static1.w;
|
|
2008
|
-
vColor =
|
|
2009
|
-
clamp(pos.z/pos.w+1.0, 0.0, 1.0) *
|
|
2010
|
-
vec4(1.0, 1.0, 1.0, topacity) *
|
|
2011
|
-
vec4(
|
|
2012
|
-
(rgba) & 0xffu,
|
|
2013
|
-
(rgba >> 8) & 0xffu,
|
|
2014
|
-
(rgba >> 16) & 0xffu,
|
|
2015
|
-
(rgba >> 24) & 0xffu) / 255.0;
|
|
2016
|
-
|
|
2017
|
-
vec2 vCenter = vec2(pos) / pos.w;
|
|
2018
|
-
gl_Position = vec4(
|
|
2019
|
-
vCenter
|
|
2020
|
-
+ position.x * majorAxis / viewport
|
|
2021
|
-
+ position.y * minorAxis / viewport, 0.0, 1.0);
|
|
2022
|
-
|
|
2023
|
-
vPosition = position;
|
|
2024
|
-
}
|
|
2025
|
-
`;
|
|
2026
|
-
}
|
|
2027
|
-
_getFragmentSource() {
|
|
2028
|
-
return `#version 300 es
|
|
2029
|
-
precision highp float;
|
|
2030
|
-
|
|
2031
|
-
in vec4 vColor;
|
|
2032
|
-
in vec2 vPosition;
|
|
2033
|
-
|
|
2034
|
-
out vec4 fragColor;
|
|
2035
|
-
|
|
2036
|
-
void main () {
|
|
2037
|
-
float A = -dot(vPosition, vPosition);
|
|
2038
|
-
if (A < -4.0) discard;
|
|
2039
|
-
float B = exp(A) * vColor.a;
|
|
2040
|
-
fragColor = vec4(B * vColor.rgb, B);
|
|
2041
|
-
}
|
|
2042
|
-
`;
|
|
2043
|
-
}
|
|
2044
|
-
}
|
|
2045
|
-
class ht {
|
|
2046
|
-
constructor(t, F, U) {
|
|
2047
|
-
this.bounds = t, this.boxes = F, this.left = null, this.right = null, this.pointIndices = [], U.length > 1 ? this.split(t, F, U) : U.length > 0 && (this.pointIndices = U);
|
|
2048
|
-
}
|
|
2049
|
-
split(t, F, U) {
|
|
2050
|
-
const l = t.size().maxComponent();
|
|
2051
|
-
U.sort((Q, d) => F[Q].center().getComponent(l) - F[d].center().getComponent(l));
|
|
2052
|
-
const a = Math.floor(U.length / 2), n = U.slice(0, a), e = U.slice(a);
|
|
2053
|
-
this.left = new ht(t, F, n), this.right = new ht(t, F, e);
|
|
2054
|
-
}
|
|
2055
|
-
queryRange(t) {
|
|
2056
|
-
return this.bounds.intersects(t) ? this.left !== null && this.right !== null ? this.left.queryRange(t).concat(this.right.queryRange(t)) : this.pointIndices.filter((F) => t.intersects(this.boxes[F])) : [];
|
|
2057
|
-
}
|
|
2058
|
-
}
|
|
2059
|
-
class nl {
|
|
2060
|
-
constructor(t, F) {
|
|
2061
|
-
const U = F.map((l, a) => a);
|
|
2062
|
-
this.root = new ht(t, F, U);
|
|
2063
|
-
}
|
|
2064
|
-
queryRange(t) {
|
|
2065
|
-
return this.root.queryRange(t);
|
|
2066
|
-
}
|
|
2067
|
-
}
|
|
2068
|
-
class ol {
|
|
2069
|
-
constructor(t, F = 100, U = 1) {
|
|
2070
|
-
let l = 0, a = null, n = [];
|
|
2071
|
-
this.testPoint = (e, Q) => {
|
|
2072
|
-
if (t.renderData === null || t.camera === null) return console.error("IntersectionTester cannot be called before renderProgram has been initialized"), null;
|
|
2073
|
-
if ((() => {
|
|
2074
|
-
if (t.renderData === null) return void console.error("IntersectionTester cannot be called before renderProgram has been initialized");
|
|
2075
|
-
n = [];
|
|
2076
|
-
const r = t.renderData, c = new Array(r.offsets.size);
|
|
2077
|
-
let B = 0;
|
|
2078
|
-
const W = new ot(new I(1 / 0, 1 / 0, 1 / 0), new I(-1 / 0, -1 / 0, -1 / 0));
|
|
2079
|
-
for (const J of r.offsets.keys()) {
|
|
2080
|
-
const h = J.bounds;
|
|
2081
|
-
c[B++] = h, W.expand(h.min), W.expand(h.max), n.push(J);
|
|
2082
|
-
}
|
|
2083
|
-
W.permute(), a = new nl(W, c), l = r.vertexCount;
|
|
2084
|
-
})(), a === null) return console.error("Failed to build octree for IntersectionTester"), null;
|
|
2085
|
-
const d = t.renderData, A = t.camera;
|
|
2086
|
-
l !== d.vertexCount && console.warn("IntersectionTester has not been rebuilt since the last render");
|
|
2087
|
-
const i = A.screenPointToRay(e, Q);
|
|
2088
|
-
for (let r = 0; r < F; r += U) {
|
|
2089
|
-
const c = A.position.add(i.multiply(r)), B = new I(c.x - U / 2, c.y - U / 2, c.z - U / 2), W = new I(c.x + U / 2, c.y + U / 2, c.z + U / 2), J = new ot(B, W), h = a.queryRange(J);
|
|
2090
|
-
if (h.length > 0) return n[h[0]];
|
|
2091
|
-
}
|
|
2092
|
-
return null;
|
|
2093
|
-
};
|
|
2094
|
-
}
|
|
2095
|
-
}
|
|
2096
|
-
export {
|
|
2097
|
-
Ql as Camera,
|
|
2098
|
-
qt as CameraData,
|
|
2099
|
-
ut as Color32,
|
|
2100
|
-
sl as FPSControls,
|
|
2101
|
-
el as FadeInPass,
|
|
2102
|
-
ol as IntersectionTester,
|
|
2103
|
-
al as Loader,
|
|
2104
|
-
tt as Matrix3,
|
|
2105
|
-
Ut as Matrix4,
|
|
2106
|
-
bt as Object3D,
|
|
2107
|
-
il as OrbitControls,
|
|
2108
|
-
Al as PLYLoader,
|
|
2109
|
-
Zl as Plane,
|
|
2110
|
-
z as Quaternion,
|
|
2111
|
-
Fl as RenderData,
|
|
2112
|
-
Yt as RenderProgram,
|
|
2113
|
-
dl as Scene,
|
|
2114
|
-
Rl as ShaderPass,
|
|
2115
|
-
St as ShaderProgram,
|
|
2116
|
-
dt as Splat,
|
|
2117
|
-
lt as SplatData,
|
|
2118
|
-
ct as Splatv,
|
|
2119
|
-
mt as SplatvData,
|
|
2120
|
-
Vl as SplatvLoader,
|
|
2121
|
-
I as Vector3,
|
|
2122
|
-
nt as Vector4,
|
|
2123
|
-
cl as VideoRenderProgram,
|
|
2124
|
-
Bl as WebGLRenderer
|
|
2125
|
-
};
|